diff options
author | anbbna <117081688+anbbna@users.noreply.github.com> | 2024-03-13 07:27:18 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-13 07:27:18 +0800 |
commit | 65f07b804c2c05cf49bd043f2a6e9a0020198165 (patch) | |
tree | 87178eb6394ce5192cb8877afa93ba612511cfe7 | |
parent | 418f0066ebfcde8cd72d33cc103fc1c3e36a1205 (diff) | |
download | llvm-65f07b804c2c05cf49bd043f2a6e9a0020198165.zip llvm-65f07b804c2c05cf49bd043f2a6e9a0020198165.tar.gz llvm-65f07b804c2c05cf49bd043f2a6e9a0020198165.tar.bz2 |
[MIPS] Introduce NAL instruction support for Mipsr6 and prer6 (#84429)
NAL is an assembly idiom on Pre-R6 instruction sets (which is
implemented in binutils), or an actual instruction on Release 6
instruction set, and is used to read the PC, due to the nature of the
MIPS architecture.
Since we can't read the PC directly, on pre-R6 we use a always-not-taken
Branch and Link operation to the address of the next instruction, which
effectively writes the address to $31, thus PC is read with offset +8.
MIPS Release 6 removed the conventional Branch and Link instructions,
but kept NAL as an actual instruction for compatibility on the assembly
level. The instruction has the same encoding of the pre-R6 ones, and
with the same behavior: PC + 8 -> $31.
-rw-r--r-- | llvm/lib/Target/Mips/Mips32r6InstrFormats.td | 11 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/Mips32r6InstrInfo.td | 16 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.td | 3 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsScheduleGeneric.td | 2 | ||||
-rw-r--r-- | llvm/test/MC/Mips/mips32/nal.s | 14 | ||||
-rw-r--r-- | llvm/test/MC/Mips/mips32r6/nal.s | 21 |
6 files changed, 65 insertions, 2 deletions
diff --git a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td index ccb6d1d..8536c52 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td @@ -86,6 +86,7 @@ def OPCODE5_BC1NEZ : OPCODE5<0b01101>; def OPCODE5_BC2EQZ : OPCODE5<0b01001>; def OPCODE5_BC2NEZ : OPCODE5<0b01101>; def OPCODE5_BGEZAL : OPCODE5<0b10001>; +def OPCODE5_NAL : OPCODE5<0b10000>; def OPCODE5_SIGRIE : OPCODE5<0b10111>; // The next four constants are unnamed in the spec. These names are taken from // the OPGROUP names they are used with. @@ -201,6 +202,16 @@ class BAL_FM : MipsR6Inst { let Inst{15-0} = offset; } +// NAL for Release 6 +class NAL_FM : MipsR6Inst { + bits<32> Inst; + + let Inst{31-26} = OPGROUP_REGIMM.Value; + let Inst{25-21} = 0b00000; + let Inst{20-16} = OPCODE5_NAL.Value; + let Inst{15-0} = 0x00; +} + class COP0_EVP_DVP_FM<bits<1> sc> : MipsR6Inst { bits<5> rt; diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index 854563ab..9c29acb 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -73,6 +73,7 @@ class AUI_ENC : AUI_FM; class AUIPC_ENC : PCREL16_FM<OPCODE5_AUIPC>; class BAL_ENC : BAL_FM; +class NAL_ENC : NAL_FM; class BALC_ENC : BRANCH_OFF26_FM<0b111010>; class BC_ENC : BRANCH_OFF26_FM<0b110010>; class BEQC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_ADDI>, @@ -381,6 +382,12 @@ class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE, bit isCTI = 1; } +class NAL_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE, + MipsR6Arch<instr_asm> { + string AsmString = instr_asm; + bit isCTI = 1; +} + class CMP_BC_DESC_BASE<string instr_asm, DAGOperand opnd, RegisterOperand GPROpnd> : BRANCH_DESC_BASE, MipsR6Arch<instr_asm> { @@ -424,6 +431,12 @@ class BAL_DESC : BC_DESC_BASE<"bal", brtarget> { bit isCTI = 1; } +class NAL_DESC : NAL_DESC_BASE<"nal"> { + bit hasDelaySlot = 1; + list<Register> Defs = [RA]; + bit isCTI = 1; +} + class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> { bit isCall = 1; list<Register> Defs = [RA]; @@ -868,6 +881,8 @@ def AUI : R6MMR6Rel, AUI_ENC, AUI_DESC, ISA_MIPS32R6; def AUIPC : R6MMR6Rel, AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6; def BAL : BAL_ENC, BAL_DESC, ISA_MIPS32R6; def BALC : R6MMR6Rel, BALC_ENC, BALC_DESC, ISA_MIPS32R6; +def NAL : NAL_ENC, NAL_DESC, ISA_MIPS32R6; + let AdditionalPredicates = [NotInMicroMips] in { def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6, HARDFLOAT; def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6, HARDFLOAT; @@ -948,7 +963,6 @@ let AdditionalPredicates = [NotInMicroMips] in { def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6; def MULU : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6; } -def NAL; // BAL with rd=0 let AdditionalPredicates = [NotInMicroMips] in { def PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6; def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT; diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 4b6f4b2..23e04c4 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -3049,6 +3049,9 @@ def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, simm32:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; + +def : MipsInstAlias<"nal", (BLTZAL ZERO, 0), 1>, ISA_MIPS1_NOT_32R6_64R6; + def SRemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "rem\t$rd, $rs, $rt">, diff --git a/llvm/lib/Target/Mips/MipsScheduleGeneric.td b/llvm/lib/Target/Mips/MipsScheduleGeneric.td index a3df88a..6771a897 100644 --- a/llvm/lib/Target/Mips/MipsScheduleGeneric.td +++ b/llvm/lib/Target/Mips/MipsScheduleGeneric.td @@ -285,7 +285,7 @@ def GenericWriteJumpAndLink : SchedWriteRes<[GenericIssueCTISTD]> { // jalr, jr.hb, jr, jalr.hb, jarlc, jialc def : InstRW<[GenericWriteJump], (instrs B, BAL, BAL_BR, BEQ, BNE, BGTZ, BGEZ, BLEZ, BLTZ, BLTZAL, J, JALX, JR, JR_HB, ERET, - ERet, ERETNC, DERET)>; + ERet, ERETNC, DERET, NAL)>; def : InstRW<[GenericWriteJump], (instrs BEQL, BNEL, BGEZL, BGTZL, BLEZL, BLTZL)>; diff --git a/llvm/test/MC/Mips/mips32/nal.s b/llvm/test/MC/Mips/mips32/nal.s new file mode 100644 index 0000000..72c7231 --- /dev/null +++ b/llvm/test/MC/Mips/mips32/nal.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc %s -triple=mipsel-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32-EL +# RUN: llvm-mc %s -triple=mips-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32-EB + +# Whether it is a macro or an actual instruction, it always has a delay slot. +# Ensure the delay slot is filled correctly. +# MIPS32-EL: 00 00 10 04 bltzal $zero, 0x4 +# MIPS32-EL-NEXT: 00 00 00 00 nop +# MIPS32-EB: 04 10 00 00 bltzal $zero, 0x4 +# MIPS32-EB-NEXT: 00 00 00 00 nop + +nal_test: + nal diff --git a/llvm/test/MC/Mips/mips32r6/nal.s b/llvm/test/MC/Mips/mips32r6/nal.s new file mode 100644 index 0000000..94c1a77 --- /dev/null +++ b/llvm/test/MC/Mips/mips32r6/nal.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc %s -triple=mipsisa32r6el-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32R6-EL +# RUN: llvm-mc %s -triple=mipsisa32r6-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32R6-EB + +# Whether it is a macro or an actual instruction, it always has a delay slot. +# Ensure the delay slot is filled correctly. +# Also ensure that NAL does not reside in a forbidden slot. +# MIPS32R6-EL: 00 00 80 f8 bnezc $4, 0x4 +# MIPS32R6-EL-NEXT: 00 00 00 00 nop +# MIPS32R6-EL: 00 00 10 04 nal +# MIPS32R6-EL-NEXT: 00 00 00 00 nop +# MIPS32R6-EB: f8 80 00 00 bnezc $4, 0x4 +# MIPS32R6-EB-NEXT: 00 00 00 00 nop +# MIPS32R6-EB: 04 10 00 00 nal +# MIPS32R6-EB-NEXT: 00 00 00 00 nop + +nal_test: + # We generate a fobidden solt just for testing. + bnezc $a0, 0 + nal |