First of all, I think it might be a bit easier to work from a reference doc
, at least initially, rather than an emulator written in x86 assembly language... a lot of the optimizations possible for an x86-hosted emulator will probably not translate well to SH2, because they're based on the fact that x86 is derived from the same architecture as Z80 (not directly of course, but they're both extensions to the 8080, so their instruction sets are much closer than either one is to SuperH). With my complaining now out of the way:
btw about sign. Can we use it to detect sign:
MOV.B @(R0,Rm),Rn 0000nnnnmmmm1100 (R0 + Rm) --> Sign extension --> Rn
i.e. we can move value to r0 then use this instruction and then check Rn??
I'm not sure what you're trying to accomplish exactly.
That instruction will read a byte from memory into a register and handle the sign extension (this just means padding it with zeroes if it's positive and padding it with ones if it's negative). It's for loading bytes without mangling the positive/negative aspect of it in the transition to a 32-bit number.
I'm not as familiar with SH or Z80 as I'd like to be... this information might not be completely correct, and probably isn't the fastest way to implement these checks...
If you want to know how to set the negative flag of the Z80 F register, as far as I know you can just copy bit 7 of the result to the emulated Z80 F register (according to the doc I linked above, this is how it works in a real Z80).
As for the other flags, here are my thoughts:
Note that when I refer to "copying" a bit, it is probably most easily achieved by using an instruction sequence similar to the following:
and #(bit mask), r0
xor #(bit mask), r0 (if an inversion is needed)
(necessary SHLLx/SHRLx instructions to shift the bit to the appropriate place)
or r0, (register where emulated Z80 F is stored)
Zero : Use CMP/PL on the result, then copy and invert the T flag (of the SH status register). This is also used by the comparison/search instructions as a true/false flag, which will need a different implementation.
bit 5: A copy of bit 5 of the result. This is officially unused, but a couple ZX Spectrum games are known to depend on it working correctly. It's probably not important for now.
Half-carry: As this relates to 4-bit math, I'm not sure how to implement it quickly (but then, I'm not fully awake yet either...).
bit 3: A copy of bit 3 of the result. Basically the same as bit 5.
Parity/Overflow Flag: This is a mess. It's used for indicating an overflow for add/subtract, but also for indicating parity for logical operations. It's probably best to use lookup tables of some sort for this one.
N: Set to 0 by addition instructions, and set to 1 by subtraction instructions. Apparently that's all there is to it.
Carry: For adds, I think it should be sufficient to copy bit 8 of the result. For subtracts, it would be necessary to invert the bit.
I also did some calculations regarding performance. For a 3.58MHz Z80, you get almost 8 SH cycles per Z80 cycle. Z80 instructions take varying amounts of time to execute, but the minimum is 4 cycles. So, you get somewhere around 30 SH cycles for these instructions. The ones that access memory give you more cycles (these are listed in the Z80 manual; in Z80 terms, clock cycles are called "T states" ). You have to take a 16 (I think; it will be more if the Saturn RAM has wait states) cycle loss on each Z80 instruction due to the pipeline flushes from jumping in and out of the instruction code. I think this means that some instructions will need more than their fair share of cycles. Hopefully the difference will be made up by unused cycles in the longer Z80 instructions...
Hope this helps
Edit: the code tag apparently doesn't treat angle brackets correctly...
(Edited by ExCyber at 2:23 pm on Dec. 24, 2001)