diff options
Diffstat (limited to 'src/dynarec/arm64/dynarec_arm64_67.c')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_67.c | 184 |
1 files changed, 164 insertions, 20 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index c50e5013..04065e7a 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -1,7 +1,6 @@ #include <stdio.h> #include <stdlib.h> #include <stddef.h> -#include <pthread.h> #include <errno.h> #include "debug.h" @@ -22,14 +21,6 @@ #include "dynarec_arm64_helper.h" #include "dynarec_arm64_functions.h" -#define GETGX(a, w) \ - gd = ((nextop&0x38)>>3)+(rex.r<<3); \ - a = sse_get_reg(dyn, ninst, x1, gd, w) - -#define GETGM(a) \ - gd = ((nextop&0x38)>>3); \ - a = mmx_get_reg(dyn, ninst, x1, x2, x3, gd) - #define GETGm gd = ((nextop&0x38)>>3) uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog) @@ -38,7 +29,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin uint8_t opcode = F8; uint8_t nextop; - uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2; + uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2; int64_t fixedaddress; int unscaled; int8_t i8; @@ -56,12 +47,14 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MAYUSE(lock); MAYUSE(cacheupd); - // REX prefix before the 67 are ignored - rex.rex = 0; - while(opcode>=0x40 && opcode<=0x4f) { - rex.rex = opcode; - opcode = F8; + if(rex.is32bits) { + // should do a different file + DEFAULT; + return addr; } + + GETREX(); + rep = 0; while((opcode==0xF2) || (opcode==0xF3)) { rep = opcode-0xF1; @@ -173,6 +166,28 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin opcode=F8; switch(opcode) { + case 0x11: + switch(rep) { + case 0: + INST_NAME("MOVUPS Ex,Gx"); + nextop = F8; + GETG; + v0 = sse_get_reg(dyn, ninst, x1, gd, 0); + if(MODREG) { + ed = (nextop&7)+(rex.b<<3); + v1 = sse_get_reg_empty(dyn, ninst, x1, ed); + VMOVQ(v1, v0); + } else { + addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0); + VST128(v0, ed, fixedaddress); + SMWRITE2(); + } + break; + default: + DEFAULT; + } + break; + case 0x2E: // no special check... case 0x2F: @@ -215,6 +230,20 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin VLD64(v0, ed, fixedaddress); } break; + case 2: + INST_NAME("MOVDQU Gx,Ex"); + nextop = F8; + if(MODREG) { + v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0); + GETGX_empty(v0); + VMOVQ(v0, v1); + } else { + GETGX_empty(v0); + SMREAD(); + addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0); + VLD128(v0, ed, fixedaddress); + } + break; default: DEFAULT; } @@ -240,6 +269,40 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; + case 0xB6: + INST_NAME("MOVZX Gd, Eb"); + nextop = F8; + GETGD; + if(MODREG) { + if(rex.rex) { + eb1 = xRAX+(nextop&7)+(rex.b<<3); + eb2 = 0; \ + } else { + ed = (nextop&7); + eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx + eb2 = (ed&4)>>2; // L or H + } + UBFXxw(gd, eb1, eb2*8, 8); + } else { + SMREAD(); + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 0); + LDB(gd, ed, fixedaddress); + } + break; + case 0xB7: + INST_NAME("MOVZX Gd, Ew"); + nextop = F8; + GETGD; + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + UBFXxw(gd, ed, 0, 16); + } else { + SMREAD(); + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0); + LDH(gd, ed, fixedaddress); + } + break; + default: DEFAULT; } @@ -564,6 +627,54 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4); break; + case 0x63: + INST_NAME("MOVSXD Gd, Ed"); + nextop = F8; + GETGD; + if(rex.w) { + if(MODREG) { // reg <= reg + SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3)); + } else { // mem <= reg + SMREAD(); + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0); + LDSW(gd, ed, fixedaddress); + } + } else { + if(MODREG) { // reg <= reg + MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3)); + } else { // mem <= reg + SMREAD(); + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0); + LDW(gd, ed, fixedaddress); + } + } + break; + + case 0x66: + opcode=F8; + switch(opcode) { + + case 0x89: + INST_NAME("MOV Ew, Gw"); + nextop = F8; + GETGD; // don't need GETGW here + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + if(ed!=gd) { + BFIx(ed, gd, 0, 16); + } + } else { + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0); + STH(gd, ed, fixedaddress); + SMWRITELOCK(lock); + } + break; + + default: + DEFAULT; + } + break; + case 0x81: case 0x83: nextop = F8; @@ -641,7 +752,40 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; } break; - + + case 0x88: + INST_NAME("MOV Eb, Gb"); + nextop = F8; + gd = ((nextop&0x38)>>3)+(rex.r<<3); + if(rex.rex) { + gb2 = 0; + gb1 = xRAX + gd; + } else { + gb2 = ((gd&4)>>2); + gb1 = xRAX+(gd&3); + } + if(gb2) { + gd = x4; + UBFXw(gd, gb1, gb2*8, 8); + } else { + gd = gb1; // no need to extract + } + if(MODREG) { + ed = (nextop&7) + (rex.b<<3); + if(rex.rex) { + eb1 = xRAX+ed; + eb2 = 0; + } else { + eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx + eb2 = ((ed&4)>>2); // L or H + } + BFIx(eb1, gd, eb2*8, 8); + } else { + addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 0); + STB(gd, ed, fixedaddress); + SMWRITELOCK(lock); + } + break; case 0x89: INST_NAME("MOV Ed, Gd"); nextop=F8; @@ -914,9 +1058,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRAX, x2); MOVw_REG(xRDX, x4); } else { - if(ninst && dyn->insts - && dyn->insts[ninst-1].x64.addr - && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31 + if(ninst && dyn->insts + && dyn->insts[ninst-1].x64.addr + && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31 && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) { SET_DFNONE(x2); GETED32(0); @@ -952,7 +1096,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRDX, x4); } else { if(ninst && dyn->insts - && dyn->insts[ninst-1].x64.addr + && dyn->insts[ninst-1].x64.addr && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48 && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) { SET_DFNONE(x2) |