From 205e07d68684bc331c16b7bcea44b8d5ca84f7e8 Mon Sep 17 00:00:00 2001
From: mengqinggang <mengqinggang@loongson.cn>
Date: Thu, 23 Nov 2023 15:42:49 +0800
Subject: [PATCH 021/123] LoongArch: Add call36 and tail36 pseudo instructions
 for medium code model

  For tail36, it is necessary to explicitly indicate the temporary register.
  Therefore, the compiler and users will know that the tail will use a register.

  call36 func
    pcalau18i $ra, %call36(func)
    jirl      $ra, $ra, 0;

  tail36 $t0, func
    pcalau18i $t0, %call36(func)
    jirl      $zero, $t0, 0;
---
 gas/testsuite/gas/loongarch/medium-call.d   | 10 ++++++++--
 gas/testsuite/gas/loongarch/medium-call.s   |  2 ++
 ld/testsuite/ld-loongarch-elf/medium-call.s |  2 ++
 opcodes/loongarch-opc.c                     | 11 +++++++++++
 4 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/gas/testsuite/gas/loongarch/medium-call.d b/gas/testsuite/gas/loongarch/medium-call.d
index 4183818c..3491760b 100644
--- a/gas/testsuite/gas/loongarch/medium-call.d
+++ b/gas/testsuite/gas/loongarch/medium-call.d
@@ -10,6 +10,12 @@ Disassembly of section .text:
 [ 	]+0:[ 	]+1e000001[ 	]+pcaddu18i[ 	]+\$ra, 0
 [ 	]+0: R_LARCH_CALL36[ 	]+a
 [ 	]+4:[ 	]+4c000021[ 	]+jirl[ 	]+\$ra, \$ra, 0
-[ 	]+8:[ 	]+1e00000c[ 	]+pcaddu18i[ 	]+\$t0, 0
+[ 	]+8:[ 	]+1e000001[ 	]+pcaddu18i[ 	]+\$ra, 0
 [ 	]+8: R_LARCH_CALL36[ 	]+a
-[ 	]+c:[ 	]+4c000180[ 	]+jr[ 	]+\$t0
+[ 	]+c:[ 	]+4c000021[ 	]+jirl[ 	]+\$ra, \$ra, 0
+[ 	]+10:[ 	]+1e00000c[ 	]+pcaddu18i[ 	]+\$t0, 0
+[ 	]+10: R_LARCH_CALL36[ 	]+a
+[ 	]+14:[ 	]+4c000180[ 	]+jr[ 	]+\$t0
+[ 	]+18:[ 	]+1e00000c[ 	]+pcaddu18i[ 	]+\$t0, 0
+[ 	]+18: R_LARCH_CALL36[ 	]+a
+[ 	]+1c:[ 	]+4c000180[ 	]+jr[ 	]+\$t0
diff --git a/gas/testsuite/gas/loongarch/medium-call.s b/gas/testsuite/gas/loongarch/medium-call.s
index f2977d1c..74d15076 100644
--- a/gas/testsuite/gas/loongarch/medium-call.s
+++ b/gas/testsuite/gas/loongarch/medium-call.s
@@ -1,6 +1,8 @@
   # call .L1, r1(ra) temp register, r1(ra) return register.
+  call36 a
   pcaddu18i $r1, %call36(a)
   jirl	    $r1, $r1, 0
   # tail .L1, r12(t0) temp register, r0(zero) return register.
+  tail36 $r12, a
   pcaddu18i $r12, %call36(a)
   jirl	    $r0, $r12, 0
diff --git a/ld/testsuite/ld-loongarch-elf/medium-call.s b/ld/testsuite/ld-loongarch-elf/medium-call.s
index 4d1888b7..50a6b8e7 100644
--- a/ld/testsuite/ld-loongarch-elf/medium-call.s
+++ b/ld/testsuite/ld-loongarch-elf/medium-call.s
@@ -1,7 +1,9 @@
 .L1:
   # call .L1, r1(ra) temp register, r1(ra) return register.
+  call36 .L1
   pcaddu18i $r1, %call36(.L1)
   jirl	    $r1, $r1, 0
   # tail .L1, r12(t0) temp register, r0(zero) return register.
+  tail36 $r12, .L1
   pcaddu18i $r12, %call36(.L1)
   jirl	    $r0, $r12, 0
diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
index 15c7da63..b47817f8 100644
--- a/opcodes/loongarch-opc.c
+++ b/opcodes/loongarch-opc.c
@@ -293,6 +293,15 @@ const char *const loongarch_x_normal_name[32] =
   &LARCH_opts.ase_lp64,		      \
   &LARCH_opts.ase_gpcr
 
+#define INSN_LA_CALL		      \
+  "pcaddu18i $ra,%%call36(%1);"    \
+  "jirl $ra,$ra,0;",    \
+  0, 0
+
+#define INSN_LA_TAIL		      \
+  "pcaddu18i %1,%%call36(%2);"   \
+  "jirl $zero,%1,0;",   \
+  0, 0
 
 static struct loongarch_opcode loongarch_macro_opcodes[] =
 {
@@ -340,6 +349,8 @@ static struct loongarch_opcode loongarch_macro_opcodes[] =
   { 0, 0, "la.tls.gd",	"r,l",	  INSN_LA_TLS_GD64,		0 },
   { 0, 0, "la.tls.gd",	"r,l",	  INSN_LA_TLS_GD64_LARGE_ABS,	0 },
   { 0, 0, "la.tls.gd",	"r,r,l",  INSN_LA_TLS_GD64_LARGE_PCREL,	0 },
+  { 0, 0, "call36",	"la",	  INSN_LA_CALL,			0 },
+  { 0, 0, "tail36",	"r,la",	  INSN_LA_TAIL,			0 },
   { 0, 0, "pcaddi",	"r,la",	  "pcaddi %1, %%pcrel_20(%2)",	&LARCH_opts.ase_ilp32, 0, 0 },
   { 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminate the list.  */
 };
-- 
2.33.0

