2 Copyright (C) 2021-2025 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING3. If not,
18 see <http://www.gnu.org/licenses/>. */
21 #include "loongarch-lex.h"
22 #include "loongarch-parse.h"
23 static void yyerror (const char *s ATTRIBUTE_UNUSED
)
29 static struct reloc_info
*top
, *end
;
31 static expressionS const_0
=
38 is_const
(struct reloc_info
*info
)
40 return
(info
->type
== BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE
41 && info
->value.X_op
== O_constant
);
45 loongarch_parse_expr
(const char *expr
,
46 struct reloc_info
*reloc_stack_top
,
52 struct yy_buffer_state
*buffstate
;
53 top
= reloc_stack_top
;
54 end
= top
+ max_reloc_num
;
55 buffstate
= yy_scan_string
(expr
);
60 if
(is_const
(top
- 1))
61 *imm
= (--top
)->value.X_add_number
;
64 *reloc_num
= top
- reloc_stack_top
;
66 yy_delete_buffer
(buffstate
);
72 emit_const
(offsetT imm
)
75 as_fatal
(_
("expr too huge"));
76 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE
;
77 top
->value.X_op
= O_constant
;
78 top
->value.X_add_number
= imm
;
83 my_getExpression
(expressionS
*ep
, const char *str
)
90 char *str_1
= (char *) str
;
91 j
= strtol
(str_1
, &str_1
, 10);
92 get_internal_label
(ep
, j
, *str_1
== 'f');
95 save_in
= input_line_pointer
;
96 input_line_pointer
= (char *)str
;
98 ret
= input_line_pointer
;
99 input_line_pointer
= save_in
;
104 emit_const_var
(const char *op
)
109 as_fatal
(_
("expr too huge"));
111 my_getExpression
(&ep
, op
);
113 if
(ep.X_op
!= O_constant
)
114 as_bad
("illegal operand: %s", op
);
116 top
->value.X_op
= O_constant
;
117 top
->value.X_add_number
= ep.X_add_number
;
118 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE
;
123 reloc
(const char *op_c_str
, const char *id_c_str
, offsetT addend
)
125 expressionS id_sym_expr
;
126 bfd_reloc_code_real_type btype
;
129 as_fatal
(_
("expr too huge"));
131 /* For compatible old asm code. */
132 if
(0 == strcmp
(op_c_str
, "plt"))
133 btype
= BFD_RELOC_LARCH_B26
;
136 btype
= loongarch_larch_reloc_name_lookup
(NULL
, op_c_str
);
137 if
(btype
== BFD_RELOC_NONE
)
138 as_fatal
(_
("unsupported modifier %s"), op_c_str
);
143 my_getExpression
(&id_sym_expr
, id_c_str
);
144 id_sym_expr.X_add_number
+= addend
;
148 id_sym_expr.X_op
= O_constant
;
149 id_sym_expr.X_add_number
= addend
;
152 top
->value
= id_sym_expr
;
160 struct reloc_info
*s_top
= top
- 1;
161 if
(is_const
(s_top
))
163 offsetT opr
= s_top
->value.X_add_number
;
180 s_top
->value.X_add_number
= opr
;
185 as_fatal
(_
("expr too huge"));
189 top
->type
= BFD_RELOC_LARCH_SOP_NOT
;
194 top
->value
= const_0
;
202 struct reloc_info
*last_1st
= top
- 1, *last_2nd
= top
- 2;
203 if
(is_const
(last_1st
) && is_const
(last_2nd
))
205 offsetT opr1
= last_2nd
->value.X_add_number
;
206 offsetT opr2
= last_1st
->value.X_add_number
;
228 /* Algorithm right shift. */
229 opr1
= (offsetT
)opr1
>> (offsetT
)opr2
;
267 last_2nd
->value.X_add_number
= opr1
;
274 as_fatal
(_
("expr too huge"));
278 top
->type
= BFD_RELOC_LARCH_SOP_ADD
;
281 top
->type
= BFD_RELOC_LARCH_SOP_SUB
;
284 top
->type
= BFD_RELOC_LARCH_SOP_SL
;
287 top
->type
= BFD_RELOC_LARCH_SOP_SR
;
290 top
->type
= BFD_RELOC_LARCH_SOP_AND
;
295 top
->value
= const_0
;
303 struct reloc_info
*last_1st
= top
- 1;
304 struct reloc_info
*last_2nd
= top
- 2;
305 struct reloc_info
*last_3rd
= top
- 3;
306 if
(is_const
(last_1st
) && is_const
(last_2nd
) && is_const
(last_3rd
))
308 offsetT opr1
= last_3rd
->value.X_add_number
;
309 offsetT opr2
= last_2nd
->value.X_add_number
;
310 offsetT opr3
= last_1st
->value.X_add_number
;
311 opr1
= opr1 ? opr2
: opr3
;
312 last_3rd
->value.X_add_number
= opr1
;
320 as_fatal
(_
("expr too huge"));
321 top
->type
= BFD_RELOC_LARCH_SOP_IF_ELSE
;
322 top
->value
= const_0
;
335 %token
<c_str
> IDENTIFIER
338 %token LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP
343 : INTEGER
{emit_const
($1);}
344 | IDENTIFIER
{emit_const_var
($1);}
346 |
'%' IDENTIFIER
'(' IDENTIFIER addend
')' {reloc
($2, $4, $5); free
($2); free
($4);}
347 |
'%' IDENTIFIER
'(' INTEGER addend
')' {reloc
($2, NULL
, $4 + $5); free
($2);}
351 : addend
'-' INTEGER
{$$
-= $3;}
352 | addend
'+' INTEGER
{$$
+= $3;}
358 |
'+' unary_expression
{emit_unary
('+');}
359 |
'-' unary_expression
{emit_unary
('-');}
360 |
'~' unary_expression
{emit_unary
('~');}
361 |
'!' unary_expression
{emit_unary
('!');}
364 multiplicative_expression
366 | multiplicative_expression
'*' unary_expression
{emit_bin
('*');}
367 | multiplicative_expression
'/' unary_expression
{emit_bin
('/');}
368 | multiplicative_expression
'%' unary_expression
{emit_bin
('%');}
372 : multiplicative_expression
373 | shift_expression LEFT_OP multiplicative_expression
{emit_bin
(LEFT_OP
);}
374 | shift_expression RIGHT_OP multiplicative_expression
{emit_bin
(RIGHT_OP
);}
379 | additive_expression
'+' shift_expression
{emit_bin
('+');}
380 | additive_expression
'-' shift_expression
{emit_bin
('-');}
383 relational_expression
384 : additive_expression
385 | relational_expression
'<' additive_expression
{emit_bin
('<');}
386 | relational_expression
'>' additive_expression
{emit_bin
('>');}
387 | relational_expression LE_OP additive_expression
{emit_bin
(LE_OP
);}
388 | relational_expression GE_OP additive_expression
{emit_bin
(GE_OP
);}
392 : relational_expression
393 | equality_expression EQ_OP relational_expression
{emit_bin
(EQ_OP
);}
394 | equality_expression NE_OP relational_expression
{emit_bin
(NE_OP
);}
398 : equality_expression
399 | and_expression
'&' equality_expression
{emit_bin
('&');}
402 exclusive_or_expression
404 | exclusive_or_expression
'^' and_expression
{emit_bin
('^');}
407 inclusive_or_expression
408 : exclusive_or_expression
409 | inclusive_or_expression
'|' exclusive_or_expression
{emit_bin
('|');}
412 logical_and_expression
413 : inclusive_or_expression
414 | logical_and_expression AND_OP inclusive_or_expression
{emit_bin
(AND_OP
);}
417 logical_or_expression
418 : logical_and_expression
419 | logical_or_expression OR_OP logical_and_expression
{emit_bin
(OR_OP
);}
422 conditional_expression
423 : logical_or_expression
424 | logical_or_expression
'?' expression
':' conditional_expression
{emit_if_else
();}
428 : conditional_expression