diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 18 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_logic.c | 107 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 6 |
3 files changed, 127 insertions, 4 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 99ebcb3c..b3d75989 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -208,7 +208,15 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6); WBACK; break; - case 5: + case 4: // AND + if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");} + SETFLAGS(X_ALL, SF_SET_PENDING); + GETED((opcode==0x81)?4:1); + if(opcode==0x81) i64 = F32S; else i64 = F8S; + emit_and32c(dyn, ninst, rex, ed, i64, x3, x4); + WBACK; + break; + case 5: // SUB if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");} SETFLAGS(X_ALL, SF_SET_PENDING); GETED((opcode==0x81)?4:1); @@ -216,6 +224,14 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6); WBACK; break; + case 6: // XOR + if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");} + SETFLAGS(X_ALL, SF_SET_PENDING); + GETED((opcode==0x81)?4:1); + if(opcode==0x81) i64 = F32S; else i64 = F8S; + emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4); + WBACK; + break; case 7: // CMP if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");} SETFLAGS(X_ALL, SF_SET_PENDING); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_logic.c b/src/dynarec/rv64/dynarec_rv64_emit_logic.c index 0f7527d9..5f85749f 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c @@ -56,3 +56,110 @@ void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s emit_pf(dyn, ninst, s1, s3, s4); } } + +// emit XOR32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch +void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4) +{ + CLEAR_FLAGS(); + IFX(X_PEND) { + SET_DF(s4, rex.w?d_xor64:d_xor32); + } else IFX(X_ALL) { + SET_DFNONE(s4); + } + + if(c>=-2048 && c<=2047) { + XORI(s1, s1, c); + if(!rex.w && (c&0xffffffff00000000)) { + ZEROUP(s1); + } + } else { + MOV64xw(s3, c); + XOR(s1, s1, s3); + } + + // test sign bit before zeroup. + IFX(X_SF) { + BGE(s1, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + if (!rex.w) { + ZEROUP(s1); + } + + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + +// emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch +void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) +{ + CLEAR_FLAGS(); + IFX_PENDOR0 { + SET_DF(s3, rex.w?d_tst64:d_tst32); + } else { + SET_DFNONE(s4); + } + + AND(s1, s1, s2); // res = s1 & s2 + + IFX_PENDOR0 { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_SF) { + if (!rex.w) ZEROUP(s1); + SRLI(s3, s1, rex.w?63:31); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + +// emit AND32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch +void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4) +{ + CLEAR_FLAGS(); + IFX_PENDOR0 { + SET_DF(s3, rex.w?d_tst64:d_tst32); + } else { + SET_DFNONE(s4); + } + + if(c>=-2048 && c<=2047) { + ANDI(s1, s1, c); + } else { + MOV64xw(s3, c); + AND(s1, s1, s3); // res = s1 & s2 + } + + IFX_PENDOR0 { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_SF) { + if (!rex.w) ZEROUP(s1); + SRLI(s3, s1, rex.w?63:31); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 803fbcf2..ece99d3f 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -543,9 +543,9 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i //void emit_or32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); //void emit_or32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); -//void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); -//void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); -//void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); +void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); +void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); +void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); //void emit_or8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_or8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); //void emit_xor8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); |