diff --git a/src/asmjit/arm/a64assembler.cpp b/src/asmjit/arm/a64assembler.cpp index c926766..32514b9 100644 --- a/src/asmjit/arm/a64assembler.cpp +++ b/src/asmjit/arm/a64assembler.cpp @@ -53,6 +53,21 @@ static constexpr uint32_t kWX = InstDB::kWX; static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; #undef VALUE +// a64::Assembler - ExtendOpToRegType +// ================================== + +static inline RegType extendOptionToRegType(uint32_t option) noexcept { + uint32_t pred = (uint32_t(RegType::kARM_GpW) << (0x0 * 4)) | // 0b000 - UXTB. + (uint32_t(RegType::kARM_GpW) << (0x1 * 4)) | // 0b001 - UXTH. + (uint32_t(RegType::kARM_GpW) << (0x2 * 4)) | // 0b010 - UXTW. + (uint32_t(RegType::kARM_GpX) << (0x3 * 4)) | // 0b011 - UXTX|LSL. + (uint32_t(RegType::kARM_GpW) << (0x4 * 4)) | // 0b100 - SXTB. + (uint32_t(RegType::kARM_GpW) << (0x5 * 4)) | // 0b101 - SXTH. + (uint32_t(RegType::kARM_GpW) << (0x6 * 4)) | // 0b110 - SXTW. + (uint32_t(RegType::kARM_GpX) << (0x7 * 4)) ; // 0b111 - SXTX. + return RegType((pred >> (option * 4u)) & 0xFu); +} + // asmjit::a64::Assembler - SizeOp // =============================== @@ -1228,9 +1243,6 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co } if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - if (!checkSignature(o1, o2)) - goto InvalidInstruction; - uint32_t opSize = x ? 64 : 32; uint64_t shift = 0; uint32_t sType = uint32_t(ShiftOp::kLSL); @@ -1247,11 +1259,17 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co if (sType <= uint32_t(ShiftOp::kASR)) { bool hasSP = o0.as().isSP() || o1.as().isSP(); if (!hasSP) { - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; + if (!checkSignature(o1, o2)) { + goto InvalidInstruction; + } - if (shift >= opSize) + if (!checkGpId(o0, o1, kZR)) { + goto InvalidPhysId; + } + + if (shift >= opSize) { goto InvalidImmediate; + } opcode.reset(uint32_t(opData.shiftedOp) << 21); opcode.addImm(x, 31); @@ -1264,8 +1282,10 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co } // SP register can only be used with LSL or Extend. - if (sType != uint32_t(ShiftOp::kLSL)) + if (sType != uint32_t(ShiftOp::kLSL)) { goto InvalidImmediate; + } + sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW); } @@ -1273,8 +1293,9 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co opcode.reset(uint32_t(opData.extendedOp) << 21); sType -= uint32_t(ShiftOp::kUXTB); - if (sType > 7 || shift > 4) + if (sType > 7 || shift > 4) { goto InvalidImmediate; + } if (!(opcode.get() & B(29))) { // ADD|SUB (extend) - ZR is not allowed. @@ -1287,6 +1308,11 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co goto InvalidPhysId; } + // Validate whether the register operands match extend option. + if (o2.as().type() != extendOptionToRegType(sType) || o1.as().type() < o2.as().type()) { + goto InvalidInstruction; + } + opcode.addImm(x, 31); opcode.addReg(o2, 16); opcode.addImm(sType, 13); @@ -1412,9 +1438,6 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co } if (isign4 == ENC_OPS2(Reg, Reg) || isign4 == ENC_OPS3(Reg, Reg, Imm)) { - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - uint32_t opSize = x ? 64 : 32; uint32_t sType = 0; uint64_t shift = 0; @@ -1429,8 +1452,13 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co // Shift operation - LSL, LSR, ASR. if (sType <= uint32_t(ShiftOp::kASR)) { if (!hasSP) { - if (shift >= opSize) + if (!checkSignature(o0, o1)) { + goto InvalidInstruction; + } + + if (shift >= opSize) { goto InvalidImmediate; + } opcode.reset(uint32_t(opData.shiftedOp) << 21); opcode.addImm(x, 31); @@ -1451,8 +1479,14 @@ Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, co // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX. sType -= uint32_t(ShiftOp::kUXTB); - if (sType > 7 || shift > 4) + if (sType > 7 || shift > 4) { goto InvalidImmediate; + } + + // Validate whether the register operands match extend option. + if (o1.as().type() != extendOptionToRegType(sType) || o0.as().type() < o1.as().type()) { + goto InvalidInstruction; + } opcode.reset(uint32_t(opData.extendedOp) << 21); opcode.addImm(x, 31); diff --git a/test/asmjit_test_assembler_a64.cpp b/test/asmjit_test_assembler_a64.cpp index 8da77b3..4bb4710 100644 --- a/test/asmjit_test_assembler_a64.cpp +++ b/test/asmjit_test_assembler_a64.cpp @@ -42,6 +42,7 @@ static void ASMJIT_NOINLINE testA64AssemblerBase(AssemblerTester TEST_INSTRUCTION("E103038B", add(x1, xzr, x3)); TEST_INSTRUCTION("5F00030B", add(wzr, w2, w3)); TEST_INSTRUCTION("5F00038B", add(xzr, x2, x3)); + TEST_INSTRUCTION("4140238B", add(x1, x2, w3, uxtw(0))); TEST_INSTRUCTION("83004011", add(w3, w4, 0, lsl(12))); TEST_INSTRUCTION("83004091", add(x3, x4, 0, lsl(12))); TEST_INSTRUCTION("83005011", add(w3, w4, 1024, lsl(12))); @@ -210,7 +211,8 @@ static void ASMJIT_NOINLINE testA64AssemblerBase(AssemblerTester TEST_INSTRUCTION("3F00022B", cmn(w1, w2)); TEST_INSTRUCTION("3F0002AB", cmn(x1, x2)); TEST_INSTRUCTION("3F08222B", cmn(w1, w2, uxtb(2))); - TEST_INSTRUCTION("3F0822AB", cmn(x1, x2, uxtb(2))); + TEST_INSTRUCTION("3F0822AB", cmn(x1, w2, uxtb(2))); + TEST_INSTRUCTION("5F4023AB", cmn(x2, w3, uxtw(0))); TEST_INSTRUCTION("FF43212B", cmn(wsp, w1)); TEST_INSTRUCTION("FF07212B", cmn(wsp, w1, uxtb(1))); TEST_INSTRUCTION("FF6321AB", cmn(sp, x1)); @@ -224,7 +226,8 @@ static void ASMJIT_NOINLINE testA64AssemblerBase(AssemblerTester TEST_INSTRUCTION("3F00026B", cmp(w1, w2)); TEST_INSTRUCTION("3F0002EB", cmp(x1, x2)); TEST_INSTRUCTION("3F08226B", cmp(w1, w2, uxtb(2))); - TEST_INSTRUCTION("3F0822EB", cmp(x1, x2, uxtb(2))); + TEST_INSTRUCTION("3F0822EB", cmp(x1, w2, uxtb(2))); + TEST_INSTRUCTION("5F4023EB", cmp(x2, w3, uxtw(0))); TEST_INSTRUCTION("FF43216B", cmp(wsp, w1)); TEST_INSTRUCTION("FF07216B", cmp(wsp, w1, uxtb(1))); TEST_INSTRUCTION("FF6321EB", cmp(sp, x1)); diff --git a/test/asmjit_test_perf_a64.cpp b/test/asmjit_test_perf_a64.cpp index 36d23a4..938aa9b 100644 --- a/test/asmjit_test_perf_a64.cpp +++ b/test/asmjit_test_perf_a64.cpp @@ -177,13 +177,13 @@ static void generateGpSequenceInternal( cc.cmn(wA, wB); cc.cmn(xA, xB); cc.cmn(wA, wB, uxtb(2)); - cc.cmn(xA, xB, uxtb(2)); + cc.cmn(xA, wB, uxtb(2)); cc.cmp(wA, 33); cc.cmp(xA, 33); cc.cmp(wA, wB); cc.cmp(xA, xB); cc.cmp(wA, wB, uxtb(2)); - cc.cmp(xA, xB, uxtb(2)); + cc.cmp(xA, wB, uxtb(2)); cc.crc32b(wA, wB, wC); cc.crc32b(wzr, wB, wC); cc.crc32b(wA, wzr, wC);