diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-03-24 15:18:55 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-24 08:18:55 +0100 |
| commit | c3223245e561f1f78c4e2b053c43a14929df615e (patch) | |
| tree | 2755051a3ce627de544a059d062e89371c922610 /src | |
| parent | fdf43e58747f06f69096d4ca40cb633fd0393470 (diff) | |
| download | box64-c3223245e561f1f78c4e2b053c43a14929df615e.tar.gz box64-c3223245e561f1f78c4e2b053c43a14929df615e.zip | |
[RV64_DYNAREC] Added more opcodes (#631)
* [RV64_DYNAREC] Added 80 /6 XOR opcode * [RV64_DYNAREC] Added 02 ADD opcode * [RV64_DYNAREC] Added 66 23 AND opcode * [RV64_DYNAREC] Added 66 0B OR opcode * [RV64_DYNAREC] Added 32 XOR opcode * [RV64_DYNAREC] Added 08 OR opcode * [RV64_DYNAREC] Added 20 AND opcode * [ARM64_DYNAREC] Fixed a issue with 66 0F BE MOVSX opcode
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_660f.c | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 38 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 18 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_logic.c | 54 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 57 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 6 |
6 files changed, 168 insertions, 7 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index 73669980..ff7abff7 100755 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -1792,7 +1792,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx eb2 = (ed&4)>>2; // L or H } - SBFXw(x1, eb1, eb2, 8); + SBFXw(x1, eb1, eb2*8, 8); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 0); diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index ff009df7..e1455292 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -62,7 +62,15 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; - + case 0x02: + INST_NAME("ADD Gb, Eb"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETEB(x2, 0); + GETGB(x1); + emit_add8(dyn, ninst, x1, x2, x3, x4); + GBBACK(x5); + break; case 0x03: INST_NAME("ADD Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -71,14 +79,12 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETED(0); emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5); break; - case 0x05: INST_NAME("ADD EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING); i64 = F32S; emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); break; - case 0x08: INST_NAME("OR Eb, Gb"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -147,6 +153,15 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; + case 0x20: + INST_NAME("AND Eb, Gb"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETEB(x1, 0); + GETGB(x3); + emit_and8(dyn, ninst, x1, x3, x4, x5); + EBBACK(x3); + break; case 0x21: INST_NAME("AND Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -223,6 +238,15 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni WBACK; } break; + case 0x32: + INST_NAME("XOR Gb, Eb"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETEB(x1, 0); + GETGB(x3); + emit_xor8(dyn, ninst, x1, x3, x4, x5); + GBBACK(x5); + break; case 0x33: INST_NAME("XOR Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -497,6 +521,14 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_sub8c(dyn, ninst, x1, u8, x3, x4, x5, x6); EBBACK(x3); break; + case 6: // XOR + INST_NAME("XOR Eb, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEB(x1, 1); + u8 = F8; + emit_xor8c(dyn, ninst, x1, u8, x3, x4); + EBBACK(x3); + break; case 7: // CMP INST_NAME("CMP Eb, Ib"); SETFLAGS(X_ALL, SF_SET_PENDING); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 13e4a32c..e296b662 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -61,6 +61,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode switch(opcode) { + case 0x0B: + INST_NAME("OR Gw, Ew"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_or16(dyn, ninst, x1, x2, x4, x5); + GWBACK; + break; case 0x0D: INST_NAME("OR AX, Iw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -85,6 +94,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_and16(dyn, ninst, x1, x2, x4, x5); EWBACK; break; + case 0x23: + INST_NAME("AND Gw, Ew"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_and16(dyn, ninst, x1, x2, x4, x5); + GWBACK; + break; case 0x25: INST_NAME("AND AX, Iw"); 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 981c5141..8ccb1785 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c @@ -23,6 +23,60 @@ #include "dynarec_rv64_functions.h" #include "dynarec_rv64_helper.h" +// emit XOR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed) +void emit_xor8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) +{ + CLEAR_FLAGS(); + IFX(X_PEND) { + SET_DF(s4, d_xor8); + } else IFX(X_ALL) { + SET_DFNONE(); + } + XOR(s1, s1, s2); + IFX(X_SF) { + SRLI(s3, s1, 7); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + +// emit XOR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch +void emit_xor8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4) +{ + CLEAR_FLAGS(); + IFX(X_PEND) { + SET_DF(s4, d_xor8); + } else IFX(X_ALL) { + SET_DFNONE(); + } + XORI(s1, s1, c&0xff); + IFX(X_SF) { + SRLI(s3, s1, 7); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit XOR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index d1cfaddb..dc9b81fd 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -254,6 +254,63 @@ void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } +// emit ADD8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch +void emit_add8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) +{ + CLEAR_FLAGS(); + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, op1)); + SB(s2, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s3, d_add8); + } else IFX(X_ALL) { + SET_DFNONE(); + } + IFX(X_AF | X_OF) { + OR(s3, s1, s2); // s3 = op1 | op2 + AND(s4, s1, s2); // s4 = op1 & op2 + } + ADD(s1, s1, s2); + + IFX(X_AF|X_OF) { + NOT(s4, s1); // s4 = ~res + AND(s3, s4, s3); // s3 = ~res & (op1 | op2) + OR(s3, s3, s2); // cc = (~res & (op1 | op2)) | (op1 & op2) + IFX(X_AF) { + ANDI(s4, s3, 0x08); // AF: cc & 0x08 + BEQZ(s4, 8); + ORI(xFlags, xFlags, 1 << F_AF); + } + IFX(X_OF) { + SRLI(s3, s3, 6); + SRLI(s4, s3, 1); + XOR(s3, s3, s4); + ANDI(s3, s3, 1); // OF: xor of two MSB's of cc + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_OF2); + } + } + IFX(X_CF) { + SRLI(s3, s1, 8); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_CF); + } + IFX(X_PEND) { + SH(s1, xEmu, offsetof(x64emu_t, res)); + } + ANDI(s1, s1, 0xff); + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_SF) { + SRLI(s3, s1, 7); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} // emit ADD8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s2, int s3, int s4) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 23d4078b..bcdbc840 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -768,7 +768,7 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5); -//void emit_add8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_add8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4); void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5); @@ -782,8 +782,8 @@ void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s 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 s2, int s3, int s4); -//void emit_xor8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); -//void emit_xor8c(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); +void emit_xor8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_and8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_and8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); |