The secrets of the 68000
Moderators: simonsunnyboy, Mug UK, Zorro 2, Moderator Team
The secrets of the 68000
I plan to use this thread to post and discuss about interesting undocumented aspects of the 68000.
Fx Cast: Atari St cycle accurate fpga core
The I/N field on the bus and address error stack frame
Quiz of the day for advanced 68000 coders:
It has been observed that the instruction MOVE Dn,-(An), if it provokes a bus or address error when writing the operand, the I/N bit would be set on the exception stack frame. According to the official documentation, the I/N set indicates that the processor wasn't processing an instruction. The observation actually is not accurate. The I/N might be set, but not always. Let's consider the following code sequence:
This will provoke an address error and the processor will create an extended stack frame that includes the I/N field as described in the manual. The I/N will be set in some circumstances, not always.
When I/N will be set and when it will be not, and why? Assume, of course, that SSP was valid and the stack frame was created successfully.
Edit: Added the size of the last instruction explicitly. I didn't include it before because most assemblers assume a default word size. There was no intention to hide it.
It has been observed that the instruction MOVE Dn,-(An), if it provokes a bus or address error when writing the operand, the I/N bit would be set on the exception stack frame. According to the official documentation, the I/N set indicates that the processor wasn't processing an instruction. The observation actually is not accurate. The I/N might be set, but not always. Let's consider the following code sequence:
Code: Select all
moveq #1,D0
move.l D0,A0 ; A1 = 1
move.w D0,-(A0) ; Attempt to access address -1 and provokes an address error exception
When I/N will be set and when it will be not, and why? Assume, of course, that SSP was valid and the stack frame was created successfully.
Edit: Added the size of the last instruction explicitly. I didn't include it before because most assemblers assume a default word size. There was no intention to hide it.
Fx Cast: Atari St cycle accurate fpga core
Re: The secrets of the 68000
I didn't test my theory, because that would be cheating. 
But it is revealing that you omitted the operand size from the MOVE instruction. Thus, my guess is as follows: It depends on that size. If there is only one write access (.B / .W), the instruction is considered finished when the exception occurs. But if two write cycles are required (and the error occurs during the first cycle as in your example), the instruction is still considered under way.

But it is revealing that you omitted the operand size from the MOVE instruction. Thus, my guess is as follows: It depends on that size. If there is only one write access (.B / .W), the instruction is considered finished when the exception occurs. But if two write cycles are required (and the error occurs during the first cycle as in your example), the instruction is still considered under way.
Re: The secrets of the 68000
Not at all. You can testczietz wrote:I didn't test my theory, because that would be cheating.

