mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 19:31:58 +00:00
[ARM64] Add diagnostics for bitfield extract/insert instructions
Unfortunately, since ARM64 models all these instructions as aliases, the checks need to be done at the time the alias is seen rather than during instruction validation as AArch64 does it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208529 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0ce7616654
commit
f1e04540f6
@ -4181,6 +4181,20 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
uint64_t Op3Val = Op3CE->getValue();
|
||||
uint64_t Op4Val = Op4CE->getValue();
|
||||
|
||||
uint64_t RegWidth = 0;
|
||||
if (ARM64MCRegisterClasses[ARM64::GPR64allRegClassID].contains(
|
||||
Op1->getReg()))
|
||||
RegWidth = 64;
|
||||
else
|
||||
RegWidth = 32;
|
||||
|
||||
if (Op3Val >= RegWidth)
|
||||
return Error(Op3->getStartLoc(),
|
||||
"expected integer in range [0, 31]");
|
||||
if (Op4Val < 1 || Op4Val > RegWidth)
|
||||
return Error(Op4->getStartLoc(),
|
||||
"expected integer in range [1, 32]");
|
||||
|
||||
uint64_t NewOp3Val = 0;
|
||||
if (ARM64MCRegisterClasses[ARM64::GPR32allRegClassID].contains(
|
||||
Op1->getReg()))
|
||||
@ -4190,6 +4204,10 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
|
||||
uint64_t NewOp4Val = Op4Val - 1;
|
||||
|
||||
if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
|
||||
return Error(Op4->getStartLoc(),
|
||||
"requested insert overflows register");
|
||||
|
||||
const MCExpr *NewOp3 =
|
||||
MCConstantExpr::Create(NewOp3Val, getContext());
|
||||
const MCExpr *NewOp4 =
|
||||
@ -4231,28 +4249,45 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
if (Op3CE && Op4CE) {
|
||||
uint64_t Op3Val = Op3CE->getValue();
|
||||
uint64_t Op4Val = Op4CE->getValue();
|
||||
|
||||
uint64_t RegWidth = 0;
|
||||
if (ARM64MCRegisterClasses[ARM64::GPR64allRegClassID].contains(
|
||||
Op1->getReg()))
|
||||
RegWidth = 64;
|
||||
else
|
||||
RegWidth = 32;
|
||||
|
||||
if (Op3Val >= RegWidth)
|
||||
return Error(Op3->getStartLoc(),
|
||||
"expected integer in range [0, 31]");
|
||||
if (Op4Val < 1 || Op4Val > RegWidth)
|
||||
return Error(Op4->getStartLoc(),
|
||||
"expected integer in range [1, 32]");
|
||||
|
||||
uint64_t NewOp4Val = Op3Val + Op4Val - 1;
|
||||
|
||||
if (NewOp4Val >= Op3Val) {
|
||||
const MCExpr *NewOp4 =
|
||||
MCConstantExpr::Create(NewOp4Val, getContext());
|
||||
Operands[4] = ARM64Operand::CreateImm(
|
||||
NewOp4, Op4->getStartLoc(), Op4->getEndLoc(), getContext());
|
||||
if (Tok == "bfxil")
|
||||
Operands[0] = ARM64Operand::CreateToken(
|
||||
"bfm", false, Op->getStartLoc(), getContext());
|
||||
else if (Tok == "sbfx")
|
||||
Operands[0] = ARM64Operand::CreateToken(
|
||||
"sbfm", false, Op->getStartLoc(), getContext());
|
||||
else if (Tok == "ubfx")
|
||||
Operands[0] = ARM64Operand::CreateToken(
|
||||
"ubfm", false, Op->getStartLoc(), getContext());
|
||||
else
|
||||
llvm_unreachable("No valid mnemonic for alias?");
|
||||
if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
|
||||
return Error(Op4->getStartLoc(),
|
||||
"requested extract overflows register");
|
||||
|
||||
delete Op;
|
||||
delete Op4;
|
||||
}
|
||||
const MCExpr *NewOp4 =
|
||||
MCConstantExpr::Create(NewOp4Val, getContext());
|
||||
Operands[4] = ARM64Operand::CreateImm(
|
||||
NewOp4, Op4->getStartLoc(), Op4->getEndLoc(), getContext());
|
||||
if (Tok == "bfxil")
|
||||
Operands[0] = ARM64Operand::CreateToken(
|
||||
"bfm", false, Op->getStartLoc(), getContext());
|
||||
else if (Tok == "sbfx")
|
||||
Operands[0] = ARM64Operand::CreateToken(
|
||||
"sbfm", false, Op->getStartLoc(), getContext());
|
||||
else if (Tok == "ubfx")
|
||||
Operands[0] = ARM64Operand::CreateToken(
|
||||
"ubfm", false, Op->getStartLoc(), getContext());
|
||||
else
|
||||
llvm_unreachable("No valid mnemonic for alias?");
|
||||
|
||||
delete Op;
|
||||
delete Op4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user