diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-02-10 15:35:38 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-10 08:35:38 +0100 |
| commit | 2cb25c095a113e575bf5e4e9fe051c283daaf659 (patch) | |
| tree | 17b090d92b76fbf91c77af74fecf4ccdabda96c1 | |
| parent | d0039c65b47f3c7b0ca28b44b9124e8b19fc9bf3 (diff) | |
| download | box64-2cb25c095a113e575bf5e4e9fe051c283daaf659.tar.gz box64-2cb25c095a113e575bf5e4e9fe051c283daaf659.zip | |
[LA64_DYNAREC] Added more opcodes (#2339)
| -rw-r--r-- | CMakeLists.txt | 5 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 26 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 4 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66f0.c | 132 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f0.c | 37 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 2 |
6 files changed, 204 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 711dd035..23a9eaa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1044,11 +1044,12 @@ if(LARCH64_DYNAREC) "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_64.c" "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66.c" "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_6664.c" - "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_67.c" - "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f30f.c" "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_660f.c" + "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66f0.c" + "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_67.c" "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f0.c" "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f20f.c" + "${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f30f.c" ) endif() diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index e0366227..192c9445 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -416,6 +416,32 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; } break; + case 0xF0: + INST_NAME("MOVBE Gd, Ed"); + nextop = F8; + GETGD; + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LDxw(gd, ed, fixedaddress); + if (rex.w) { + REVB_D(gd, gd); + } else { + REVB_2W(gd, gd); + ZEROUP(gd); + } + break; + case 0xF1: + INST_NAME("MOVBE Ed, Gd"); + nextop = F8; + GETGD; + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0); + if (rex.w) + REVB_D(x1, gd); + else + REVB_2W(x1, gd); + SDxw(x1, wback, fixedaddress); + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 548f01bf..8d3ae2e5 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -859,6 +859,10 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DEFAULT; } break; + + case 0xF0: + return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + case 0xF7: nextop = F8; switch ((nextop >> 3) & 7) { diff --git a/src/dynarec/la64/dynarec_la64_66f0.c b/src/dynarec/la64/dynarec_la64_66f0.c new file mode 100644 index 00000000..e2c74406 --- /dev/null +++ b/src/dynarec/la64/dynarec_la64_66f0.c @@ -0,0 +1,132 @@ +#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 "la64_emitter.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_helper.h" +#include "dynarec_la64_functions.h" + + +uintptr_t dynarec64_66F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog) +{ + (void)ip; + (void)rep; + (void)need_epilog; + + uint8_t opcode = F8; + uint8_t nextop; + uint8_t gd, ed, u8; + uint8_t wback, wb1, wb2, gb1, gb2; + int32_t i32; + int64_t i64, j64; + uint64_t u64; + int64_t fixedaddress; + int unscaled; + MAYUSE(gb1); + MAYUSE(gb2); + MAYUSE(wb1); + MAYUSE(wb2); + MAYUSE(j64); + + while ((opcode == 0xF2) || (opcode == 0xF3)) { + rep = opcode - 0xF1; + opcode = F8; + } + + GETREX(); + + switch (opcode) { + case 0x81: + case 0x83: + nextop = F8; + SMDMB(); + switch ((nextop >> 3) & 7) { + case 0: // ADD + if (opcode == 0x81) { + INST_NAME("LOCK ADD Ew, Iw"); + } else { + INST_NAME("LOCK ADD Ew, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + if (MODREG) { + if (opcode == 0x81) + u64 = F16; + else + u64 = (uint16_t)(int16_t)F8S; + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MOV64x(x5, u64); + BSTRPICK_D(x6, ed, 15, 0); + emit_add16(dyn, ninst, x6, x5, x3, x4, x2); + BSTRINS_D(ed, x6, 15, 0); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 2 : 1); + if (opcode == 0x81) + u64 = F16; + else + u64 = (uint16_t)(int16_t)F8S; + MOV64x(x5, u64); + + if (la64_lam_bh) { + AMADD_DB_H(x1, x5, wback); + } else { + ANDI(x3, wback, 0b10); + BNEZ_MARK(x3); + // lower 16 bits + MARKLOCK; + LL_W(x1, wback, 0); + ADD_D(x4, x1, x5); + MV(x3, x1); + BSTRINS_D(x3, x4, 15, 0); + SC_W(x3, wback, 0); + BEQZ_MARKLOCK(x3); + IFXORNAT (X_ALL | X_PEND) { + BSTRPICK_D(x1, x1, 15, 0); + } + B_MARK3_nocond; + MARK; + // upper 16 bits + XORI(wback, wback, 0b10); + MARK2; + LL_W(x1, wback, 0); + BSTRPICK_D(x3, x1, 15, 0); + SRLI_W(x1, x1, 16); + ADD_D(x4, x1, x5); + BSTRINS_D(x3, x4, 31, 15); + SC_W(x3, wback, 0); + BEQZ_MARK2(x3); + MARK3; + } + // final + IFXORNAT (X_ALL | X_PEND) { + emit_add16(dyn, ninst, x1, x5, x3, x4, x6); + } + } + break; + default: + DEFAULT; + } + SMDMB(); + break; + + default: + DEFAULT; + } + + return addr; +} diff --git a/src/dynarec/la64/dynarec_la64_f0.c b/src/dynarec/la64/dynarec_la64_f0.c index 4ff48729..d4786552 100644 --- a/src/dynarec/la64/dynarec_la64_f0.c +++ b/src/dynarec/la64/dynarec_la64_f0.c @@ -462,6 +462,43 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } SMDMB(); break; + + case 0x66: + return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + + case 0x80: + nextop = F8; + SMDMB(); + switch ((nextop >> 3) & 7) { + case 1: // OR + INST_NAME("LOCK OR Eb, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + if (MODREG) { + GETEB(x1, 1); + u8 = F8; + emit_or8c(dyn, ninst, x1, u8, x2, x4, x5); + EBBACK(); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x5, x1, &fixedaddress, rex, LOCK_LOCK, 0, 1); + u8 = F8; + ANDI(x2, wback, 3); + SLLI_D(x2, x2, 3); // offset in bits + ANDI(x3, wback, ~3); // aligned addr + ADDI_D(x1, xZR, u8); + SLL_D(x1, x1, x2); // Ib << offset + AMOR_DB_W(x4, x1, x3); + IFXORNAT (X_ALL | X_PEND) { + SRL_D(x1, x4, x2); + ANDI(x1, x1, 0xFF); + emit_or8c(dyn, ninst, x1, u8, x2, x4, x5); + } + } + break; + default: + DEFAULT; + } + SMDMB(); + break; case 0x81: case 0x83: nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 09d6cad5..eaa385cb 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -843,6 +843,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define dynarec64_67 STEPNAME(dynarec64_67) #define dynarec64_F30F STEPNAME(dynarec64_F30F) #define dynarec64_660F STEPNAME(dynarec64_660F) +#define dynarec64_66F0 STEPNAME(dynarec64_66F0) #define dynarec64_F0 STEPNAME(dynarec64_F0) #define dynarec64_F20F STEPNAME(dynarec64_F20F) @@ -1091,6 +1092,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni uintptr_t dynarec64_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog); uintptr_t dynarec64_67(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); +uintptr_t dynarec64_66F0(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_F0(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_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); |