From: Mihai Popa Date: Mon, 13 May 2013 14:10:04 +0000 (+0000) Subject: The purpose of the patch is to fix the syntax of ARM mrc and mrc2 instructions when... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=f86e436fb95670ed110818fefa403f21ae104639;p=oota-llvm.git The purpose of the patch is to fix the syntax of ARM mrc and mrc2 instructions when they are used to write to the APSR. In this case, the destination operand should be APSR_nzcv, and the encoding of the target should be 0b1111 (same as for PC). In pre-UAL syntax, this form used the PC register as a textual target. This is still allowed for backward compatibility. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181705 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index b0d34a76b01..4de5b4f41c4 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -94,6 +94,7 @@ getReservedRegs(const MachineFunction &MF) const { Reserved.set(ARM::SP); Reserved.set(ARM::PC); Reserved.set(ARM::FPSCR); + Reserved.set(ARM::APSR_NZCV); if (TFI->hasFP(MF)) Reserved.set(FramePtr); if (hasBasePointer(MF)) diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 1bd174e3416..89f92a589db 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -4636,11 +4636,11 @@ def : ARMInstAlias<"mcr${p} $cop, $opc1, $Rt, $CRn, $CRm", (MCR p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn, c_imm:$CRm, 0, pred:$p)>; def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */, - (outs GPR:$Rt), + (outs GPRwithAPSR:$Rt), (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), []>; def : ARMInstAlias<"mrc${p} $cop, $opc1, $Rt, $CRn, $CRm", - (MRC GPR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, + (MRC GPRwithAPSR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm, 0, pred:$p)>; def : ARMPat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2), @@ -4650,7 +4650,7 @@ class MovRCopro2 pattern> : ABXI<0b1110, oops, iops, NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), pattern> { - let Inst{31-28} = 0b1111; + let Inst{31-24} = 0b11111110; let Inst{20} = direction; let Inst{4} = 1; @@ -4679,11 +4679,11 @@ def : ARMInstAlias<"mcr2$ $cop, $opc1, $Rt, $CRn, $CRm", (MCR2 p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn, c_imm:$CRm, 0)>; def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */, - (outs GPR:$Rt), + (outs GPRwithAPSR:$Rt), (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), []>; def : ARMInstAlias<"mrc2$ $cop, $opc1, $Rt, $CRn, $CRm", - (MRC2 GPR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, + (MRC2 GPRwithAPSR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm, 0)>; def : ARMV5TPat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, diff --git a/lib/Target/ARM/ARMRegisterInfo.td b/lib/Target/ARM/ARMRegisterInfo.td index b0f576bc2b6..85743d8d5ad 100644 --- a/lib/Target/ARM/ARMRegisterInfo.td +++ b/lib/Target/ARM/ARMRegisterInfo.td @@ -157,12 +157,15 @@ def Q15 : ARMReg<15, "q15", [D30, D31]>; // Current Program Status Register. // We model fpscr with two registers: FPSCR models the control bits and will be -// reserved. FPSCR_NZCV models the flag bits and will be unreserved. -def CPSR : ARMReg<0, "cpsr">; -def APSR : ARMReg<1, "apsr">; -def SPSR : ARMReg<2, "spsr">; -def FPSCR : ARMReg<3, "fpscr">; -def FPSCR_NZCV : ARMReg<3, "fpscr_nzcv"> { +// reserved. FPSCR_NZCV models the flag bits and will be unreserved. APSR_NZCV +// models the APSR when it's accessed by some special instructions. In such cases +// it has the same encoding as PC. +def CPSR : ARMReg<0, "cpsr">; +def APSR : ARMReg<1, "apsr">; +def APSR_NZCV : ARMReg<15, "apsr_nzcv">; +def SPSR : ARMReg<2, "spsr">; +def FPSCR : ARMReg<3, "fpscr">; +def FPSCR_NZCV : ARMReg<3, "fpscr_nzcv"> { let Aliases = [FPSCR]; } def ITSTATE : ARMReg<4, "itstate">; @@ -207,6 +210,16 @@ def GPRnopc : RegisterClass<"ARM", [i32], 32, (sub GPR, PC)> { }]; } +// GPRs without the PC but with APSR. Some instructions allow accessing the +// APSR, while actually encoding PC in the register field. This is usefull +// for assembly and disassembly only. +def GPRwithAPSR : RegisterClass<"ARM", [i32], 32, (add GPR, APSR_NZCV)> { + let AltOrders = [(add LR, GPRnopc), (trunc GPRnopc, 8)]; + let AltOrderSelect = [{ + return 1 + MF.getTarget().getSubtarget().isThumb1Only(); + }]; +} + // GPRsp - Only the SP is legal. Used by Thumb1 instructions that want the // implied SP argument list. // FIXME: It would be better to not use this at all and refactor the diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index ac937f35345..d2896377cc9 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -156,6 +156,9 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo, static DecodeStatus DecodeGPRnopcRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeGPRwithAPSRRegisterClass(MCInst &Inst, + unsigned RegNo, uint64_t Address, + const void *Decoder); static DecodeStatus DecodetGPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo, @@ -920,6 +923,21 @@ DecodeGPRnopcRegisterClass(MCInst &Inst, unsigned RegNo, return S; } +static DecodeStatus +DecodeGPRwithAPSRRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + + if (RegNo == 15) + { + Inst.addOperand(MCOperand::CreateReg(ARM::APSR_NZCV)); + return MCDisassembler::Success; + } + + Check(S, DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder)); + return S; +} + static DecodeStatus DecodetGPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s index 71b5b5da09b..5227bdd2397 100644 --- a/test/MC/ARM/basic-arm-instructions.s +++ b/test/MC/ARM/basic-arm-instructions.s @@ -1062,10 +1062,18 @@ Lforward: @ MRC/MRC2 @------------------------------------------------------------------------------ mrc p14, #0, r1, c1, c2, #4 + mrc p15, #7, apsr_nzcv, c15, c6, #6 + mrc p15, #7, pc, c15, c6, #6 mrc2 p14, #0, r1, c1, c2, #4 - -@ CHECK: mrc p14, #0, r1, c1, c2, #4 @ encoding: [0x92,0x1e,0x11,0xee] -@ CHECK: mrc2 p14, #0, r1, c1, c2, #4 @ encoding: [0x92,0x1e,0x11,0xfe] + mrc2 p10, #7, apsr_nzcv, c15, c0, #1 + mrc2 p10, #7, pc, c15, c0, #1 + +@ CHECK: mrc p14, #0, r1, c1, c2, #4 @ encoding: [0x92,0x1e,0x11,0xee] +@ CHECK: mrc p15, #7, apsr_nzcv, c15, c6, #6 @ encoding: [0xd6,0xff,0xff,0xee] +@ CHECK: mrc p15, #7, pc, c15, c6, #6 @ encoding: [0xd6,0xff,0xff,0xee] +@ CHECK: mrc2 p14, #0, r1, c1, c2, #4 @ encoding: [0x92,0x1e,0x11,0xfe] +@ CHECK: mrc2 p10, #7, apsr_nzcv, c15, c0, #1 @ encoding: [0x30,0xfa,0xff,0xfe] +@ CHECK: mrc2 p10, #7, pc, c15, c0, #1 @ encoding: [0x30,0xfa,0xff,0xfe] @------------------------------------------------------------------------------ @ MRRC/MRRC2 diff --git a/test/MC/Disassembler/ARM/basic-arm-instructions.txt b/test/MC/Disassembler/ARM/basic-arm-instructions.txt index 9f63e1e914f..c92322e8d7e 100644 --- a/test/MC/Disassembler/ARM/basic-arm-instructions.txt +++ b/test/MC/Disassembler/ARM/basic-arm-instructions.txt @@ -757,10 +757,14 @@ # MRC/MRC2 #------------------------------------------------------------------------------ # CHECK: mrc p14, #0, r1, c1, c2, #4 +# CHECK: mrc p15, #7, apsr_nzcv, c15, c6, #6 # CHECK: mrc2 p14, #0, r1, c1, c2, #4 +# CHECK: mrc2 p9, #7, apsr_nzcv, c15, c0, #1 0x92 0x1e 0x11 0xee +0xd6 0xff 0xff 0xee 0x92 0x1e 0x11 0xfe +0x30 0xf9 0xff 0xfe #------------------------------------------------------------------------------ # MRRC/MRRC2