2 Copyright (C) 2021-2023 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;
135 btype = loongarch_larch_reloc_name_lookup (NULL, op_c_str);
139 my_getExpression (&id_sym_expr, id_c_str);
140 id_sym_expr.X_add_number += addend;
144 id_sym_expr.X_op = O_constant;
145 id_sym_expr.X_add_number = addend;
148 top->value = id_sym_expr;
156 struct reloc_info *s_top = top - 1;
157 if (is_const (s_top))
159 offsetT opr = s_top->value.X_add_number;
176 s_top->value.X_add_number = opr;
181 as_fatal (_("expr too huge"));
185 top->type = BFD_RELOC_LARCH_SOP_NOT;
190 top->value = const_0;
198 struct reloc_info *last_1st = top - 1, *last_2nd = top - 2;
199 if (is_const (last_1st) && is_const (last_2nd))
201 offsetT opr1 = last_2nd->value.X_add_number;
202 offsetT opr2 = last_1st->value.X_add_number;
224 /* Algorithm right shift. */
225 opr1 = (offsetT)opr1 >> (offsetT)opr2;
263 last_2nd->value.X_add_number = opr1;
270 as_fatal (_("expr too huge"));
274 top->type = BFD_RELOC_LARCH_SOP_ADD;
277 top->type = BFD_RELOC_LARCH_SOP_SUB;
280 top->type = BFD_RELOC_LARCH_SOP_SL;
283 top->type = BFD_RELOC_LARCH_SOP_SR;
286 top->type = BFD_RELOC_LARCH_SOP_AND;
291 top->value = const_0;
299 struct reloc_info *last_1st = top - 1;
300 struct reloc_info *last_2nd = top - 2;
301 struct reloc_info *last_3rd = top - 3;
302 if (is_const (last_1st) && is_const (last_2nd) && is_const (last_3rd))
304 offsetT opr1 = last_3rd->value.X_add_number;
305 offsetT opr2 = last_2nd->value.X_add_number;
306 offsetT opr3 = last_1st->value.X_add_number;
307 opr1 = opr1 ? opr2 : opr3;
308 last_3rd->value.X_add_number = opr1;
316 as_fatal (_("expr too huge"));
317 top->type = BFD_RELOC_LARCH_SOP_IF_ELSE;
318 top->value = const_0;
331 %token <c_str> IDENTIFIER
334 %token LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP
339 : INTEGER {emit_const ($1);}
340 | IDENTIFIER {emit_const_var ($1);}
342 | '%' IDENTIFIER '(' IDENTIFIER addend ')' {reloc ($2, $4, $5); free ($2); free ($4);}
343 | '%' IDENTIFIER '(' INTEGER addend ')' {reloc ($2, NULL, $4 + $5); free ($2);}
347 : addend '-' INTEGER {$$ -= $3;}
348 | addend '+' INTEGER {$$ += $3;}
354 | '+' unary_expression {emit_unary ('+');}
355 | '-' unary_expression {emit_unary ('-');}
356 | '~' unary_expression {emit_unary ('~');}
357 | '!' unary_expression {emit_unary ('!');}
360 multiplicative_expression
362 | multiplicative_expression '*' unary_expression {emit_bin ('*');}
363 | multiplicative_expression '/' unary_expression {emit_bin ('/');}
364 | multiplicative_expression '%' unary_expression {emit_bin ('%');}
368 : multiplicative_expression
369 | additive_expression '+' multiplicative_expression {emit_bin ('+');}
370 | additive_expression '-' multiplicative_expression {emit_bin ('-');}
374 : additive_expression
375 | shift_expression LEFT_OP additive_expression {emit_bin (LEFT_OP);}
376 | shift_expression RIGHT_OP additive_expression {emit_bin (RIGHT_OP);}
379 relational_expression
381 | relational_expression '<' shift_expression {emit_bin ('<');}
382 | relational_expression '>' shift_expression {emit_bin ('>');}
383 | relational_expression LE_OP shift_expression {emit_bin (LE_OP);}
384 | relational_expression GE_OP shift_expression {emit_bin (GE_OP);}
388 : relational_expression
389 | equality_expression EQ_OP relational_expression {emit_bin (EQ_OP);}
390 | equality_expression NE_OP relational_expression {emit_bin (NE_OP);}
394 : equality_expression
395 | and_expression '&' equality_expression {emit_bin ('&');}
398 exclusive_or_expression
400 | exclusive_or_expression '^' and_expression {emit_bin ('^');}
403 inclusive_or_expression
404 : exclusive_or_expression
405 | inclusive_or_expression '|' exclusive_or_expression {emit_bin ('|');}
408 logical_and_expression
409 : inclusive_or_expression
410 | logical_and_expression AND_OP inclusive_or_expression {emit_bin (AND_OP);}
413 logical_or_expression
414 : logical_and_expression
415 | logical_or_expression OR_OP logical_and_expression {emit_bin (OR_OP);}
418 conditional_expression
419 : logical_or_expression
420 | logical_or_expression '?' expression ':' conditional_expression {emit_if_else ();}
424 : conditional_expression