about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-23 11:25:02 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-23 11:25:02 +0100
commitc9d593fa17916b0a542a801cafa4ea2a0d8c59bc (patch)
treeb147f7de6daf912473d11074d4e7013aced0140e /src
parented452e81ae59982da75774ad52f6bfafe24096fb (diff)
downloadbox64-c9d593fa17916b0a542a801cafa4ea2a0d8c59bc.tar.gz
box64-c9d593fa17916b0a542a801cafa4ea2a0d8c59bc.zip
[DYNAREC] Added F0 83 opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/dynarec_arm64_f0.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/dynarec/dynarec_arm64_f0.c b/src/dynarec/dynarec_arm64_f0.c
index 5756db77..11939fc1 100644
--- a/src/dynarec/dynarec_arm64_f0.c
+++ b/src/dynarec/dynarec_arm64_f0.c
@@ -33,6 +33,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
     uint16_t u16;
     uint8_t gd, ed;
     uint8_t wback, wb1, wb2, gb1, gb2;
+    int64_t i64;
     int fixedaddress;
     MAYUSE(u16);
     MAYUSE(u8);
@@ -148,6 +149,187 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }
             break;
                     
+        case 0x81:
+        case 0x83:
+            nextop = F8;
+            switch((nextop>>3)&7) {
+                case 0: //ADD
+                    if(opcode==0x81) {
+                        INST_NAME("LOCK ADD Ed, Id");
+                    } else {
+                        INST_NAME("LOCK ADD Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET);
+                    if(MODREG) {
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        ed = xRAX+(nextop&7)+(rex.b<<3);
+                        MOV64xw(x5, i64);
+                        emit_add32(dyn, ninst, rex, ed, x5, x3, x4);
+                    } else {
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        MOV64xw(x5, i64);
+                        TSTx_mask(wback, 1, 0, 1+rex.w);    // mask=3 or 7
+                        B_MARK(cNE);
+                        MARKLOCK;
+                        LDAXRxw(x1, wback);
+                        emit_add32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRxw(x3, x1, wback);
+                        CBNZx_MARKLOCK(x3);
+                        B_NEXT_nocond;
+                        MARK;   // unaligned! also, not enough 
+                        LDRxw_U12(x1, wback, 0);
+                        LDAXRB(x4, wback);
+                        BFIxw(x1, x4, 0, 8); // re-inject
+                        emit_add32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRB(x3, x1, wback);
+                        CBNZx_MARK(x3);
+                        STRxw_U12(x1, wback, 0);    // put the whole value
+                    }
+                    break;
+                case 1: //OR
+                    if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
+                    SETFLAGS(X_ALL, SF_SET);
+                    if(MODREG) {
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        ed = xRAX+(nextop&7)+(rex.b<<3);
+                        MOV64xw(x5, i64);
+                        emit_or32(dyn, ninst, rex, ed, x5, x3, x4);
+                    } else {
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        MOV64xw(x5, i64);
+                        MARKLOCK;
+                        LDAXRxw(x1, wback);
+                        emit_or32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRxw(x3, x1, wback);
+                        CBNZx_MARKLOCK(x3);
+                    }
+                    break;
+                case 2: //ADC
+                    if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_ALL, SF_SET);
+                    if(MODREG) {
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        ed = xRAX+(nextop&7)+(rex.b<<3);
+                        MOV64xw(x5, i64);
+                        emit_adc32(dyn, ninst, rex, ed, x5, x3, x4);
+                    } else {
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        MOV64xw(x5, i64);
+                        MARKLOCK;
+                        LDAXRxw(x1, wback);
+                        emit_adc32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRxw(x3, x1, wback);
+                        CBNZx_MARKLOCK(x3);
+                    }
+                    break;
+                case 3: //SBB
+                    if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_ALL, SF_SET);
+                    if(MODREG) {
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        ed = xRAX+(nextop&7)+(rex.b<<3);
+                        MOV64xw(x5, i64);
+                        emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4);
+                    } else {
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        MOV64xw(x5, i64);
+                        MARKLOCK;
+                        LDAXRxw(x1, wback);
+                        emit_sbb32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRxw(x3, x1, wback);
+                        CBNZx_MARKLOCK(x3);
+                    }
+                    break;
+                case 4: //AND
+                    if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
+                    SETFLAGS(X_ALL, SF_SET);
+                    if(MODREG) {
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        ed = xRAX+(nextop&7)+(rex.b<<3);
+                        MOV64xw(x5, i64);
+                        emit_and32(dyn, ninst, rex, ed, x5, x3, x4);
+                    } else {
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        MOV64xw(x5, i64);
+                        MARKLOCK;
+                        LDAXRxw(x1, wback);
+                        emit_and32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRxw(x3, x1, wback);
+                        CBNZx_MARKLOCK(x3);
+                    }
+                    break;
+                case 5: //SUB
+                    if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
+                    SETFLAGS(X_ALL, SF_SET);
+                    if(MODREG) {
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        ed = xRAX+(nextop&7)+(rex.b<<3);
+                        MOV64xw(x5, i64);
+                        emit_sub32(dyn, ninst, rex, ed, x5, x3, x4);
+                    } else {
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        MOV64xw(x5, i64);
+                        TSTx_mask(wback, 1, 0, 1+rex.w);    // mask=3 or 7
+                        B_MARK(cNE);
+                        MARKLOCK;
+                        LDAXRxw(x1, wback);
+                        emit_sub32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRxw(x3, x1, wback);
+                        CBNZx_MARKLOCK(x3);
+                        B_NEXT_nocond;
+                        MARK;   // unaligned! also, not enough 
+                        LDRxw_U12(x1, wback, 0);
+                        LDAXRB(x4, wback);
+                        BFIxw(x1, x4, 0, 8); // re-inject
+                        emit_sub32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRB(x3, x1, wback);
+                        CBNZx_MARK(x3);
+                        STRxw_U12(x1, wback, 0);    // put the whole value
+                    }
+                    break;
+                case 6: //XOR
+                    if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
+                    SETFLAGS(X_ALL, SF_SET);
+                    if(MODREG) {
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        ed = xRAX+(nextop&7)+(rex.b<<3);
+                        MOV64xw(x5, i64);
+                        emit_xor32(dyn, ninst, rex, ed, x5, x3, x4);
+                    } else {
+                        addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        MOV64xw(x5, i64);
+                        MARKLOCK;
+                        LDAXRxw(x1, wback);
+                        emit_xor32(dyn, ninst, rex, x1, x5, x3, x4);
+                        STLXRxw(x3, x1, wback);
+                        CBNZx_MARKLOCK(x3);
+                    }
+                    break;
+                case 7: //CMP
+                    if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
+                    SETFLAGS(X_ALL, SF_SET);
+                    GETED(0);
+                    // No need to LOCK, this is readonly
+                    if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                    if(i32) {
+                        MOV64xw(x5, i64);
+                        emit_cmp32(dyn, ninst, rex, ed, x5, x3, x4, x6);
+                    } else {
+                        emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
+                    }
+                    break;
+            }
+            break;
+            
         default:
             DEFAULT;
     }