diff options
| author | Daniel Dunbar <daniel@zuster.org> | 2010-05-22 21:02:33 +0000 | 
|---|---|---|
| committer | Daniel Dunbar <daniel@zuster.org> | 2010-05-22 21:02:33 +0000 | 
| commit | b52fcd6304692a032d796345a75ae427058c5101 (patch) | |
| tree | 291e88d337a4646fcd444ec9aa968385715e84fa | |
| parent | 346782c12ca093fdd5ad99dabbe4a900b8ae29a7 (diff) | |
| download | bcm5719-llvm-b52fcd6304692a032d796345a75ae427058c5101.tar.gz bcm5719-llvm-b52fcd6304692a032d796345a75ae427058c5101.zip  | |
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.
llvm-svn: 104453
| -rw-r--r-- | llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 85 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86Instr64bit.td | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.td | 39 | ||||
| -rw-r--r-- | llvm/test/MC/AsmParser/X86/x86_64-imm-widths.s | 105 | 
4 files changed, 195 insertions, 38 deletions
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index b291ef63b70..25ec6ce150c 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -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())); diff --git a/llvm/lib/Target/X86/X86Instr64bit.td b/llvm/lib/Target/X86/X86Instr64bit.td index 24a1296c163..f2919f54f1b 100644 --- a/llvm/lib/Target/X86/X86Instr64bit.td +++ b/llvm/lib/Target/X86/X86Instr64bit.td @@ -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 diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 5a5535a2db3..6e73766c8cc 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -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;  }  //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AsmParser/X86/x86_64-imm-widths.s b/llvm/test/MC/AsmParser/X86/x86_64-imm-widths.s new file mode 100644 index 00000000000..6243717ba82 --- /dev/null +++ b/llvm/test/MC/AsmParser/X86/x86_64-imm-widths.s @@ -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  | 

