diff --git a/id/src/main/java/com/ledmington/cpu/InstructionChecker.java b/id/src/main/java/com/ledmington/cpu/InstructionChecker.java index e1330dd8..2eebf64b 100644 --- a/id/src/main/java/com/ledmington/cpu/InstructionChecker.java +++ b/id/src/main/java/com/ledmington/cpu/InstructionChecker.java @@ -299,7 +299,7 @@ public final class InstructionChecker { Map.entry(Opcode.VPCMPEQQ, List.of(RX_RX_M128)), Map.entry(Opcode.VPCMPNEQB, List.of(RK_RY_RY, RK_RY_M256)), Map.entry(Opcode.VZEROALL, List.of(NO_ARGS)), - Map.entry(Opcode.VMOVQ, List.of(R64_RX, RX_M64, M64_RX)), + Map.entry(Opcode.VMOVQ, List.of(R64_RX, RX_RX, RX_M64, M64_RX)), Map.entry(Opcode.VMOVD, List.of(RX_M32)), Map.entry(Opcode.PCMPISTRI, List.of(RX_RX_I8, RX_M128_I8)), Map.entry(Opcode.PUNPCKLBW, List.of(RX_RX)), diff --git a/id/src/main/java/com/ledmington/cpu/InstructionDecoder.java b/id/src/main/java/com/ledmington/cpu/InstructionDecoder.java index 0a37fc44..7fcc1e81 100644 --- a/id/src/main/java/com/ledmington/cpu/InstructionDecoder.java +++ b/id/src/main/java/com/ledmington/cpu/InstructionDecoder.java @@ -3779,9 +3779,12 @@ private static Instruction parseVex2Opcodes( yield Instruction.builder() .opcode(Opcode.VMOVQ) .op(RegisterXMM.fromByte(getByteFromReg(vex2, modrm))) - .op(parseIndirectOperand(b, pref, modrm) - .pointer(PointerSize.QWORD_PTR) - .build()) + .op( + isIndirectOperandNeeded(modrm) + ? parseIndirectOperand(b, pref, modrm) + .pointer(PointerSize.QWORD_PTR) + .build() + : RegisterXMM.fromByte(getByteFromRM(pref, modrm))) .build(); } case VMOVQ_M64_RXMM_OPCODE -> { @@ -3896,10 +3899,17 @@ private static Instruction parseVex3Opcodes( return switch (opcodeFirstByte) { case VMOVQ_OPCODE -> { final ModRM modrm = modrm(b); + final byte r1 = getByteFromRM(vex3, modrm); + final byte r2 = or(vex3.x() ? 0 : (byte) 0b00010000, getByteFromReg(vex3, modrm)); yield Instruction.builder() .opcode(Opcode.VMOVQ) - .op(Register64.fromByte(getByteFromRM(vex3, modrm))) - .op(RegisterXMM.fromByte(getByteFromReg(vex3, modrm))) + .op(vex3.x() ? Register64.fromByte(r1) : RegisterXMM.fromByte(r1)) + .op( + isIndirectOperandNeeded(modrm) + ? parseIndirectOperand(b, pref, modrm) + .pointer(PointerSize.XMMWORD_PTR) + .build() + : (RegisterXMM.fromByte(r2))) .build(); } case KMOVQ_RK_R64_OPCODE -> { @@ -4114,12 +4124,12 @@ private static Instruction parseEvexOpcodes( final byte VPMINUD_OPCODE = (byte) 0x3b; final byte VPCMPNEQUB_OPCODE = (byte) 0x3e; final byte VPCMPxxB_OPCODE = (byte) 0x3f; - final byte VMOVQ_RX_M128_OPCODE = (byte) 0x6e; + final byte VMOVQ_R_M_OPCODE = (byte) 0x6e; final byte VMOVDQU64_RZMM_M512_OPCODE = (byte) 0x6f; final byte VPCMPEQB_OPCODE = (byte) 0x74; final byte VPBROADCASTB_OPCODE = (byte) 0x7a; final byte VPBROADCASTD_OPCODE = (byte) 0x7c; - final byte VMOVQ_R64_RX_OPCODE = (byte) 0x7e; + final byte VMOVQ_R_R_OPCODE = (byte) 0x7e; final byte VMOVDQU64_M512_RZMM_OPCODE = (byte) 0x7f; final byte VPMINUB_OPCODE = (byte) 0xda; final byte VMOVNTDQ_OPCODE = (byte) 0xe7; @@ -4219,21 +4229,29 @@ private static Instruction parseEvexOpcodes( .op(RegisterZMM.fromByte(getByteFromReg(evex, modrm))) .build(); } - case VMOVQ_R64_RX_OPCODE -> { + case VMOVQ_R_R_OPCODE -> { final ModRM modrm = modrm(b); - yield new GeneralInstruction( - Opcode.VMOVQ, - Register64.fromByte(getByteFromRM(evex, modrm)), - RegisterXMM.fromByte(or(evex.r1() ? 0 : (byte) 0b00010000, getByteFromReg(evex, modrm)))); + final byte r1 = getByteFromReg(evex, modrm); + final byte r2 = or(evex.b() ? 0 : (byte) 0b00010000, getByteFromRM(evex, modrm)); + yield Instruction.builder() + .opcode(Opcode.VMOVQ) + .op( + evex.p() == (byte) 0b00000010 + ? RegisterXMM.fromByte(or(evex.r1() ? 0 : (byte) 0b00010000, r1)) + : Register64.fromByte(modrm.reg())) + .op(RegisterXMM.fromByte(r2)) + .build(); } - case VMOVQ_RX_M128_OPCODE -> { + case VMOVQ_R_M_OPCODE -> { final ModRM modrm = modrm(b); - yield new GeneralInstruction( - Opcode.VMOVQ, - RegisterXMM.fromByte(or(evex.r1() ? 0 : (byte) 0b00010000, getByteFromReg(evex, modrm))), - parseIndirectOperand(b, pref, modrm) + final byte r1 = or(evex.r1() ? 0 : (byte) 0b00010000, getByteFromReg(evex, modrm)); + yield Instruction.builder() + .opcode(Opcode.VMOVQ) + .op(RegisterXMM.fromByte(r1)) + .op(parseIndirectOperand(b, pref, modrm) .pointer(PointerSize.QWORD_PTR) - .build()); + .build()) + .build(); } case VPCMPNEQUB_OPCODE -> { final ModRM modrm = modrm(b); diff --git a/id/src/main/java/com/ledmington/cpu/x86/EvexPrefix.java b/id/src/main/java/com/ledmington/cpu/x86/EvexPrefix.java index 66ff36c6..55f92143 100644 --- a/id/src/main/java/com/ledmington/cpu/x86/EvexPrefix.java +++ b/id/src/main/java/com/ledmington/cpu/x86/EvexPrefix.java @@ -163,15 +163,6 @@ public boolean r1() { return r1; } - /** - * Returns the M field value. - * - * @return The M field. - */ - public byte m() { - return m; - } - /** * Returns the W bit value. * @@ -190,6 +181,15 @@ public byte v() { return v; } + /** + * Returns the P field value. + * + * @return The P field. + */ + public byte p() { + return p; + } + /** * Returns the Z bit value. * diff --git a/id/src/test/java/com/ledmington/cpu/X64Encodings.java b/id/src/test/java/com/ledmington/cpu/X64Encodings.java index d7191f35..af92c3e5 100644 --- a/id/src/test/java/com/ledmington/cpu/X64Encodings.java +++ b/id/src/test/java/com/ledmington/cpu/X64Encodings.java @@ -114,11 +114,11 @@ import static com.ledmington.cpu.x86.RegisterXMM.XMM13; import static com.ledmington.cpu.x86.RegisterXMM.XMM14; import static com.ledmington.cpu.x86.RegisterXMM.XMM15; -import static com.ledmington.cpu.x86.RegisterXMM.XMM16; import static com.ledmington.cpu.x86.RegisterXMM.XMM17; import static com.ledmington.cpu.x86.RegisterXMM.XMM18; import static com.ledmington.cpu.x86.RegisterXMM.XMM2; import static com.ledmington.cpu.x86.RegisterXMM.XMM3; +import static com.ledmington.cpu.x86.RegisterXMM.XMM30; import static com.ledmington.cpu.x86.RegisterXMM.XMM4; import static com.ledmington.cpu.x86.RegisterXMM.XMM5; import static com.ledmington.cpu.x86.RegisterXMM.XMM6; @@ -10321,7 +10321,10 @@ Opcode.MOVABS, new SegmentedAddress(DS, new Immediate(0x12345678deadbeefL)), EAX test(new GeneralInstruction(Opcode.VZEROALL), "vzeroall", "c5 fc 77"), // Vmovq test(new GeneralInstruction(Opcode.VMOVQ, RDI, XMM0), "vmovq rdi,xmm0", "c4 e1 f9 7e c7"), - test(new GeneralInstruction(Opcode.VMOVQ, RDI, XMM16), "vmovq rdi,xmm16", "62 e1 fd 08 7e c7"), + test(new GeneralInstruction(Opcode.VMOVQ, RSI, XMM30), "vmovq rsi,xmm30", "62 61 fd 08 7e f6"), + test(new GeneralInstruction(Opcode.VMOVQ, XMM0, XMM1), "vmovq xmm0,xmm1", "c5 fa 7e c1"), + test(new GeneralInstruction(Opcode.VMOVQ, XMM9, XMM18), "vmovq xmm9,xmm18", "62 31 fe 08 7e ca"), + test(new GeneralInstruction(Opcode.VMOVQ, XMM18, XMM9), "vmovq xmm18,xmm9", "62 c1 fe 08 7e d1"), test( new GeneralInstruction( Opcode.VMOVQ, @@ -10356,6 +10359,30 @@ Opcode.MOVABS, new SegmentedAddress(DS, new Immediate(0x12345678deadbeefL)), EAX XMM0), "vmovq QWORD PTR [rdi],xmm0", "c5 f9 d6 07"), + test( + new GeneralInstruction( + Opcode.VMOVQ, + XMM0, + IndirectOperand.builder() + .pointer(QWORD_PTR) + .base(RDI) + .index(R9) + .scale(1) + .build()), + "vmovq xmm0,QWORD PTR [rdi+r9*1]", + "c4 a1 7a 7e 04 0f"), + test( + new GeneralInstruction( + Opcode.VMOVQ, + XMM17, + IndirectOperand.builder() + .pointer(QWORD_PTR) + .base(RDI) + .index(R9) + .scale(1) + .build()), + "vmovq xmm17,QWORD PTR [rdi+r9*1]", + "62 a1 fd 08 6e 0c 0f"), // Vmovd test( new GeneralInstruction(