upd7725 overflow (attn: byuu)

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: upd7725 overflow (attn: byuu)

Post by Near »

So, the real way to rule all of this out for good ...

Lord Nightmare has a pile of uPD7720 chips unflashed. If we:

1) write a uPD7720 assembler,
2) write a test program in uPD7720 syntax to evaluate all input/output combinations of flags,
3) write an emulator for the 7720 (MAME's could work but it's an insane hack) to debug the test program,

Then Lord Nightmare could try to flash the program onto one of his chips. I'm not sure if he's capable of then putting it into a circuit design and sending / receiving values from the chip, but it's possible we can find someone else capable of doing so that would be up for the task.

Barring this, we're never really going to know for sure, with 100% confidence, how all of this works.

There's still the open question of how exactly S1 is modified on other ALU operations. Manual just says indeterminate, but there are several valid possibilities.

If someone is willing to do the other parts ... I'll volunteer to do part 1 and write a uPD7720 assembler. But you might not like the syntax I come up with ... and I'll be quite saddened if I do the work for nothing >_<

...

Also, here are the relevant sections from the manuals I have:

Image

Image
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: upd7725 overflow (attn: byuu)

Post by AWJ »

nocash wrote:PS. I think my implemention might have opposite S1 values (ie. 0=positive vs 1=positive), this works as long as SGN opcode is processing S1 accordingly.
The manual is clear that the chip can distinguish between two overflows in the same direction (OV1 flag remains set) and two overflows in opposite directions (OV1 flag becomes clear). It has to be able to do so in order to produce the correct overflow state after three operations, as advertised. Your implementation doesn't do that.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: upd7725 overflow (attn: byuu)

Post by nocash »

Ah, yes, got it you are right. Two overflows in same direction won't work with my code.

Hmmm, web.archive is somehow overloading my PC (no chance to download the pdf files), but it does seem to have more/different files than datasheetarchive. Thanks for posting the relevant pages!
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: upd7725 overflow (attn: byuu)

Post by AWJ »

Just noticed the question about multiply overflow in byuu's forum thread. 0x8000 * 0x8000 -> int31 is considered an "overflow" because the sign of the result is wrong. Multiplying two negative numbers should produce a positive result, but int31(0x40000000) is negative.
Lord Nightmare
Posts: 131
Joined: Wed Apr 05, 2006 10:12 am
Location: PA, USA
Contact:

Re: upd7725 overflow (attn: byuu)

Post by Lord Nightmare »

I'm trying to figure out in what circumstances the " if (!flag.ov1) flag.s1 = flag.s0;" should run.
In byuu's code in higan, it runs on OP opcodes, before ov1 is recalculated(which I believe is correct), it is updated on any add/sub/adc/sbb/inc/dec opcode(which I believe is correct), it is left alone on a nop(which I believe is correct), and not on an or/and/xor/cmp/shr1/shl1/shl2/shl4/xchg(which I'm not sure about). It also isn't updated on an RT/JMP opcode, nor on an LD opcode. (also not sure about these, guessing that it shouldn't be touched on RT/JMP, unsure about LD)

In MAME, I made it run for all OP alu types except for NOP(where it is left alone), and ov1 is only updated during add/sub/adc/sbb/inc/dec opcodes (ov1 is updated after ov0 is), and is explicitly cleared(along with ov0) on or/and/xor/cmp/shr1/shl1/shl2/shl4/xchg opcodes.

I'm not 100% sure which way is correct, given that branches can happen based on s1 and ov1 status.

LN
"When life gives you zombies... *CHA-CHIK!* ...you make zombie-ade!"
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: upd7725 overflow (attn: byuu)

Post by Near »

You're guessing no matter what you do with the other ALU ops.

I'm willing to match your behavior, but I worry that people might see it in the future and think that's definitely how it works, when in truth we have no idea. Needs a clear source code comment that we're guessing, even if it is the most logical conclusion to us.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: upd7725 overflow (attn: byuu)

Post by AWJ »

Well, I wrote a program that should allow you to test any sequence of ALU operations you want, if someone wants to figure out how to assemble, burn and test it (don't forget the screwy bit order the '7720 needs for its program ROM) The command protocol is heavily based on the DSP-1, including the need to input a dummy operand for no-operand commands. It doesn't use serial I/O, DMA, or anything else fancy. It also doesn't use the data ROM at all.

Protocol:

Wait for RQM to go high, write 8 bit opcode/carry selector:

Code: Select all

000CPPPP

000 = must be zero
C = incoming carry B flag
PPPP = opcode (same order as native instruction encoding--0001 is OR, etc.)
Wait for RQM to go high, write 16-bit right-side operand (LSB first). You have to do this even for unary opcodes like the shifts (the operand value is ignored).

Wait for RQM to go high, read 16-bit result (value in accumulator A after executing opcode).

Wait for RQM to go high, read 8-bit flags as follows:

Code: Select all

11SsczVv

11 = always 1
S = SA1
s = SA0
c = CA
z = ZA
V = OVA1
v = OVA0
Accumulator A and its flags (should be) preserved between operations, i.e. you should be able to do a sequence of additions/subtractions and look at the flags after each step.

Code: Select all

       : ld     0400,sr ; 8-bit
       : ld     00c0,dr
