[HN Gopher] An invalid 68030 instruction accidentally allowed th...
___________________________________________________________________
An invalid 68030 instruction accidentally allowed the Mac Classic
II to boot
Author : todsacerdoti
Score : 282 points
Date : 2025-01-25 20:29 UTC (1 days ago)
(HTM) web link (www.downtowndougbrown.com)
(TXT) w3m dump (www.downtowndougbrown.com)
| ChuckMcM wrote:
| That is quite the journey. I find I don't have the patience these
| days to go quite so far down the rabbit hole as the author does,
| but I resonate with that feeling of accomplishment in _knowing_
| something versus just thinking you know something.
| dougg3 wrote:
| Author here. Yeah, I have a tendency to go into pretty big deep
| dives when I find stuff like this. It's so rewarding at the
| end, even if it does take a lot of time!
| mrandish wrote:
| Finding a previously unknown undocumented instruction at this
| late date in a line of processors as prevalent and
| historically significant as the 68k is surprising. Congrats
| on your achievement! If someone does dive into fully
| characterizing the undocumented instruction so it can be
| properly supported in emulators (as you suggested), please
| post about it on HN. I suspect, like many undocumented CPU
| instructions, it was probably to help the original designers
| test or verify something during development but it would be
| interesting to know.
|
| While obviously a subjective judgement, a lot of people who
| hand coded assembler on 68k processors regard the ISA as
| especially elegant, powerful and fun to develop for. In many
| ways I think of it as peak CISC, thanks to its orthogonal
| instruction set and wildly flexible addressing modes. And of
| course the platforms which used it are legendary, from
| consumer (Mac/Lisa, Amiga, Atari ST, Sinclair QL) to
| workstations (SUN, Apollo, Quantel) to gaming (Sega Genesis,
| Neo Geo, Capcom, Atari, Namco, Sega, Taito, Konami) to
| embedded (automation, print/network controllers,
| synthesizers, appliances). I'm certainly biased but to this
| day the 68k (and its 8-bit little brother the 6809) are the
| only CPUs I still enjoy writing assembler on.
| dougg3 wrote:
| Thank you! Yes, I will definitely make another post if and
| when someone figures out what the instruction does.
| userbinator wrote:
| _I suspect, like many undocumented CPU instructions, it was
| probably to help the original designers test or verify
| something during development but it would be interesting to
| know._
|
| Or simply be an emergent but unintended behaviour of the
| implementation, as is the case for most of the undocumented
| 6502, Z80, and x86 instructions I know of.
| bell-cot wrote:
| > a lot of people who hand coded assembler on 68k
| processors regard the ISA as especially elegant, powerful
| and fun to develop for. In many ways I think of it as peak
| CISC, thanks to its orthogonal instruction set and wildly
| flexible addressing modes.
|
| I definitely agree...but I'd say Motorola really got
| carried away with those wildly flexible addressing modes.
| Which lead them into implementation, power draw, and gate-
| delay hells by the late 1980's and the 68040. The future
| was ever-rising transistor counts and clock speeds - and
| their 68k architecture just couldn't go there.
| mrandish wrote:
| > I'd say Motorola really got carried away with those
| wildly flexible addressing modes.
|
| Yeah, while they could certainly be extremely powerful,
| I'll admit the edges of my 68000 programmer's reference
| card quickly got dog-eared from how often I'd need to
| remind myself exactly how some program-counter relative
| indexed redirection+offset instruction worked. Almost
| made me miss the days of simple 8-bit loads, stores,
| compares and branches being all we had.
|
| > The future was ever-rising transistor counts and clock
| speeds - and their 68k architecture just couldn't go
| there
|
| I've always wanted to understand more about why Motorola
| abandoned the 68k architecture. I understand the broad
| factors cited in the Wikipedia article and on
| RetroStackExchange but I don't recall anyone citing
| supporting the addressing modes specifically (though it
| makes sense). I never programmed x86 assembler but my
| sense was that ISA also had its own oddball complexities.
| I never understood if there was some fundamental
| conceptual difference between the 68k and x86 ISAs that
| prevented one from being able to scale into the future
| while the other could. Would love any more info or links
| if you have them handy.
| basementcat wrote:
| Do the '040/060 also support this "undocumented instruction"?
| dougg3 wrote:
| On the 040, it seems to do something that actually involves D1.
| Definitely doesn't touch A1 at all. I didn't test further, but
| it's possible it just handles the instruction as a normal CAS.
|
| It did cause a system error the first time I stepped through
| the instruction with MacsBug on my LC 475, but then it was fine
| after that.
| mras0 wrote:
| Have an Amiga w/ 060, and that instruction doesn't seem to
| modify any A registers. (Only did a very quick test of those
| exact instruction words)
| basementcat wrote:
| I appreciate that I can ask an esoteric question about the
| behavior of a 30 year old microprocessor and multiple people
| respond with test results on actual hardware within a few
| hours. Can y'all also post the mask revision (if known) and
| whether it is an EC or LC device? (In case it impacts
| behavior)
| mras0 wrote:
| Rev5 "full" 060 (not EC/LC). Quick capture of crappy
| methodology: https://imgur.com/a/XwQ1Tnp (PCR with revision
| number is in d0)
| ahefner wrote:
| Today by, way of your screenshot, I discover Asm-Pro.
| Just got into Amiga recently (by way of receiving one
| from my uncle's closet..) and have been meaning to
| backfill my shameful lack of 68k asm knowledge. Thanks!
| dougg3 wrote:
| My test of an 040 (no A1 change, D1 changed) was on a chip
| with the following markings:
|
| XC68LC040RC25B
|
| 02E23G QEDP9348D MALAYSIA
| cluckindan wrote:
| Time to fuzz the rest of the processor.
| AnimalMuppet wrote:
| WOW.
|
| _Amazing_ work. Thanks for the exposition.
|
| (I miss the 68000 line. Those were such great chips...)
| aruggirello wrote:
| I miss the assembly. It was so clear and logical, like great
| engineering should always be. You could browse through it and
| comprehend at a glance what was happening. By contrast x86
| assembly looks like pure rubbish, with stuff that most of the
| time looks like clever hacks coming from a bad night's sleep,
| like subtracting a register from itself to get zero... c'mon!
| jjuran wrote:
| I hate to disappoint you, but the canonical way to clear a
| 68K address register is `SUBA.L An,An`. My asm-coded
| replacement for the Metrowerks code resource runtime uses it:
|
| <https://github.com/jjuran/metamage_1/blob/master/mac/toolcha
| ...>
| TapamN wrote:
| Does Ken Shirriff have time to look at a 68030?
| kens wrote:
| Unfortunately, not any time soon.
| phibz wrote:
| That's great. Merely speak his name and he appears.
|
| Love the work you do Ken. Thank you.
| Waterluvian wrote:
| We're confident this wasn't some ROM DRM type feature?
| the-rc wrote:
| I was thinking maybe it's a way to save some bytes, like people
| used to do with undocumented opcodes in 6502 programs.
| userbinator wrote:
| An "unintentional emulator trap" is how I would characterise
| it.
| rep_lodsb wrote:
| Wouln't have prevented hardware clones, since they would have
| used the same chip. It's fairly certain nobody at Apple knew
| about this instruction.
| khazhoux wrote:
| 30+ years later, I'm still always amazed at how effective the Mac
| debugger UI could be with such a tiny screen resolution. It's
| really quite masterful.
| 1over137 wrote:
| This seems like it will be impossible in the future with today's
| Macs. Apple's technical documentation is rubbish these days.
| kevingadd wrote:
| I think in modern environments the odds of this sort of bug
| slipping into released firmware/software are much lower.
| Address spaces are much bigger and the vast majority of
| addresses aren't mapped so doing a memory operation on a
| garbage address is going to fail most of the time, and invalid
| instructions will probably fail too.
|
| Reading from a jump table with an index that's too big is a
| realistic sort of bug to have, so I could see that part making
| it into modern shipped software. But I would expect the process
| to fall over when it happens, not keep on trucking like it did
| here.
|
| FWIW, WebAssembly is an environment where bugs of this sort are
| more possible, since it has a single linear address space where
| every address is both readable and writable. So if your garbage
| address is within range you can do an erroneous read, write or
| CAS and get away with it. But then invalid instructions like in
| the post will cause the WASM module to fail to load, so it's
| still not 1:1 comparable with this issue in the mac's ROM.
| 1over137 wrote:
| Sorry, the "this" I was referring to was the ability to
| consult docs, reverse engineer to this extent, etc.
| saagarjha wrote:
| I think you're underestimating people who do this.
| grishka wrote:
| IMO the reason Apple doesn't provide this level of hardware
| documentation is because modern Macs don't have comparable
| expansion capabilities. The kind that expose system buses on
| connectors that users are supposed to plug cards into, and
| third-party developers to interact directly with hardware to
| make those cards work. On a modern Mac, you've got USB and
| Thunderbolt that you can interact with from a userspace
| program.
|
| Though I'm not denying that some of the newer macOS APIs are
| very poorly documented. As in, you know you've stumbled upon
| _the cool shit_ when you end up on one of those old pages with
| a blue gradient in the header that says "Apple documentation
| archive".
| hajile wrote:
| Was this copy protection to keep it from running on systems or
| does this happen on all 68030?
| kevingadd wrote:
| The contents of the post make me pretty confident that this
| wasn't copy protection, the jump table involved here is just
| missing an entry for the machine because (most likely) everyone
| involved in working on the ROM forgot to add a new entry to the
| jump table and it happened to work without a table entry by
| pure chance.
| kstenerud wrote:
| CAS has always been a bitch. I think I've received more bug
| reports about that instruction's emulation than any other
| instruction.
|
| Incidentally, I remember another old "bug" in King of Fighters
| that "incorrectly" checked the carry flag of the SBCD
| instruction, which it used to decrement the round timer and end
| the current round. Completely undocumented of course, but if you
| don't emulate the arithmetic status flags when doing binary coded
| decimal operations, the round timer in KOF will just keep on
| going forever, cycling from 00 to 99 :P
|
| SNK were really the gods of the 68000 chip.
| mrandish wrote:
| > SNK were really the gods of the 68000 chip.
|
| As a fan of retro arcade machines and the 68k, I'd love to hear
| more about why SNK were godly in how they maximized the 68K.
| azinman2 wrote:
| Yes - were they doing something that Apple, Amiga and the
| Unix vendors weren't?
| userbinator wrote:
| Nearly all CPUs have undocumented instructions, and the 68k is no
| exception; it's just that the vast majority of people with enough
| interest and low-level knowledge at the time were focused on the
| x86/PC instead, which was arguably a far more open and stable
| architecture than Apple's. The 8088 and 8086 microcode was
| disassembled and studied extensively a few years ago, and I
| believe there's been some attempts at simulating it at the
| transistor level already. Even before that, the structure of the
| x86 opcode space was also explored in detail by many, with
| documents like these resulting from such effort:
|
| http://ref.x86asm.net/geek.html
|
| https://gist.github.com/seanjensengrey/f971c20d05d4d0efc0781...
|
| _We don't really know the exact details of what this instruction
| does. With some limited testing, I believe I've observed that the
| resulting value of A1 depends on the original A1 value, the value
| of A7, and the program counter. But I'm not sure. Maybe someone
| can make a program that tries out a bunch of different register
| values and memory contents, and attempt to deduce what exactly
| the instruction does so that it can be emulated accurately. Until
| someone decides that it's worth trying to figure out, MAME is
| patching this bug out of the ROM in order to allow the Classic II
| to boot._
|
| IMHO this is definitely worth figuring out for accurate
| emulation. I'm not familiar with 68k but the bits in the
| instruction offer a good clue - my theory is that bits 5:3 of the
| 2nd word seem like another mode field, and instead of selecting
| one of the Dn registers via mode 000, 101 is selecting (d16, An)
| again and the Dc field, containing 001, is being interpreted as
| A1.
| pjmlp wrote:
| At the time Mac Classic was relevant, PC still wasn't thar
| great in home computing, no one was bothering with this stuff
| in x86/PC.
|
| We were still bothering with demoscene stuff in 8 bit home
| computers, and those of us busy with 16 bit home systems were
| focused on Atari and Amiga systems.
|
| PC and x86 at home only took off, meany really taking off among
| demoscene and other home users, was when VGA and sound cards
| became part of a standard PC.
| userbinator wrote:
| The Mac Classic was released in 1990, the Mac Classic II that
| is the subject of this article was released in 1991. At that
| time PCs with 286s and 386s were already common, and the 486
| was just starting to gain marketshare at the high end. Most
| of the undocumented 8086 instructions had already been known
| for almost a decade; and the majority of those who knew were
| not demosceners. Many developers used Asm exclusively, and
| the "classic hacker mindset" was very much alive among them.
| pjmlp wrote:
| Depends on where in the globe one were and in my demoscene
| circles PCs only took off as interesting after Windows 95,
| folks using MS-DOS or Windows 3.x were mostly due to their
| parents family computer.
| zargon wrote:
| This is 1992 we're talking about. You might be confusing the
| Mac Classic II with mid-80s Macs due to the form factor.
| pjmlp wrote:
| Where Amiga and Atari were still calling the shots among
| European demoscene.
| TazeTSchnitzel wrote:
| I think non-x86/non-PC-compatible home computers did remain
| relevant for a bit longer in Europe and Japan than in the US
| but by 1992 the writing must have been on the wall.
| fulafel wrote:
| nitpick: 68k of course wasn't Apple's architecture. The '030
| was the nicest GP CPU around in its day, used in the Amiga
| 3000, Atari Falcon, Sun 3, NeXT Cube etc.
| adrianmonk wrote:
| > _I've discovered an undocumented MC68030 instruction that
| performs a read-modify-write bus cycle and also changes the value
| of the A1 register._
|
| Rather than a "real" instruction that CPU designers consciously
| created and which was meant to do something useful but wasn't
| documented, it could just be that this is an illegal instruction
| and the logic in the CPU is doing whatever it happens to do when
| given don't-care inputs. (Maybe this is what the author meant,
| and I'm just catching up.)
|
| Normally the CPU would detect illegal instructions and cause an
| exception. This would mean there are certain situations where it
| doesn't.
|
| I found a manual at https://www.nxp.com/docs/en/reference-
| manual/MC68030UM.pdf. On page 8-9 of the manual (which is page
| 276 in the PDF file), it says:
|
| > _An illegal instruction is an instruction that contains any bit
| pattern in its first word that does not correspond to the bit
| pattern of the first word of a valid MC68030 instruction or is a
| MOVEC instruction with an undefined register specification field
| in the first extension word._
|
| Note "in its first word". According to the write-up, the
| instruction is 3 words long. The first word is normal, and the
| weird bits occur in the second word. So quite possibly the 68030
| doesn't validate this second word, just plows forward with the
| logic that implements the CAS instruction, and lets whatever
| happens happen.
|
| (Great write-up and amazing dedication, by the way!)
| rep_lodsb wrote:
| It looks to me (not being an 68k expert) that only the first
| word is considered the "opcode": the second word just selects
| what "D" registers are used for the CAS operation. Normally one
| would expect the zero bits to be completely ignored in that
| case, since they don't have any role in the instruction.
|
| But maybe on the 68030 in this case, the bits must be zero even
| if they have no documented use, because there is hardwired
| logic for another instruction that is activated by those bits
| being set, somewhat like the 6502 illegal opcodes?
| userbinator wrote:
| This is the closest I could find to what the 68000 opcode map
| looks like:
|
| http://goldencrystal.free.fr/M68kOpcodes-v2.3.pdf
|
| It's reminiscent of ARM, but the relevant part is that the
| CAS instruction's second word bits 5:0 look like a "modrm"
| (to use the x86 terminology) where the officially documented
| values select only Dn, but the undocumented variant would
| correspond to (d16,An). At least, that's my theory for why A1
| gets modified.
| userbinator wrote:
| Update: from the linked thread at
| https://68kmla.org/bb/index.php?threads/classic-ii-
| possible-... there is this quote that supports my theory:
|
| _This seems to put something into A1 [...]If you clear bit
| 3 from the second word of the instruction this stops
| happening._
| dougg3 wrote:
| It also appears that I may not have been the first one to
| discover that something odd was going on with that bit,
| causing it to use A0-A7 (with weird results) instead of
| D0-D7:
|
| https://eab.abime.net/showthread.php?t=119675
| sowbug wrote:
| In college, I took a computer architecture course that briefly
| went into CPU microcode. The fake CPU we studied divided
| opcodes into bit fields where a certain bit caused a certain
| primitive operation, like maybe triggering an adder. From this
| you could see that a specific opcode was just a particular
| composition of the right primitives. "Valid" opcodes were
| simply the combinations that were useful enough to document,
| and "invalid" ones were superfluous or meaningless
| combinations. Once you understand this, illegal/invalid/mystery
| opcodes are a lot less surprising; rather, they're inevitable.
|
| I was also taking a logic course at the time and dreaming in
| terms of truth tables, so it was quite a formative time in my
| early understanding of processor architecture.
| submeta wrote:
| I had an Amiga 2000 with an 68000 processor when I was a kid. How
| I got excited when I heared about the 68020, or even 68030! And
| then even RISC architecture. Those were things that got me
| excited back in those days. I could let my Amiga say a sentence
| like ,,Hello, how are you?", in a robotic tone, and my friends
| were baffled as if they'd been to the moon and back. I couldn't
| have imagined that less then four decades later I'd be talking to
| my computer in natural language using llms. And with Python, VS
| Code, and LLM in my toolbelt I can automate almost anything I
| wish to. Crazy times!
| fredoralive wrote:
| Re Egret and Command-Power, I'm pretty sure the key combination
| (and the command-control-power hard reset combo) is always
| active, and not a Macsbug thing. ISTR you can trigger sad Macs on
| boot with it, which would be before Macsbug is loaded (I think),
| and also access the mini debugger if Macsbug isn't loaded. At
| least from what I remember about my old LCII (would have to dig
| it out to double check though).
| dougg3 wrote:
| I've been trying it out a bunch lately. From what I've seen,
| machines with Egret don't have it enabled by default, but
| machines with the newer Cuda do.
| Zardoz84 wrote:
| > By buying a Classic II and hacking the ROM...
|
| I think that to be a perfect article, they should wrote :
|
| By the magic of buying a Classic II and hacking the ROM...
| kazinator wrote:
| It's not miraculous. If the flaw had prevented the system from
| booting (in a way that has a high repro rate) they would have
| fixed it.
|
| The system booted in spite of that undocumented instruction. When
| things work, you don't go looking for undocumented things that
| are contributing to the working state.
|
| Millions of C programs work accidentally, in spite of undefined
| behavior. Nothing gets investigated until a compiler change
| triggers something.
| dougg3 wrote:
| Don't you think, as a Mac ROM developer, the chances of your
| software bug being accidentally fixed by the CPU through an
| undocumented instruction are pretty low? That's what I was
| getting at when I wrote that.
|
| Of course they would have fixed it if it had prevented the
| system from booting, I even said that in the article. I still
| think the odds of what happened here were pretty small. That's
| what I meant by miraculous.
| ptek wrote:
| Damn this instruction won't speed up Amiga chunky to planar
| conversion.
| knuckleheadsmif wrote:
| Perhaps it is 'undocumented' and is used as proof of someone
| copying the source code some portion of the source code.
|
| Another possibility is that is a special institution in the chip
| specifically for Apple that again was used as a copy write
| detection or protection scheme.
___________________________________________________________________
(page generated 2025-01-26 23:01 UTC)