summaryrefslogtreecommitdiff
path: root/arch/arm64/il.cpp
diff options
context:
space:
mode:
authorGalen Williamson <galen@vector35.com>2025-03-25 21:27:51 -0400
committerGalen Williamson <galen@vector35.com>2025-03-31 18:31:33 -0400
commitb095215397ca8fe7e9808f312403ec4494de76f6 (patch)
tree5eebe61a44d2f95aa5fadd78d9974234fca376be /arch/arm64/il.cpp
parent8093106217331012734564301118244748535715 (diff)
[aarch64] Updating Aarch64 system registers to 2024-12 spec, fix MSR/MRS lifting to use ReadMSR/WriteMSR intrinsics that take enums, removing the sysregs from the register list of the architecture
* sysregs are no longer registers, add enum for TLBI and AT operands * add erroneously missing cases for unsupported encodings, add enum for DC operands
Diffstat (limited to 'arch/arm64/il.cpp')
-rw-r--r--arch/arm64/il.cpp335
1 files changed, 298 insertions, 37 deletions
diff --git a/arch/arm64/il.cpp b/arch/arm64/il.cpp
index 977b57d5..9d99a7ff 100644
--- a/arch/arm64/il.cpp
+++ b/arch/arm64/il.cpp
@@ -5,7 +5,7 @@
#include "il.h"
#include "neon_intrinsics.h"
-#include "sysregs.h"
+#include "sysregs_gen.h"
using namespace BinaryNinja;
@@ -1184,6 +1184,16 @@ bool GetLowLevelILForInstruction(
switch (instr.operation)
{
case ARM64_ADD:
+ switch (instr.encoding)
+ {
+ case ENC_ADD_Z_P_ZZ_:
+ case ENC_ADD_Z_ZI_:
+ case ENC_ADD_Z_ZZ_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
case ARM64_ADDS:
il.AddInstruction(
ILSETREG_O(operand1, il.Add(REGSZ_O(operand1), ILREG_O(operand2),
@@ -1197,26 +1207,100 @@ bool GetLowLevelILForInstruction(
break;
case ARM64_AND:
case ARM64_ANDS:
+ switch (instr.encoding)
+ {
+ case ENC_AND_P_P_PP_Z:
+ case ENC_AND_Z_P_ZZ_:
+ case ENC_AND_Z_ZI_:
+ case ENC_AND_Z_ZZ_:
+ case ENC_ANDS_P_P_PP_Z:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(
ILSETREG_O(operand1, il.And(REGSZ_O(operand1), ILREG_O(operand2),
ReadILOperand(il, operand3, REGSZ_O(operand1)), SETFLAGS)));
break;
case ARM64_ADR:
+ switch (instr.encoding)
+ {
+ case ENC_ADR_Z_AZ_SD_SAME_SCALED:
+ case ENC_ADR_Z_AZ_D_S32_SCALED:
+ case ENC_ADR_Z_AZ_D_U32_SCALED:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
case ARM64_ADRP:
il.AddInstruction(ILSETREG_O(operand1, il.ConstPointer(REGSZ_O(operand1), IMM_O(operand2))));
break;
case ARM64_ASR:
+ switch (instr.encoding)
+ {
+ case ENC_ASR_Z_P_ZI_:
+ case ENC_ASR_Z_P_ZW_:
+ case ENC_ASR_Z_P_ZZ_:
+ case ENC_ASR_Z_ZI_:
+ case ENC_ASR_Z_ZW_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(ILSETREG_O(operand1, il.ArithShiftRight(REGSZ_O(operand2), ILREG_O(operand2),
ReadILOperand(il, operand3, REGSZ_O(operand2)))));
break;
case ARM64_AESD:
+ switch (instr.encoding)
+ {
+ case ENC_AESD_Z_ZZ_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_AESD,
{ILREG_O(operand1), ILREG_O(operand2)}));
break;
case ARM64_AESE:
+ switch (instr.encoding)
+ {
+ case ENC_AESE_Z_ZZ_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_AESE,
{ILREG_O(operand1), ILREG_O(operand2)}));
break;
+ case ARM64_AESIMC:
+ switch (instr.encoding)
+ {
+ case ENC_AESIMC_Z_Z_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
+ il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_AESIMC,
+ {ILREG_O(operand1), ILREG_O(operand2)}));
+ break;
+ case ARM64_AESMC:
+ switch (instr.encoding)
+ {
+ case ENC_AESMC_Z_Z_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
+ il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_AESMC,
+ {ILREG_O(operand1), ILREG_O(operand2)}));
+ break;
case ARM64_BTI:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_HINT_BTI, {}));
break;
@@ -1317,7 +1401,16 @@ bool GetLowLevelILForInstruction(
return false;
case ARM64_BIC:
case ARM64_BICS:
- switch (instr.encoding) {
+ switch (instr.encoding)
+ {
+ case ENC_BIC_AND_Z_ZI_:
+ case ENC_BIC_P_P_PP_Z:
+ case ENC_BIC_Z_P_ZZ_:
+ case ENC_BIC_Z_ZZ_:
+ case ENC_BICS_P_P_PP_Z:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
case ENC_BIC_ASIMDIMM_L_HL:
case ENC_BIC_ASIMDIMM_L_SL:
il.AddInstruction(ILSETREG_O(operand1,
@@ -1512,8 +1605,9 @@ bool GetLowLevelILForInstruction(
{RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_CLZ, {ILREG_O(operand2)}));
break;
case ARM64_DC:
- il.AddInstruction(
- il.Intrinsic({}, ARM64_INTRIN_DC, {ILREG_O(operand2)})); /* operand1 is <dc_op> */
+ // il.AddInstruction(
+ // il.Intrinsic({}, ARM64_INTRIN_DC, {ILREG_O(operand2)})); /* operand1 is <dc_op> */
+ il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_DC, {il.Const(4, operand1.immediate), ReadILOperand(il, operand2, 8)}));
break;
case ARM64_DMB:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_DMB, {}));
@@ -1522,11 +1616,30 @@ bool GetLowLevelILForInstruction(
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_DSB, {}));
break;
case ARM64_EON:
+ switch (instr.encoding)
+ {
+ case ENC_EON_EOR_Z_ZI_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(ILSETREG_O(
operand1, il.Xor(REGSZ_O(operand1), ILREG_O(operand2),
il.Not(REGSZ_O(operand1), ReadILOperand(il, operand3, REGSZ_O(operand1))))));
break;
case ARM64_EOR:
+ switch (instr.encoding)
+ {
+ case ENC_EOR_P_P_PP_Z:
+ case ENC_EOR_Z_P_ZZ_:
+ case ENC_EOR_Z_ZI_:
+ case ENC_EOR_Z_ZZ_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(ILSETREG_O(operand1, il.Xor(REGSZ_O(operand1), ILREG_O(operand2),
ReadILOperand(il, operand3, REGSZ_O(operand1)))));
break;
@@ -1601,8 +1714,8 @@ bool GetLowLevelILForInstruction(
for (int i = 0; i < dst_n; ++i)
il.AddInstruction(ILSETREG(
dsts[i], il.FloatAdd(rsize, ILREG(srcs1[i]), ILREG(srcs2[i]))));
+ break;
}
- break;
default:
ABORT_LIFT;
}
@@ -1649,7 +1762,6 @@ bool GetLowLevelILForInstruction(
break;
}
case ENC_FADDP_Z_P_ZZ_:
- il.AddInstruction(il.Unimplemented());
default:
ABORT_LIFT;
}
@@ -1781,8 +1893,9 @@ bool GetLowLevelILForInstruction(
dsts[i], il.FloatDiv(rsize, ILREG(srcs1[i]), ILREG(srcs2[i]))));
break;
}
+ case ENC_FDIV_Z_P_ZZ_:
default:
- il.AddInstruction(il.Unimplemented());
+ ABORT_LIFT;
}
break;
case ARM64_FMOV:
@@ -1855,7 +1968,7 @@ bool GetLowLevelILForInstruction(
break;
}
default:
- il.AddInstruction(il.Unimplemented());
+ ABORT_LIFT;
}
break;
case ARM64_FMUL:
@@ -1906,7 +2019,7 @@ bool GetLowLevelILForInstruction(
break;
}
default:
- il.AddInstruction(il.Unimplemented());
+ ABORT_LIFT;
}
break;
case ARM64_FNEG:
@@ -1936,7 +2049,7 @@ bool GetLowLevelILForInstruction(
break;
}
default:
- il.AddInstruction(il.Unimplemented());
+ ABORT_LIFT;
}
break;
case ARM64_FNMUL:
@@ -1979,6 +2092,16 @@ bool GetLowLevelILForInstruction(
case ARM64_LDRAB:
SetPacAttr = true;
case ARM64_LDR:
+ switch (instr.encoding)
+ {
+ case ENC_LDR_P_BI_:
+ case ENC_LDR_Z_BI_:
+ case ENC_LDR_ZA_RI_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
case ARM64_LDUR:
LoadStoreOperand(il, true, instr.operands[0], instr.operands[1], 0);
if (SetPacAttr)
@@ -2131,8 +2254,39 @@ bool GetLowLevelILForInstruction(
ILSETREG_O(operand1, il.LogicalShiftRight(REGSZ_O(operand2), ILREG_O(operand2),
ReadILOperand(il, operand3, REGSZ_O(operand2)))));
break;
- case ARM64_DUP:
case ARM64_MOV:
+ switch (instr.encoding)
+ {
+ case ENC_MOV_AND_P_P_PP_Z:
+ case ENC_MOV_CPY_Z_O_I_:
+ case ENC_MOV_CPY_Z_P_I_:
+ case ENC_MOV_CPY_Z_P_R_:
+ case ENC_MOV_CPY_Z_P_V_:
+ case ENC_MOV_DUP_Z_I_:
+ case ENC_MOV_DUP_Z_R_:
+ case ENC_MOV_DUP_Z_ZI_:
+ case ENC_MOV_DUP_Z_ZI_2:
+ case ENC_MOV_DUPM_Z_I_:
+ case ENC_MOV_MOVA_Z_P_RZA_B:
+ case ENC_MOV_MOVA_Z_P_RZA_H:
+ case ENC_MOV_MOVA_Z_P_RZA_W:
+ case ENC_MOV_MOVA_Z_P_RZA_D:
+ case ENC_MOV_MOVA_Z_P_RZA_Q:
+ case ENC_MOV_MOVA_ZA_P_RZ_B:
+ case ENC_MOV_MOVA_ZA_P_RZ_H:
+ case ENC_MOV_MOVA_ZA_P_RZ_W:
+ case ENC_MOV_MOVA_ZA_P_RZ_D:
+ case ENC_MOV_MOVA_ZA_P_RZ_Q:
+ case ENC_MOV_ORR_P_P_PP_Z:
+ case ENC_MOV_ORR_Z_ZZ_:
+ case ENC_MOV_SEL_P_P_PP_:
+ case ENC_MOV_SEL_Z_P_ZZ_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
+ case ARM64_DUP:
case ARM64_MOVN:
case ARM64_UMOV:
case ARM64_INS:
@@ -2217,6 +2371,10 @@ bool GetLowLevelILForInstruction(
}
break;
}
+ case ENC_DUP_P_P_PI_:
+ case ENC_DUP_Z_I_:
+ case ENC_DUP_Z_R_:
+ case ENC_DUP_Z_ZI_:
default:
// case ENC_MOVS_ORRS_P_P_PP_Z:
// il.AddInstruction(il.Unimplemented());
@@ -2254,12 +2412,20 @@ bool GetLowLevelILForInstruction(
case ARM64_MUL:
switch (instr.encoding)
{
- case ENC_MUL_ASIMDSAME_ONLY:
- case ENC_MUL_ASIMDELEM_R:
- break;
- default:
- il.AddInstruction(
- ILSETREG_O(operand1, il.Mult(REGSZ_O(operand1), ILREG_O(operand2), ILREG_O(operand3))));
+ case ENC_MUL_Z_P_ZZ_:
+ case ENC_MUL_Z_ZI_:
+ case ENC_MUL_Z_ZZ_:
+ case ENC_MUL_Z_ZZI_H:
+ case ENC_MUL_Z_ZZI_S:
+ case ENC_MUL_Z_ZZI_D:
+ case ENC_MUL_ASIMDSAME_ONLY:
+ case ENC_MUL_ASIMDELEM_R:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default:
+ il.AddInstruction(
+ ILSETREG_O(operand1, il.Mult(REGSZ_O(operand1), ILREG_O(operand2), ILREG_O(operand3))));
}
break;
case ARM64_MADD:
@@ -2268,20 +2434,19 @@ bool GetLowLevelILForInstruction(
break;
case ARM64_MRS:
{
- ExprId reg = ILREG_O(operand2);
- const char* name = get_system_register_name((SystemReg)operand2.sysreg);
+ uint32_t reg = operand2.sysreg;
+ const char* name = get_system_register_name((SystemReg)(reg));
if (strlen(name) == 0)
{
- LogWarn("Unknown system register %d @ 0x%" PRIx64
- ": S%d_%d_c%d_c%d_%d, using generic system register instead\n",
- operand2.sysreg, addr, operand2.implspec[0], operand2.implspec[1], operand2.implspec[2],
- operand2.implspec[3], operand2.implspec[4]);
- reg = il.Register(8, FAKEREG_SYSREG_UNKNOWN);
+ LogDebug("MSR Unknown system register %d @ 0x%" PRIx64
+ ": S%d_%d_c%d_c%d_%d",
+ operand2.sysreg, addr, operand2.implspec[0], operand2.implspec[1], operand2.implspec[2],
+ operand2.implspec[3], operand2.implspec[4]);
}
il.AddInstruction(
- il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_MRS, {reg}));
+ il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_MRS, {il.Const(4, reg)}));
break;
}
case ARM64_MSUB:
@@ -2297,26 +2462,23 @@ bool GetLowLevelILForInstruction(
case ARM64_MSR:
{
uint32_t dst = operand1.sysreg;
- const char* name = get_system_register_name((SystemReg)dst);
+ const char* name = get_system_register_name((SystemReg)(dst));
if (strlen(name) == 0)
{
- LogWarn("Unknown system register %d @ 0x%" PRIx64
- ": S%d_%d_c%d_c%d_%d, using generic system register instead\n",
- dst, addr, operand1.implspec[0], operand1.implspec[1], operand1.implspec[2],
+ LogDebug("MSR Unknown system register %d @ 0x%" PRIx64
+ ": S%d_%d_c%d_c%d_%d",
+ operand1.sysreg, addr, operand1.implspec[0], operand1.implspec[1], operand1.implspec[2],
operand1.implspec[3], operand1.implspec[4]);
- dst = FAKEREG_SYSREG_UNKNOWN;
}
switch (operand2.operandClass)
{
case IMM32:
- il.AddInstruction(il.Intrinsic(
- {RegisterOrFlag::Register(dst)}, ARM64_INTRIN_MSR, {il.Const(4, IMM_O(operand2))}));
+ il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_MSR, {il.Const(4, dst), il.Const(4, IMM_O(operand2))}));
break;
case REG:
- il.AddInstruction(
- il.Intrinsic({RegisterOrFlag::Register(dst)}, ARM64_INTRIN_MSR, {ILREG_O(operand2)}));
+ il.AddInstruction( il.Intrinsic({}, ARM64_INTRIN_MSR, {il.Const(4, dst), ILREG_O(operand2)}));
break;
default:
LogError("unknown MSR operand class: %x\n", operand2.operandClass);
@@ -2325,6 +2487,16 @@ bool GetLowLevelILForInstruction(
break;
}
case ARM64_NEG:
+ switch (instr.encoding)
+ {
+ case ENC_NEG_ASISDMISC_R:
+ case ENC_NEG_ASIMDMISC_R:
+ case ENC_NEG_Z_P_Z_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
case ARM64_NEGS:
il.AddInstruction(ILSETREG_O(
operand1, il.Neg(REGSZ_O(operand1), ReadILOperand(il, instr.operands[1], REGSZ_O(operand1)),
@@ -2452,6 +2624,15 @@ bool GetLowLevelILForInstruction(
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_PRFM, {ReadILOperand(il, operand2, 8)}));
break;
case ARM64_ORN:
+ switch (instr.encoding)
+ {
+ case ENC_ORN_ORR_Z_ZI_:
+ case ENC_ORN_P_P_PP_Z:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(ILSETREG_O(
operand1, il.Or(REGSZ_O(operand1), ILREG_O(operand2),
il.Not(REGSZ_O(operand1), ReadILOperand(il, operand3, REGSZ_O(operand1))))));
@@ -2480,9 +2661,12 @@ bool GetLowLevelILForInstruction(
case ENC_ORR_ASIMDSAME_ONLY:
// Let the neon intrinsic lifter take over.
break;
+ case ENC_ORR_P_P_PP_Z:
+ case ENC_ORR_Z_P_ZZ_:
+ case ENC_ORR_Z_ZI_:
+ case ENC_ORR_Z_ZZ_:
default:
- il.AddInstruction(il.Unimplemented());
- break;
+ ABORT_LIFT;
}
break;
case ARM64_PSB:
@@ -2676,7 +2860,7 @@ bool GetLowLevelILForInstruction(
case ENC_UCVTF_Z_P_Z_X2D:
case ENC_UCVTF_Z_P_Z_X2FP16:
case ENC_UCVTF_Z_P_Z_X2S:
- break;
+ ABORT_LIFT;
default:
break;
}
@@ -2814,6 +2998,16 @@ bool GetLowLevelILForInstruction(
LoadStoreOperandPair(il, false, instr.operands[0], instr.operands[1], instr.operands[2]);
break;
case ARM64_STR:
+ switch (instr.encoding)
+ {
+ case ENC_STR_P_BI_:
+ case ENC_STR_Z_BI_:
+ case ENC_STR_ZA_RI_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
case ARM64_STLR:
case ARM64_STUR:
case ARM64_STLUR:
@@ -2832,6 +3026,16 @@ bool GetLowLevelILForInstruction(
LoadStoreOperandSize(il, false, false, 2, instr.operands[0], instr.operands[1]);
break;
case ARM64_SUB:
+ switch (instr.encoding)
+ {
+ case ENC_SUB_Z_P_ZZ_:
+ case ENC_SUB_Z_ZI_:
+ case ENC_SUB_Z_ZZ_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
case ARM64_SUBS:
il.AddInstruction(ILSETREG_O(
operand1, il.Sub(REGSZ_O(operand1), ILREG_O(operand2),
@@ -2890,14 +3094,38 @@ bool GetLowLevelILForInstruction(
il.AddInstruction(il.Store(2, ILREG_O(operand3), il.LowPart(2, ILREG_O(operand1))));
break;
case ARM64_SXTB:
+ switch (instr.encoding)
+ {
+ case ENC_SXTB_Z_P_Z_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(
ILSETREG_O(operand1, ExtractRegister(il, operand2, 0, 1, true, REGSZ_O(operand1))));
break;
case ARM64_SXTH:
+ switch (instr.encoding)
+ {
+ case ENC_SXTH_Z_P_Z_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(
ILSETREG_O(operand1, ExtractRegister(il, operand2, 0, 2, true, REGSZ_O(operand1))));
break;
case ARM64_SXTW:
+ switch (instr.encoding)
+ {
+ case ENC_SXTW_Z_P_Z_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(
ILSETREG_O(operand1, ExtractRegister(il, operand2, 0, 4, true, REGSZ_O(operand1))));
break;
@@ -2917,6 +3145,15 @@ bool GetLowLevelILForInstruction(
il.AddInstruction(il.And(REGSZ_O(operand1), ILREG_O(operand1),
ReadILOperand(il, operand2, REGSZ_O(operand1)), SETFLAGS));
break;
+ case ARM64_TLBI:
+ if (operand2.operandClass == REG)
+ il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_TLBI_REG, {il.Const(4, operand1.immediate), ReadILOperand(il, operand2, 8)}));
+ else
+ il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_TLBI, {il.Const(4, operand1.immediate)}));
+ break;
+ case ARM64_AT:
+ il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_AT, {il.Const(4, operand1.immediate), ReadILOperand(il, operand2, 8)}));
+ break;
case ARM64_UMADDL:
il.AddInstruction(ILSETREG_O(operand1,
il.Add(REGSZ_O(operand1), ILREG_O(operand4),
@@ -3072,6 +3309,14 @@ bool GetLowLevelILForInstruction(
il.Const(1, 64)))));
break;
case ARM64_UDIV:
+ switch (instr.encoding)
+ {
+ case ENC_UDIV_Z_P_ZZ_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(ILSETREG_O(
operand1, il.DivUnsigned(REGSZ_O(operand2), ILREG_O(operand2), ILREG_O(operand3))));
break;
@@ -3104,10 +3349,26 @@ bool GetLowLevelILForInstruction(
break;
}
case ARM64_UXTB:
+ switch (instr.encoding)
+ {
+ case ENC_UXTB_Z_P_Z_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(
ILSETREG_O(operand1, ExtractRegister(il, operand2, 0, 1, false, REGSZ_O(operand1))));
break;
case ARM64_UXTH:
+ switch (instr.encoding)
+ {
+ case ENC_UXTH_Z_P_Z_:
+ if (!preferIntrinsics())
+ il.AddInstruction(il.Unimplemented());
+ return true;
+ default: break;
+ }
il.AddInstruction(
ILSETREG_O(operand1, ExtractRegister(il, operand2, 0, 2, false, REGSZ_O(operand1))));
break;