diff options
-rw-r--r-- | gas/config/tc-loongarch.c | 59 | ||||
-rw-r--r-- | gas/testsuite/gas/loongarch/loongarch.exp | 1 | ||||
-rw-r--r-- | gas/testsuite/gas/loongarch/pseudo_op_option.d | 36 | ||||
-rw-r--r-- | gas/testsuite/gas/loongarch/pseudo_op_option.s | 19 | ||||
-rw-r--r-- | gas/testsuite/gas/loongarch/pseudo_op_option_fail.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/loongarch/pseudo_op_option_fail.s | 2 |
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 |