Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M68k a line trap support for at least Classic Mac, Apple Lisa, and Sharp X68000 #7126

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

hippietrail
Copy link
Contributor

@hippietrail hippietrail commented Oct 30, 2024

Here's my work so far on #140 and #487 to get so-called "A-line traps" working with the disassembler for Motorola 68000.

This is an early draft for discussion, not intended to be merged yet.

  • The names (and their all-caps defines) "MacTrap", "LisaTrap", and "X86Trap" are just for clarity of currently known styles while still researching how many ways A-line and F-line traps are used.
  • In particular, in the main dialog these don't have different names from "regular" 680x0... but then again neither does the ColdFire CPU. See included screenshot.
  • Adding op011 for the opcode is clear but I just picked opx015 for the second 16-bit word of the Lisa variant because it's the right size. I don't know if it's the best semantically.
  • There may be platforms that use A-line and/or F-line traps in different ways to these three.
  • There's no decompiler support, and I don't think there can be. They're like function calls and will have different calling conventions, use of stack and registers.
  • I picked atrap and ftrap based on discussion in the feature request. It may be better to mimic what the platforms' native SDKs did? But there may be multiple platforms that did it different ways. The m and l suffixes are also just for clarity and need not stay.
  • I put the new instruction definitions at the top before all the standard ones and inside the with : extGUARD=1 {, both of which might not be best.

I noticed that while the Lisa format is very different, using 2 16-bit words instead of one, that the X68000 and Classic Mac also differ to a lesser extent. Mac only needs the high $f nybble while the X68000 needs the high $ff byte. They could be unified or not which would mean part that's semantically part of the platform's instruction would appear in a naïve listing.

Screenshot 2024-10-30 at 10 22 04 pm

What Apple Lisa code currently looks like without this support:
Screenshot 2024-10-30 at 10 41 20 pm
The same with this support:
Screenshot 2024-10-30 at 10 42 58 pm
What Classic Mac code looks like with this support:
Screenshot 2024-10-30 at 10 44 23 pm
What X68000 code looks like with this support:
Screenshot 2024-10-31 at 2 12 39 pm

@hippietrail
Copy link
Contributor Author

hippietrail commented Oct 30, 2024

I have learned that the Atari ST actually did use A-line traps. Specifically for low-level graphics. Unlike Amiga and Classic Mac, it also used the 68000 trap instruction. Here's a sample with both:
Screenshot 2024-10-31 at 1 01 33 am
Nice little intro here: Writing Our First Atari ST Programs

@hippietrail
Copy link
Contributor Author

It turns out at least one platform did extensively use F-line traps, the Sharp X68000. So I'll have to make it conditional whether to use FPU opcodes or F-line traps.

@hippietrail hippietrail changed the title M68k a line trap support for at least Classic Mac and Apple Lisa M68k a line trap support for at least Classic Mac, Apple Lisa, and Sharp X68000 Oct 31, 2024
@hippietrail
Copy link
Contributor Author

Apparently TI's graphing calculators that ran 68000 CPUs used both A-line and F-line traps in various ways: https://www.omnimaga.org/other-calculator-discussion-and-news/best-ti-89-(titanium)-shell/15/#msg_116730

@hippietrail
Copy link
Contributor Author

hippietrail commented Oct 31, 2024

Palm OS also used A-line traps: https://jacobfilipp.com/DrDobbs/articles/DDJ/1999/9911/9911d/9911d.htm

In C it used a SYS_TRAP() macro. Not sure about asm yet.

@hippietrail
Copy link
Contributor Author

hippietrail commented Nov 2, 2024

Microware OS-9 for 68K seems to have not used A-line or F-line at all, but did use the trap instruction: https://lms.ee.hm.edu/~seck/AlleDateien/OS9HILFE/OS9-Manuals-Teil2/68k_tech.pdf

@sarnau
Copy link

sarnau commented Nov 4, 2024

I have learned that the Atari ST actually did use A-line traps. Specifically for low-level graphics. Unlike Amiga and Classic Mac, it also used the 68000 trap instruction.

The Atari ST used:

TRAP #1 (GEMDOS), TRAP #13 (BIOS) and TRAP #14 (XBIOS) with a standard 68k C calling convention.

TRAP #2 (AES/VDI) is used with a fixed 68k register convention.

LINEA #0 … LINEA #15 are used for Line-A draw primitives, also using a 68k registers for I/o parameters.

Very old TOS versions used Line-F as well to compress function calls in the ROM from 6 bytes to 2 bytes to make it fit into 192kb ROM. The 12 bit value in the opcode is the function, while parameters follow the standard 68k C calling conversion.

@hippietrail
Copy link
Contributor Author

hippietrail commented Nov 4, 2024

Very old TOS versions used Line-F as well to compress function calls in the ROM from 6 bytes to 2 bytes to make it fit into 192kb ROM. The 12 bit value in the opcode is the function, while parameters follow the standard 68k C calling conversion.

I was hunting for this Atari Line-F stuff and just found it a couple of hours ago. Not easy to Google. My impression was that it was one part of TOS 1.04 aka "Rainbow TOS", AES I think, and that's where I found it. I didn't check other versions though.

@sarnau
Copy link

sarnau commented Nov 4, 2024

Yes, the Line-F stuff existed in 192kb ROMs (1.0 till 1.62). When Atari switched to the 256KB ROMs they removed that Line-F code. It exists only in the AES/Desktop code in the ROM. Honestly despite spending a LOT of time reverse engineering on the Atari in the 80s and optimizing the TOS I never touched the Line-F stuff – it was never that important. And today you can look and even compile the leaked source code for the TOS, so the need is simply not there.

I can probably provide you with the info, if you really care.

@hippietrail
Copy link
Contributor Author

Yes, the Line-F stuff existed in 192kb ROMs (1.0 till 1.62). When Atari switched to the 256KB ROMs they removed that Line-F code. It exists only in the AES/Desktop code in the ROM.

I was an Amiga guy back in the day so I'm a bit ignorant. Was Desktop part of AES? I only just read a few minutes ago that Desktop used F-line as well as AES.

Honestly despite spending a LOT of time reverse engineering on the Atari in the 80s and optimizing the TOS I never touched the Line-F stuff – it was never that important. And today you can look and even compile the leaked source code for the TOS, so the need is simply not there.

For me it's just for the fun of retrocomputing + the fun of disassembling + something interesting to program (-:

I can probably provide you with the info, if you really care.

I just wanted to get a thorough overview of how they were used across systems before hastily jumping in to a too-limited solution. When the Lisa's use was only the second I ever saw I though they might get used a myriad ways, but it's the only real outlier.

I'm guessing the specifics, such as what each trap does would belong in a platform-specific script rather than have anything to do with the sleigh, but that's all beyond what I have learned yet in Ghidra.

(Also, and off-topic for this thread, but I have some questions about Atari ST object and library file formats if there's an appropriate place to start such a thread. On GitHub or one of the Atari forums?)

@sarnau
Copy link

sarnau commented Nov 4, 2024

I wouldn't call it "ignorant" at all, it is just not knowing.

BIOS/XBIOS/GEMDOS = low level file system, etc. stuff
VDI = all the high-level graphics APIs
AES = all the code for the UI (menus, windows, dialogs)
Desktop = simple version of the Amiga Workbench or the Macintosh Finder.

We might want to separate the processor issues (2 byte 68k alignment, function calling conventions) from the file formats and system API integration. I think for the latter some people try to support syscalls for Linux, which is similar – maybe they have some pointers. I think this is the most critical and tricky part to get the 68k CPU adopted to support the different APIs in general, so that the decompiler works as well (the disassembler itself is trivial)

Optionally support for system variables, symbol tables, etc. is all part of loaders. These are not hard to write (Classic Mac are tricky because of the resource forks) and are sitting on top of the CPU changes, which are required.

I have done some stuff for Ghidra for the Atari ST, C64 and the Atari 400/800/XE series – some with Java code. I am coming from IDA, but as a hobby guy I can no longer afford the license (I spend the money for it, but >$1k for a hobby per year – nope – so I am doing more and more with Ghidra)

@hippietrail
Copy link
Contributor Author

Optionally support for system variables, symbol tables, etc. is all part of loaders. These are not hard to write (Classic Mac are tricky because of the resource forks) and are sitting on top of the CPU changes, which are required.

Loaders (and FileSystems) are what I've mostly been working on. Classic Mac was my first one for a 32-bit platform I didn't really know. It's in my project RetroGhidra but I don't think anybody has tried using it yet. I'm sure there are many features of loaders I haven't learned yet.

I have done some stuff for Ghidra for the Atari ST, C64 and the Atari 400/800/XE series – some with Java code. I am coming from IDA, but as a hobby guy I can no longer afford the license (I spend the money for it, but >$1k for a hobby per year – nope – so I am doing more and more with Ghidra)

I have some loaders for those in RetroGhidra too, but other people have made better ones for Ghidra already. I've looked at the free IDA a few times but it's too limited and I don't have spare money.

@hippietrail
Copy link
Contributor Author

Related problem with M68K:

I was just told that while OS9 didn't use A-line or F-line traps, it does a similar the to what Apple Lisa does with A-line traps except with the regular trap instruction.

It adds an extra word after the instruction which most disassemblers don't know about and hence misinterpret as an instruction, likely a bad instruction.

@th-otto
Copy link

th-otto commented Jan 5, 2025

You can find the code of LineF handler used in AtariST: https://github.com/th-otto/tos1x/blob/master/aes/linefhdl.S

Some explanations are at the top of that file.

Unfortunately, the list of functions is also OS version dependent. The list there is for TOS 1.04, but 1.00/1.02 have a different one. In the 256k ROMs (1.06 and later) that ugly hack is not used anymore. The LineA trap however was still used in the latest ROMs, but only to call 16 functions.

@th-otto
Copy link

th-otto commented Jan 6, 2025

I'm currently struggling trying to implement something similar for the Atari's LineF trap handler. What i did is

  • add
  op00 = (0,0)
  op111 = (1,11)

to the instr token

  • define a new pseudo opcode:
define pcodeop linefcall;
  • match the opcode
:linefcall "#"t is op=15 & op111 & op00=0 [ t = op111 * 2; ] {
	local vector:2 = op111 * 2;
	linefcall(vector);
}

But i have two problems with this:

  • i have to disable all the other FPU opcodes, otherwise the decompiler sometimes seem to see both instructions, possibly decoding the effective address from the real FPU instructions.
  • The above should match only opcodes where bit 0 is zero, but it matches both:

Screenshot_20250106_084308

Any hint what i am doing wrong?

@ABratovic
Copy link

ABratovic commented Jan 13, 2025

@th-otto
Your F15C I believe is a FRESTORE instruction with Cp-ID code of 000 used by the MC68851 Paged-Memory Management Unit, I strongly suspect you'll also have opcode F11C in your code which is the FSAVE instruction.
These instructions are used by all types of coprocessors not just the MC68881 or MC68882 Floating-Point Coprocessor which uses Cp-ID of 001.

In the 68020 and later they're built in opcodes called cpRESTORE and cpSAVE
The datasheet calls bits 11-9 the Cp-ID, in the 68020 datasheet it says ID codes of 0x000-0x101 are reserved for Motorola coprocessors, codes 0x110-0x111 are reserved for user-defined coprocessors. Alas I don't have codes for a 68000 so I don't know if your F801 is a custom emulation or a cpGEN instruction for a Motorola device with Cp-ID = 0x100 and is followed by a command word. What is the opcode following your F801??

For your F15C a dirty hack could be
:frestore eal is (op=15 & copid<6 & op68=5 & $(POSTINC_CTL_ADDR_MODES))... & eal { restoreFPUStateFrame(eal); }
and same for fsave

@ABratovic
Copy link

ABratovic commented Jan 13, 2025

Hi @th-otto
Found this data at https://bigbookofamigahardware.com/bboah/Product.aspx?id=1643
Based on this info I suspect your F801 is a cpGEN Coprocessor General Function instruction used to pass a command word to coprocessor.

The 68851 is an external memory management unit (MMU) which is designed to provide paged memory support for the 68010 or 68020. It cannot be used with later versions of the processors such as the 040 or 060 because they have an internal MMU. It also cannot be used with EC versions of the 030, and possibly EC versions of the 020. Very few cards for the Amiga make use of the 68851 primarily because it can only be used with a small range of processors and most Amiga's and accelerator cards use a processor which either has it's own MMU or cannot support an MMU. One of the few cards which does use this is the Commodore A2620.

@th-otto
Copy link

th-otto commented Jan 13, 2025

Thanks for your answer, but that is not the problem ;) The code in question is run on a plain 68000, which has no MMU, FPU or any other coprocessor. Instead all those opcodes generate a LineF exception, and the handler then fetches the opcode that caused the exception, and either calls a function from a table, or emulates return from that function.

But my problem is solved i think. In my first tries i had used a processor description without the linefreturn opcode. Clearing all the opcodes, and dissassembling again with the new definition, seems to have fixed it. Code now looks quite good, eg.

Screenshot_20250113_124634

is decompiled to

Screenshot_20250113_123629

@hippietrail
Copy link
Contributor Author

There is overlap between MC68881/MC68882 opcodes and F-line opcodes. A couple of 68000 systems used F-line traps for random things before those MMU chips were even released. This is not that unusual and Ghidra processor definition architecture can already handle it. But it wasn't designed around arbitrary trapping instructions either.

@hippietrail
Copy link
Contributor Author

But my problem is solved i think. In my first tries i had used a processor description without the linefreturn opcode. Clearing all the opcodes, and dissassembling again with the new definition, seems to have fixed it. Code now looks quite good, eg.

Nice! It looks like you got further with that stuff that I managed to. I went back to working on Loaders and FileSystems when I got stuck on my processor before even starting p-code support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature: Processor/68000 Status: Triage Information is being gathered
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants