diff options
Diffstat (limited to 'src/dynarec/arm64/dynarec_arm64_66.c')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 235 |
1 files changed, 218 insertions, 17 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index fa69a836..ff269cf2 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -1,7 +1,6 @@ #include <stdio.h> #include <stdlib.h> #include <stddef.h> -#include <pthread.h> #include <errno.h> #include "debug.h" @@ -50,14 +49,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin rep = opcode-0xF1; opcode = F8; } - // REX prefix before the 66 are ignored - rex.rex = 0; - while(opcode>=0x40 && opcode<=0x4f) { - rex.rex = opcode; - opcode = F8; - } + GETREX(); - if(rex.w && opcode!=0x0f) // rex.w cancels "66", but not for 66 0f type of prefix + 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) { @@ -88,7 +82,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin emit_add16(dyn, ninst, x1, x2, x3, x4); BFIx(xRAX, x1, 0, 16); break; - + case 0x09: INST_NAME("OR Ew, Gw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -295,6 +289,70 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + INST_NAME("INC Reg16 (32bits)"); + SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING); + gd = xRAX + (opcode&7); + UXTHw(x1, gd); + emit_inc16(dyn, ninst, x1, x2, x3); + BFIw(gd, x1, 0, 16); + break; + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + INST_NAME("DEC Reg16 (32bits)"); + SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING); + gd = xRAX + (opcode&7); + UXTHw(x1, gd); + emit_dec16(dyn, ninst, x1, x2, x3); + BFIw(gd, x1, 0, 16); + break; + + case 0x60: + if(rex.is32bits) { + INST_NAME("PUSHA 16 (32bits)"); + MOVw_REG(x1, xRSP); + STRH_S9_preindex(xRAX, xRSP, -2); + STRH_S9_preindex(xRCX, xRSP, -2); + STRH_S9_preindex(xRDX, xRSP, -2); + STRH_S9_preindex(xRBX, xRSP, -2); + STRH_S9_preindex(x1, xRSP, -2); + STRH_S9_preindex(xRBP, xRSP, -2); + STRH_S9_preindex(xRSI, xRSP, -2); + STRH_S9_preindex(xRDI, xRSP, -2); + } else { + DEFAULT; + } + break; + case 0x61: + if(rex.is32bits) { + INST_NAME("POPA 16 (32bits)"); + MOVw_REG(x1, xRSP); + LDRH_S9_postindex(xRDI, xRSP, 2); + LDRH_S9_postindex(xRSI, xRSP, 2); + LDRH_S9_postindex(xRBP, xRSP, 2); + LDRH_S9_postindex(x1, xRSP, 2); + LDRH_S9_postindex(xRBX, xRSP, 2); + LDRH_S9_postindex(xRDX, xRSP, 2); + LDRH_S9_postindex(xRCX, xRSP, 2); + LDRH_S9_postindex(xRAX, xRSP, 2); + } else { + DEFAULT; + } + break; + case 0x64: addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog); break; @@ -425,7 +483,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; } break; - + case 0x85: INST_NAME("TEST Ew, Gw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -463,7 +521,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIx(gd, x1, 0, 16); } break; - + case 0x89: INST_NAME("MOV Ew, Gw"); nextop = F8; @@ -495,6 +553,19 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIx(gd, x1, 0, 16); } break; + case 0x8C: + INST_NAME("MOV EW, Seg"); + nextop=F8; + u8 = (nextop&0x38)>>3; + LDRw_U12(x3, xEmu, offsetof(x64emu_t, segs[u8])); + if((nextop&0xC0)==0xC0) { // reg <= seg + UXTHw(xRAX+(nextop&7)+(rex.b<<3), x3); + } else { // mem <= seg + addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0); + STH(x3, wback, fixedaddress); + SMWRITE2(); + } + break; case 0x90: case 0x91: @@ -521,18 +592,47 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIw(xRAX, x1, 0, 16); break; + case 0x9C: + INST_NAME("PUSHF"); + READFLAGS(X_ALL); + PUSH1_16(xFlags); + break; + case 0x9D: + INST_NAME("POPF"); + SETFLAGS(X_ALL, SF_SET); + POP1_16(x1); // probably not usefull... + BFIw(xFlags, x1, 0, 16); + MOV32w(x1, 0x3F7FD7); + ANDw_REG(xFlags, xFlags, x1); + ORRw_mask(xFlags, xFlags, 0b011111, 0); //mask=0x00000002 + SET_DFNONE(x1); + if(box64_wine) { // should this be done all the time? + TBZ_NEXT(xFlags, F_TF); + MOV64x(x1, addr); + STORE_XEMU_CALL(x1); + CALL(native_singlestep, -1); + BFCw(xFlags, F_TF, 1); + } + break; + case 0xA1: INST_NAME("MOV EAX,Od"); - u64 = F64; - MOV64x(x1, u64); + if(rex.is32bits) + u64 = F32; + else + u64 = F64; + MOV64z(x1, u64); LDRH_U12(x2, x1, 0); BFIx(xRAX, x2, 0, 16); break; case 0xA3: INST_NAME("MOV Od,EAX"); - u64 = F64; - MOV64x(x1, u64); + if(rex.is32bits) + u64 = F32; + else + u64 = F64; + MOV64z(x1, u64); STRH_U12(xRAX, x1, 0); SMWRITE(); break; @@ -564,6 +664,46 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; + case 0xA7: + switch(rep) { + case 1: + case 2: + if(rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");} + MAYSETFLAGS(); + SETFLAGS(X_ALL, SF_SET_PENDING); + CBZx_NEXT(xRCX); + TBNZ_MARK2(xFlags, F_DF); + MARK; // Part with DF==0 + LDRH_S9_postindex(x1, xRSI, 2); + LDRH_S9_postindex(x2, xRDI, 2); + SUBx_U12(xRCX, xRCX, 1); + CMPSw_REG(x1, x2); + B_MARK3((rep==1)?cEQ:cNE); + CBNZx_MARK(xRCX); + B_MARK3_nocond; + MARK2; // Part with DF==1 + LDRH_S9_postindex(x1, xRSI, -2); + LDRH_S9_postindex(x2, xRDI, -2); + SUBx_U12(xRCX, xRCX, 1); + CMPSw_REG(x1, x2); + B_MARK3((rep==1)?cEQ:cNE); + CBNZx_MARK2(xRCX); + MARK3; // end + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5); + break; + default: + INST_NAME("CMPSW"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETDIR(x3, 2); + LDRH_U12(x1, xRSI, 0); + LDRH_U12(x2, xRDI, 0); + ADDx_REG(xRSI, xRSI, x3); + ADDx_REG(xRDI, xRDI, x3); + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5); + break; + } + break; + case 0xA9: INST_NAME("TEST AX,Iw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -596,6 +736,67 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; + case 0xAD: + if(rep) { + INST_NAME("REP LODSW"); + CBZx_NEXT(xRCX); + TBNZ_MARK2(xFlags, F_DF); + MARK; // Part with DF==0 + LDRH_S9_postindex(xRAX, xRSI, 2); + SUBx_U12(xRCX, xRCX, 1); + CBNZx_MARK(xRCX); + B_NEXT_nocond; + MARK2; // Part with DF==1 + LDRH_S9_postindex(xRAX, xRSI, -2); + SUBx_U12(xRCX, xRCX, 1); + CBNZx_MARK2(xRCX); + // done + } else { + INST_NAME("STOSW"); + GETDIR(x3, 2); + LDRH_U12(xRAX, xRSI, 0); + ADDx_REG(xRSI, xRSI, x3); + } + break; + + case 0xAF: + switch(rep) { + case 1: + case 2: + if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");} + MAYSETFLAGS(); + SETFLAGS(X_ALL, SF_SET_PENDING); + CBZx_NEXT(xRCX); + UXTHw(x1, xRAX); + TBNZ_MARK2(xFlags, F_DF); + MARK; // Part with DF==0 + LDRH_S9_postindex(x2, xRDI, 2); + SUBx_U12(xRCX, xRCX, 1); + CMPSw_REG(x1, x2); + B_MARK3((rep==1)?cEQ:cNE); + CBNZx_MARK(xRCX); + B_MARK3_nocond; + MARK2; // Part with DF==1 + LDRH_S9_postindex(x2, xRDI, -2); + SUBx_U12(xRCX, xRCX, 1); + CMPSw_REG(x1, x2); + B_MARK3((rep==1)?cEQ:cNE); + CBNZx_MARK2(xRCX); + MARK3; // end + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5); + break; + default: + INST_NAME("SCASW"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETDIR(x3, 2); + UXTHw(x1, xRAX); + LDRH_U12(x2, xRDI, 0); + ADDx_REG(xRDI, xRDI, x3); + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5); + break; + } + break; + case 0xB8: case 0xB9: case 0xBA: @@ -822,7 +1023,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; } break; - + case 0xF0: return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); @@ -898,7 +1099,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; } break; - + case 0xFF: nextop = F8; switch((nextop>>3)&7) { |