2 Copyright (C) 2021-2022 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
)
89 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 reloc
(const char *op_c_str
, const char *id_c_str
, offsetT addend
)
106 expressionS id_sym_expr
;
109 as_fatal
(_
("expr too huge"));
113 my_getExpression
(&id_sym_expr
, id_c_str
);
114 id_sym_expr.X_add_number
+= addend
;
118 id_sym_expr.X_op
= O_constant
;
119 id_sym_expr.X_add_number
= addend
;
122 if
(strcmp
(op_c_str
, "abs") == 0)
124 top
->value
= id_sym_expr
;
125 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE
;
128 else if
(strcmp
(op_c_str
, "pcrel") == 0)
130 top
->value
= id_sym_expr
;
131 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_PCREL
;
134 else if
(strcmp
(op_c_str
, "gprel") == 0)
136 top
->value
= id_sym_expr
;
137 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_GPREL
;
140 else if
(strcmp
(op_c_str
, "tprel") == 0)
142 top
->value
= id_sym_expr
;
143 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
;
146 else if
(strcmp
(op_c_str
, "tlsgot") == 0)
148 top
->value
= id_sym_expr
;
149 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT
;
152 else if
(strcmp
(op_c_str
, "tlsgd") == 0)
154 top
->value
= id_sym_expr
;
155 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
;
158 else if
(strcmp
(op_c_str
, "plt") == 0)
160 top
->value
= id_sym_expr
;
161 top
->type
= BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL
;
165 as_fatal
(_
("unknown reloc hint: %s"), op_c_str
);
171 struct reloc_info
*s_top
= top
- 1;
172 if
(is_const
(s_top
))
174 offsetT opr
= s_top
->value.X_add_number
;
191 s_top
->value.X_add_number
= opr
;
196 as_fatal
(_
("expr too huge"));
200 top
->type
= BFD_RELOC_LARCH_SOP_NOT
;
205 top
->value
= const_0
;
213 struct reloc_info
*last_1st
= top
- 1, *last_2nd
= top
- 2;
214 if
(is_const
(last_1st
) && is_const
(last_2nd
))
216 offsetT opr1
= last_2nd
->value.X_add_number
;
217 offsetT opr2
= last_1st
->value.X_add_number
;
239 /* Algorithm right shift. */
240 opr1
= (offsetT
)opr1
>> (offsetT
)opr2
;
278 last_2nd
->value.X_add_number
= opr1
;
285 as_fatal
(_
("expr too huge"));
289 top
->type
= BFD_RELOC_LARCH_SOP_ADD
;
292 top
->type
= BFD_RELOC_LARCH_SOP_SUB
;
295 top
->type
= BFD_RELOC_LARCH_SOP_SL
;
298 top
->type
= BFD_RELOC_LARCH_SOP_SR
;
301 top
->type
= BFD_RELOC_LARCH_SOP_AND
;
306 top
->value
= const_0
;
314 struct reloc_info
*last_1st
= top
- 1;
315 struct reloc_info
*last_2nd
= top
- 2;
316 struct reloc_info
*last_3rd
= top
- 3;
317 if
(is_const
(last_1st
) && is_const
(last_2nd
) && is_const
(last_3rd
))
319 offsetT opr1
= last_3rd
->value.X_add_number
;
320 offsetT opr2
= last_2nd
->value.X_add_number
;
321 offsetT opr3
= last_1st
->value.X_add_number
;
322 opr1
= opr1 ? opr2
: opr3
;
323 last_3rd
->value.X_add_number
= opr1
;
331 as_fatal
(_
("expr too huge"));
332 top
->type
= BFD_RELOC_LARCH_SOP_IF_ELSE
;
333 top
->value
= const_0
;
346 %token
<c_str
> IDENTIFIER
349 %token LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP
354 : INTEGER
{emit_const
($1);}
356 |
'%' IDENTIFIER
'(' IDENTIFIER addend
')' {reloc
($2, $4, $5); free
($2); free
($4);}
357 |
'%' IDENTIFIER
'(' INTEGER addend
')' {reloc
($2, NULL
, $4 + $5); free
($2);}
361 : addend
'-' INTEGER
{$$
-= $3;}
362 | addend
'+' INTEGER
{$$
+= $3;}
368 |
'+' unary_expression
{emit_unary
('+');}
369 |
'-' unary_expression
{emit_unary
('-');}
370 |
'~' unary_expression
{emit_unary
('~');}
371 |
'!' unary_expression
{emit_unary
('!');}
374 multiplicative_expression
376 | multiplicative_expression
'*' unary_expression
{emit_bin
('*');}
377 | multiplicative_expression
'/' unary_expression
{emit_bin
('/');}
378 | multiplicative_expression
'%' unary_expression
{emit_bin
('%');}
382 : multiplicative_expression
383 | additive_expression
'+' multiplicative_expression
{emit_bin
('+');}
384 | additive_expression
'-' multiplicative_expression
{emit_bin
('-');}
388 : additive_expression
389 | shift_expression LEFT_OP additive_expression
{emit_bin
(LEFT_OP
);}
390 | shift_expression RIGHT_OP additive_expression
{emit_bin
(RIGHT_OP
);}
393 relational_expression
395 | relational_expression
'<' shift_expression
{emit_bin
('<');}
396 | relational_expression
'>' shift_expression
{emit_bin
('>');}
397 | relational_expression LE_OP shift_expression
{emit_bin
(LE_OP
);}
398 | relational_expression GE_OP shift_expression
{emit_bin
(GE_OP
);}
402 : relational_expression
403 | equality_expression EQ_OP relational_expression
{emit_bin
(EQ_OP
);}
404 | equality_expression NE_OP relational_expression
{emit_bin
(NE_OP
);}
408 : equality_expression
409 | and_expression
'&' equality_expression
{emit_bin
('&');}
412 exclusive_or_expression
414 | exclusive_or_expression
'^' and_expression
{emit_bin
('^');}
417 inclusive_or_expression
418 : exclusive_or_expression
419 | inclusive_or_expression
'|' exclusive_or_expression
{emit_bin
('|');}
422 logical_and_expression
423 : inclusive_or_expression
424 | logical_and_expression AND_OP inclusive_or_expression
{emit_bin
(AND_OP
);}
427 logical_or_expression
428 : logical_and_expression
429 | logical_or_expression OR_OP logical_and_expression
{emit_bin
(OR_OP
);}
432 conditional_expression
433 : logical_or_expression
434 | logical_or_expression
'?' expression
':' conditional_expression
{emit_if_else
();}
438 : conditional_expression