From: Venkatraman Govindaraju Date: Sat, 1 Mar 2014 07:46:33 +0000 (+0000) Subject: [Sparc] Add support to disassemble sparc memory instructions. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=06f2e69c2f43b22b6030b1e8992a636f5fee88d8;p=oota-llvm.git [Sparc] Add support to disassemble sparc memory instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202575 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp index 6233805431c..ae07e0b4f74 100644 --- a/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ b/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -174,6 +174,22 @@ static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder); +static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder); +static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder); +static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder); +static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn, + uint64_t Address, const void *Decoder); +static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn, + uint64_t Address, const void *Decoder); +static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn, + uint64_t Address, const void *Decoder); +static DecodeStatus DecodeStoreQFP(MCInst &Inst, unsigned insn, + uint64_t Address, const void *Decoder); #include "SparcGenDisassemblerTables.inc" @@ -226,3 +242,97 @@ SparcDisassembler::getInstruction(MCInst &instr, return MCDisassembler::Fail; } + + +typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeMem(MCInst &MI, unsigned insn, uint64_t Address, + const void *Decoder, + bool isLoad, DecodeFunc DecodeRD) { + unsigned rd = fieldFromInstruction(insn, 25, 5); + unsigned rs1 = fieldFromInstruction(insn, 14, 5); + bool isImm = fieldFromInstruction(insn, 13, 1); + unsigned rs2 = 0; + unsigned simm13 = 0; + if (isImm) + simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); + else + rs2 = fieldFromInstruction(insn, 0, 5); + + DecodeStatus status; + if (isLoad) { + status = DecodeRD(MI, rd, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + } + + // Decode rs1. + status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + + // Decode imm|rs2. + if (isImm) + MI.addOperand(MCOperand::CreateImm(simm13)); + else { + status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + } + + if (!isLoad) { + status = DecodeRD(MI, rd, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + } + return MCDisassembler::Success; +} + +static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, true, + DecodeIntRegsRegisterClass); +} + +static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, true, + DecodeFPRegsRegisterClass); +} + +static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, true, + DecodeDFPRegsRegisterClass); +} + +static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, true, + DecodeQFPRegsRegisterClass); +} + +static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn, + uint64_t Address, const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, false, + DecodeIntRegsRegisterClass); +} + +static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, false, + DecodeFPRegsRegisterClass); +} + +static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn, + uint64_t Address, const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, false, + DecodeDFPRegsRegisterClass); +} + +static DecodeStatus DecodeStoreQFP(MCInst &Inst, unsigned insn, + uint64_t Address, const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, false, + DecodeQFPRegsRegisterClass); +} diff --git a/lib/Target/Sparc/SparcInstr64Bit.td b/lib/Target/Sparc/SparcInstr64Bit.td index a5b48f90340..77b394dd7c9 100644 --- a/lib/Target/Sparc/SparcInstr64Bit.td +++ b/lib/Target/Sparc/SparcInstr64Bit.td @@ -235,7 +235,8 @@ def UDIVXri : F3_2<2, 0b001101, let Predicates = [Is64Bit] in { // 64-bit loads. -defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>; +let DecoderMethod = "DecodeLoadInt" in + defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>; let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in def TLS_LDXrr : F3_1<3, 0b001011, @@ -270,10 +271,12 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>; def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>; // Sign-extending load of i32 into i64 is a new SPARC v9 instruction. -defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>; +let DecoderMethod = "DecodeLoadInt" in + defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>; // 64-bit stores. -defm STX : Store<"stx", 0b001110, store, I64Regs, i64>; +let DecoderMethod = "DecodeStoreInt" in + defm STX : Store<"stx", 0b001110, store, I64Regs, i64>; // Truncating stores from i64 are identical to the i32 stores. def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>; diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index ae10ca0bd41..57b692562e4 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -387,28 +387,38 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, } // Section B.1 - Load Integer Instructions, p. 90 -defm LDSB : Load<"ldsb", 0b001001, sextloadi8, IntRegs, i32>; -defm LDSH : Load<"ldsh", 0b001010, sextloadi16, IntRegs, i32>; -defm LDUB : Load<"ldub", 0b000001, zextloadi8, IntRegs, i32>; -defm LDUH : Load<"lduh", 0b000010, zextloadi16, IntRegs, i32>; -defm LD : Load<"ld", 0b000000, load, IntRegs, i32>; +let DecoderMethod = "DecodeLoadInt" in { + defm LDSB : Load<"ldsb", 0b001001, sextloadi8, IntRegs, i32>; + defm LDSH : Load<"ldsh", 0b001010, sextloadi16, IntRegs, i32>; + defm LDUB : Load<"ldub", 0b000001, zextloadi8, IntRegs, i32>; + defm LDUH : Load<"lduh", 0b000010, zextloadi16, IntRegs, i32>; + defm LD : Load<"ld", 0b000000, load, IntRegs, i32>; +} // Section B.2 - Load Floating-point Instructions, p. 92 -defm LDF : Load<"ld", 0b100000, load, FPRegs, f32>; -defm LDDF : Load<"ldd", 0b100011, load, DFPRegs, f64>; -defm LDQF : Load<"ldq", 0b100010, load, QFPRegs, f128>, - Requires<[HasV9, HasHardQuad]>; +let DecoderMethod = "DecodeLoadFP" in + defm LDF : Load<"ld", 0b100000, load, FPRegs, f32>; +let DecoderMethod = "DecodeLoadDFP" in + defm LDDF : Load<"ldd", 0b100011, load, DFPRegs, f64>; +let DecoderMethod = "DecodeLoadQFP" in + defm LDQF : Load<"ldq", 0b100010, load, QFPRegs, f128>, + Requires<[HasV9, HasHardQuad]>; // Section B.4 - Store Integer Instructions, p. 95 -defm STB : Store<"stb", 0b000101, truncstorei8, IntRegs, i32>; -defm STH : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>; -defm ST : Store<"st", 0b000100, store, IntRegs, i32>; +let DecoderMethod = "DecodeStoreInt" in { + defm STB : Store<"stb", 0b000101, truncstorei8, IntRegs, i32>; + defm STH : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>; + defm ST : Store<"st", 0b000100, store, IntRegs, i32>; +} // Section B.5 - Store Floating-point Instructions, p. 97 -defm STF : Store<"st", 0b100100, store, FPRegs, f32>; -defm STDF : Store<"std", 0b100111, store, DFPRegs, f64>; -defm STQF : Store<"stq", 0b100110, store, QFPRegs, f128>, - Requires<[HasV9, HasHardQuad]>; +let DecoderMethod = "DecodeStoreFP" in + defm STF : Store<"st", 0b100100, store, FPRegs, f32>; +let DecoderMethod = "DecodeStoreDFP" in + defm STDF : Store<"std", 0b100111, store, DFPRegs, f64>; +let DecoderMethod = "DecodeStoreQFP" in + defm STQF : Store<"stq", 0b100110, store, QFPRegs, f128>, + Requires<[HasV9, HasHardQuad]>; // Section B.9 - SETHI Instruction, p. 104 def SETHIi: F2_1<0b100, diff --git a/test/MC/Disassembler/Sparc/sparc-mem.txt b/test/MC/Disassembler/Sparc/sparc-mem.txt new file mode 100644 index 00000000000..37222476415 --- /dev/null +++ b/test/MC/Disassembler/Sparc/sparc-mem.txt @@ -0,0 +1,154 @@ +# RUN: llvm-mc --disassemble %s -triple=sparcv9-unknown-linux | FileCheck %s + +# CHECK: ldsb [%i0+%l6], %o2 +0xd4 0x4e 0x00 0x16 + +# CHECK: ldsb [%i0+32], %o2 +0xd4 0x4e 0x20 0x20 + +# CHECK: ldsb [%g1], %o4 +0xd8 0x48 0x60 0x00 + +# CHECK: ldsh [%i0+%l6], %o2 +0xd4 0x56 0x00 0x16 + +# CHECK: ldsh [%i0+32], %o2 +0xd4 0x56 0x20 0x20 + +# CHECK: ldsh [%g1], %o4 +0xd8 0x50 0x60 0x00 + +# CHECK: ldub [%i0+%l6], %o2 +0xd4 0x0e 0x00 0x16 + +# CHECK: ldub [%i0+32], %o2 +0xd4 0x0e 0x20 0x20 + +# CHECK: ldub [%g1], %o2 +0xd4 0x08 0x60 0x00 + +# CHECK: lduh [%i0+%l6], %o2 +0xd4 0x16 0x00 0x16 + +# CHECK: lduh [%i0+32], %o2 +0xd4 0x16 0x20 0x20 + +# CHECK: lduh [%g1], %o2 +0xd4 0x10 0x60 0x00 + +# CHECK: ld [%i0+%l6], %o2 +0xd4 0x06 0x00 0x16 + +# CHECK: ld [%i0+32], %o2 +0xd4 0x06 0x20 0x20 + +# CHECK: ld [%g1], %o2 +0xd4 0x00 0x60 0x00 + +# CHECK: ld [%i0+%l6], %f2 +0xc5 0x06 0x00 0x16 + +# CHECK: ld [%i0+32], %f2 +0xc5 0x06 0x20 0x20 + +# CHECK: ld [%g1], %f2 +0xc5 0x00 0x60 0x00 + +# CHECK: ldd [%i0+%l6], %f2 +0xc5 0x1e 0x00 0x16 + +# CHECK: ldd [%i0+32], %f2 +0xc5 0x1e 0x20 0x20 + +# CHECK: ldd [%g1], %f2 +0xc5 0x18 0x60 0x00 + +# CHECK: ldq [%i0+%l6], %f4 +0xc9 0x16 0x00 0x16 + +# CHECK: ldq [%i0+32], %f4 +0xc9 0x16 0x20 0x20 + +# CHECK: ldq [%g1], %f4 +0xc9 0x10 0x60 0x00 + +# CHECK: ldx [%i0+%l6], %o2 +0xd4 0x5e 0x00 0x16 + +# CHECK: ldx [%i0+32], %o2 +0xd4 0x5e 0x20 0x20 + +# CHECK: ldx [%g1], %o2 +0xd4 0x58 0x60 0x00 + +# CHECK: ldsw [%i0+%l6], %o2 +0xd4 0x46 0x00 0x16 + +# CHECK: ldsw [%i0+32], %o2 +0xd4 0x46 0x20 0x20 + +# CHECK: ldsw [%g1], %o2 +0xd4 0x40 0x60 0x00 + +# CHECK: stb %o2, [%i0+%l6] +0xd4 0x2e 0x00 0x16 + +# CHECK: stb %o2, [%i0+32] +0xd4 0x2e 0x20 0x20 + +# CHECK: stb %o2, [%g1] +0xd4 0x28 0x60 0x00 + +# CHECK: sth %o2, [%i0+%l6] +0xd4 0x36 0x00 0x16 + +# CHECK: sth %o2, [%i0+32] +0xd4 0x36 0x20 0x20 + +# CHECK: sth %o2, [%g1] +0xd4 0x30 0x60 0x00 + +# CHECK: st %o2, [%i0+%l6] +0xd4 0x26 0x00 0x16 + +# CHECK: st %o2, [%i0+32] +0xd4 0x26 0x20 0x20 + +# CHECK: st %o2, [%g1] +0xd4 0x20 0x60 0x00 + +# CHECK: st %f2, [%i0+%l6] +0xc5 0x26 0x00 0x16 + +# CHECK: st %f2, [%i0+32] +0xc5 0x26 0x20 0x20 + +# CHECK: st %f2, [%g1] +0xc5 0x20 0x60 0x00 + +# CHECK: std %f2, [%i0+%l6] +0xc5 0x3e 0x00 0x16 + +# CHECK: std %f2, [%i0+32] +0xc5 0x3e 0x20 0x20 + +# CHECK: std %f2, [%g1] +0xc5 0x38 0x60 0x00 + +# CHECK: stq %f4, [%i0+%l6] +0xc9 0x36 0x00 0x16 + +# CHECK: stq %f4, [%i0+32] +0xc9 0x36 0x20 0x20 + +# CHECK: stq %f4, [%g1] +0xc9 0x30 0x60 0x00 + +# CHECK: stx %o2, [%i0+%l6] +0xd4 0x76 0x00 0x16 + +# CHECK: stx %o2, [%i0+32] +0xd4 0x76 0x20 0x20 + +# CHECK: stx %o2, [%g1] +0xd4 0x70 0x60 0x00