Index: llvm/trunk/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h =================================================================== --- llvm/trunk/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h +++ llvm/trunk/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h @@ -69,13 +69,22 @@ MCOperand decodeOperand_SReg_256(unsigned Val) const; MCOperand decodeOperand_SReg_512(unsigned Val) const; - enum { OP32 = true, OP64 = false }; + enum OpWidthTy { + OPW32, + OPW64, + OPW128, + OPW_LAST_, + OPW_FIRST_ = OPW32 + }; + unsigned getVgprClassId(const OpWidthTy Width) const; + unsigned getSgprClassId(const OpWidthTy Width) const; + unsigned getTtmpClassId(const OpWidthTy Width) const; static MCOperand decodeIntImmed(unsigned Imm); static MCOperand decodeFPImmed(bool Is32, unsigned Imm); MCOperand decodeLiteralConstant() const; - MCOperand decodeSrcOp(bool Is32, unsigned Val) const; + MCOperand decodeSrcOp(const OpWidthTy Width, unsigned Val) const; MCOperand decodeSpecialReg32(unsigned Val) const; MCOperand decodeSpecialReg64(unsigned Val) const; }; Index: llvm/trunk/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp +++ llvm/trunk/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp @@ -20,6 +20,7 @@ #include "AMDGPUDisassembler.h" #include "AMDGPU.h" #include "AMDGPURegisterInfo.h" +#include "SIDefines.h" #include "Utils/AMDGPUBaseInfo.h" #include "llvm/MC/MCContext.h" @@ -193,19 +194,27 @@ int shift = 0; switch (SRegClassID) { case AMDGPU::SGPR_32RegClassID: - case AMDGPU::SReg_32RegClassID: break; + case AMDGPU::TTMP_32RegClassID: + break; case AMDGPU::SGPR_64RegClassID: - case AMDGPU::SReg_64RegClassID: shift = 1; break; - case AMDGPU::SReg_128RegClassID: + case AMDGPU::TTMP_64RegClassID: + shift = 1; + break; + case AMDGPU::SGPR_128RegClassID: + case AMDGPU::TTMP_128RegClassID: // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in // this bundle? case AMDGPU::SReg_256RegClassID: // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in // this bundle? - case AMDGPU::SReg_512RegClassID: shift = 2; break; + case AMDGPU::SReg_512RegClassID: + shift = 2; + break; // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in // this bundle? - default: assert(false); break; + default: + assert(false); + break; } if (Val % (1 << shift)) *CommentStream << "Warning: " << getRegClassName(SRegClassID) @@ -214,11 +223,11 @@ } MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const { - return decodeSrcOp(OP32, Val); + return decodeSrcOp(OPW32, Val); } MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const { - return decodeSrcOp(OP64, Val); + return decodeSrcOp(OPW64, Val); } MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const { @@ -241,7 +250,7 @@ // table-gen generated disassembler doesn't care about operand types // leaving only registry class so SSrc_32 operand turns into SReg_32 // and therefore we accept immediates and literals here as well - return decodeSrcOp(OP32, Val); + return decodeSrcOp(OPW32, Val); } MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0(unsigned Val) const { @@ -251,11 +260,11 @@ MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const { // see decodeOperand_SReg_32 comment - return decodeSrcOp(OP64, Val); + return decodeSrcOp(OPW64, Val); } MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const { - return createSRegOperand(AMDGPU::SReg_128RegClassID, Val); + return decodeSrcOp(OPW128, Val); } MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const { @@ -278,12 +287,17 @@ } MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) { - assert(Imm >= 128 && Imm <= 208); - return MCOperand::createImm((Imm <= 192) ? (Imm - 128) : (192 - Imm)); + using namespace AMDGPU::EncValues; + assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX); + return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ? + (static_cast(Imm) - INLINE_INTEGER_C_MIN) : + (INLINE_INTEGER_C_POSITIVE_MAX - static_cast(Imm))); + // Cast prevents negative overflow. } MCOperand AMDGPUDisassembler::decodeFPImmed(bool Is32, unsigned Imm) { - assert(Imm >= 240 && Imm <= 248); + assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN + && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX); // ToDo: case 248: 1/(2*PI) - is allowed only on VI // ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as // literal constant. @@ -305,24 +319,63 @@ return MCOperand::createImm(Is32? FloatToBits(V) : DoubleToBits(V)); } -MCOperand AMDGPUDisassembler::decodeSrcOp(bool Is32, unsigned Val) const { +unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const { using namespace AMDGPU; + assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); + switch (Width) { + default: // fall + case OPW32: return VGPR_32RegClassID; + case OPW64: return VReg_64RegClassID; + case OPW128: return VReg_128RegClassID; + } +} + +unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const { + using namespace AMDGPU; + assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); + switch (Width) { + default: // fall + case OPW32: return SGPR_32RegClassID; + case OPW64: return SGPR_64RegClassID; + case OPW128: return SGPR_128RegClassID; + } +} + +unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const { + using namespace AMDGPU; + assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); + switch (Width) { + default: // fall + case OPW32: return TTMP_32RegClassID; + case OPW64: return TTMP_64RegClassID; + case OPW128: return TTMP_128RegClassID; + } +} + +MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val) const { + using namespace AMDGPU::EncValues; assert(Val < 512); // enum9 - if (Val >= 256) - return createRegOperand(Is32 ? VGPR_32RegClassID : VReg_64RegClassID, - Val - 256); - if (Val <= 101) - return createSRegOperand(Is32 ? SGPR_32RegClassID : SGPR_64RegClassID, - Val); + if (VGPR_MIN <= Val && Val <= VGPR_MAX) { + return createRegOperand(getVgprClassId(Width), Val - VGPR_MIN); + } + if (SGPR_MIN <= Val && Val <= SGPR_MAX) { + return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN); + } + if (TTMP_MIN <= Val && Val <= TTMP_MAX) { + return createSRegOperand(getTtmpClassId(Width), Val - TTMP_MIN); + } + + assert(Width == OPW32 || Width == OPW64); + const bool Is32 = (Width == OPW32); - if (Val >= 128 && Val <= 208) + if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX) return decodeIntImmed(Val); - if (Val >= 240 && Val <= 248) + if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX) return decodeFPImmed(Is32, Val); - if (Val == 255) + if (Val == LITERAL_CONST) return decodeLiteralConstant(); return Is32 ? decodeSpecialReg32(Val) : decodeSpecialReg64(Val); @@ -338,25 +391,10 @@ case 105: break; case 106: return createRegOperand(VCC_LO); case 107: return createRegOperand(VCC_HI); - // ToDo: no support for tba_lo/_hi register - case 108: - case 109: break; - // ToDo: no support for tma_lo/_hi register - case 110: - case 111: break; - // ToDo: no support for ttmp[0:11] register - case 112: - case 113: - case 114: - case 115: - case 116: - case 117: - case 118: - case 119: - case 120: - case 121: - case 122: - case 123: break; + case 108: return createRegOperand(TBA_LO); + case 109: return createRegOperand(TBA_HI); + case 110: return createRegOperand(TMA_LO); + case 111: return createRegOperand(TMA_HI); case 124: return createRegOperand(M0); case 126: return createRegOperand(EXEC_LO); case 127: return createRegOperand(EXEC_HI); @@ -375,6 +413,8 @@ switch (Val) { case 102: return createRegOperand(getMCReg(FLAT_SCR, STI)); case 106: return createRegOperand(VCC); + case 108: return createRegOperand(TBA); + case 110: return createRegOperand(TMA); case 126: return createRegOperand(EXEC); default: break; } Index: llvm/trunk/lib/Target/AMDGPU/SIDefines.h =================================================================== --- llvm/trunk/lib/Target/AMDGPU/SIDefines.h +++ llvm/trunk/lib/Target/AMDGPU/SIDefines.h @@ -97,6 +97,29 @@ namespace llvm { namespace AMDGPU { +namespace EncValues { // Encoding values of enum9/8/7 operands + +enum { + SGPR_MIN = 0, + SGPR_MAX = 101, + TTMP_MIN = 112, + TTMP_MAX = 123, + INLINE_INTEGER_C_MIN = 128, + INLINE_INTEGER_C_POSITIVE_MAX = 192, // 64 + INLINE_INTEGER_C_MAX = 208, + INLINE_FLOATING_C_MIN = 240, + INLINE_FLOATING_C_MAX = 248, + LITERAL_CONST = 255, + VGPR_MIN = 256, + VGPR_MAX = 511 +}; + +} // namespace EncValues +} // namespace AMDGPU +} // namespace llvm + +namespace llvm { +namespace AMDGPU { namespace SendMsg { // Encoding of SIMM16 used in s_sendmsg* insns. enum Id { // Message ID, width(3) [3:0]. Index: llvm/trunk/test/MC/Disassembler/AMDGPU/trap_vi.txt =================================================================== --- llvm/trunk/test/MC/Disassembler/AMDGPU/trap_vi.txt +++ llvm/trunk/test/MC/Disassembler/AMDGPU/trap_vi.txt @@ -0,0 +1,109 @@ +# RUN: llvm-mc -arch=amdgcn -mcpu=tonga -disassemble -show-encoding < %s | FileCheck %s -check-prefix=VI + +#===----------------------------------------------------------------------===# +# Trap Handler related - 32 bit registers +#===----------------------------------------------------------------------===# + +# VI: s_add_u32 ttmp0, ttmp0, 4 ; encoding: [0x70,0x84,0x70,0x80] +0x70,0x84,0x70,0x80 + +# VI: s_add_u32 ttmp4, 8, ttmp4 ; encoding: [0x88,0x74,0x74,0x80] +0x88,0x74,0x74,0x80 + +# VI: s_add_u32 ttmp4, ttmp4, 0x100 ; encoding: [0x74,0xff,0x74,0x80,0x00,0x01,0x00,0x00] +0x74,0xff,0x74,0x80,0x00,0x01,0x00,0x00 + +# VI: s_add_u32 ttmp4, ttmp4, 4 ; encoding: [0x74,0x84,0x74,0x80] +0x74,0x84,0x74,0x80 + +# VI: s_add_u32 ttmp4, ttmp8, ttmp4 ; encoding: [0x78,0x74,0x74,0x80] +0x78,0x74,0x74,0x80 + +# VI: s_and_b32 ttmp10, ttmp8, 0x80 ; encoding: [0x78,0xff,0x7a,0x86,0x80,0x00,0x00,0x00] +0x78,0xff,0x7a,0x86,0x80,0x00,0x00,0x00 + +# VI: s_and_b32 ttmp9, tma_hi, 0xffff ; encoding: [0x6f,0xff,0x79,0x86,0xff,0xff,0x00,0x00] +0x6f,0xff,0x79,0x86,0xff,0xff,0x00,0x00 + +# VI: s_and_b32 ttmp9, ttmp9, 0x1ff ; encoding: [0x79,0xff,0x79,0x86,0xff,0x01,0x00,0x00] +0x79,0xff,0x79,0x86,0xff,0x01,0x00,0x00 + +# VI: s_and_b32 ttmp9, tma_lo, 0xffff0000 ; encoding: [0x6e,0xff,0x79,0x86,0x00,0x00,0xff,0xff] +0x6e,0xff,0x79,0x86,0x00,0x00,0xff,0xff + +# VI: s_and_b32 ttmp9, ttmp9, ttmp8 ; encoding: [0x79,0x78,0x79,0x86] +0x79,0x78,0x79,0x86 + +# VI: s_and_b32 ttmp8, ttmp1, 0x1000000 ; encoding: [0x71,0xff,0x78,0x86,0x00,0x00,0x00,0x01] +0x71,0xff,0x78,0x86,0x00,0x00,0x00,0x01 + +# VI: s_cmp_eq_i32 ttmp8, 0 ; encoding: [0x78,0x80,0x00,0xbf] +0x78,0x80,0x00,0xbf + +# VI: s_cmp_eq_i32 ttmp8, 0xfe ; encoding: [0x78,0xff,0x00,0xbf,0xfe,0x00,0x00,0x00] +0x78,0xff,0x00,0xbf,0xfe,0x00,0x00,0x00 + +# VI: s_lshr_b32 ttmp8, ttmp8, 12 ; encoding: [0x78,0x8c,0x78,0x8f] +0x78,0x8c,0x78,0x8f + +# VI: v_mov_b32_e32 v1, ttmp8 ; encoding: [0x78,0x02,0x02,0x7e] +0x78,0x02,0x02,0x7e + +# VI: s_mov_b32 m0, ttmp8 ; encoding: [0x78,0x00,0xfc,0xbe] +0x78,0x00,0xfc,0xbe + +# VI: s_mov_b32 ttmp10, 0 ; encoding: [0x80,0x00,0xfa,0xbe] +0x80,0x00,0xfa,0xbe + +# VI: s_mov_b32 ttmp11, 0x1024fac ; encoding: [0xff,0x00,0xfb,0xbe,0xac,0x4f,0x02,0x01] +0xff,0x00,0xfb,0xbe,0xac,0x4f,0x02,0x01 + +# VI: s_mov_b32 ttmp8, m0 ; encoding: [0x7c,0x00,0xf8,0xbe] +0x7c,0x00,0xf8,0xbe + +# VI: s_mov_b32 ttmp8, tma_lo ; encoding: [0x6e,0x00,0xf8,0xbe] +0x6e,0x00,0xf8,0xbe + +# VI: s_mul_i32 ttmp8, 0x324, ttmp8 ; encoding: [0xff,0x78,0x78,0x92,0x24,0x03,0x00,0x00] +0xff,0x78,0x78,0x92,0x24,0x03,0x00,0x00 + +# VI: s_or_b32 ttmp9, ttmp9, 0x280000 ; encoding: [0x79,0xff,0x79,0x87,0x00,0x00,0x28,0x00] +0x79,0xff,0x79,0x87,0x00,0x00,0x28,0x00 + +#===----------------------------------------------------------------------===# +# Trap Handler related - Pairs and quadruples of registers +#===----------------------------------------------------------------------===# + +# VI: s_mov_b64 ttmp[4:5], exec ; encoding: [0x7e,0x01,0xf4,0xbe] +0x7e,0x01,0xf4,0xbe + +# VI: s_mov_b64 ttmp[4:5], exec ; encoding: [0x7e,0x01,0xf4,0xbe] +0x7e,0x01,0xf4,0xbe + +# VI: s_mov_b64 exec, ttmp[4:5] ; encoding: [0x74,0x01,0xfe,0xbe] +0x74,0x01,0xfe,0xbe + +# VI: s_mov_b64 tba, ttmp[4:5] ; encoding: [0x74,0x01,0xec,0xbe] +0x74,0x01,0xec,0xbe + +# VI: s_mov_b64 ttmp[4:5], tba ; encoding: [0x6c,0x01,0xf4,0xbe] +0x6c,0x01,0xf4,0xbe + +# VI: s_mov_b64 tma, ttmp[4:5] ; encoding: [0x74,0x01,0xee,0xbe] +0x74,0x01,0xee,0xbe + +# VI: s_mov_b64 ttmp[4:5], tma ; encoding: [0x6e,0x01,0xf4,0xbe] +0x6e,0x01,0xf4,0xbe + +#===----------------------------------------------------------------------===# +# Trap Handler related - Some specific instructions +#===----------------------------------------------------------------------===# + +# VI: s_setpc_b64 ttmp[2:3] ; encoding: [0x72,0x1d,0x80,0xbe] +0x72,0x1d,0x80,0xbe + +# VI: v_readfirstlane_b32 ttmp8, v1 ; encoding: [0x01,0x05,0xf0,0x7e] +0x01,0x05,0xf0,0x7e + +# VI: buffer_atomic_inc v1, off, ttmp[8:11], 56 glc ; encoding: [0x00,0x40,0x2c,0xe1,0x00,0x01,0x1e,0xb8] +0x00,0x40,0x2c,0xe1,0x00,0x01,0x1e,0xb8