diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-08-06 16:34:37 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-06 10:34:37 +0200 |
| commit | 676efe40327a8324889a736110ffea897b03736d (patch) | |
| tree | 7813154233fd3ee8ea2674670810ba16e8269c82 /src | |
| parent | dd7b99ffd1445d824bd351488c6f7b976f77fc9e (diff) | |
| download | box64-676efe40327a8324889a736110ffea897b03736d.tar.gz box64-676efe40327a8324889a736110ffea897b03736d.zip | |
[LA64_DYNAREC] Added more opcodes (#2902)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 3 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_64.c | 29 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 5 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_67.c | 187 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 13 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_emitter.h | 12 |
6 files changed, 248 insertions, 1 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index 556ccd34..b8464a2e 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -377,6 +377,9 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni i64 = F32S; emit_sub32c(dyn, ninst, rex, xRAX, i64, x2, x3, x4, x5); break; + case 0x2E: + INST_NAME("CS:"); + break; case 0x30: INST_NAME("XOR Eb, Gb"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); diff --git a/src/dynarec/la64/dynarec_la64_64.c b/src/dynarec/la64/dynarec_la64_64.c index 906e8fe7..62de36e1 100644 --- a/src/dynarec/la64/dynarec_la64_64.c +++ b/src/dynarec/la64/dynarec_la64_64.c @@ -444,6 +444,22 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else LDXxw(xRAX, x4, x1); break; + case 0xA3: + INST_NAME("MOV FS:Od, EAX"); + grab_segdata(dyn, addr, ninst, x4, seg, 0); + if (rex.is32bits) + u64 = F32; + else + u64 = F64; + if (u64 < 0x800) { + ADDIz(x1, x4, u64); + } else { + MOV64z(x1, u64); + ADDz(x1, x1, x4); + } + SDxw(xRAX, x1, 0); + SMWRITE2(); + break; case 0xC6: INST_NAME("MOV Seg:Eb, Ib"); nextop = F8; @@ -502,6 +518,19 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITE2(); } break; + case 0xFF: + nextop = F8; + switch ((nextop >> 3) & 7) { + case 6: // Push Ed + INST_NAME("PUSH Ed"); + grab_segdata(dyn, addr, ninst, x6, seg, (MODREG)); + GETEDOz(x6, 0, x3); + PUSH1z(ed); + break; + default: + DEFAULT; + } + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 109683d3..cc29e3bc 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -1026,6 +1026,11 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_dec16(dyn, ninst, x1, x2, x4, x5, x6); EWBACK; break; + case 6: // Push Ew + INST_NAME("PUSH Ew"); + GETEW(x1, 0); + PUSH1_16(ed); + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_67.c b/src/dynarec/la64/dynarec_la64_67.c index 908ec378..70cb6536 100644 --- a/src/dynarec/la64/dynarec_la64_67.c +++ b/src/dynarec/la64/dynarec_la64_67.c @@ -60,6 +60,47 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } switch(opcode) { + case 0x0F: + opcode = F8; + switch (opcode) { + case 0xB6: + INST_NAME("MOVZX Gd, Eb"); + nextop = F8; + GETGD; + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + if (rex.rex) { + eb1 = TO_NAT(ed); + eb2 = 0; + } else { + eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx + eb2 = ((ed & 4) << 1); // L or H + } + BSTRPICK_D(gd, eb1, eb2 + 7, eb2); + } else { + SMREAD(); + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LD_BU(gd, ed, fixedaddress); + } + break; + case 0xB7: + INST_NAME("MOVZX Gd, Ew"); + nextop = F8; + GETGD; + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + BSTRPICK_D(gd, ed, 15, 0); + } else { + SMREAD(); + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LD_HU(gd, ed, fixedaddress); + } + break; + default: + DEFAULT; + } + break; + case 0x19: INST_NAME("SBB Ed, Gd"); READFLAGS(X_CF); @@ -97,6 +138,140 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni MOV64xw(x2, i64); emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); break; + + case 0x81: + case 0x83: + nextop = F8; + switch ((nextop >> 3) & 7) { + case 0: // ADD + if (opcode == 0x81) { + INST_NAME("ADD Ed, Id"); + } else { + INST_NAME("ADD Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + GETED32((opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6); + WBACK; + break; + case 1: // OR + if (opcode == 0x81) { + INST_NAME("OR Ed, Id"); + } else { + INST_NAME("OR Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + GETED32((opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + emit_or32c(dyn, ninst, rex, ed, i64, x3, x4); + WBACK; + break; + case 2: // ADC + if (opcode == 0x81) { + INST_NAME("ADC Ed, Id"); + } else { + INST_NAME("ADC Ed, Ib"); + } + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + GETED32((opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + MOV64xw(x5, i64); + emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x5, x6); + WBACK; + break; + case 3: // SBB + if (opcode == 0x81) { + INST_NAME("SBB Ed, Id"); + } else { + INST_NAME("SBB Ed, Ib"); + } + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + GETED32((opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + MOV64xw(x5, i64); + emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, x5); + WBACK; + break; + case 4: // AND + if (opcode == 0x81) { + INST_NAME("AND Ed, Id"); + } else { + INST_NAME("AND Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + GETED32((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, NAT_FLAGS_FUSION); + GETED32((opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + 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, NAT_FLAGS_FUSION); + GETED32((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, NAT_FLAGS_FUSION); + GETED32((opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + if (i64) { + MOV64x(x2, i64); + emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6); + } else + emit_cmp32_0(dyn, ninst, rex, nextop, ed, x3, x4, x5); + break; + } + break; case 0x88: INST_NAME("MOV Eb, Gb"); nextop = F8; @@ -142,6 +317,18 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITELOCK(lock); } break; + case 0x8B: + INST_NAME("MOV Gd, Ed"); + nextop = F8; + GETGD; + if (MODREG) { + MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3))); + } else { + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0); + SMREADLOCK(lock); + LDxw(gd, ed, fixedaddress); + } + break; case 0x8D: INST_NAME("LEA Gd, Ed"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 92f271bf..0121004c 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -136,7 +136,18 @@ } \ ed = x1; \ } - +// GETEDOz can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI +#define GETEDOz(O, D, S) \ + if (MODREG) { \ + ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + wback = 0; \ + } else { \ + SMREAD(); \ + addr = geted(dyn, addr, ninst, nextop, &wback, x2, S, &fixedaddress, rex, NULL, 1, D); \ + ADDz(S, wback, O); \ + LDz(x1, S, fixedaddress); \ + ed = x1; \ + } // GETSED can use r1 for ed, and r2 for wback. ed will be sign extended! #define GETSED(D) \ if (MODREG) { \ diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index 44c35e05..466180f7 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -2528,6 +2528,18 @@ LSX instruction starts with V, LASX instruction starts with XV. if (reg != xRSP) ADDI_D(xRSP, xRSP, 4); \ } while (0); +#define PUSH1_16(reg) \ + do { \ + ST_H(reg, xRSP, -2); \ + ADDI_D(xRSP, xRSP, -2); \ + } while (0) + +#define POP1_16(reg) \ + do { \ + LD_HU(reg, xRSP, 0); \ + if (reg != xRSP) ADDI_D(xRSP, xRSP, 2); \ + } while (0) + // POP reg #define POP1z(reg) \ do { \ |