; === main loop ===
loop   : ld     00e0,b
       : jrqm   *       ; wait for (8-bit) read or write (read flags or write opcode)
       : mov    dr,tr | and dr,b   ; get opcode and carry-in
       : jnzb   loop

; === decode opcode ===
       : ld     0000,sr ; 16-bit
       : or     tr,b
       : jrqm   *       ; wait for (16-bit) write (operand)
       : mov    drnf,tr | shr1 b ; get operand
       : jcb    opxxx1
opxxx0 : shr1   b
       : jcb    opxx10
opxx00 : shr1   b
       : jcb    opx100
opx000 : shr1   b
       : jncb   afterop ; 0000 = nop
       : jcb    op1000
opx100 : shr1   b
       : jncb   op0100
       : jcb    op1100
opxx10 : shr1   b
       : jcb    opx110
opx010 : shr1   b
       : jncb   op0010
       : jcb    op1010
opx110 : shr1   b
       : jncb   op0110
       : jcb    op1110
opxxx1 : shr1   b
       : jcb    opxx11
opxx01 : shr1   b
       : jcb    opx101
opx001 : shr1   b
       : jncb   op0001
       : jcb    op1001
opx101 : shr1   b
       : jncb   op0101
       : jcb    op1101
opxx11 : shr1   b
       : jcb    opx111
opx011 : shr1   b
       : jncb   op0011
       : jcb    op1011
opx111 : shr1   b
       : jncb   op0111
       : jcb    op1111

; === execute opcode ===
op0001 : shr1   b
       : or     tr,a
       : jmp    afterop
op0010 : shr1   b
       : and    tr,a
       : jmp    afterop
op0011 : shr1   b
       : xor    tr,a
       : jmp    afterop
op0100 : shr1   b
       : sub    tr,a
       : jmp    afterop
op0101 : shr1   b
       : add    tr,a
       : jmp    afterop
op0110 : shr1   b
       : sbb    tr,a
       : jmp    afterop
op0111 : shr1   b
       : adc    tr,a
       : jmp    afterop
op1000 : shr1   b
       : dec    a
       : jmp    afterop
op1001 : shr1   b
       : inc    a
       : jmp    afterop
op1010 : shr1   b
       : cmp    a
       : jmp    afterop
op1011 : shr1   b
       : shr1   a
       : jmp    afterop
op1100 : shr1   b
       : shl1   a
       : jmp    afterop
op1101 : shr1   b
       : shl2   a
       : jmp    afterop
op1110 : shr1   b
       : shl4   a
       : jmp    afterop
op1111 : shr1   b
       : xchg   a

; === output result and flags ===
afterop: mov    a,dr    ; send result
       : ld     00c0,b
       : jnsa1  nosa1
       : ld     0020,tr
       : or     tr,b
nosa1  : jnsa0  nosa0
       : ld     0010,tr
       : or     tr,b
nosa0  : jnca   noca
       : ld     0008,tr
       : or     tr,b
noca   : jnza   noza
       : ld     0004,tr
       : or     tr,b
noza   : jnova1 noova1
       : ld     0002,tr
       : or     tr,b
noova1 : jnova0 noova0
       : ld     0001,tr
       : or     tr,b
noova0 : jrqm   *       ; wait for (16-bit) read (result)
       : ld     0400,sr ; 8-bit
       : mov    b,dr    ; send flags
       : jmp    loop    ; back to the top
Someone should eyeball my code before using up rare chips, especially the rats' nest of branches that is the command decoding (also based on the DSP1 code--and there really isn't any better way to do it as far as I can tell)
I'm trying to figure out in what circumstances the " if (!flag.ov1) flag.s1 = flag.s0;" should run.
The docs say that S1 is "indeterminate" after any ALU operation other than addition/subtraction or NOP. LD and JMP instructions definitely shouldn't affect any flags at all (there's no accumulator/flag select field in those instructions, and somewhere one of the docs explicitly clarifies that loading a value into one of the accumulators via MOV or LD doesn't update its sign or zero flags)
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: upd7725 overflow (attn: byuu)

Post by Near »

Any test program should be debugged thoroughly with an emulator before being burned.

These chips are exceedingly rare.
Lord Nightmare
Posts: 131
Joined: Wed Apr 05, 2006 10:12 am
Location: PA, USA
Contact:

Re: upd7725 overflow (attn: byuu)

Post by Lord Nightmare »

The 10 blank upd77P20s I have have windows; if I run out, I can always uv-erase them and try again, I think they're good for 100+ prog/erase cycles at least.
What I don't have (and I wish I did) are blank upd77P25D chips with windows; those are significantly rarer.

EDIT: There is actually someone selling pulled upd77P25D chips, from china, on ebay. Whether these are 'real' or remarked something else, I don't know. They're about $5 each + $6shipping even for more than one, and there's 50+ available. I ordered two of them, since for $16 its worth a shot at them being real.

LN
"When life gives you zombies... *CHA-CHIK!* ...you make zombie-ade!"
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: upd7725 overflow (attn: byuu)

Post by AWJ »

The 7720 and 7725 appear to be pin-compatible, except that the EPROM versions of both require power on pin 1. I wonder if you could put a programmed 7720 onto a suitable SNES cartridge for software testing, rather than have to use an Arduino or something.
Post Reply