mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-20 02:58:10 +00:00
MC/X86: Subdivide immediates a bit more, so that we properly recognize immediates based on the width of the target instruction. For example:
addw $0xFFFF, %ax should match the same as addw $-1, %ax but we used to match it to the longer encoding. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@104453 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
54ddf3d9c7
commit
62e4c671b6
@ -186,32 +186,71 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
|
||||
bool isImm() const { return Kind == Immediate; }
|
||||
|
||||
bool isImmSExt8() const {
|
||||
// Accept immediates which fit in 8 bits when sign extended, and
|
||||
// non-absolute immediates.
|
||||
bool isImmSExti16i8() const {
|
||||
if (!isImm())
|
||||
return false;
|
||||
|
||||
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) {
|
||||
int64_t Value = CE->getValue();
|
||||
return Value == (int64_t) (int8_t) Value;
|
||||
}
|
||||
// If this isn't a constant expr, just assume it fits and let relaxation
|
||||
// handle it.
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
if (!CE)
|
||||
return true;
|
||||
|
||||
return true;
|
||||
// Otherwise, check the value is in a range that makes sense for this
|
||||
// extension.
|
||||
uint64_t Value = CE->getValue();
|
||||
return (( Value <= 0x000000000000007FULL)||
|
||||
(0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
|
||||
(0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
|
||||
}
|
||||
|
||||
bool isImmSExt32() const {
|
||||
// Accept immediates which fit in 32 bits when sign extended, and
|
||||
// non-absolute immediates.
|
||||
bool isImmSExti32i8() const {
|
||||
if (!isImm())
|
||||
return false;
|
||||
|
||||
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) {
|
||||
int64_t Value = CE->getValue();
|
||||
return Value == (int64_t) (int32_t) Value;
|
||||
}
|
||||
// If this isn't a constant expr, just assume it fits and let relaxation
|
||||
// handle it.
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
if (!CE)
|
||||
return true;
|
||||
|
||||
return true;
|
||||
// Otherwise, check the value is in a range that makes sense for this
|
||||
// extension.
|
||||
uint64_t Value = CE->getValue();
|
||||
return (( Value <= 0x000000000000007FULL)||
|
||||
(0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
|
||||
(0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
|
||||
}
|
||||
bool isImmSExti64i8() const {
|
||||
if (!isImm())
|
||||
return false;
|
||||
|
||||
// If this isn't a constant expr, just assume it fits and let relaxation
|
||||
// handle it.
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
if (!CE)
|
||||
return true;
|
||||
|
||||
// Otherwise, check the value is in a range that makes sense for this
|
||||
// extension.
|
||||
uint64_t Value = CE->getValue();
|
||||
return (( Value <= 0x000000000000007FULL)||
|
||||
(0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
|
||||
}
|
||||
bool isImmSExti64i32() const {
|
||||
if (!isImm())
|
||||
return false;
|
||||
|
||||
// If this isn't a constant expr, just assume it fits and let relaxation
|
||||
// handle it.
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
if (!CE)
|
||||
return true;
|
||||
|
||||
// Otherwise, check the value is in a range that makes sense for this
|
||||
// extension.
|
||||
uint64_t Value = CE->getValue();
|
||||
return (( Value <= 0x000000007FFFFFFFULL)||
|
||||
(0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
|
||||
}
|
||||
|
||||
bool isMem() const { return Kind == Memory; }
|
||||
@ -245,18 +284,6 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
addExpr(Inst, getImm());
|
||||
}
|
||||
|
||||
void addImmSExt8Operands(MCInst &Inst, unsigned N) const {
|
||||
// FIXME: Support user customization of the render method.
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
addExpr(Inst, getImm());
|
||||
}
|
||||
|
||||
void addImmSExt32Operands(MCInst &Inst, unsigned N) const {
|
||||
// FIXME: Support user customization of the render method.
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
addExpr(Inst, getImm());
|
||||
}
|
||||
|
||||
void addMemOperands(MCInst &Inst, unsigned N) const {
|
||||
assert((N == 5) && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
// 64-bits but only 32 bits are significant.
|
||||
def i64i32imm : Operand<i64> {
|
||||
let ParserMatchClass = ImmSExt32AsmOperand;
|
||||
let ParserMatchClass = ImmSExti64i32AsmOperand;
|
||||
}
|
||||
|
||||
// 64-bits but only 32 bits are significant, and those bits are treated as being
|
||||
@ -32,7 +32,7 @@ def i64i32imm_pcrel : Operand<i64> {
|
||||
|
||||
// 64-bits but only 8 bits are significant.
|
||||
def i64i8imm : Operand<i64> {
|
||||
let ParserMatchClass = ImmSExt8AsmOperand;
|
||||
let ParserMatchClass = ImmSExti64i8AsmOperand;
|
||||
}
|
||||
|
||||
// Special i64mem for addresses of load folding tail calls. These are not
|
||||
|
@ -270,24 +270,49 @@ def SSECC : Operand<i8> {
|
||||
let PrintMethod = "printSSECC";
|
||||
}
|
||||
|
||||
def ImmSExt32AsmOperand : AsmOperandClass {
|
||||
let Name = "ImmSExt32";
|
||||
class ImmSExtAsmOperandClass : AsmOperandClass {
|
||||
let SuperClasses = [ImmAsmOperand];
|
||||
let RenderMethod = "addImmOperands";
|
||||
}
|
||||
|
||||
def ImmSExt8AsmOperand : AsmOperandClass {
|
||||
let Name = "ImmSExt8";
|
||||
let SuperClasses = [ImmSExt32AsmOperand];
|
||||
// Sign-extended immediate classes. We don't need to define the full lattice
|
||||
// here because there is no instruction with an ambiguity between ImmSExti64i32
|
||||
// and ImmSExti32i8.
|
||||
//
|
||||
// The strange ranges come from the fact that the assembler always works with
|
||||
// 64-bit immediates, but for a 16-bit target value we want to accept both "-1"
|
||||
// (which will be a -1ULL), and "0xFF" (-1 in 16-bits).
|
||||
|
||||
// [0, 0x7FFFFFFF] | [0xFFFFFFFF80000000, 0xFFFFFFFFFFFFFFFF]
|
||||
def ImmSExti64i32AsmOperand : ImmSExtAsmOperandClass {
|
||||
let Name = "ImmSExti64i32";
|
||||
}
|
||||
|
||||
// [0, 0x0000007F] | [0x000000000000FF80, 0x000000000000FFFF] | [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF]
|
||||
def ImmSExti16i8AsmOperand : ImmSExtAsmOperandClass {
|
||||
let Name = "ImmSExti16i8";
|
||||
let SuperClasses = [ImmSExti64i32AsmOperand];
|
||||
}
|
||||
|
||||
// [0, 0x0000007F] | [0x00000000FFFFFF80, 0x00000000FFFFFFFF] | [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF]
|
||||
def ImmSExti32i8AsmOperand : ImmSExtAsmOperandClass {
|
||||
let Name = "ImmSExti32i8";
|
||||
}
|
||||
|
||||
// [0, 0x0000007F] | [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF]
|
||||
def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass {
|
||||
let Name = "ImmSExti64i8";
|
||||
let SuperClasses = [ImmSExti16i8AsmOperand, ImmSExti32i8AsmOperand, ImmSExti64i32AsmOperand];
|
||||
}
|
||||
|
||||
// A couple of more descriptive operand definitions.
|
||||
// 16-bits but only 8 bits are significant.
|
||||
def i16i8imm : Operand<i16> {
|
||||
let ParserMatchClass = ImmSExt8AsmOperand;
|
||||
let ParserMatchClass = ImmSExti16i8AsmOperand;
|
||||
}
|
||||
// 32-bits but only 8 bits are significant.
|
||||
def i32i8imm : Operand<i32> {
|
||||
let ParserMatchClass = ImmSExt8AsmOperand;
|
||||
let ParserMatchClass = ImmSExti32i8AsmOperand;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
105
test/MC/AsmParser/X86/x86_64-imm-widths.s
Normal file
105
test/MC/AsmParser/X86/x86_64-imm-widths.s
Normal file
@ -0,0 +1,105 @@
|
||||
// RUN: llvm-mc -triple x86_64- --show-encoding %s | FileCheck %s
|
||||
|
||||
// CHECK: addb $0, %al
|
||||
// CHECK: encoding: [0x04,0x00]
|
||||
addb $0x00, %al
|
||||
|
||||
// CHECK: addb $127, %al
|
||||
// CHECK: encoding: [0x04,0x7f]
|
||||
addb $0x7F, %al
|
||||
|
||||
// CHECK: addb $128, %al
|
||||
// CHECK: encoding: [0x04,0x80]
|
||||
addb $0x80, %al
|
||||
|
||||
// CHECK: addb $255, %al
|
||||
// CHECK: encoding: [0x04,0xff]
|
||||
addb $0xFF, %al
|
||||
|
||||
// CHECK: addw $0, %ax
|
||||
// CHECK: encoding: [0x66,0x83,0xc0,0x00]
|
||||
addw $0x0000, %ax
|
||||
|
||||
// CHECK: addw $127, %ax
|
||||
// CHECK: encoding: [0x66,0x83,0xc0,0x7f]
|
||||
addw $0x007F, %ax
|
||||
|
||||
// CHECK: addw $65408, %ax
|
||||
// CHECK: encoding: [0x66,0x83,0xc0,0x80]
|
||||
addw $0xFF80, %ax
|
||||
|
||||
// CHECK: addw $65535, %ax
|
||||
// CHECK: encoding: [0x66,0x83,0xc0,0xff]
|
||||
addw $0xFFFF, %ax
|
||||
|
||||
// CHECK: addl $0, %eax
|
||||
// CHECK: encoding: [0x83,0xc0,0x00]
|
||||
addl $0x00000000, %eax
|
||||
|
||||
// CHECK: addl $127, %eax
|
||||
// CHECK: encoding: [0x83,0xc0,0x7f]
|
||||
addl $0x0000007F, %eax
|
||||
|
||||
// CHECK: addl $65408, %eax
|
||||
// CHECK: encoding: [0x05,0x80,0xff,0x00,0x00]
|
||||
addl $0xFF80, %eax
|
||||
|
||||
// CHECK: addl $65535, %eax
|
||||
// CHECK: encoding: [0x05,0xff,0xff,0x00,0x00]
|
||||
addl $0xFFFF, %eax
|
||||
|
||||
// CHECK: addl $4294967168, %eax
|
||||
// CHECK: encoding: [0x83,0xc0,0x80]
|
||||
addl $0xFFFFFF80, %eax
|
||||
|
||||
// CHECK: addl $4294967295, %eax
|
||||
// CHECK: encoding: [0x83,0xc0,0xff]
|
||||
addl $0xFFFFFFFF, %eax
|
||||
|
||||
// CHECK: addq $0, %rax
|
||||
// CHECK: encoding: [0x48,0x83,0xc0,0x00]
|
||||
addq $0x0000000000000000, %rax
|
||||
|
||||
// CHECK: addq $127, %rax
|
||||
// CHECK: encoding: [0x48,0x83,0xc0,0x7f]
|
||||
addq $0x000000000000007F, %rax
|
||||
|
||||
// CHECK: addq $-128, %rax
|
||||
// CHECK: encoding: [0x48,0x83,0xc0,0x80]
|
||||
addq $0xFFFFFFFFFFFFFF80, %rax
|
||||
|
||||
// CHECK: addq $-1, %rax
|
||||
// CHECK: encoding: [0x48,0x83,0xc0,0xff]
|
||||
addq $0xFFFFFFFFFFFFFFFF, %rax
|
||||
|
||||
// CHECK: addq $0, %rax
|
||||
// CHECK: encoding: [0x48,0x83,0xc0,0x00]
|
||||
addq $0x0000000000000000, %rax
|
||||
|
||||
// CHECK: addq $65408, %rax
|
||||
// CHECK: encoding: [0x48,0x05,0x80,0xff,0x00,0x00]
|
||||
addq $0xFF80, %rax
|
||||
|
||||
// CHECK: addq $65535, %rax
|
||||
// CHECK: encoding: [0x48,0x05,0xff,0xff,0x00,0x00]
|
||||
addq $0xFFFF, %rax
|
||||
|
||||
// CHECK: movq $4294967168, %rax
|
||||
// CHECK: encoding: [0x48,0xb8,0x80,0xff,0xff,0xff,0x00,0x00,0x00,0x00]
|
||||
movq $0xFFFFFF80, %rax
|
||||
|
||||
// CHECK: movq $4294967295, %rax
|
||||
// CHECK: encoding: [0x48,0xb8,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00]
|
||||
movq $0xFFFFFFFF, %rax
|
||||
|
||||
// CHECK: addq $2147483647, %rax
|
||||
// CHECK: encoding: [0x48,0x05,0xff,0xff,0xff,0x7f]
|
||||
addq $0x000000007FFFFFFF, %rax
|
||||
|
||||
// CHECK: addq $-2147483648, %rax
|
||||
// CHECK: encoding: [0x48,0x05,0x00,0x00,0x00,0x80]
|
||||
addq $0xFFFFFFFF80000000, %rax
|
||||
|
||||
// CHECK: addq $-256, %rax
|
||||
// CHECK: encoding: [0x48,0x05,0x00,0xff,0xff,0xff]
|
||||
addq $0xFFFFFFFFFFFFFF00, %rax
|
Loading…
Reference in New Issue
Block a user