aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/config/tc-loongarch.c59
-rw-r--r--gas/testsuite/gas/loongarch/loongarch.exp1
-rw-r--r--gas/testsuite/gas/loongarch/pseudo_op_option.d36
-rw-r--r--gas/testsuite/gas/loongarch/pseudo_op_option.s19
-rw-r--r--gas/testsuite/gas/loongarch/pseudo_op_option_fail.l2
-rw-r--r--gas/testsuite/gas/loongarch/pseudo_op_option_fail.s2
6 files changed, 119 insertions, 0 deletions
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index e7de9d8..5ca33c6 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -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 },
};
diff --git a/gas/testsuite/gas/loongarch/loongarch.exp b/gas/testsuite/gas/loongarch/loongarch.exp
index 8cfe0ab..40d937f 100644
--- a/gas/testsuite/gas/loongarch/loongarch.exp
+++ b/gas/testsuite/gas/loongarch/loongarch.exp
@@ -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
index 0000000..53921a1
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/pseudo_op_option.d
@@ -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
index 0000000..f21b726
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/pseudo_op_option.s
@@ -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
index 0000000..ffb9a72
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/pseudo_op_option_fail.l
@@ -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
index 0000000..e368cdb
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/pseudo_op_option_fail.s
@@ -0,0 +1,2 @@
+ .text
+ .option pop