From 551542f99a2bcd690f19e1bb17ac16172feef583 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Tue, 16 Mar 2021 16:37:37 +0100 Subject: [PATCH] [DYNAREC] Added 85 opcode --- CMakeLists.txt | 2 +- src/dynarec/arm64_emitter.h | 1 + src/dynarec/arm64_printer.c | 25 ++ src/dynarec/dynarec_arm64_00.c | 9 + src/dynarec/dynarec_arm64_emit_tests.c | 408 +++++++++++++++++++++++++ src/dynarec/dynarec_arm64_helper.h | 2 +- 6 files changed, 445 insertions(+), 2 deletions(-) create mode 100755 src/dynarec/dynarec_arm64_emit_tests.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f0c3c00c..7676533b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,7 +245,7 @@ if(ARM_DYNAREC) set(DYNAREC_PASS "${BOX64_ROOT}/src/dynarec/dynarec_arm64_helper.c" - #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_tests.c" + "${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_tests.c" "${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_math.c" #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_logic.c" #"${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_shift.c" diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h index 60c12748..7fabde02 100755 --- a/src/dynarec/arm64_emitter.h +++ b/src/dynarec/arm64_emitter.h @@ -240,6 +240,7 @@ #define ANDxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 0, Rm, 0, Rn, Rd)) #define ANDSx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b11, 0b00, 0, Rm, 0, Rn, Rd)) #define ANDSw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, 0, Rn, Rd)) +#define ANDSxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b11, 0b00, 0, Rm, 0, Rn, Rd)) #define ORRx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, 0, Rn, Rd)) #define ORRx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, lsl, 0, Rm, 0, Rn, Rd)) #define ORRxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, 0, Rn, Rd)) diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c index 56dfd5c3..2a66f553 100755 --- a/src/dynarec/arm64_printer.c +++ b/src/dynarec/arm64_printer.c @@ -258,6 +258,31 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) return buff; } // ---- LOGIC + if(isMask(opcode, "f11100100Nrrrrrrssssssnnnnnddddd", &a)) { + int i = (a.N<<12)|(imms<<6)|immr; + if(sf==0 && a.N==1) + snprintf(buff, sizeof(buff), "invalid ANDS %s, %s, 0x%x", Wt[Rd], Wt[Rn], i); + else if(Rd==31) + snprintf(buff, sizeof(buff), "TST %s, 0x%x", sf?Xt[Rn]:Wt[Rn], i); + else + snprintf(buff, sizeof(buff), "ANDS %s, %s, 0x%x", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], i); + return buff; + } + if(isMask(opcode, "f1101010hh0mmmmmiiiiiinnnnnddddd", &a)) { + const char* shifts[] = { "LSL", "LSR", "ASR", "ROR" }; + if(shift==0 && imm==0) { + if(Rd==31) + snprintf(buff, sizeof(buff), "TST %s, %s", sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]); + else + snprintf(buff, sizeof(buff), "ANDS %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]); + } else { + if(Rd==31) + snprintf(buff, sizeof(buff), "TST %s, %s, %s %d", sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[shift], imm); + else + snprintf(buff, sizeof(buff), "ANDS %s, %s, %s, %s %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[shift], imm); + } + return buff; + } // ---- SHIFT if(isMask(opcode, "f10100110Nrrrrrrssssssnnnnnddddd", &a)) { diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c index 3f5e8b85..4c786ebd 100755 --- a/src/dynarec/dynarec_arm64_00.c +++ b/src/dynarec/dynarec_arm64_00.c @@ -136,6 +136,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; + case 0x85: + INST_NAME("TEST Ed, Gd"); + SETFLAGS(X_ALL, SF_SET); + nextop=F8; + GETGD; + GETED(0); + emit_test32(dyn, ninst, rex, ed, gd, x3, x5, x6); + break; + case 0x89: INST_NAME("MOV Ed, Gd"); nextop=F8; diff --git a/src/dynarec/dynarec_arm64_emit_tests.c b/src/dynarec/dynarec_arm64_emit_tests.c new file mode 100755 index 00000000..cfd7f6b4 --- /dev/null +++ b/src/dynarec/dynarec_arm64_emit_tests.c @@ -0,0 +1,408 @@ +#include +#include +#include +#include +#include + +#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_arm64.h" +#include "dynarec_arm64_private.h" +#include "arm64_printer.h" +#include "../tools/bridge_private.h" + +#include "dynarec_arm64_functions.h" +#include "dynarec_arm64_helper.h" + +// emit CMP32 instruction, from cmp s1 , s2, using s3 and s4 as scratch +//void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) +//{ +// IFX(X_PEND) { +// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1)); +// STR_IMM9(s2, xEmu, offsetof(x64emu_t, op2)); +// SET_DF(s4, d_cmp32); +// } else { +// SET_DFNONE(s4); +// } +// SUBS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 - s2 +// IFX(X_PEND) { +// STR_IMM9(s3, xEmu, offsetof(x64emu_t, res)); +// } +// IFX(X_ZF|X_CF) { +// BIC_IMM8(xFlags, xFlags, (1<x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0) +// IFX(X_CF|X_AF) { +// SUB_REG_LSL_IMM5(s3, s1, s2, 0); +// } +// AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied +// MOV32(s4, GetParityTab()); +// LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer +// SUB_REG_LSL_IMM5(s3, s1, s2, 0); +// AND_IMM8(s3, s3, 31); +// MVN_REG_LSR_REG(s4, s4, s3); +// BFI(xFlags, s4, F_PF, 1); +// } +//} + +// emit CMP32 instruction, from cmp s1 , 0, using s3 and s4 as scratch +//void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) +//{ +// IFX(X_PEND) { +// MOVW(s4, 0); +// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1)); +// STR_IMM9(s4, xEmu, offsetof(x64emu_t, op2)); +// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res)); +// SET_DF(s4, d_cmp32); +// } else { +// SET_DFNONE(s4); +// } +// SUBS_IMM8(s3, s1, 0); // res = s1 - 0 +// // and now the tricky ones (and mostly unused), PF and AF +// // bc = (res & (~d | s)) | (~d & s) => is 0 here... +// IFX(X_CF | X_AF | X_ZF) { +// BIC_IMM8(xFlags, xFlags, (1<> 14) ^ ((bc>>14)>>1)) & 1 +// } +// } +// IFX(X_PF) { +// IFX(X_CF|X_AF|X_OF) { +// SUB_REG_LSL_IMM5(s3, s1, s2, 0); +// } +// AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied +// MOV32(s4, GetParityTab()); +// LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer +// SUB_REG_LSL_IMM5(s3, s1, s2, 0); +// AND_IMM8(s3, s3, 31); +// MVN_REG_LSR_REG(s4, s4, s3); +// BFI(xFlags, s4, F_PF, 1); +// } +//} + +// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch +//void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) +//{ +// IFX(X_PEND) { +// MOVW(s3, 0); +// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1)); +// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2)); +// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res)); +// SET_DF(s3, d_cmp16); +// } else { +// SET_DFNONE(s3); +// } +// // bc = (res & (~d | s)) | (~d & s) = 0 +// IFX(X_CF | X_AF | X_ZF) { +// BIC_IMM8(xFlags, xFlags, (1<> 6) ^ ((bc>>6)>>1)) & 1 +// } +// } +// IFX(X_PF) { +// IFX(X_CF|X_AF|X_OF) { +// SUB_REG_LSL_IMM5(s3, s1, s2, 0); +// } +// AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied +// MOV32(s4, GetParityTab()); +// LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer +// SUB_REG_LSL_IMM5(s3, s1, s2, 0); +// AND_IMM8(s3, s3, 31); +// MVN_REG_LSR_REG(s4, s4, s3); +// BFI(xFlags, s4, F_PF, 1); +// } +//} +// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch +//void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) +//{ +// IFX(X_PEND) { +// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1)); +// MOVW(s4, 0); +// STR_IMM9(s4, xEmu, offsetof(x64emu_t, op2)); +// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res)); +// SET_DF(s3, d_cmp8); +// } else { +// SET_DFNONE(s4); +// } +// // bc = (res & (~d | s)) | (~d & s) = 0 +// IFX(X_CF | X_AF | X_ZF) { +// BIC_IMM8(xFlags, xFlags, (1<x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0) + IFX(X_PF) { + ANDw_U12(s3, s3, 0xE0); // lsr 5 masking pre-applied + LSRw(s3, s3, 5); + MOV64x(s4, (uintptr_t)GetParityTab()); + LDRw_REG_LSL2(s4, s4, s3); + ANDw_U12(s3, s1, 31); + LSRw_REG(s4, s4, s3); + MVNx(s4, s4); + BFIx(xFlags, s4, F_PF, 1); + } +} + +// emit TEST16 instruction, from test s1 , s2, using s3 and s4 as scratch +//void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) +//{ +// IFX(X_PEND) { +// SET_DF(s3, d_tst16); +// } else { +// SET_DFNONE(s4); +// } +// IFX(X_OF) { +// BFC(xFlags, F_OF, 1); +// } +// IFX(X_ZF|X_CF) { +// BIC_IMM8(xFlags, xFlags, (1<x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0) +// IFX(X_PF) { +// AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied +// MOV32(s4, GetParityTab()); +// LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer +// AND_REG_LSL_IMM5(s3, s1, s2, 0); +// AND_IMM8(s3, s3, 31); +// MVN_REG_LSR_REG(s4, s4, s3); +// BFI(xFlags, s4, F_PF, 1); +// } +//} + +// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch +//void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) +//{ +// IFX(X_PEND) { +// SET_DF(s3, d_tst8); +// } else { +// SET_DFNONE(s4); +// } +// IFX(X_OF) { +// BFC(xFlags, F_OF, 1); +// } +// IFX(X_ZF|X_CF) { +// BIC_IMM8(xFlags, xFlags, (1<x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0) +// IFX(X_PF) { +// AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied +// MOV32(s4, GetParityTab()); +// LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer +// AND_REG_LSL_IMM5(s3, s1, s2, 0); +// AND_IMM8(s3, s3, 31); +// MVN_REG_LSR_REG(s4, s4, s3); +// BFI(xFlags, s4, F_PF, 1); +// } +//} diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index 3d947a5c..4fef2acb 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -611,7 +611,7 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save //void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); //void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); -//void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); //void emit_add32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); //void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);