diff options
| author | Yang Liu <numbksco@gmail.com> | 2024-03-03 03:10:04 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-02 20:10:04 +0100 |
| commit | de4ffcc8bc104e3a9c42f82b01d074bfb80b46b0 (patch) | |
| tree | d05995a9cc5602d72e1e0dee09a6f78a3b3ff67b /src | |
| parent | ebaedca7084932d1d101614dd20dd534804f867e (diff) | |
| download | box64-de4ffcc8bc104e3a9c42f82b01d074bfb80b46b0.tar.gz box64-de4ffcc8bc104e3a9c42f82b01d074bfb80b46b0.zip | |
[LA64_DYNAREC] Added more and more opcodes (#1314)
* [LA64_DYNAREC] Added C1 /5 SHR opcode * [LA64_DYNAREC] Added C1 /7 SAR opcode * [LA64_DYNAREC] Added D1 /7 SAR opcode * [LA64_DYNAREC] Added D1 /5 SHR opcode * [LA64_DYNAREC] Added FF /4 JMP opcode * [LA64_DYNAREC] Added 66 0F 1F NOP opcode * [LA64_DYNAREC] Added B8..BF MOV opcodes * [LA64_DYNAREC] Added C7 MOV opcode * [LA64_DYNAREC] Added 0F 05 SYSCALL opcode
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 101 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 82 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 72 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_660f.c | 62 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_emit_shift.c | 175 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 47 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_emitter.h | 27 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_printer.c | 20 |
8 files changed, 571 insertions, 15 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index 9616a1e1..351ec85c 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -105,6 +105,9 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0x0F: switch (rep) { + case 0: + addr = dynarec64_0F(dyn, addr, ip, ninst, rex, ok, need_epilog); + break; case 2: addr = dynarec64_F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; @@ -186,6 +189,10 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni gd = TO_LA64((opcode & 0x07) + (rex.b << 3)); POP1z(gd); break; + break; + case 0x66: + addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + break; case 0x81: case 0x83: nextop = F8; @@ -312,6 +319,47 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } } break; + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + INST_NAME("MOV Reg, Id"); + gd = TO_LA64((opcode & 7) + (rex.b << 3)); + if (rex.w) { + u64 = F64; + MOV64x(gd, u64); + } else { + u32 = F32; + MOV32w(gd, u32); + } + break; + case 0xC1: + nextop = F8; + switch ((nextop >> 3) & 7) { + case 5: + INST_NAME("SHR Ed, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + u8 = (F8) & (rex.w ? 0x3f : 0x1f); + emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { WBACK; } + break; + case 7: + INST_NAME("SAR Ed, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + u8 = (F8) & (rex.w ? 0x3f : 0x1f); + emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { WBACK; } + break; + default: + DEFAULT; + } + break; case 0xC3: INST_NAME("RET"); // SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...) @@ -323,6 +371,25 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni *need_epilog = 0; *ok = 0; break; + case 0xC7: + INST_NAME("MOV Ed, Id"); + nextop = F8; + if (MODREG) { // reg <= i32 + i64 = F32S; + ed = TO_LA64((nextop & 7) + (rex.b << 3)); + MOV64xw(ed, i64); + } else { // mem <= i32 + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, &lock, 0, 4); + i64 = F32S; + if (i64) { + MOV64xw(x3, i64); + ed = x3; + } else + ed = xZR; + SDxw(ed, wback, fixedaddress); + SMWRITELOCK(lock); + } + break; case 0xCC: SETFLAGS(X_ALL, SF_SET); SKIPTEST(x1); @@ -345,7 +412,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni // FIXME: Even the basic support of isSimpleWrapper is disabled for now. GETIP(ip + 1); // read the 0xCC - STORE_XEMU_CALL(x3); + STORE_XEMU_CALL(); ADDI_D(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip CALL_S(x64Int3, -1); LOAD_XEMU_CALL(); @@ -367,12 +434,33 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LD_D(x3, x2, 0); CBZ_NEXT(x3); GETIP(ip); - STORE_XEMU_CALL(x3); + STORE_XEMU_CALL(); CALL(native_int3, -1); LOAD_XEMU_CALL(); } } break; + case 0xD1: + nextop = F8; + switch ((nextop >> 3) & 7) { + case 5: + INST_NAME("SHR Ed, 1"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(0); + emit_shr32c(dyn, ninst, rex, ed, 1, x3, x4); + WBACK; + break; + case 7: + INST_NAME("SAR Ed, 1"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(0); + emit_sar32c(dyn, ninst, rex, ed, 1, x3, x4); + WBACK; + break; + default: + DEFAULT; + } + break; case 0xE9: case 0xEB: BARRIER(BARRIER_MAYBE); @@ -446,6 +534,15 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni PUSH1z(xRIP); jump_to_next(dyn, 0, ed, ninst, rex.is32bits); break; + case 4: // JMP Ed + INST_NAME("JMP Ed"); + READFLAGS(X_PEND); + BARRIER(BARRIER_FLOAT); + GETEDz(0); + jump_to_next(dyn, 0, ed, ninst, rex.is32bits); + *need_epilog = 0; + *ok = 0; + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c new file mode 100644 index 00000000..4c1a2aba --- /dev/null +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -0,0 +1,82 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <errno.h> + +#include "debug.h" +#include "box64context.h" +#include "dynarec.h" +#include "emu/x64emu_private.h" +#include "emu/x64run_private.h" +#include "x64run.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "emu/x64run_private.h" +#include "x64trace.h" +#include "dynarec_native.h" +#include "my_cpuid.h" +#include "emu/x87emu_private.h" +#include "emu/x64shaext.h" +#include "bitutils.h" + +#include "la64_printer.h" +#include "dynarec_la64_private.h" +#include "dynarec_la64_functions.h" +#include "dynarec_la64_helper.h" + +uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) +{ + (void)ip; + (void)need_epilog; + + uint8_t opcode = F8; + uint8_t nextop, u8; + uint8_t gd, ed; + uint8_t wb1, wback, wb2, gback; + uint8_t eb1, eb2; + uint8_t gb1, gb2; + int32_t i32, i32_; + int cacheupd = 0; + int v0, v1; + int q0, q1; + int d0, d1; + int s0, s1; + uint64_t tmp64u; + int64_t j64; + int64_t fixedaddress, gdoffset; + int unscaled; + MAYUSE(wb2); + MAYUSE(gback); + MAYUSE(eb1); + MAYUSE(eb2); + MAYUSE(q0); + MAYUSE(q1); + MAYUSE(d0); + MAYUSE(d1); + MAYUSE(s0); + MAYUSE(j64); + MAYUSE(cacheupd); + + switch (opcode) { + case 0x05: + INST_NAME("SYSCALL"); + NOTEST(x1); + SMEND(); + GETIP(addr); + STORE_XEMU_CALL(); + CALL_S(x64Syscall, -1); + LOAD_XEMU_CALL(); + TABLE64(x3, addr); // expected return address + BNE_MARK(xRIP, x3); + LD_W(w1, xEmu, offsetof(x64emu_t, quit)); + CBZ_NEXT(w1); + MARK; + LOAD_XEMU_REM(); + jump_to_epilog(dyn, 0, xRIP, ninst); + break; + default: + DEFAULT; + } + return addr; +} diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c new file mode 100644 index 00000000..7626102c --- /dev/null +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -0,0 +1,72 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <errno.h> + +#include "debug.h" +#include "box64context.h" +#include "dynarec.h" +#include "emu/x64emu_private.h" +#include "emu/x64run_private.h" +#include "x64run.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "emu/x64run_private.h" +#include "x64trace.h" +#include "dynarec_native.h" +#include "custommem.h" + +#include "la64_printer.h" +#include "dynarec_la64_private.h" +#include "dynarec_la64_helper.h" +#include "dynarec_la64_functions.h" + + +uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog) +{ + uint8_t opcode = F8; + uint8_t nextop, u8; + int16_t i16; + uint16_t u16; + uint64_t u64; + int32_t i32; + int64_t j64; + uint8_t gd, ed; + uint8_t wback, wb1; + int64_t fixedaddress; + int unscaled; + int lock; + MAYUSE(u8); + MAYUSE(u16); + MAYUSE(u64); + MAYUSE(j64); + MAYUSE(lock); + + while ((opcode == 0x2E) || (opcode == 0x36) || (opcode == 0x66)) // ignoring CS:, SS: or multiple 0x66 + opcode = F8; + + while ((opcode == 0xF2) || (opcode == 0xF3)) { + rep = opcode - 0xF1; + opcode = F8; + } + + GETREX(); + + if (rex.w && !(opcode == 0x0f || opcode == 0xf0 || opcode == 0x64 || opcode == 0x65)) // rex.w cancels "66", but not for 66 0f type of prefix + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode + + switch (opcode) { + + case 0x0F: + switch (rep) { + case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + default: + DEFAULT; + } + break; + default: + DEFAULT; + } + return addr; +} diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c new file mode 100644 index 00000000..5f7192ca --- /dev/null +++ b/src/dynarec/la64/dynarec_la64_660f.c @@ -0,0 +1,62 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <errno.h> + +#include "debug.h" +#include "box64context.h" +#include "dynarec.h" +#include "emu/x64emu_private.h" +#include "emu/x64run_private.h" +#include "x64run.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "emu/x64run_private.h" +#include "x64trace.h" +#include "dynarec_native.h" +#include "bitutils.h" + +#include "la64_printer.h" +#include "dynarec_la64_private.h" +#include "dynarec_la64_functions.h" +#include "dynarec_la64_helper.h" + +uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) +{ + (void)ip; + (void)need_epilog; + + uint8_t opcode = F8; + uint8_t nextop, u8, s8; + int32_t i32; + uint8_t gd, ed; + uint8_t wback, wb1, wb2, gback; + uint8_t eb1, eb2; + int64_t j64; + uint64_t tmp64u, tmp64u2; + int v0, v1; + int q0, q1; + int d0, d1, d2; + int64_t fixedaddress, gdoffset; + int unscaled; + + MAYUSE(d0); + MAYUSE(d1); + MAYUSE(q0); + MAYUSE(q1); + MAYUSE(eb1); + MAYUSE(eb2); + MAYUSE(j64); + + switch (opcode) { + case 0x1F: + INST_NAME("NOP (multibyte)"); + nextop = F8; + FAKEED; + break; + default: + DEFAULT; + } + return addr; +} diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c new file mode 100644 index 00000000..24d7f102 --- /dev/null +++ b/src/dynarec/la64/dynarec_la64_emit_shift.c @@ -0,0 +1,175 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <errno.h> + +#include "debug.h" +#include "box64context.h" +#include "dynarec.h" +#include "emu/x64emu_private.h" +#include "emu/x64run_private.h" +#include "x64run.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "emu/x64run_private.h" +#include "x64trace.h" +#include "dynarec_native.h" + +#include "la64_printer.h" +#include "dynarec_la64_private.h" +#include "dynarec_la64_functions.h" +#include "dynarec_la64_helper.h" + +// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch +void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) +{ + CLEAR_FLAGS(s3); + + IFX(X_PEND) { + if (c) { + MOV64x(s3, c); + SDxw(s3, xEmu, offsetof(x64emu_t, op2)); + } else + SDxw(xZR, xEmu, offsetof(x64emu_t, op2)); + SDxw(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s4, rex.w ? d_shr64 : d_shr32); + } else IFX(X_ALL) { + SET_DFNONE(); + } + if (!c) { + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + + if (la64_lbt) { + IFX(X_PEND) {} else { MOV64x(s3, c); } + IFX(X_ALL) { + if (rex.w) X64_SRL_D(s1, s3); else X64_SRL_W(s1, s3); + X64_GET_EFLAGS(s3, X_ALL); + OR(xFlags, xFlags, s3); + } + + SRLIxw(s1, s1, c); + + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + + IFX(X_CF) { + if (c > 1) { + SRAI_D(s3, s1, c - 1); + ANDI(s3, s3, 1); // LSB == F_CF + } else { + // no need to shift + ANDI(s3, s1, 1); // LSB == F_CF + } + OR(xFlags, xFlags, s3); + } + IFX(X_OF) { + // OF flag is affected only on 1-bit shifts + // OF flag is set to the most-significant bit of the original operand + if (c == 1) { + SRLIxw(s3, s1, rex.w ? 63 : 31); + SLLI_D(s3, s3, F_OF); + OR(xFlags, xFlags, s3); + } + } + + SRLIxw(s1, s1, c); + + 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, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + + +// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch +void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) +{ + CLEAR_FLAGS(s3); + + IFX(X_PEND) { + if (c) { + MOV64x(s3, c); + SDxw(s3, xEmu, offsetof(x64emu_t, op2)); + } else + SDxw(xZR, xEmu, offsetof(x64emu_t, op2)); + SDxw(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s4, rex.w ? d_sar64 : d_sar32); + } else IFX(X_ALL) { + SET_DFNONE(); + } + if (!c) { + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + + if (la64_lbt) { + IFX(X_PEND) {} else { MOV64x(s3, c); } + IFX(X_ALL) { + if (rex.w) X64_SRA_D(s1, s3); else X64_SRA_W(s1, s3); + X64_GET_EFLAGS(s3, X_ALL); + OR(xFlags, xFlags, s3); + } + + SRAIxw(s1, s1, c); + + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + + IFX(X_CF) { + if (c > 1) { + SRAI_D(s3, s1, c - 1); + ANDI(s3, s3, 1); // LSB == F_CF + } else { + // no need to shift + ANDI(s3, s1, 1); // LSB == F_CF + } + OR(xFlags, xFlags, s3); + } + + SRAIxw(s1, s1, c); + + // SRAIW sign-extends, so test sign bit before clearing upper bits + 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, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} \ No newline at end of file diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index e1088ec9..67d562b2 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -255,20 +255,27 @@ #define LOAD_REG(A) LD_D(x##A, xEmu, offsetof(x64emu_t, regs[_##A])) // Need to also store current value of some register, as they may be used by functions like setjmp -#define STORE_XEMU_CALL(s0) \ - STORE_REG(RBX); \ - STORE_REG(RDX); \ - STORE_REG(RSP); \ - STORE_REG(RBP); \ - STORE_REG(RDI); \ - STORE_REG(RSI); \ - STORE_REG(R8); \ - STORE_REG(R9); \ - STORE_REG(R10); \ - STORE_REG(R11); +#define STORE_XEMU_CALL() \ + STORE_REG(R8); \ + STORE_REG(R9); \ + STORE_REG(R10); \ + STORE_REG(R11); \ + STORE_REG(R12); \ + STORE_REG(R13); \ + STORE_REG(R14); \ + STORE_REG(R15); #define LOAD_XEMU_CALL() +#define LOAD_XEMU_REM() \ + LOAD_REG(R8); \ + LOAD_REG(R9); \ + LOAD_REG(R10); \ + LOAD_REG(R11); \ + LOAD_REG(R12); \ + LOAD_REG(R13); \ + LOAD_REG(R14); \ + LOAD_REG(R15); #define SET_DFNONE() \ if (!dyn->f.dfnone) { \ @@ -440,7 +447,10 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define native_pass STEPNAME(native_pass) #define dynarec64_00 STEPNAME(dynarec64_00) +#define dynarec64_0F STEPNAME(dynarec64_0F) +#define dynarec64_66 STEPNAME(dynarec64_66) #define dynarec64_F30F STEPNAME(dynarec64_F30F) +#define dynarec64_660F STEPNAME(dynarec64_660F) #define geted STEPNAME(geted) #define geted32 STEPNAME(geted32) @@ -458,6 +468,8 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define emit_sub32c STEPNAME(emit_sub32c) #define emit_sub8 STEPNAME(emit_sub8) #define emit_sub8c STEPNAME(emit_sub8c) +#define emit_shr32c STEPNAME(emit_shr32c) +#define emit_sar32c STEPNAME(emit_sar32c) #define emit_pf STEPNAME(emit_pf) @@ -496,6 +508,8 @@ void emit_sub32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5); void emit_sub8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_sub8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4, int s5); +void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); +void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); void emit_pf(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4); @@ -527,7 +541,10 @@ void CacheTransform(dynarec_la64_t* dyn, int ninst, int cacheupd, int s1, int s2 #endif uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); +uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); +uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); #if STEP < 3 #define PASS3(A) @@ -638,4 +655,12 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ST_W(s2, xEmu, offsetof(x64emu_t, test.test)); \ } +#define GETREX() \ + rex.rex = 0; \ + if (!rex.is32bits) \ + while (opcode >= 0x40 && opcode <= 0x4f) { \ + rex.rex = opcode; \ + opcode = F8; \ + } + #endif //__DYNAREC_LA64_HELPER_H__ \ No newline at end of file diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index f8d8a20e..e3235633 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -112,8 +112,6 @@ f24-f31 fs0-fs7 Static registers Callee #define type_3R(opc, rk, rj, rd) ((opc) << 15 | (rk) << 10 | (rj) << 5 | (rd)) #define type_3RI2(opc, imm2, rk, rj, rd) ((opc) << 17 | ((imm2) & 0x3) << 15 | (rk) << 10 | (rj) << 5 | (rd)) #define type_2R(opc, rj, rd) ((opc) << 10 | (rj) << 5 | (rd)) -#define type_2RI5(opc, imm5, rj, rd) ((opc) << 15 | ((imm5) & 0x1F) << 10 | (rj) << 5 | (rd)) -#define type_2RI6(opc, imm6, rj, rd) ((opc) << 16 | ((imm6) & 0x3F) << 10 | (rj) << 5 | (rd)) #define type_2RI8(opc, imm8, rj, rd) ((opc) << 18 | ((imm8) & 0xFF) << 10 | (rj) << 5 | (rd)) #define type_2RI12(opc, imm12, rj, rd) ((opc) << 22 | ((imm12) & 0xFFF) << 10 | (rj) << 5 | (rd)) #define type_2RI14(opc, imm14, rj, rd) ((opc) << 24 | ((imm14) & 0x3FFF) << 10 | (rj) << 5 | (rd)) @@ -223,6 +221,31 @@ f24-f31 fs0-fs7 Static registers Callee // GR[rd] = ROTR(GR[rj][63:0], imm6) (Rotate To Right) #define ROTRI_D(rd, rj, imm6) EMIT(type_2RI6(0b0000000001001101, imm6, rj, rd)) +// GR[rd] = SLL(GR[rj][31:0], imm5) (Shift Left Logical) +#define SLLI_W(rd, rj, imm5) EMIT(type_2RI5(0b00000000010000001, imm5, rj, rd)) +// GR[rd] = SRL(GR[rj][31:0], imm5) (Shift Right Logical) +#define SRLI_W(rd, rj, imm5) EMIT(type_2RI5(0b00000000010001001, imm5, rj, rd)) +// GR[rd] = SRA(GR[rj][31:0], imm5) (Shift Right Arithmetic) +#define SRAI_W(rd, rj, imm5) EMIT(type_2RI5(0b00000000010010001, imm5, rj, rd)) +// GR[rd] = ROTR(GR[rj][31:0], imm5) (Rotate To Right) +#define ROTRI_W(rd, rj, imm5) EMIT(type_2RI5(0b00000000010011001, imm5, rj, rd)) + +// Shift Right Logical Immediate +#define SRLIxw(rd, rs1, imm) \ + if (rex.w) { \ + SRLI_D(rd, rs1, imm); \ + } else { \ + SRLI_W(rd, rs1, imm); \ + } + +// Shift Right Arithmetic Immediate +#define SRAIxw(rd, rs1, imm) \ + if (rex.w) { \ + SRAI_D(rd, rs1, imm); \ + } else { \ + SRAI_W(rd, rs1, imm); \ + } + // rd = rj + (rk << imm6) #define ADDSL(rd, rs1, rs2, imm6, scratch) \ if (!(imm6)) { \ diff --git a/src/dynarec/la64/la64_printer.c b/src/dynarec/la64/la64_printer.c index 62718191..72ada67d 100644 --- a/src/dynarec/la64/la64_printer.c +++ b/src/dynarec/la64/la64_printer.c @@ -235,6 +235,26 @@ const char* la64_print(uint32_t opcode, uintptr_t addr) snprintf(buff, sizeof(buff), "%-15s %s, %s, %u", "ROTRI.D", Xt[Rd], Xt[Rj], imm); return buff; } + // SLLI.W + if(isMask(opcode, "00000000010000001iiiiijjjjjddddd", &a)) { + snprintf(buff, sizeof(buff), "%-15s %s, %s, %u", "SLLI.W", Xt[Rd], Xt[Rj], imm); + return buff; + } + // SRLI.W + if(isMask(opcode, "00000000010001001iiiiijjjjjddddd", &a)) { + snprintf(buff, sizeof(buff), "%-15s %s, %s, %u", "SRLI.W", Xt[Rd], Xt[Rj], imm); + return buff; + } + // SRAI.W + if(isMask(opcode, "00000000010010001iiiiijjjjjddddd", &a)) { + snprintf(buff, sizeof(buff), "%-15s %s, %s, %u", "SRAI.W", Xt[Rd], Xt[Rj], imm); + return buff; + } + // ROTRI.W + if(isMask(opcode, "00000000010011001iiiiijjjjjddddd", &a)) { + snprintf(buff, sizeof(buff), "%-15s %s, %s, %u", "ROTRI.W", Xt[Rd], Xt[Rj], imm); + return buff; + } // BEQ if(isMask(opcode, "010110iiiiiiiiiiiiiiiijjjjjddddd", &a)) { snprintf(buff, sizeof(buff), "%-15s %s, %s, %d", "BEQ", Xt[Rd], Xt[Rj], imm << 2); |