summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2012-03-11 16:09:16 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2012-03-11 16:09:16 +0000
commitb1847da7dcdbbee396967e0d68c8dcbc84be6958 (patch)
tree5423028ddeb132a8c373207b083d60cbd3df4f3d
parentd0dc1c8b58ca5eb95dabe9026f263b3107ed5610 (diff)
PowerPC: Corrected DIVW divide-by-zero crashes, flags, and corner-case results [R. Belmont]
-rw-r--r--src/emu/cpu/powerpc/ppcdrc.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/src/emu/cpu/powerpc/ppcdrc.c b/src/emu/cpu/powerpc/ppcdrc.c
index 2e70ba94196..3620f4f45d6 100644
--- a/src/emu/cpu/powerpc/ppcdrc.c
+++ b/src/emu/cpu/powerpc/ppcdrc.c
@@ -3072,10 +3072,44 @@ static int generate_instruction_1f(powerpc_state *ppc, drcuml_block *block, comp
return TRUE;
case 0x1eb: /* DIVWx */
- case 0x3eb: /* DIVWOx */
+ case 0x3eb: /* DIVWOx */
+ UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0
+ UML_JMPc(block, COND_NE, compiler->labelnum); // bne 0:
+ UML_CMP(block, R32(G_RA(op)), 0x80000000); // cmp rb, #80000000
+ UML_JMPc(block, COND_AE, compiler->labelnum); // bae 0:
+
+ UML_MOV(block, R32(G_RD(op)), 0x0); // move rd, #0
+ if (op & M_OE)
+ {
+ UML_OR(block, XERSO32, XERSO32, 0x1); // SO = 1
+ }
+ UML_JMP(block, compiler->labelnum+3); // jmp 3:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+
+ UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0
+ UML_JMPc(block, COND_Z, compiler->labelnum); // beq 1:
+
+ UML_CMP(block, R32(G_RB(op)), 0xffffffff); // cmp rb, #ffffffff
+ UML_JMPc(block, COND_NE, compiler->labelnum+1); // bne 2:
+ UML_CMP(block, R32(G_RA(op)), 0x80000000); // cmp ra, #80000000
+ UML_JMPc(block, COND_NE, compiler->labelnum+1); // bne 2:
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ // do second branch
+ UML_MOV(block, R32(G_RD(op)), 0xffffffff); // move rd, #ffffffff
+ if (op & M_OE)
+ {
+ UML_OR(block, XERSO32, XERSO32, 0x1); // SO = 1
+ }
+ UML_JMP(block, compiler->labelnum+1); // jmp 3:
+
+ UML_LABEL(block, compiler->labelnum++); // 2:
UML_DIVS(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // divs rd,rd,ra,rb
- generate_compute_flags(ppc, block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
- return TRUE;
+ generate_compute_flags(ppc, block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
+
+ UML_LABEL(block, compiler->labelnum++); // 3:
+ return TRUE;
case 0x01c: /* ANDx */
UML_AND(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // and ra,rs,rb