Sorry, no. It wasn't intentional and I edited the post and added the size explicitly. If the size of the instruction would have been byte then no address error exception would be generated at all. A bus error could still happen depending on the platform. But no, the question assumes a word size that generates an address error exception.But it is revealing that you omitted the operand size from the MOVE instruction. Thus, my guess is as follows: It depends on that size. If there is only one write access (.B / .W), the instruction is considered finished when the exception occurs. But if two write cycles are required (and the error occurs during the first cycle as in your example), the instruction is still considered under way.
Fx Cast: Atari St cycle accurate fpga core
Re: The secrets of the 68000
Now you've intrigued me and I had a look at the 68000 manual. (Even though that is definitively cheating.) With respect to the I/N bit is says: "The processor is processing an instruction if it is in the normal state or processing a group 2 exception; the processor is not processing an instruction if it is processing a group 0 or a group 1 exception."
EDIT:
So -- still not tested on the actual HW -- I'd now say that the state of the bit depends on whether your code is inside another exception handler. An address error while processing a group 0 exception (bus or address error) will cause a double fault and halt the CPU, but the behavior described in the manual should be observable by triggering the address error during a group 1 exception. For example in an interrupt handler.
After testing, I think that my previous theory was not correct -- but the basic idea was. In order for the I/N bit to be set to 1, the address error must not occur in the handler of a group 1 exception, but when the processor is actually setting up processing of a group 1 exception. I.e., when the TRACE bit is set while your code executes.
So, I see that the I/N bit is set, when running this code, while it is cleared when I comment the line marked with "<===".
EDIT:
So -- still not tested on the actual HW -- I'd now say that the state of the bit depends on whether your code is inside another exception handler. An address error while processing a group 0 exception (bus or address error) will cause a double fault and halt the CPU, but the behavior described in the manual should be observable by triggering the address error during a group 1 exception. For example in an interrupt handler.
After testing, I think that my previous theory was not correct -- but the basic idea was. In order for the I/N bit to be set to 1, the address error must not occur in the handler of a group 1 exception, but when the processor is actually setting up processing of a group 1 exception. I.e., when the TRACE bit is set while your code executes.
So, I see that the I/N bit is set, when running this code, while it is cleared when I comment the line marked with "<===".
Code: Select all
move.l #inthdl,0x24.w
ori #0x8000,sr | <===
moveq #1,D0
move.l D0,A0
move.w D0,-(A0)
inthdl:
rte
Re: The secrets of the 68000
It was wrong indeed. Interrupt or exception handler is a software concept, not a hardware one. The processor doesn't care, and even doesn't really know if you are inside a handler or not. So it is even possible to have an address or bus error inside a group 0 exception handler and it will not halt the cpu.czietz wrote: EDIT:
So -- still not tested on the actual HW -- I'd now say that the state of the bit depends on whether your code is inside another exception handler. An address error while processing a group 0 exception (bus or address error) will cause a double fault and halt the CPU, but the behavior described in the manual should be observable by triggering the address error during a group 1 exception. For example in an interrupt handler.
After testing, I think that my previous theory was not correct -- but the basic idea was.
Right. Or more precisely, when the processor is processing the exception itself and before the exception handler takes control. That includes saving the stack frame (normal or extended) and fetching the exception vector..In order for the I/N bit to be set to 1, the address error must not occur in the handler of a group 1 exception, but when the processor is actually setting up processing of a group 1 exception.
This is partially true. But this is not the only circumstances that the I/N would be set. And you don't explain why it is set. It shouldn't (at least according to you might except). The address error didn't occur when saving the stack or when fetching the exception vector. The processor was still executing a regular instruction.... I.e., when the TRACE bit is set while your code executes.
So, I see that the I/N bit is set, when running this code, while it is cleared when I comment the line marked with "<===".
Code: Select all
move.l #inthdl,0x24.w ori #0x8000,sr | <=== moveq #1,D0 move.l D0,A0 move.w D0,-(A0) inthdl: rte
Fx Cast: Atari St cycle accurate fpga core
Re: The secrets of the 68000
Another clue might be that for "MOVE.W D0,-(A0)" the write access that causes the address error only happens after the prefetch for the next instruction. Unlike you, I don't know how the internal sequencer of the 68000 works, but one could assume that the I/N bit due to the upcoming TRACE handler is updated in parallel to the prefetch. This would explain why the I/N is not set even with tracing in effect, if the address error is triggered by "MOVE.W D0,(A0)", instead.
Re: The secrets of the 68000
You are getting closer. It is not directly related to the prefetch, but to the address error hapening at the last microcycle of the instruction.czietz wrote:Another clue might be that for "MOVE.W D0,-(A0)" the write access that causes the address error only happens after the prefetch for the next instruction. Unlike you, I don't know how the internal sequencer of the 68000 works, but one could assume that the I/N bit due to the upcoming TRACE handler is updated in parallel to the prefetch. This would explain why the I/N is not set even with tracing in effect, if the address error is triggered by "MOVE.W D0,(A0)", instead.
I am posting a small article on the next message elaborating about the bus/address error exception stack frame. Last section of the article elaborates on this issue of the I/N bit.
Fx Cast: Atari St cycle accurate fpga core
Re: The I/N field on the bus and address error stack frame
Attached in a small article I wrote about the bus and address exception stack frame.
Whole article in PDF form (updated version): I am pasting here the sections relevant to the I/N field. But it might be easier to understand the context checking the whole article.
..., but also the I/N field is set indicating, or seeming to indicate, that the processor wasn’t executing an instruction when the exception was triggered. Normally the I/N field would be set only when the processor was already processing a group 1 exception, such as when a bus or address error occurs when saving the PC or the SR during an interrupt. It is not expected to be set when processing an instruction. The reason that it would be set in some circumstances, is once more again, how the microcode works.
As explained in the previous section, the processor updates its state for the next instruction before it actually completes. This includes updating the TVN (Trap Vector Number) latch. The TVN is used slightly differently depending on the exception group. For group 1 exceptions, besides specifying the vector number, it is also the flag to process an exception after the current instruction completes.
Group 0 exceptions, on the other hand, are processed after the current microinstruction and do not update or modify the TVN latch until later, once the exception is already processing.
Consider the following code sequence (assembled machine code is included because it would be useful for the waveform below):
When the write to memory occurs as part of the third instruction, the EA is odd which will provoke an address error. In this particular instruction using pre decrement addressing mode, the write bus cycle is performed at the end of the instruction. That means that the TVN latch is updated before the write cycle completes (either normally or not). In addition, because in this particular code sequence the next instruction is illegal, the TVN is set for an illegal exception. Lastly, once the exception microcode starts, the I/N field in the SSW is set because the TVN latch indicates a group 1 exception. Note that this would not happen if the following instruction would be a regular one, not unless another group 1 exception, like Trace or Interrupt was being triggered.
It might seem surprising that both the IRD and the TVN are updated before the current instruction actually completes. From a software processing point of view, it could be expected that first the instruction completes, only then the state for the next instruction is updated, and finally the next instruction or exception is processed. But hardware doesn’t work like that. There is certainly no gap between instructions, and there isn’t an exact edge that absolutely separates one instruction from the other. For pipelining reasons and because of internal delays, some updates must be performed some cycles ahead. In this case specifically, the processor cannot update the TVN latch at the very last cycle. The TVN latch determines the address of the next microcode and the processor needs a couple of cycles to decode the address and the internal microcode ROM output.
FX68K simulation waveform
This is a simulation waveform of my FX68K FPGA core performing the above code. The waveform for a real 68000 would be slightly different, mainly because synchronization is different. But the result would be exactly the same.
The yellow vertical marks enclose the faulty bus cycle that attempts to access an odd address. Note the flow of the opcodes through the prefetch. Both the IRD and the TVN latch are updated at the start of the last microcycle of the MOVE instruction, coinciding also with the start of the bus cycle. The address error is signaled internally rather early; this is needed to abort the bus cycle at the external signals. However, internally the bus cycle continues, the MOVE instruction is still executing and the actual exception microcode has not yet started. Exception processing, including updating the SSW as one of its first tasks, starts a couple of cycles later (not shown on the waveform). By then, IRD already has the ILLEGAL instruction’s opcode, and the TVN latch indicates a group 1 exception.
Edit: Expanded the elaboration about the TVN usage and group 0 exceptions
Whole article in PDF form (updated version): I am pasting here the sections relevant to the I/N field. But it might be easier to understand the context checking the whole article.
..., but also the I/N field is set indicating, or seeming to indicate, that the processor wasn’t executing an instruction when the exception was triggered. Normally the I/N field would be set only when the processor was already processing a group 1 exception, such as when a bus or address error occurs when saving the PC or the SR during an interrupt. It is not expected to be set when processing an instruction. The reason that it would be set in some circumstances, is once more again, how the microcode works.
As explained in the previous section, the processor updates its state for the next instruction before it actually completes. This includes updating the TVN (Trap Vector Number) latch. The TVN is used slightly differently depending on the exception group. For group 1 exceptions, besides specifying the vector number, it is also the flag to process an exception after the current instruction completes.
Group 0 exceptions, on the other hand, are processed after the current microinstruction and do not update or modify the TVN latch until later, once the exception is already processing.
Consider the following code sequence (assembled machine code is included because it would be useful for the waveform below):
Code: Select all
7001 moveq #1,d0
2040 move.l d0,a0
3100 move.w d0,-(a0)
4AFC illegal
It might seem surprising that both the IRD and the TVN are updated before the current instruction actually completes. From a software processing point of view, it could be expected that first the instruction completes, only then the state for the next instruction is updated, and finally the next instruction or exception is processed. But hardware doesn’t work like that. There is certainly no gap between instructions, and there isn’t an exact edge that absolutely separates one instruction from the other. For pipelining reasons and because of internal delays, some updates must be performed some cycles ahead. In this case specifically, the processor cannot update the TVN latch at the very last cycle. The TVN latch determines the address of the next microcode and the processor needs a couple of cycles to decode the address and the internal microcode ROM output.
FX68K simulation waveform
This is a simulation waveform of my FX68K FPGA core performing the above code. The waveform for a real 68000 would be slightly different, mainly because synchronization is different. But the result would be exactly the same.
The yellow vertical marks enclose the faulty bus cycle that attempts to access an odd address. Note the flow of the opcodes through the prefetch. Both the IRD and the TVN latch are updated at the start of the last microcycle of the MOVE instruction, coinciding also with the start of the bus cycle. The address error is signaled internally rather early; this is needed to abort the bus cycle at the external signals. However, internally the bus cycle continues, the MOVE instruction is still executing and the actual exception microcode has not yet started. Exception processing, including updating the SSW as one of its first tasks, starts a couple of cycles later (not shown on the waveform). By then, IRD already has the ILLEGAL instruction’s opcode, and the TVN latch indicates a group 1 exception.
Edit: Expanded the elaboration about the TVN usage and group 0 exceptions
You do not have the required permissions to view the files attached to this post.
Fx Cast: Atari St cycle accurate fpga core
-
- Atari User
- Posts: 30
- Joined: Fri Nov 11, 2016 1:57 pm
- Location: Paris, France
- Contact:
Re: The secrets of the 68000
Fascinating!
Thanks for this clear and detailed explanation.
I guess no emulator handles this correctly?
Thanks for this clear and detailed explanation.
I guess no emulator handles this correctly?
-
- Atari God
- Posts: 1267
- Joined: Sun Aug 03, 2014 5:54 pm
Re: The secrets of the 68000
Well, what is "correctly"? If i understand that, it could also happen that an interrupt happens as the "next" instruction, which would have the same effect as the illegal instruction in the example. So imho for an exception handler, the I/N field in the stack frame is rather meaningless.
-
- Atari User
- Posts: 30
- Joined: Fri Nov 11, 2016 1:57 pm
- Location: Paris, France
- Contact:
Re: The secrets of the 68000
By masking interrupts it is possible to have a deterministic behavior. Based on that trick, one could write a small protection scheme that works on a real HW but fails on emulators.
Re: The secrets of the 68000
Not that I know. But I'm in contact with Toni Wilen (Winuae maintainer) and already let him know.orionfuzion wrote:I guess no emulator handles this correctly?
Well, you can say that an exception handler can't reliable check the I/N field. But that's not the point. The point is that under some conditions the hardware has some specific behavior, and an emulator (or FPGA core, or clone) should ideally reproduce exactly the same behavior. Otherwise, and as orionfuzion is saying, some code might depend on this (intentionally or not )and have different behavior than on real hardware.ThorstenOtto wrote:Well, what is "correctly"? If i understand that, it could also happen that an interrupt happens as the "next" instruction, which would have the same effect as the illegal instruction in the example. So imho for an exception handler, the I/N field in the stack frame is rather meaningless.
You might think that probably no software depend on this. But there are several ST protections that do depend on the exact content of the exception stack frame including the undocumented bits on the first word of the stack frame (see my article for a description of those undocumented bits). And it is just by chance that no case, that I know, sets the I/N field. If just by chance it would have, say, a LINE-A or LINE-F opcode after the instruction that provokes the exception, then, bingo ...

