Skip to content

Commit 65f07b8

Browse files
authored
[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.
1 parent 418f006 commit 65f07b8

File tree

6 files changed

+65
-2
lines changed

6 files changed

+65
-2
lines changed

llvm/lib/Target/Mips/Mips32r6InstrFormats.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def OPCODE5_BC1NEZ : OPCODE5<0b01101>;
8686
def OPCODE5_BC2EQZ : OPCODE5<0b01001>;
8787
def OPCODE5_BC2NEZ : OPCODE5<0b01101>;
8888
def OPCODE5_BGEZAL : OPCODE5<0b10001>;
89+
def OPCODE5_NAL : OPCODE5<0b10000>;
8990
def OPCODE5_SIGRIE : OPCODE5<0b10111>;
9091
// The next four constants are unnamed in the spec. These names are taken from
9192
// the OPGROUP names they are used with.
@@ -201,6 +202,16 @@ class BAL_FM : MipsR6Inst {
201202
let Inst{15-0} = offset;
202203
}
203204

205+
// NAL for Release 6
206+
class NAL_FM : MipsR6Inst {
207+
bits<32> Inst;
208+
209+
let Inst{31-26} = OPGROUP_REGIMM.Value;
210+
let Inst{25-21} = 0b00000;
211+
let Inst{20-16} = OPCODE5_NAL.Value;
212+
let Inst{15-0} = 0x00;
213+
}
214+
204215
class COP0_EVP_DVP_FM<bits<1> sc> : MipsR6Inst {
205216
bits<5> rt;
206217

llvm/lib/Target/Mips/Mips32r6InstrInfo.td

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class AUI_ENC : AUI_FM;
7373
class AUIPC_ENC : PCREL16_FM<OPCODE5_AUIPC>;
7474

7575
class BAL_ENC : BAL_FM;
76+
class NAL_ENC : NAL_FM;
7677
class BALC_ENC : BRANCH_OFF26_FM<0b111010>;
7778
class BC_ENC : BRANCH_OFF26_FM<0b110010>;
7879
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,
381382
bit isCTI = 1;
382383
}
383384

385+
class NAL_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE,
386+
MipsR6Arch<instr_asm> {
387+
string AsmString = instr_asm;
388+
bit isCTI = 1;
389+
}
390+
384391
class CMP_BC_DESC_BASE<string instr_asm, DAGOperand opnd,
385392
RegisterOperand GPROpnd> : BRANCH_DESC_BASE,
386393
MipsR6Arch<instr_asm> {
@@ -424,6 +431,12 @@ class BAL_DESC : BC_DESC_BASE<"bal", brtarget> {
424431
bit isCTI = 1;
425432
}
426433

434+
class NAL_DESC : NAL_DESC_BASE<"nal"> {
435+
bit hasDelaySlot = 1;
436+
list<Register> Defs = [RA];
437+
bit isCTI = 1;
438+
}
439+
427440
class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> {
428441
bit isCall = 1;
429442
list<Register> Defs = [RA];
@@ -868,6 +881,8 @@ def AUI : R6MMR6Rel, AUI_ENC, AUI_DESC, ISA_MIPS32R6;
868881
def AUIPC : R6MMR6Rel, AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6;
869882
def BAL : BAL_ENC, BAL_DESC, ISA_MIPS32R6;
870883
def BALC : R6MMR6Rel, BALC_ENC, BALC_DESC, ISA_MIPS32R6;
884+
def NAL : NAL_ENC, NAL_DESC, ISA_MIPS32R6;
885+
871886
let AdditionalPredicates = [NotInMicroMips] in {
872887
def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6, HARDFLOAT;
873888
def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6, HARDFLOAT;
@@ -948,7 +963,6 @@ let AdditionalPredicates = [NotInMicroMips] in {
948963
def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6;
949964
def MULU : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6;
950965
}
951-
def NAL; // BAL with rd=0
952966
let AdditionalPredicates = [NotInMicroMips] in {
953967
def PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6;
954968
def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT;

llvm/lib/Target/Mips/MipsInstrInfo.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,9 @@ def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
30493049
simm32:$imm), 0>,
30503050
ISA_MIPS1_NOT_32R6_64R6;
30513051

3052+
3053+
def : MipsInstAlias<"nal", (BLTZAL ZERO, 0), 1>, ISA_MIPS1_NOT_32R6_64R6;
3054+
30523055
def SRemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
30533056
(ins GPR32Opnd:$rs, GPR32Opnd:$rt),
30543057
"rem\t$rd, $rs, $rt">,

llvm/lib/Target/Mips/MipsScheduleGeneric.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ def GenericWriteJumpAndLink : SchedWriteRes<[GenericIssueCTISTD]> {
285285
// jalr, jr.hb, jr, jalr.hb, jarlc, jialc
286286
def : InstRW<[GenericWriteJump], (instrs B, BAL, BAL_BR, BEQ, BNE, BGTZ, BGEZ,
287287
BLEZ, BLTZ, BLTZAL, J, JALX, JR, JR_HB, ERET,
288-
ERet, ERETNC, DERET)>;
288+
ERet, ERETNC, DERET, NAL)>;
289289

290290
def : InstRW<[GenericWriteJump], (instrs BEQL, BNEL, BGEZL, BGTZL, BLEZL,
291291
BLTZL)>;

llvm/test/MC/Mips/mips32/nal.s

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# RUN: llvm-mc %s -triple=mipsel-linux-gnu -filetype=obj -o - | \
2+
# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32-EL
3+
# RUN: llvm-mc %s -triple=mips-linux-gnu -filetype=obj -o - | \
4+
# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32-EB
5+
6+
# Whether it is a macro or an actual instruction, it always has a delay slot.
7+
# Ensure the delay slot is filled correctly.
8+
# MIPS32-EL: 00 00 10 04 bltzal $zero, 0x4
9+
# MIPS32-EL-NEXT: 00 00 00 00 nop
10+
# MIPS32-EB: 04 10 00 00 bltzal $zero, 0x4
11+
# MIPS32-EB-NEXT: 00 00 00 00 nop
12+
13+
nal_test:
14+
nal

llvm/test/MC/Mips/mips32r6/nal.s

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# RUN: llvm-mc %s -triple=mipsisa32r6el-linux-gnu -filetype=obj -o - | \
2+
# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32R6-EL
3+
# RUN: llvm-mc %s -triple=mipsisa32r6-linux-gnu -filetype=obj -o - | \
4+
# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32R6-EB
5+
6+
# Whether it is a macro or an actual instruction, it always has a delay slot.
7+
# Ensure the delay slot is filled correctly.
8+
# Also ensure that NAL does not reside in a forbidden slot.
9+
# MIPS32R6-EL: 00 00 80 f8 bnezc $4, 0x4
10+
# MIPS32R6-EL-NEXT: 00 00 00 00 nop
11+
# MIPS32R6-EL: 00 00 10 04 nal
12+
# MIPS32R6-EL-NEXT: 00 00 00 00 nop
13+
# MIPS32R6-EB: f8 80 00 00 bnezc $4, 0x4
14+
# MIPS32R6-EB-NEXT: 00 00 00 00 nop
15+
# MIPS32R6-EB: 04 10 00 00 nal
16+
# MIPS32R6-EB-NEXT: 00 00 00 00 nop
17+
18+
nal_test:
19+
# We generate a fobidden solt just for testing.
20+
bnezc $a0, 0
21+
nal

0 commit comments

Comments
 (0)