gdb/testsuite: fix gdb.trace/signal.exp on x86
[binutils-gdb/blckswan.git] / gas / config / loongarch-parse.y
blob710f854c74f75594ba16eed3dc8ad373a4d2ebab
1 /*
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)
9 any later version.
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/>. */
20 #include "as.h"
21 #include "loongarch-lex.h"
22 #include "loongarch-parse.h"
23 static void yyerror (const char *s ATTRIBUTE_UNUSED)
26 int yylex (void);
29 static struct reloc_info *top, *end;
31 static expressionS const_0 =
33 .X_op = O_constant,
34 .X_add_number = 0
37 static int
38 is_const (struct reloc_info *info)
40 return (info->type == BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE
41 && info->value.X_op == O_constant);
44 int
45 loongarch_parse_expr (const char *expr,
46 struct reloc_info *reloc_stack_top,
47 size_t max_reloc_num,
48 size_t *reloc_num,
49 offsetT *imm)
51 int ret;
52 struct yy_buffer_state *buffstate;
53 top = reloc_stack_top;
54 end = top + max_reloc_num;
55 buffstate = yy_scan_string (expr);
56 ret = yyparse ();
58 if (ret == 0)
60 if (is_const (top - 1))
61 *imm = (--top)->value.X_add_number;
62 else
63 *imm = 0;
64 *reloc_num = top - reloc_stack_top;
66 yy_delete_buffer (buffstate);
68 return ret;
71 static void
72 emit_const (offsetT imm)
74 if (end <= top)
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;
79 top++;
82 static const char *
83 my_getExpression (expressionS *ep, const char *str)
85 char *save_in, *ret;
86 if (*str == ':')
88 unsigned long j;
89 char *str_1 = (char *) str;
90 str_1++;
91 j = strtol (str_1, &str_1, 10);
92 get_internal_label (ep, j, *str_1 == 'f');
93 return NULL;
95 save_in = input_line_pointer;
96 input_line_pointer = (char *)str;
97 expression (ep);
98 ret = input_line_pointer;
99 input_line_pointer = save_in;
100 return ret;
103 static void
104 reloc (const char *op_c_str, const char *id_c_str, offsetT addend)
106 expressionS id_sym_expr;
108 if (end <= top)
109 as_fatal (_("expr too huge"));
111 if (id_c_str)
113 my_getExpression (&id_sym_expr, id_c_str);
114 id_sym_expr.X_add_number += addend;
116 else
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;
126 top++;
128 else if (strcmp (op_c_str, "pcrel") == 0)
130 top->value = id_sym_expr;
131 top->type = BFD_RELOC_LARCH_SOP_PUSH_PCREL;
132 top++;
134 else if (strcmp (op_c_str, "gprel") == 0)
136 top->value = id_sym_expr;
137 top->type = BFD_RELOC_LARCH_SOP_PUSH_GPREL;
138 top++;
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;
144 top++;
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;
150 top++;
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;
156 top++;
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;
162 top++;
164 else
165 as_fatal (_("unknown reloc hint: %s"), op_c_str);
168 static void
169 emit_unary (char op)
171 struct reloc_info *s_top = top - 1;
172 if (is_const (s_top))
174 offsetT opr = s_top->value.X_add_number;
175 switch (op)
177 case '+':
178 break;
179 case '-':
180 opr = -opr;
181 break;
182 case '~':
183 opr = ~opr;
184 break;
185 case '!':
186 opr = !opr;
187 break;
188 default:
189 abort ();
191 s_top->value.X_add_number = opr;
193 else
195 if (end <= top)
196 as_fatal (_("expr too huge"));
197 switch (op)
199 case '!':
200 top->type = BFD_RELOC_LARCH_SOP_NOT;
201 break;
202 default:
203 abort ();
205 top->value = const_0;
206 top++;
210 static void
211 emit_bin (int op)
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;
218 switch (op)
220 case '*':
221 opr1 = opr1 * opr2;
222 break;
223 case '/':
224 opr1 = opr1 / opr2;
225 break;
226 case '%':
227 opr1 = opr1 % opr2;
228 break;
229 case '+':
230 opr1 = opr1 + opr2;
231 break;
232 case '-':
233 opr1 = opr1 - opr2;
234 break;
235 case LEFT_OP:
236 opr1 = opr1 << opr2;
237 break;
238 case RIGHT_OP:
239 /* Algorithm right shift. */
240 opr1 = (offsetT)opr1 >> (offsetT)opr2;
241 break;
242 case '<':
243 opr1 = opr1 < opr2;
244 break;
245 case '>':
246 opr1 = opr1 > opr2;
247 break;
248 case LE_OP:
249 opr1 = opr1 <= opr2;
250 break;
251 case GE_OP:
252 opr1 = opr1 >= opr2;
253 break;
254 case EQ_OP:
255 opr1 = opr1 == opr2;
256 break;
257 case NE_OP:
258 opr1 = opr1 != opr2;
259 break;
260 case '&':
261 opr1 = opr1 & opr2;
262 break;
263 case '^':
264 opr1 = opr1 ^ opr2;
265 break;
266 case '|':
267 opr1 = opr1 | opr2;
268 break;
269 case AND_OP:
270 opr1 = opr1 && opr2;
271 break;
272 case OR_OP:
273 opr1 = opr1 || opr2;
274 break;
275 default:
276 abort ();
278 last_2nd->value.X_add_number = opr1;
279 last_1st->type = 0;
280 top--;
282 else
284 if (end <= top)
285 as_fatal (_("expr too huge"));
286 switch (op)
288 case '+':
289 top->type = BFD_RELOC_LARCH_SOP_ADD;
290 break;
291 case '-':
292 top->type = BFD_RELOC_LARCH_SOP_SUB;
293 break;
294 case LEFT_OP:
295 top->type = BFD_RELOC_LARCH_SOP_SL;
296 break;
297 case RIGHT_OP:
298 top->type = BFD_RELOC_LARCH_SOP_SR;
299 break;
300 case '&':
301 top->type = BFD_RELOC_LARCH_SOP_AND;
302 break;
303 default:
304 abort ();
306 top->value = const_0;
307 top++;
311 static void
312 emit_if_else (void)
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;
324 last_2nd->type = 0;
325 last_1st->type = 0;
326 top -= 2;
328 else
330 if (end <= top)
331 as_fatal (_("expr too huge"));
332 top->type = BFD_RELOC_LARCH_SOP_IF_ELSE;
333 top->value = const_0;
334 top++;
340 %union {
341 char *c_str;
342 offsetT imm;
345 %token <imm> INTEGER
346 %token <c_str> IDENTIFIER
347 %type <imm> addend
349 %token LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP
350 %start expression
353 primary_expression
354 : INTEGER {emit_const ($1);}
355 | '(' expression ')'
356 | '%' IDENTIFIER '(' IDENTIFIER addend ')' {reloc ($2, $4, $5); free ($2); free ($4);}
357 | '%' IDENTIFIER '(' INTEGER addend ')' {reloc ($2, NULL, $4 + $5); free ($2);}
360 addend
361 : addend '-' INTEGER {$$ -= $3;}
362 | addend '+' INTEGER {$$ += $3;}
363 | {$$ = 0;}
366 unary_expression
367 : primary_expression
368 | '+' unary_expression {emit_unary ('+');}
369 | '-' unary_expression {emit_unary ('-');}
370 | '~' unary_expression {emit_unary ('~');}
371 | '!' unary_expression {emit_unary ('!');}
374 multiplicative_expression
375 : unary_expression
376 | multiplicative_expression '*' unary_expression {emit_bin ('*');}
377 | multiplicative_expression '/' unary_expression {emit_bin ('/');}
378 | multiplicative_expression '%' unary_expression {emit_bin ('%');}
381 additive_expression
382 : multiplicative_expression
383 | additive_expression '+' multiplicative_expression {emit_bin ('+');}
384 | additive_expression '-' multiplicative_expression {emit_bin ('-');}
387 shift_expression
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
394 : shift_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);}
401 equality_expression
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);}
407 and_expression
408 : equality_expression
409 | and_expression '&' equality_expression {emit_bin ('&');}
412 exclusive_or_expression
413 : and_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 ();}
437 expression
438 : conditional_expression