mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
[ARM64] Add proper bounds checking/diagnostics to logical shifts
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208540 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5c39a97a60
commit
b0b587163d
@ -108,6 +108,18 @@ class ArithmeticShifterOperand<int width> : AsmOperandClass {
|
||||
def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
|
||||
def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
|
||||
|
||||
// Shifter operand for logical register shifted encodings.
|
||||
class LogicalShifterOperand<int width> : AsmOperandClass {
|
||||
let SuperClasses = [ShifterOperand];
|
||||
let Name = "LogicalShifter" # width;
|
||||
let PredicateMethod = "isLogicalShifter<" # width # ">";
|
||||
let RenderMethod = "addLogicalShifterOperands";
|
||||
let DiagnosticType = "AddSubRegShift" # width;
|
||||
}
|
||||
|
||||
def LogicalShifterOperand32 : LogicalShifterOperand<32>;
|
||||
def LogicalShifterOperand64 : LogicalShifterOperand<64>;
|
||||
|
||||
// Shifter operand for logical vector 128/64-bit shifted encodings.
|
||||
def LogicalVecShifterOperand : AsmOperandClass {
|
||||
let SuperClasses = [ShifterOperand];
|
||||
@ -525,20 +537,24 @@ def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
|
||||
// An arithmetic shifter operand:
|
||||
// {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
|
||||
// {5-0} - imm6
|
||||
def logical_shift : Operand<i32> {
|
||||
class logical_shift<int width> : Operand<i32> {
|
||||
let PrintMethod = "printShifter";
|
||||
let ParserMatchClass = ShifterOperand;
|
||||
let ParserMatchClass = !cast<AsmOperandClass>(
|
||||
"LogicalShifterOperand" # width);
|
||||
}
|
||||
|
||||
class logical_shifted_reg<ValueType Ty, RegisterClass regclass>
|
||||
def logical_shift32 : logical_shift<32>;
|
||||
def logical_shift64 : logical_shift<64>;
|
||||
|
||||
class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
|
||||
: Operand<Ty>,
|
||||
ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
|
||||
let PrintMethod = "printShiftedRegister";
|
||||
let MIOperandInfo = (ops regclass, logical_shift);
|
||||
let MIOperandInfo = (ops regclass, shiftop);
|
||||
}
|
||||
|
||||
def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>;
|
||||
def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>;
|
||||
def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
|
||||
def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
|
||||
|
||||
// A logical vector shifter operand:
|
||||
// {7-6} - shift type: 00 = lsl
|
||||
|
@ -671,9 +671,9 @@ def : InstAlias<"tst $src1, $src2",
|
||||
(ANDSXrs XZR, GPR64:$src1, GPR64:$src2, 0)>;
|
||||
|
||||
def : InstAlias<"tst $src1, $src2, $sh",
|
||||
(ANDSWrs WZR, GPR32:$src1, GPR32:$src2, logical_shift:$sh)>;
|
||||
(ANDSWrs WZR, GPR32:$src1, GPR32:$src2, logical_shift32:$sh)>;
|
||||
def : InstAlias<"tst $src1, $src2, $sh",
|
||||
(ANDSXrs XZR, GPR64:$src1, GPR64:$src2, logical_shift:$sh)>;
|
||||
(ANDSXrs XZR, GPR64:$src1, GPR64:$src2, logical_shift64:$sh)>;
|
||||
|
||||
def : InstAlias<"mvn $Wd, $Wm",
|
||||
(ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, 0)>;
|
||||
@ -681,9 +681,9 @@ def : InstAlias<"mvn $Xd, $Xm",
|
||||
(ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, 0)>;
|
||||
|
||||
def : InstAlias<"mvn $Wd, $Wm, $sh",
|
||||
(ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, logical_shift:$sh)>;
|
||||
(ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, logical_shift32:$sh)>;
|
||||
def : InstAlias<"mvn $Xd, $Xm, $sh",
|
||||
(ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, logical_shift:$sh)>;
|
||||
(ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, logical_shift64:$sh)>;
|
||||
|
||||
def : Pat<(not GPR32:$Wm), (ORNWrr WZR, GPR32:$Wm)>;
|
||||
def : Pat<(not GPR64:$Xm), (ORNXrr XZR, GPR64:$Xm)>;
|
||||
|
@ -845,6 +845,18 @@ public:
|
||||
ST == ARM64_AM::ASR) && ARM64_AM::getShiftValue(Shifter.Val) < width;
|
||||
}
|
||||
|
||||
template <unsigned width>
|
||||
bool isLogicalShifter() const {
|
||||
if (!isShifter())
|
||||
return false;
|
||||
|
||||
// A logical shifter is LSL, LSR, ASR or ROR.
|
||||
ARM64_AM::ShiftType ST = ARM64_AM::getShiftType(Shifter.Val);
|
||||
return (ST == ARM64_AM::LSL || ST == ARM64_AM::LSR ||
|
||||
ST == ARM64_AM::ASR || ST == ARM64_AM::ROR) &&
|
||||
ARM64_AM::getShiftValue(Shifter.Val) < width;
|
||||
}
|
||||
|
||||
bool isMovImm32Shifter() const {
|
||||
if (!isShifter())
|
||||
return false;
|
||||
@ -1453,6 +1465,11 @@ public:
|
||||
Inst.addOperand(MCOperand::CreateImm(getShifter()));
|
||||
}
|
||||
|
||||
void addLogicalShifterOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateImm(getShifter()));
|
||||
}
|
||||
|
||||
void addMovImm32ShifterOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateImm(getShifter()));
|
||||
@ -3677,18 +3694,6 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst,
|
||||
// in the instructions being checked and this keeps the nested conditionals
|
||||
// to a minimum.
|
||||
switch (Inst.getOpcode()) {
|
||||
case ARM64::ANDWrs:
|
||||
case ARM64::ANDSWrs:
|
||||
case ARM64::EORWrs:
|
||||
case ARM64::ORRWrs: {
|
||||
if (!Inst.getOperand(3).isImm())
|
||||
return Error(Loc[3], "immediate value expected");
|
||||
int64_t shifter = Inst.getOperand(3).getImm();
|
||||
ARM64_AM::ShiftType ST = ARM64_AM::getShiftType(shifter);
|
||||
if (ST == ARM64_AM::LSL && shifter > 31)
|
||||
return Error(Loc[3], "shift value out of range");
|
||||
return false;
|
||||
}
|
||||
case ARM64::ADDSWri:
|
||||
case ARM64::ADDSXri:
|
||||
case ARM64::ADDWri:
|
||||
|
@ -182,19 +182,19 @@ foo:
|
||||
|
||||
; logical instructions on 32-bit regs with shift > 31 is not legal
|
||||
orr w0, w0, w0, lsl #32
|
||||
; CHECK-ERRORS: error: shift value out of range
|
||||
; CHECK-ERRORS: error: expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]
|
||||
; CHECK-ERRORS: orr w0, w0, w0, lsl #32
|
||||
; CHECK-ERRORS: ^
|
||||
eor w0, w0, w0, lsl #32
|
||||
; CHECK-ERRORS: error: shift value out of range
|
||||
; CHECK-ERRORS: error: expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]
|
||||
; CHECK-ERRORS: eor w0, w0, w0, lsl #32
|
||||
; CHECK-ERRORS: ^
|
||||
and w0, w0, w0, lsl #32
|
||||
; CHECK-ERRORS: error: shift value out of range
|
||||
; CHECK-ERRORS: error: expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]
|
||||
; CHECK-ERRORS: and w0, w0, w0, lsl #32
|
||||
; CHECK-ERRORS: ^
|
||||
ands w0, w0, w0, lsl #32
|
||||
; CHECK-ERRORS: error: shift value out of range
|
||||
; CHECK-ERRORS: error: expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]
|
||||
; CHECK-ERRORS: ands w0, w0, w0, lsl #32
|
||||
; CHECK-ERRORS: ^
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user