Fx Cast: Atari St cycle accurate fpga core
- Eero Tamminen
- Fuji Shaped Bastard
- Posts: 2291
- Joined: Sun Jul 31, 2011 1:11 pm
Re: The secrets of the 68000
> You might think that probably no software depend on this.
There are currently also some other differences in exception handling when comparing real HW with emulation, for example when 030 MMU raises exception on auto-increment instruction:
https://listengine.tuxfamily.org/lists. ... 00004.html
There are currently also some other differences in exception handling when comparing real HW with emulation, for example when 030 MMU raises exception on auto-increment instruction:
https://listengine.tuxfamily.org/lists. ... 00004.html
Re: The secrets of the 68000
I edited the post with the article about the I/N field. One section was expanded because I was told it was difficult to understand. The attached PDF article was also updated accordingly.
We are talking about the plain 68000. There are plenty emulation inaccuracies for the later 680X0 models, including even the 68010 (which is the closest to the 68000, of course).Eero Tamminen wrote:There are currently also some other differences in exception handling when comparing real HW with emulation, for example when 030 MMU raises exception on auto-increment instruction: ...
Fx Cast: Atari St cycle accurate fpga core
Re: The secrets of the 68000
We are having quite a long email exchange with Toni Wilen (again, Winuae maintainer). I didn't actually test it, but at this point most, if not all, Winuae inaccuracies related to bus and address error exceptions should be fixed. At least regarding the behavior, timing might not be exact. Hatari uses Winuae cpu core, so eventually this will improve Hatari emulation as well.
Fx Cast: Atari St cycle accurate fpga core
Re: The secrets of the 68000
Thank you, to everyone involved!
Re: The secrets of the 68000
great
Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net / AT Speed C16
Hatari / Steem SSE / Aranym / Saint
http://260ste.appspot.com/
SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net / AT Speed C16
Hatari / Steem SSE / Aranym / Saint
http://260ste.appspot.com/
Re: The secrets of the 68000
Hi
I confirm the latest changes from WinUAE are merged in my devel branch for Hatari and that it should support all those bus/address error behaviors for 68000 (including the examples that Ijor reported above).
I will push the changes to main tree soon, I have to do some test first with new 68030 + MMU + basic bus error to check there's no regression with CPU > 68000.
Historical note : as Amiga don't have bus error, WinUAE's cpu core didn't support it directly and it was done as an add-on at Hatari level ; now that WinUAE has optionnal support for bus error emulation, this new code will be used instead in Hatari (as it's much more accurate and avoid maintaining a patched version of cpu core in Hatari). Huge thanks to Toni for his work with WinUAE.
Nicolas
I confirm the latest changes from WinUAE are merged in my devel branch for Hatari and that it should support all those bus/address error behaviors for 68000 (including the examples that Ijor reported above).
I will push the changes to main tree soon, I have to do some test first with new 68030 + MMU + basic bus error to check there's no regression with CPU > 68000.
Historical note : as Amiga don't have bus error, WinUAE's cpu core didn't support it directly and it was done as an add-on at Hatari level ; now that WinUAE has optionnal support for bus error emulation, this new code will be used instead in Hatari (as it's much more accurate and avoid maintaining a patched version of cpu core in Hatari). Huge thanks to Toni for his work with WinUAE.
Nicolas
Re: The secrets of the 68000
Amiga does not have a bus error? That's one of the more frequent events on ST. How does that work?
Re: The secrets of the 68000
yep,
due to amiga was born as a gaming console, there were no need to use serious 68000 stuff like user/supervisor mode or full bus mastering.
the OS works on the same level as the user's applications. It means that there is no any protected area and every application have possibility override OS vectors and hardware registers.
due to amiga was born as a gaming console, there were no need to use serious 68000 stuff like user/supervisor mode or full bus mastering.
the OS works on the same level as the user's applications. It means that there is no any protected area and every application have possibility override OS vectors and hardware registers.
Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net / AT Speed C16
Hatari / Steem SSE / Aranym / Saint
http://260ste.appspot.com/
SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net / AT Speed C16
Hatari / Steem SSE / Aranym / Saint
http://260ste.appspot.com/
Re: The secrets of the 68000
Hi, this is quite a shortcut of what the Amiga is 
Yes, there's no supervisor only memory area, but instead of detecting HW by writing at different addresses and see if you get some bus error (as the TOS does when trying to detect STE/Falcon/TT for example), the Amiga and all its extension boards are using an 'autoconfig method' where each board is able to declare itself to the OS, which is quite flexible as the OS doesn't have to know all the possible board.
But as I fear the thread might soon divert to an Amiga vs ST discussion
and not to secret of 68000, Amiga was just like that. Whether it's a good thing or not to access HW without supervisor mode is another debate, at least it didn't stop Amiga from working 

Yes, there's no supervisor only memory area, but instead of detecting HW by writing at different addresses and see if you get some bus error (as the TOS does when trying to detect STE/Falcon/TT for example), the Amiga and all its extension boards are using an 'autoconfig method' where each board is able to declare itself to the OS, which is quite flexible as the OS doesn't have to know all the possible board.
But as I fear the thread might soon divert to an Amiga vs ST discussion


Re: The secrets of the 68000
Hi
just to let you know that all the work done by Toni with WinUAE's cpu core (also with some input from Ijor) has been merged in public Hatari devel source tree.
So now you can test all those "undocumented" flags/behaviours as the 68000 cpu core in Hatari should be 100% accurate.
Windows/Linux pre-built binaries are here http://antarctica.no/~hatari/latest/
Nicolas
just to let you know that all the work done by Toni with WinUAE's cpu core (also with some input from Ijor) has been merged in public Hatari devel source tree.
So now you can test all those "undocumented" flags/behaviours as the 68000 cpu core in Hatari should be 100% accurate.
Windows/Linux pre-built binaries are here http://antarctica.no/~hatari/latest/
Nicolas