]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
LoongArch: add .option directive
authorLulu Cai <cailulu@loongson.cn>
Tue, 21 May 2024 02:14:27 +0000 (10:14 +0800)
committerliuzhensong <liuzhensong@loongson.cn>
Tue, 18 Jun 2024 02:40:23 +0000 (10:40 +0800)
In some cases we may want to use different options only for certain
assembly, so the .option directive is added to control the assembler
options.

.option can accept 4 parameters:

push
pop
  Pushes or pops the current option stack. They limit the scope of
  option changes so that they do not affect other parts of the assembly
  file.

relax
norelax
  Enables or disables relaxation.

gas/config/tc-loongarch.c
gas/testsuite/gas/loongarch/loongarch.exp
gas/testsuite/gas/loongarch/pseudo_op_option.d [new file with mode: 0644]
gas/testsuite/gas/loongarch/pseudo_op_option.s [new file with mode: 0644]
gas/testsuite/gas/loongarch/pseudo_op_option_fail.l [new file with mode: 0644]
gas/testsuite/gas/loongarch/pseudo_op_option_fail.s [new file with mode: 0644]

index e7de9d863132754af485414743ab9e0cc9abfc3e..5ca33c6e2e82321c70d95d507c579dddc9872616 100644 (file)
@@ -541,6 +541,64 @@ s_dtprel (int bytes)
   demand_empty_rest_of_line ();
 }
 
+struct LARCH_option_stack
+{
+  struct LARCH_option_stack *next;
+  struct loongarch_ASEs_option options;
+};
+
+static struct LARCH_option_stack *LARCH_opts_stack = NULL;
+
+/* Handle the .option pseudo-op.
+   The alignment of .align is done by R_LARCH_ALIGN at link time.
+   If the .align directive is within the range controlled by
+   .option norelax, that is, relax is turned off, R_LARCH_ALIGN
+   cannot be generated, which may cause ld to be unable to handle
+   the alignment.  */
+static void
+s_loongarch_option (int x ATTRIBUTE_UNUSED)
+{
+  char *name = input_line_pointer, ch;
+  while (!is_end_of_line[(unsigned char) *input_line_pointer])
+    ++input_line_pointer;
+  ch = *input_line_pointer;
+  *input_line_pointer = '\0';
+
+  if (strcmp (name, "relax") == 0)
+    LARCH_opts.relax = 1;
+  else if (strcmp (name, "norelax") == 0)
+    LARCH_opts.relax = 0;
+  else if (strcmp (name, "push") == 0)
+    {
+      struct LARCH_option_stack *s;
+
+      s = XNEW (struct LARCH_option_stack);
+      s->next = LARCH_opts_stack;
+      s->options = LARCH_opts;
+      LARCH_opts_stack = s;
+    }
+  else if (strcmp (name, "pop") == 0)
+    {
+      struct LARCH_option_stack *s;
+
+      s = LARCH_opts_stack;
+      if (s == NULL)
+       as_bad (_(".option pop with no .option push"));
+      else
+       {
+         LARCH_opts_stack = s->next;
+         LARCH_opts = s->options;
+         free (s);
+       }
+    }
+  else
+    {
+      as_warn (_("unrecognized .option directive: %s"), name);
+    }
+  *input_line_pointer = ch;
+  demand_empty_rest_of_line ();
+}
+
 static const pseudo_typeS loongarch_pseudo_table[] =
 {
   { "dword", cons, 8 },
@@ -548,6 +606,7 @@ static const pseudo_typeS loongarch_pseudo_table[] =
   { "half", cons, 2 },
   { "dtprelword", s_dtprel, 4 },
   { "dtpreldword", s_dtprel, 8 },
+  { "option", s_loongarch_option, 0},
   { NULL, NULL, 0 },
 };
 
index 8cfe0aba5eb99be52370da5d690161f3b1792097..40d937f1c4b0b995cab0193c47b8202a84c0d815 100644 (file)
@@ -35,5 +35,6 @@ if [istarget loongarch*-*-*] {
 
   if [istarget loongarch64-*-*] {
     run_list_test "illegal-operand"
+    run_list_test "pseudo_op_option_fail"
   }
 }
diff --git a/gas/testsuite/gas/loongarch/pseudo_op_option.d b/gas/testsuite/gas/loongarch/pseudo_op_option.d
new file mode 100644 (file)
index 0000000..53921a1
--- /dev/null
@@ -0,0 +1,36 @@
+#as: -mrelax
+#objdump: -dr
+#skip: loongarch32-*-*
+
+.*:     file format .*
+
+
+Disassembly of section .text:
+
+0.* <.text>:
+   0:  1a000004        pcalau12i       \$a0, 0
+                       0: R_LARCH_PCALA_HI20   x
+                       0: R_LARCH_RELAX        \*ABS\*
+   4:  02c00084        addi.d          \$a0, \$a0, 0
+                       4: R_LARCH_PCALA_LO12   x
+                       4: R_LARCH_RELAX        \*ABS\*
+   8:  1a000004        pcalau12i       \$a0, 0
+                       8: R_LARCH_PCALA_HI20   x
+   c:  02c00084        addi.d          \$a0, \$a0, 0
+                       c: R_LARCH_PCALA_LO12   x
+  10:  1a000004        pcalau12i       \$a0, 0
+                       10: R_LARCH_PCALA_HI20  x
+                       10: R_LARCH_RELAX       \*ABS\*
+  14:  02c00084        addi.d          \$a0, \$a0, 0
+                       14: R_LARCH_PCALA_LO12  x
+                       14: R_LARCH_RELAX       \*ABS\*
+  18:  1a000004        pcalau12i       \$a0, 0
+                       18: R_LARCH_PCALA_HI20  x
+  1c:  02c00084        addi.d          \$a0, \$a0, 0
+                       1c: R_LARCH_PCALA_LO12  x
+  20:  1a000004        pcalau12i       \$a0, 0
+                       20: R_LARCH_PCALA_HI20  x
+                       20: R_LARCH_RELAX       \*ABS\*
+  24:  02c00084        addi.d          \$a0, \$a0, 0
+                       24: R_LARCH_PCALA_LO12  x
+                       24: R_LARCH_RELAX       \*ABS\*
diff --git a/gas/testsuite/gas/loongarch/pseudo_op_option.s b/gas/testsuite/gas/loongarch/pseudo_op_option.s
new file mode 100644 (file)
index 0000000..f21b726
--- /dev/null
@@ -0,0 +1,19 @@
+# Gas enables relax by default.
+# Push and pop can be nested, and each pop restores the options before
+# the most recent push.
+       .text
+.L1:
+       la.pcrel  $a0,x
+
+       .option push
+       .option norelax
+       la.pcrel  $a0,x
+
+       .option push
+       .option relax
+       la.pcrel  $a0,x
+       .option pop
+
+       la.pcrel  $a0,x
+       .option pop
+       la.pcrel  $a0,x
diff --git a/gas/testsuite/gas/loongarch/pseudo_op_option_fail.l b/gas/testsuite/gas/loongarch/pseudo_op_option_fail.l
new file mode 100644 (file)
index 0000000..ffb9a72
--- /dev/null
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*: Error: \.option pop with no \.option push
diff --git a/gas/testsuite/gas/loongarch/pseudo_op_option_fail.s b/gas/testsuite/gas/loongarch/pseudo_op_option_fail.s
new file mode 100644 (file)
index 0000000..e368cdb
--- /dev/null
@@ -0,0 +1,2 @@
+       .text
+       .option pop