diff --git a/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp b/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp index 31063173aab..015efea3437 100644 --- a/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp +++ b/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp @@ -49,6 +49,8 @@ public: }; } +static DecodeStatus DecodeModRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); static DecodeStatus DecodeCtrRegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); @@ -105,6 +107,23 @@ static DecodeStatus DecodeCtrRegsRegisterClass(MCInst &Inst, unsigned RegNo, return MCDisassembler::Success; } +static DecodeStatus DecodeModRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t /*Address*/, const void *Decoder) { + unsigned Register = 0; + switch (RegNo) { + case 0: + Register = Hexagon::M0; + break; + case 1: + Register = Hexagon::M1; + break; + default: + return MCDisassembler::Fail; + } + Inst.addOperand(MCOperand::CreateReg(Register)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeDoubleRegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t /*Address*/, const void *Decoder) { static const uint16_t DoubleRegDecoderTable[] = { diff --git a/lib/Target/Hexagon/HexagonFrameLowering.cpp b/lib/Target/Hexagon/HexagonFrameLowering.cpp index 041eb00dba7..cccdd4e195b 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -161,7 +161,7 @@ void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, // Handle EH_RETURN. if (MBBI->getOpcode() == Hexagon::EH_RETURN_JMPR) { assert(MBBI->getOperand(0).isReg() && "Offset should be in register!"); - BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::L2_deallocframe)); BuildMI(MBB, MBBI, dl, TII.get(Hexagon::A2_add), Hexagon::R29).addReg(Hexagon::R29).addReg(Hexagon::R28); return; @@ -198,7 +198,7 @@ void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4) return; - BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::L2_deallocframe)); } } } diff --git a/lib/Target/Hexagon/HexagonInstrInfo.td b/lib/Target/Hexagon/HexagonInstrInfo.td index b8a81a8023b..0ed527b82cc 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.td +++ b/lib/Target/Hexagon/HexagonInstrInfo.td @@ -1750,14 +1750,108 @@ def LDriw_pred : LDInst2<(outs PredRegs:$dst), "Error; should not emit", []>; -// Deallocate stack frame. -let Defs = [R29, R30, R31], Uses = [R29], hasSideEffects = 0 in { - def DEALLOCFRAME : LDInst2<(outs), (ins), +let Defs = [R29, R30, R31], Uses = [R30], hasSideEffects = 0, isCodeGenOnly = 0 in + def L2_deallocframe : LDInst<(outs), (ins), "deallocframe", - []>; + []> { + let IClass = 0b1001; + + let Inst{27-16} = 0b000000011110; + let Inst{13} = 0b0; + let Inst{4-0} = 0b11110; } -// Load and unpack bytes to halfwords. +// Load / Post increment circular addressing mode. +let Uses = [CS], hasSideEffects = 0, hasNewValue = 1, opNewValue = 0 in +class T_load_pcr MajOp> + : LDInst <(outs RC:$dst, IntRegs:$_dst_), + (ins IntRegs:$Rz, ModRegs:$Mu), + "$dst = "#mnemonic#"($Rz ++ I:circ($Mu))", [], + "$Rz = $_dst_" > { + bits<5> dst; + bits<5> Rz; + bit Mu; + + let IClass = 0b1001; + + let Inst{27-25} = 0b100; + let Inst{24-21} = MajOp; + let Inst{20-16} = Rz; + let Inst{13} = Mu; + let Inst{12} = 0b0; + let Inst{9} = 0b1; + let Inst{7} = 0b0; + let Inst{4-0} = dst; + } + +let accessSize = ByteAccess, isCodeGenOnly = 0 in { + def L2_loadrb_pcr : T_load_pcr <"memb", IntRegs, 0b1000>; + def L2_loadrub_pcr : T_load_pcr <"memub", IntRegs, 0b1001>; +} + +let accessSize = HalfWordAccess, isCodeGenOnly = 0 in { + def L2_loadrh_pcr : T_load_pcr <"memh", IntRegs, 0b1010>; + def L2_loadruh_pcr : T_load_pcr <"memuh", IntRegs, 0b1011>; +} + +let accessSize = WordAccess, isCodeGenOnly = 0 in { + def L2_loadri_pcr : T_load_pcr <"memw", IntRegs, 0b1100>; +} + +let accessSize = DoubleWordAccess, isCodeGenOnly = 0 in +def L2_loadrd_pcr : T_load_pcr <"memd", DoubleRegs, 0b1110>; + +//===----------------------------------------------------------------------===// +// Circular loads with immediate offset. +//===----------------------------------------------------------------------===// +let Uses = [CS], mayLoad = 1, hasSideEffects = 0, hasNewValue = 1 in +class T_load_pci MajOp> + : LDInstPI<(outs RC:$dst, IntRegs:$_dst_), + (ins IntRegs:$Rz, ImmOp:$offset, ModRegs:$Mu), + "$dst = "#mnemonic#"($Rz ++ #$offset:circ($Mu))", [], + "$Rz = $_dst_"> { + bits<5> dst; + bits<5> Rz; + bits<1> Mu; + bits<7> offset; + bits<4> offsetBits; + + string ImmOpStr = !cast(ImmOp); + let offsetBits = !if (!eq(ImmOpStr, "s4_3Imm"), offset{6-3}, + !if (!eq(ImmOpStr, "s4_2Imm"), offset{5-2}, + !if (!eq(ImmOpStr, "s4_1Imm"), offset{4-1}, + /* s4_0Imm */ offset{3-0}))); + let IClass = 0b1001; + let Inst{27-25} = 0b100; + let Inst{24-21} = MajOp; + let Inst{20-16} = Rz; + let Inst{13} = Mu; + let Inst{12} = 0b0; + let Inst{9} = 0b0; + let Inst{8-5} = offsetBits; + let Inst{4-0} = dst; + } + +// Byte variants of circ load +let accessSize = ByteAccess, isCodeGenOnly = 0 in { + def L2_loadrb_pci : T_load_pci <"memb", IntRegs, s4_0Imm, 0b1000>; + def L2_loadrub_pci : T_load_pci <"memub", IntRegs, s4_0Imm, 0b1001>; +} + +// Half word variants of circ load +let accessSize = HalfWordAccess, isCodeGenOnly = 0 in { + def L2_loadrh_pci : T_load_pci <"memh", IntRegs, s4_1Imm, 0b1010>; + def L2_loadruh_pci : T_load_pci <"memuh", IntRegs, s4_1Imm, 0b1011>; +} + +// Word variants of circ load +let accessSize = WordAccess, isCodeGenOnly = 0 in +def L2_loadri_pci : T_load_pci <"memw", IntRegs, s4_2Imm, 0b1100>; + +let accessSize = DoubleWordAccess, hasNewValue = 0, isCodeGenOnly = 0 in +def L2_loadrd_pci : T_load_pci <"memd", DoubleRegs, s4_3Imm, 0b1110>; + //===----------------------------------------------------------------------===// // LD - //===----------------------------------------------------------------------===// diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.td b/lib/Target/Hexagon/HexagonRegisterInfo.td index 2517b9443d4..decd94722da 100644 --- a/lib/Target/Hexagon/HexagonRegisterInfo.td +++ b/lib/Target/Hexagon/HexagonRegisterInfo.td @@ -179,6 +179,9 @@ def PredRegs : RegisterClass<"Hexagon", [i1], 32, (add (sequence "P%u", 0, 3))> let Size = 32; } +let Size = 32 in +def ModRegs : RegisterClass<"Hexagon", [i32], 32, (add M0, M1)>; + let Size = 32, isAllocatable = 0 in def CtrRegs : RegisterClass<"Hexagon", [i32], 32, (add LC0, SA0, LC1, SA1, diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp index 179e49630c9..2dd9e89943f 100644 --- a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp +++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp @@ -564,7 +564,7 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( // if we have mayStore = 1 set on ALLOCFRAME and DEALLOCFRAME, // then we don't need this PacketSU->getInstr()->getOpcode() == Hexagon::ALLOCFRAME || - PacketSU->getInstr()->getOpcode() == Hexagon::DEALLOCFRAME) + PacketSU->getInstr()->getOpcode() == Hexagon::L2_deallocframe) return false; } diff --git a/test/MC/Disassembler/Hexagon/ld.txt b/test/MC/Disassembler/Hexagon/ld.txt index a222e5b055b..e4fb21fa7fe 100644 --- a/test/MC/Disassembler/Hexagon/ld.txt +++ b/test/MC/Disassembler/Hexagon/ld.txt @@ -2,6 +2,10 @@ 0x70 0xd8 0xd5 0x41 # CHECK: if (p3) r17:16 = memd(r21 + #24) +0xb0 0xe0 0xd5 0x99 +# CHECK: r17:16 = memd(r21 ++ #40:circ(m1)) +0x10 0xe2 0xd5 0x99 +# CHECK: r17:16 = memd(r21 ++ I:circ(m1)) 0xb0 0xc0 0xd5 0x9b # CHECK: r17:16 = memd(r21++#40) 0x03 0x40 0x45 0x85 0x70 0xd8 0xd5 0x43 @@ -25,6 +29,10 @@ 0xf1 0xc3 0x15 0x91 # CHECK: r17 = memb(r21 + #31) +0xb1 0xe0 0x15 0x99 +# CHECK: r17 = memb(r21 ++ #5:circ(m1)) +0x11 0xe2 0x15 0x99 +# CHECK: r17 = memb(r21 ++ I:circ(m1)) 0xb1 0xc0 0x15 0x9b # CHECK: r17 = memb(r21++#5) 0x91 0xdd 0x15 0x41 @@ -50,6 +58,10 @@ 0xf1 0xc3 0x55 0x91 # CHECK: r17 = memh(r21 + #62) +0xb1 0xe0 0x55 0x99 +# CHECK: r17 = memh(r21 ++ #10:circ(m1)) +0x11 0xe2 0x55 0x99 +# CHECK: r17 = memh(r21 ++ I:circ(m1)) 0xb1 0xc0 0x55 0x9b # CHECK: r17 = memh(r21++#10) 0xb1 0xe6 0x55 0x9b @@ -65,6 +77,10 @@ 0xf1 0xc3 0x35 0x91 # CHECK: r17 = memub(r21 + #31) +0xb1 0xe0 0x35 0x99 +# CHECK: r17 = memub(r21 ++ #5:circ(m1)) +0x11 0xe2 0x35 0x99 +# CHECK: r17 = memub(r21 ++ I:circ(m1)) 0xb1 0xc0 0x35 0x9b # CHECK: r17 = memub(r21++#5) 0xf1 0xdb 0x35 0x41 @@ -90,6 +106,10 @@ 0xb1 0xc2 0x75 0x91 # CHECK: r17 = memuh(r21 + #42) +0xb1 0xe0 0x75 0x99 +# CHECK: r17 = memuh(r21 ++ #10:circ(m1)) +0x11 0xe2 0x75 0x99 +# CHECK: r17 = memuh(r21 ++ I:circ(m1)) 0xb1 0xc0 0x75 0x9b # CHECK: r17 = memuh(r21++#10) 0xb1 0xda 0x75 0x41 @@ -115,6 +135,12 @@ 0xb1 0xc2 0x95 0x91 # CHECK: r17 = memw(r21 + #84) +0xb1 0xe0 0x95 0x99 +# CHECK: r17 = memw(r21 ++ #20:circ(m1)) +0x11 0xe2 0x95 0x99 +# CHECK: r17 = memw(r21 ++ I:circ(m1)) +0xb1 0xc0 0x95 0x9b +# CHECK: r17 = memw(r21++#20) 0xb1 0xda 0x95 0x41 # CHECK: if (p3) r17 = memw(r21 + #84) 0xb1 0xda 0x95 0x45 @@ -125,3 +151,16 @@ 0x03 0x40 0x45 0x85 0xb1 0xda 0x95 0x47 # CHECK: p3 = r5 # CHECK-NEXT: if (!p3.new) r17 = memw(r21 + #84) +0xb1 0xe6 0x95 0x9b +# CHECK: if (p3) r17 = memw(r21++#20) +0xb1 0xee 0x95 0x9b +# CHECK: if (!p3) r17 = memw(r21++#20) +0x03 0x40 0x45 0x85 0xb1 0xf6 0x95 0x9b +# CHECK: p3 = r5 +# CHECK-NEXT: if (p3.new) r17 = memw(r21++#20) +0x03 0x40 0x45 0x85 0xb1 0xfe 0x95 0x9b +# CHECK: p3 = r5 +# CHECK-NEXT: if (!p3.new) r17 = memw(r21++#20) + +0x1e 0xc0 0x1e 0x90 +# CHECK: deallocframe