1 /* rx-parse.y Renesas RX parser 2 Copyright (C) 2008-2014 Free Software Foundation, Inc. 3 4 This file is part of GAS, the GNU Assembler. 5 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. 10 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. 15 16 You should have received a copy of the GNU General Public License 17 along with GAS; see the file COPYING. If not, write to the Free 18 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 19 02110-1301, USA. */ 20 %{ 21 22 #include "as.h" 23 #include "safe-ctype.h" 24 #include "rx-defs.h" 25 26 static int rx_lex (void); 27 28 #define COND_EQ 0 29 #define COND_NE 1 30 31 #define MEMEX 0x06 32 33 #define BSIZE 0 34 #define WSIZE 1 35 #define LSIZE 2 36 37 /* .sb .sw .l .uw */ 38 static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE }; 39 40 /* Ok, here are the rules for using these macros... 41 42 B*() is used to specify the base opcode bytes. Fields to be filled 43 in later, leave zero. Call this first. 44 45 F() and FE() are used to fill in fields within the base opcode bytes. You MUST 46 call B*() before any F() or FE(). 47 48 [UN]*O*(), PC*() appends operands to the end of the opcode. You 49 must call P() and B*() before any of these, so that the fixups 50 have the right byte location. 51 O = signed, UO = unsigned, NO = negated, PC = pcrel 52 53 IMM() adds an immediate and fills in the field for it. 54 NIMM() same, but negates the immediate. 55 NBIMM() same, but negates the immediate, for sbb. 56 DSP() adds a displacement, and fills in the field for it. 57 58 Note that order is significant for the O, IMM, and DSP macros, as 59 they append their data to the operand buffer in the order that you 60 call them. 61 62 Use "disp" for displacements whenever possible; this handles the 63 "0" case properly. */ 64 65 #define B1(b1) rx_base1 (b1) 66 #define B2(b1, b2) rx_base2 (b1, b2) 67 #define B3(b1, b2, b3) rx_base3 (b1, b2, b3) 68 #define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4) 69 70 /* POS is bits from the MSB of the first byte to the LSB of the last byte. */ 71 #define F(val,pos,sz) rx_field (val, pos, sz) 72 #define FE(exp,pos,sz) rx_field (exp_val (exp), pos, sz); 73 74 #define O1(v) rx_op (v, 1, RXREL_SIGNED); rx_range (v, -128, 255) 75 #define O2(v) rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536) 76 #define O3(v) rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216) 77 #define O4(v) rx_op (v, 4, RXREL_SIGNED) 78 79 #define UO1(v) rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255) 80 #define UO2(v) rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536) 81 #define UO3(v) rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216) 82 #define UO4(v) rx_op (v, 4, RXREL_UNSIGNED) 83 84 #define NO1(v) rx_op (v, 1, RXREL_NEGATIVE) 85 #define NO2(v) rx_op (v, 2, RXREL_NEGATIVE) 86 #define NO3(v) rx_op (v, 3, RXREL_NEGATIVE) 87 #define NO4(v) rx_op (v, 4, RXREL_NEGATIVE) 88 89 #define PC1(v) rx_op (v, 1, RXREL_PCREL) 90 #define PC2(v) rx_op (v, 2, RXREL_PCREL) 91 #define PC3(v) rx_op (v, 3, RXREL_PCREL) 92 93 #define IMM_(v,pos,size) F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \ 94 if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos) 95 #define IMM(v,pos) IMM_ (v, pos, 32) 96 #define IMMW(v,pos) IMM_ (v, pos, 16); rx_range (v, -32768, 65536) 97 #define IMMB(v,pos) IMM_ (v, pos, 8); rx_range (v, -128, 255) 98 #define NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2) 99 #define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2) 100 #define DSP(v,pos,msz) if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \ 101 else rx_linkrelax_dsp (pos); \ 102 F (displacement (v, msz), pos, 2) 103 104 #define id24(a,b2,b3) B3 (0xfb+a, b2, b3) 105 106 static void rx_check_float_support (void); 107 static int rx_intop (expressionS, int, int); 108 static int rx_uintop (expressionS, int); 109 static int rx_disp3op (expressionS); 110 static int rx_disp5op (expressionS *, int); 111 static int rx_disp5op0 (expressionS *, int); 112 static int exp_val (expressionS exp); 113 static expressionS zero_expr (void); 114 static int immediate (expressionS, int, int, int); 115 static int displacement (expressionS, int); 116 static void rtsd_immediate (expressionS); 117 static void rx_range (expressionS, int, int); 118 119 static int need_flag = 0; 120 static int rx_in_brackets = 0; 121 static int rx_last_token = 0; 122 static char * rx_init_start; 123 static char * rx_last_exp_start = 0; 124 static int sub_op; 125 static int sub_op2; 126 127 #define YYDEBUG 1 128 #define YYERROR_VERBOSE 1 129 130 %} 131 132 %name-prefix="rx_" 133 134 %union { 135 int regno; 136 expressionS exp; 137 } 138 139 %type <regno> REG FLAG CREG BCND BMCND SCCND 140 %type <regno> flag bwl bw memex 141 %type <exp> EXPR disp 142 143 %token REG FLAG CREG 144 145 %token EXPR UNKNOWN_OPCODE IS_OPCODE 146 147 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW 148 149 %token ABS ADC ADD AND_ 150 %token BCLR BCND BMCND BNOT BRA BRK BSET BSR BTST 151 %token CLRPSW CMP 152 %token DBT DIV DIVU 153 %token EDIV EDIVU EMUL EMULU 154 %token FADD FCMP FDIV FMUL FREIT FSUB FTOI 155 %token INT ITOF 156 %token JMP JSR 157 %token MACHI MACLO MAX MIN MOV MOVU MUL MULHI MULLO MULU MVFACHI MVFACMI MVFACLO 158 %token MVFC MVTACHI MVTACLO MVTC MVTIPL 159 %token NEG NOP NOT 160 %token OR 161 %token POP POPC POPM PUSH PUSHA PUSHC PUSHM 162 %token RACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND RTE RTFI RTS RTSD 163 %token SAT SATR SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF 164 %token SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE 165 %token TST 166 %token WAIT 167 %token XCHG XOR 168 169 %% 170 /* ====================================================================== */ 171 172 statement : 173 174 UNKNOWN_OPCODE 175 { as_bad (_("Unknown opcode: %s"), rx_init_start); } 176 177 /* ---------------------------------------------------------------------- */ 178 179 | BRK 180 { B1 (0x00); } 181 182 | DBT 183 { B1 (0x01); } 184 185 | RTS 186 { B1 (0x02); } 187 188 | NOP 189 { B1 (0x03); } 190 191 /* ---------------------------------------------------------------------- */ 192 193 | BRA EXPR 194 { if (rx_disp3op ($2)) 195 { B1 (0x08); rx_disp3 ($2, 5); } 196 else if (rx_intop ($2, 8, 8)) 197 { B1 (0x2e); PC1 ($2); } 198 else if (rx_intop ($2, 16, 16)) 199 { B1 (0x38); PC2 ($2); } 200 else if (rx_intop ($2, 24, 24)) 201 { B1 (0x04); PC3 ($2); } 202 else 203 { rx_relax (RX_RELAX_BRANCH, 0); 204 rx_linkrelax_branch (); 205 /* We'll convert this to a longer one later if needed. */ 206 B1 (0x08); rx_disp3 ($2, 5); } } 207 208 | BRA DOT_A EXPR 209 { B1 (0x04); PC3 ($3); } 210 211 | BRA DOT_S EXPR 212 { B1 (0x08); rx_disp3 ($3, 5); } 213 214 /* ---------------------------------------------------------------------- */ 215 216 | BSR EXPR 217 { if (rx_intop ($2, 16, 16)) 218 { B1 (0x39); PC2 ($2); } 219 else if (rx_intop ($2, 24, 24)) 220 { B1 (0x05); PC3 ($2); } 221 else 222 { rx_relax (RX_RELAX_BRANCH, 0); 223 rx_linkrelax_branch (); 224 B1 (0x39); PC2 ($2); } } 225 | BSR DOT_A EXPR 226 { B1 (0x05), PC3 ($3); } 227 228 /* ---------------------------------------------------------------------- */ 229 230 | BCND DOT_S EXPR 231 { if ($1 == COND_EQ || $1 == COND_NE) 232 { B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($3, 5); } 233 else 234 as_bad (_("Only BEQ and BNE may have .S")); } 235 236 /* ---------------------------------------------------------------------- */ 237 238 | BCND DOT_B EXPR 239 { B1 (0x20); F ($1, 4, 4); PC1 ($3); } 240 241 | BRA DOT_B EXPR 242 { B1 (0x2e), PC1 ($3); } 243 244 /* ---------------------------------------------------------------------- */ 245 246 | BRA DOT_W EXPR 247 { B1 (0x38), PC2 ($3); } 248 | BSR DOT_W EXPR 249 { B1 (0x39), PC2 ($3); } 250 | BCND DOT_W EXPR 251 { if ($1 == COND_EQ || $1 == COND_NE) 252 { B1 ($1 == COND_EQ ? 0x3a : 0x3b); PC2 ($3); } 253 else 254 as_bad (_("Only BEQ and BNE may have .W")); } 255 | BCND EXPR 256 { if ($1 == COND_EQ || $1 == COND_NE) 257 { 258 rx_relax (RX_RELAX_BRANCH, 0); 259 rx_linkrelax_branch (); 260 B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($2, 5); 261 } 262 else 263 { 264 rx_relax (RX_RELAX_BRANCH, 0); 265 /* This is because we might turn it into a 266 jump-over-jump long branch. */ 267 rx_linkrelax_branch (); 268 B1 (0x20); F ($1, 4, 4); PC1 ($2); 269 } } 270 271 /* ---------------------------------------------------------------------- */ 272 273 | MOV DOT_B '#' EXPR ',' disp '[' REG ']' 274 /* rx_disp5op changes the value if it succeeds, so keep it last. */ 275 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE)) 276 { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); } 277 else 278 { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4); 279 if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } } 280 281 | MOV DOT_W '#' EXPR ',' disp '[' REG ']' 282 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE)) 283 { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); } 284 else 285 { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMMW ($4, 12); } } 286 287 | MOV DOT_L '#' EXPR ',' disp '[' REG ']' 288 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE)) 289 { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); } 290 else 291 { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } } 292 293 /* ---------------------------------------------------------------------- */ 294 295 | RTSD '#' EXPR ',' REG '-' REG 296 { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3); 297 if ($5 == 0) 298 rx_error (_("RTSD cannot pop R0")); 299 if ($5 > $7) 300 rx_error (_("RTSD first reg must be <= second reg")); } 301 302 /* ---------------------------------------------------------------------- */ 303 304 | CMP REG ',' REG 305 { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); } 306 307 /* ---------------------------------------------------------------------- */ 308 309 | CMP disp '[' REG ']' DOT_UB ',' REG 310 { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); } 311 312 | CMP disp '[' REG ']' memex ',' REG 313 { B3 (MEMEX, 0x04, 0); F ($6, 8, 2); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); } 314 315 /* ---------------------------------------------------------------------- */ 316 317 | MOVU bw REG ',' REG 318 { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); } 319 320 /* ---------------------------------------------------------------------- */ 321 322 | MOVU bw '[' REG ']' ',' REG 323 { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); } 324 325 | MOVU bw EXPR '[' REG ']' ',' REG 326 { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2)) 327 { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); } 328 else 329 { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } } 330 331 /* ---------------------------------------------------------------------- */ 332 333 | SUB '#' EXPR ',' REG 334 { if (rx_uintop ($3, 4)) 335 { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); } 336 else 337 /* This is really an add, but we negate the immediate. */ 338 { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } } 339 340 | CMP '#' EXPR ',' REG 341 { if (rx_uintop ($3, 4)) 342 { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); } 343 else if (rx_uintop ($3, 8)) 344 { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); } 345 else 346 { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } } 347 348 | ADD '#' EXPR ',' REG 349 { if (rx_uintop ($3, 4)) 350 { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); } 351 else 352 { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } } 353 354 | MUL '#' EXPR ',' REG 355 { if (rx_uintop ($3, 4)) 356 { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); } 357 else 358 { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } } 359 360 | AND_ '#' EXPR ',' REG 361 { if (rx_uintop ($3, 4)) 362 { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); } 363 else 364 { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } } 365 366 | OR '#' EXPR ',' REG 367 { if (rx_uintop ($3, 4)) 368 { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); } 369 else 370 { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } } 371 372 | MOV DOT_L '#' EXPR ',' REG 373 { if (rx_uintop ($4, 4)) 374 { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); } 375 else if (rx_uintop ($4, 8)) 376 { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); } 377 else 378 { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } } 379 380 | MOV '#' EXPR ',' REG 381 { if (rx_uintop ($3, 4)) 382 { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); } 383 else if (rx_uintop ($3, 8)) 384 { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); } 385 else 386 { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } } 387 388 /* ---------------------------------------------------------------------- */ 389 390 | RTSD '#' EXPR 391 { B1 (0x67); rtsd_immediate ($3); } 392 393 /* ---------------------------------------------------------------------- */ 394 395 | SHLR { sub_op = 0; } op_shift 396 | SHAR { sub_op = 1; } op_shift 397 | SHLL { sub_op = 2; } op_shift 398 399 /* ---------------------------------------------------------------------- */ 400 401 | PUSHM REG '-' REG 402 { 403 if ($2 == $4) 404 { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); } 405 else 406 { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); } 407 if ($2 == 0) 408 rx_error (_("PUSHM cannot push R0")); 409 if ($2 > $4) 410 rx_error (_("PUSHM first reg must be <= second reg")); } 411 412 /* ---------------------------------------------------------------------- */ 413 414 | POPM REG '-' REG 415 { 416 if ($2 == $4) 417 { B2 (0x7e, 0xb0); F ($2, 12, 4); } 418 else 419 { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); } 420 if ($2 == 0) 421 rx_error (_("POPM cannot pop R0")); 422 if ($2 > $4) 423 rx_error (_("POPM first reg must be <= second reg")); } 424 425 /* ---------------------------------------------------------------------- */ 426 427 | ADD '#' EXPR ',' REG ',' REG 428 { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); } 429 430 /* ---------------------------------------------------------------------- */ 431 432 | INT '#' EXPR 433 { B2(0x75, 0x60), UO1 ($3); } 434 435 /* ---------------------------------------------------------------------- */ 436 437 | BSET '#' EXPR ',' REG 438 { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); } 439 | BCLR '#' EXPR ',' REG 440 { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); } 441 442 /* ---------------------------------------------------------------------- */ 443 444 | BTST '#' EXPR ',' REG 445 { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); } 446 447 /* ---------------------------------------------------------------------- */ 448 449 | SAT REG 450 { B2 (0x7e, 0x30); F ($2, 12, 4); } 451 | RORC REG 452 { B2 (0x7e, 0x40); F ($2, 12, 4); } 453 | ROLC REG 454 { B2 (0x7e, 0x50); F ($2, 12, 4); } 455 456 /* ---------------------------------------------------------------------- */ 457 458 | PUSH bwl REG 459 { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); } 460 461 /* ---------------------------------------------------------------------- */ 462 463 | POP REG 464 { B2 (0x7e, 0xb0); F ($2, 12, 4); } 465 466 /* ---------------------------------------------------------------------- */ 467 468 | PUSHC CREG 469 { if ($2 < 16) 470 { B2 (0x7e, 0xc0); F ($2, 12, 4); } 471 else 472 as_bad (_("PUSHC can only push the first 16 control registers")); } 473 474 /* ---------------------------------------------------------------------- */ 475 476 | POPC CREG 477 { if ($2 < 16) 478 { B2 (0x7e, 0xe0); F ($2, 12, 4); } 479 else 480 as_bad (_("POPC can only pop the first 16 control registers")); } 481 482 /* ---------------------------------------------------------------------- */ 483 484 | SETPSW flag 485 { B2 (0x7f, 0xa0); F ($2, 12, 4); } 486 | CLRPSW flag 487 { B2 (0x7f, 0xb0); F ($2, 12, 4); } 488 489 /* ---------------------------------------------------------------------- */ 490 491 | JMP REG 492 { B2 (0x7f, 0x00); F ($2, 12, 4); } 493 | JSR REG 494 { B2 (0x7f, 0x10); F ($2, 12, 4); } 495 | BRA opt_l REG 496 { B2 (0x7f, 0x40); F ($3, 12, 4); } 497 | BSR opt_l REG 498 { B2 (0x7f, 0x50); F ($3, 12, 4); } 499 500 /* ---------------------------------------------------------------------- */ 501 502 | SCMPU 503 { B2 (0x7f, 0x83); } 504 | SMOVU 505 { B2 (0x7f, 0x87); } 506 | SMOVB 507 { B2 (0x7f, 0x8b); } 508 | SMOVF 509 { B2 (0x7f, 0x8f); } 510 511 /* ---------------------------------------------------------------------- */ 512 513 | SUNTIL bwl 514 { B2 (0x7f, 0x80); F ($2, 14, 2); } 515 | SWHILE bwl 516 { B2 (0x7f, 0x84); F ($2, 14, 2); } 517 | SSTR bwl 518 { B2 (0x7f, 0x88); F ($2, 14, 2); } 519 520 /* ---------------------------------------------------------------------- */ 521 522 | RMPA bwl 523 { B2 (0x7f, 0x8c); F ($2, 14, 2); } 524 525 /* ---------------------------------------------------------------------- */ 526 527 | RTFI 528 { B2 (0x7f, 0x94); } 529 | RTE 530 { B2 (0x7f, 0x95); } 531 | WAIT 532 { B2 (0x7f, 0x96); } 533 | SATR 534 { B2 (0x7f, 0x93); } 535 536 /* ---------------------------------------------------------------------- */ 537 538 | MVTIPL '#' EXPR 539 { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); } 540 541 /* ---------------------------------------------------------------------- */ 542 543 /* rx_disp5op changes the value if it succeeds, so keep it last. */ 544 | MOV bwl REG ',' EXPR '[' REG ']' 545 { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2)) 546 { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); } 547 else 548 { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }} 549 550 /* ---------------------------------------------------------------------- */ 551 552 | MOV bwl EXPR '[' REG ']' ',' REG 553 { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2)) 554 { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); } 555 else 556 { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } } 557 558 /* ---------------------------------------------------------------------- */ 559 560 /* MOV a,b - if a is a reg and b is mem, src and dest are 561 swapped. */ 562 563 /* We don't use "disp" here because it causes a shift/reduce 564 conflict with the other displacement-less patterns. */ 565 566 | MOV bwl REG ',' '[' REG ']' 567 { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); } 568 569 /* ---------------------------------------------------------------------- */ 570 571 | MOV bwl '[' REG ']' ',' disp '[' REG ']' 572 { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); } 573 574 /* ---------------------------------------------------------------------- */ 575 576 | MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']' 577 { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); } 578 579 /* ---------------------------------------------------------------------- */ 580 581 | MOV bwl REG ',' REG 582 { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); } 583 584 /* ---------------------------------------------------------------------- */ 585 586 | MOV bwl '[' REG ']' ',' REG 587 { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); } 588 589 /* ---------------------------------------------------------------------- */ 590 591 | BSET '#' EXPR ',' disp '[' REG ']' DOT_B 592 { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); } 593 | BCLR '#' EXPR ',' disp '[' REG ']' DOT_B 594 { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); } 595 | BTST '#' EXPR ',' disp '[' REG ']' DOT_B 596 { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); } 597 598 /* ---------------------------------------------------------------------- */ 599 600 | PUSH bwl disp '[' REG ']' 601 { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); } 602 603 /* ---------------------------------------------------------------------- */ 604 605 | SBB { sub_op = 0; } op_dp20_rm_l 606 | NEG { sub_op = 1; sub_op2 = 1; } op_dp20_rr 607 | ADC { sub_op = 2; } op_dp20_rim_l 608 | ABS { sub_op = 3; sub_op2 = 2; } op_dp20_rr 609 | MAX { sub_op = 4; } op_dp20_rim 610 | MIN { sub_op = 5; } op_dp20_rim 611 | EMUL { sub_op = 6; } op_dp20_i 612 | EMULU { sub_op = 7; } op_dp20_i 613 | DIV { sub_op = 8; } op_dp20_rim 614 | DIVU { sub_op = 9; } op_dp20_rim 615 | TST { sub_op = 12; } op_dp20_rim 616 | XOR { sub_op = 13; } op_dp20_rim 617 | NOT { sub_op = 14; sub_op2 = 0; } op_dp20_rr 618 | STZ { sub_op = 14; } op_dp20_i 619 | STNZ { sub_op = 15; } op_dp20_i 620 621 /* ---------------------------------------------------------------------- */ 622 623 | EMUL { sub_op = 6; } op_xchg 624 | EMULU { sub_op = 7; } op_xchg 625 | XCHG { sub_op = 16; } op_xchg 626 | ITOF { sub_op = 17; } op_xchg 627 628 /* ---------------------------------------------------------------------- */ 629 630 | BSET REG ',' REG 631 { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); } 632 | BCLR REG ',' REG 633 { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); } 634 | BTST REG ',' REG 635 { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); } 636 | BNOT REG ',' REG 637 { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); } 638 639 | BSET REG ',' disp '[' REG ']' opt_b 640 { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } 641 | BCLR REG ',' disp '[' REG ']' opt_b 642 { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } 643 | BTST REG ',' disp '[' REG ']' opt_b 644 { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } 645 | BNOT REG ',' disp '[' REG ']' opt_b 646 { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } 647 648 /* ---------------------------------------------------------------------- */ 649 650 | FSUB { sub_op = 0; } float2_op 651 | FCMP { sub_op = 1; } float2_op 652 | FADD { sub_op = 2; } float2_op 653 | FMUL { sub_op = 3; } float2_op 654 | FDIV { sub_op = 4; } float2_op 655 | FTOI { sub_op = 5; } float2_op_ni 656 | ROUND { sub_op = 6; } float2_op_ni 657 658 /* ---------------------------------------------------------------------- */ 659 660 | SCCND DOT_L REG 661 { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); } 662 | SCCND bwl disp '[' REG ']' 663 { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); } 664 665 /* ---------------------------------------------------------------------- */ 666 667 | BMCND '#' EXPR ',' disp '[' REG ']' opt_b 668 { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3); 669 F ($7, 16, 4); DSP ($5, 14, BSIZE); } 670 671 /* ---------------------------------------------------------------------- */ 672 673 | BNOT '#' EXPR ',' disp '[' REG ']' opt_b 674 { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4); 675 DSP ($5, 14, BSIZE); } 676 677 /* ---------------------------------------------------------------------- */ 678 679 | MULHI REG ',' REG 680 { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); } 681 | MULLO REG ',' REG 682 { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); } 683 | MACHI REG ',' REG 684 { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); } 685 | MACLO REG ',' REG 686 { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); } 687 688 /* ---------------------------------------------------------------------- */ 689 690 /* We don't have syntax for these yet. */ 691 | MVTACHI REG 692 { id24 (2, 0x17, 0x00); F ($2, 20, 4); } 693 | MVTACLO REG 694 { id24 (2, 0x17, 0x10); F ($2, 20, 4); } 695 | MVFACHI REG 696 { id24 (2, 0x1f, 0x00); F ($2, 20, 4); } 697 | MVFACMI REG 698 { id24 (2, 0x1f, 0x20); F ($2, 20, 4); } 699 | MVFACLO REG 700 { id24 (2, 0x1f, 0x10); F ($2, 20, 4); } 701 702 | RACW '#' EXPR 703 { id24 (2, 0x18, 0x00); 704 if (rx_uintop ($3, 4) && $3.X_add_number == 1) 705 ; 706 else if (rx_uintop ($3, 4) && $3.X_add_number == 2) 707 F (1, 19, 1); 708 else 709 as_bad (_("RACW expects #1 or #2"));} 710 711 /* ---------------------------------------------------------------------- */ 712 713 | MOV bwl REG ',' '[' REG '+' ']' 714 { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); } 715 | MOV bwl REG ',' '[' '-' REG ']' 716 { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); } 717 718 /* ---------------------------------------------------------------------- */ 719 720 | MOV bwl '[' REG '+' ']' ',' REG 721 { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); } 722 | MOV bwl '[' '-' REG ']' ',' REG 723 { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); } 724 725 /* ---------------------------------------------------------------------- */ 726 727 | MOVU bw '[' REG '+' ']' ',' REG 728 { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); } 729 | MOVU bw '[' '-' REG ']' ',' REG 730 { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); } 731 732 /* ---------------------------------------------------------------------- */ 733 734 | ROTL { sub_op = 6; } op_shift_rot 735 | ROTR { sub_op = 4; } op_shift_rot 736 | REVW { sub_op = 5; } op_shift_rot 737 | REVL { sub_op = 7; } op_shift_rot 738 739 /* ---------------------------------------------------------------------- */ 740 741 | MVTC REG ',' CREG 742 { id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1); 743 F ($2, 16, 4); } 744 745 /* ---------------------------------------------------------------------- */ 746 747 | MVFC CREG ',' REG 748 { id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); } 749 750 /* ---------------------------------------------------------------------- */ 751 752 | ROTL '#' EXPR ',' REG 753 { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); } 754 | ROTR '#' EXPR ',' REG 755 { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); } 756 757 /* ---------------------------------------------------------------------- */ 758 759 | MVTC '#' EXPR ',' CREG 760 { id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); } 761 762 /* ---------------------------------------------------------------------- */ 763 764 | BMCND '#' EXPR ',' REG 765 { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5); 766 F ($5, 20, 4); } 767 768 /* ---------------------------------------------------------------------- */ 769 770 | BNOT '#' EXPR ',' REG 771 { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); } 772 773 /* ---------------------------------------------------------------------- */ 774 775 | MOV bwl REG ',' '[' REG ',' REG ']' 776 { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); } 777 778 | MOV bwl '[' REG ',' REG ']' ',' REG 779 { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); } 780 781 | MOVU bw '[' REG ',' REG ']' ',' REG 782 { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); } 783 784 /* ---------------------------------------------------------------------- */ 785 786 | SUB { sub_op = 0; } op_subadd 787 | ADD { sub_op = 2; } op_subadd 788 | MUL { sub_op = 3; } op_subadd 789 | AND_ { sub_op = 4; } op_subadd 790 | OR { sub_op = 5; } op_subadd 791 792 /* ---------------------------------------------------------------------- */ 793 /* There is no SBB #imm so we fake it with ADC. */ 794 795 | SBB '#' EXPR ',' REG 796 { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); } 797 798 /* ---------------------------------------------------------------------- */ 799 800 ; 801 802 /* ====================================================================== */ 803 804 op_subadd 805 : REG ',' REG 806 { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); } 807 | disp '[' REG ']' DOT_UB ',' REG 808 { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); } 809 | disp '[' REG ']' memex ',' REG 810 { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); } 811 | REG ',' REG ',' REG 812 { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); } 813 ; 814 815 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */ 816 817 op_dp20_rm_l 818 : REG ',' REG 819 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); } 820 | disp '[' REG ']' opt_l ',' REG 821 { B4 (MEMEX, 0xa0, 0x00 + sub_op, 0x00); 822 F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, LSIZE); } 823 ; 824 825 /* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */ 826 827 op_dp20_rm 828 : REG ',' REG 829 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); } 830 | disp '[' REG ']' DOT_UB ',' REG 831 { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); } 832 | disp '[' REG ']' memex ',' REG 833 { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00); 834 F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); } 835 ; 836 837 op_dp20_i 838 : '#' EXPR ',' REG 839 { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); } 840 ; 841 842 op_dp20_rim 843 : op_dp20_rm 844 | op_dp20_i 845 ; 846 847 op_dp20_rim_l 848 : op_dp20_rm_l 849 | op_dp20_i 850 ; 851 852 op_dp20_rr 853 : REG ',' REG 854 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); } 855 | REG 856 { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); } 857 ; 858 859 /* xchg, itof, emul, emulu */ 860 op_xchg 861 : REG ',' REG 862 { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); } 863 | disp '[' REG ']' DOT_UB ',' REG 864 { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); } 865 | disp '[' REG ']' memex ',' REG 866 { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4); 867 DSP ($1, 14, sizemap[$5]); } 868 ; 869 870 /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */ 871 op_shift_rot 872 : REG ',' REG 873 { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); } 874 ; 875 op_shift 876 : '#' EXPR ',' REG 877 { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); } 878 | '#' EXPR ',' REG ',' REG 879 { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); } 880 | op_shift_rot 881 ; 882 883 884 float2_op 885 : { rx_check_float_support (); } 886 '#' EXPR ',' REG 887 { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); } 888 | float2_op_ni 889 ; 890 891 float2_op_ni 892 : { rx_check_float_support (); } 893 REG ',' REG 894 { id24 (1, 0x83 + (sub_op << 2), 0); F ($2, 16, 4); F ($4, 20, 4); } 895 | { rx_check_float_support (); } 896 disp '[' REG ']' opt_l ',' REG 897 { id24 (1, 0x80 + (sub_op << 2), 0); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, LSIZE); } 898 ; 899 900 /* ====================================================================== */ 901 902 disp : { $$ = zero_expr (); } 903 | EXPR { $$ = $1; } 904 ; 905 906 flag : { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; } 907 ; 908 909 /* DOT_UB is not listed here, it's handled with a separate pattern. */ 910 /* Use sizemap[$n] to get LSIZE etc. */ 911 memex : DOT_B { $$ = 0; } 912 | DOT_W { $$ = 1; } 913 | { $$ = 2; } 914 | DOT_L { $$ = 2; } 915 | DOT_UW { $$ = 3; } 916 ; 917 918 bwl : { $$ = LSIZE; } 919 | DOT_B { $$ = BSIZE; } 920 | DOT_W { $$ = WSIZE; } 921 | DOT_L { $$ = LSIZE; } 922 ; 923 924 bw : { $$ = 1; } 925 | DOT_B { $$ = 0; } 926 | DOT_W { $$ = 1; } 927 ; 928 929 opt_l : {} 930 | DOT_L {} 931 ; 932 933 opt_b : {} 934 | DOT_B {} 935 ; 936 937 %% 938 /* ====================================================================== */ 939 940 static struct 941 { 942 const char * string; 943 int token; 944 int val; 945 } 946 token_table[] = 947 { 948 { "r0", REG, 0 }, 949 { "r1", REG, 1 }, 950 { "r2", REG, 2 }, 951 { "r3", REG, 3 }, 952 { "r4", REG, 4 }, 953 { "r5", REG, 5 }, 954 { "r6", REG, 6 }, 955 { "r7", REG, 7 }, 956 { "r8", REG, 8 }, 957 { "r9", REG, 9 }, 958 { "r10", REG, 10 }, 959 { "r11", REG, 11 }, 960 { "r12", REG, 12 }, 961 { "r13", REG, 13 }, 962 { "r14", REG, 14 }, 963 { "r15", REG, 15 }, 964 965 { "psw", CREG, 0 }, 966 { "pc", CREG, 1 }, 967 { "usp", CREG, 2 }, 968 { "fpsw", CREG, 3 }, 969 /* reserved */ 970 /* reserved */ 971 /* reserved */ 972 { "wr", CREG, 7 }, 973 974 { "bpsw", CREG, 8 }, 975 { "bpc", CREG, 9 }, 976 { "isp", CREG, 10 }, 977 { "fintv", CREG, 11 }, 978 { "intb", CREG, 12 }, 979 980 { "pbp", CREG, 16 }, 981 { "pben", CREG, 17 }, 982 983 { "bbpsw", CREG, 24 }, 984 { "bbpc", CREG, 25 }, 985 986 { ".s", DOT_S, 0 }, 987 { ".b", DOT_B, 0 }, 988 { ".w", DOT_W, 0 }, 989 { ".l", DOT_L, 0 }, 990 { ".a", DOT_A , 0}, 991 { ".ub", DOT_UB, 0 }, 992 { ".uw", DOT_UW , 0}, 993 994 { "c", FLAG, 0 }, 995 { "z", FLAG, 1 }, 996 { "s", FLAG, 2 }, 997 { "o", FLAG, 3 }, 998 { "i", FLAG, 8 }, 999 { "u", FLAG, 9 }, 1000 1001 #define OPC(x) { #x, x, IS_OPCODE } 1002 OPC(ABS), 1003 OPC(ADC), 1004 OPC(ADD), 1005 { "and", AND_, IS_OPCODE }, 1006 OPC(BCLR), 1007 OPC(BCND), 1008 OPC(BMCND), 1009 OPC(BNOT), 1010 OPC(BRA), 1011 OPC(BRK), 1012 OPC(BSET), 1013 OPC(BSR), 1014 OPC(BTST), 1015 OPC(CLRPSW), 1016 OPC(CMP), 1017 OPC(DBT), 1018 OPC(DIV), 1019 OPC(DIVU), 1020 OPC(EDIV), 1021 OPC(EDIVU), 1022 OPC(EMUL), 1023 OPC(EMULU), 1024 OPC(FADD), 1025 OPC(FCMP), 1026 OPC(FDIV), 1027 OPC(FMUL), 1028 OPC(FREIT), 1029 OPC(FSUB), 1030 OPC(FTOI), 1031 OPC(INT), 1032 OPC(ITOF), 1033 OPC(JMP), 1034 OPC(JSR), 1035 OPC(MVFACHI), 1036 OPC(MVFACMI), 1037 OPC(MVFACLO), 1038 OPC(MVFC), 1039 OPC(MVTACHI), 1040 OPC(MVTACLO), 1041 OPC(MVTC), 1042 OPC(MVTIPL), 1043 OPC(MACHI), 1044 OPC(MACLO), 1045 OPC(MAX), 1046 OPC(MIN), 1047 OPC(MOV), 1048 OPC(MOVU), 1049 OPC(MUL), 1050 OPC(MULHI), 1051 OPC(MULLO), 1052 OPC(MULU), 1053 OPC(NEG), 1054 OPC(NOP), 1055 OPC(NOT), 1056 OPC(OR), 1057 OPC(POP), 1058 OPC(POPC), 1059 OPC(POPM), 1060 OPC(PUSH), 1061 OPC(PUSHA), 1062 OPC(PUSHC), 1063 OPC(PUSHM), 1064 OPC(RACW), 1065 OPC(REIT), 1066 OPC(REVL), 1067 OPC(REVW), 1068 OPC(RMPA), 1069 OPC(ROLC), 1070 OPC(RORC), 1071 OPC(ROTL), 1072 OPC(ROTR), 1073 OPC(ROUND), 1074 OPC(RTE), 1075 OPC(RTFI), 1076 OPC(RTS), 1077 OPC(RTSD), 1078 OPC(SAT), 1079 OPC(SATR), 1080 OPC(SBB), 1081 OPC(SCCND), 1082 OPC(SCMPU), 1083 OPC(SETPSW), 1084 OPC(SHAR), 1085 OPC(SHLL), 1086 OPC(SHLR), 1087 OPC(SMOVB), 1088 OPC(SMOVF), 1089 OPC(SMOVU), 1090 OPC(SSTR), 1091 OPC(STNZ), 1092 OPC(STOP), 1093 OPC(STZ), 1094 OPC(SUB), 1095 OPC(SUNTIL), 1096 OPC(SWHILE), 1097 OPC(TST), 1098 OPC(WAIT), 1099 OPC(XCHG), 1100 OPC(XOR), 1101 }; 1102 1103 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0])) 1104 1105 static struct 1106 { 1107 char * string; 1108 int token; 1109 } 1110 condition_opcode_table[] = 1111 { 1112 { "b", BCND }, 1113 { "bm", BMCND }, 1114 { "sc", SCCND }, 1115 }; 1116 1117 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0])) 1118 1119 static struct 1120 { 1121 char * string; 1122 int val; 1123 } 1124 condition_table[] = 1125 { 1126 { "z", 0 }, 1127 { "eq", 0 }, 1128 { "geu", 2 }, 1129 { "c", 2 }, 1130 { "gtu", 4 }, 1131 { "pz", 6 }, 1132 { "ge", 8 }, 1133 { "gt", 10 }, 1134 { "o", 12}, 1135 /* always = 14 */ 1136 { "nz", 1 }, 1137 { "ne", 1 }, 1138 { "ltu", 3 }, 1139 { "nc", 3 }, 1140 { "leu", 5 }, 1141 { "n", 7 }, 1142 { "lt", 9 }, 1143 { "le", 11 }, 1144 { "no", 13 } 1145 /* never = 15 */ 1146 }; 1147 1148 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0])) 1149 1150 void 1151 rx_lex_init (char * beginning, char * ending) 1152 { 1153 rx_init_start = beginning; 1154 rx_lex_start = beginning; 1155 rx_lex_end = ending; 1156 rx_in_brackets = 0; 1157 rx_last_token = 0; 1158 1159 setbuf (stdout, 0); 1160 } 1161 1162 static int 1163 check_condition (char * base) 1164 { 1165 char * cp; 1166 unsigned int i; 1167 1168 if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1) 1169 return 0; 1170 if (memcmp (rx_lex_start, base, strlen (base))) 1171 return 0; 1172 cp = rx_lex_start + strlen (base); 1173 for (i = 0; i < NUM_CONDITIONS; i ++) 1174 { 1175 if (strcasecmp (cp, condition_table[i].string) == 0) 1176 { 1177 rx_lval.regno = condition_table[i].val; 1178 return 1; 1179 } 1180 } 1181 return 0; 1182 } 1183 1184 static int 1185 rx_lex (void) 1186 { 1187 unsigned int ci; 1188 char * save_input_pointer; 1189 1190 while (ISSPACE (*rx_lex_start) 1191 && rx_lex_start != rx_lex_end) 1192 rx_lex_start ++; 1193 1194 rx_last_exp_start = rx_lex_start; 1195 1196 if (rx_lex_start == rx_lex_end) 1197 return 0; 1198 1199 if (ISALPHA (*rx_lex_start) 1200 || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0) 1201 || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0) 1202 || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1]))) 1203 { 1204 unsigned int i; 1205 char * e; 1206 char save; 1207 1208 for (e = rx_lex_start + 1; 1209 e < rx_lex_end && ISALNUM (*e); 1210 e ++) 1211 ; 1212 save = *e; 1213 *e = 0; 1214 1215 if (strcmp (rx_lex_start, "%pidreg") == 0) 1216 { 1217 { 1218 rx_lval.regno = rx_pid_register; 1219 *e = save; 1220 rx_lex_start = e; 1221 rx_last_token = REG; 1222 return REG; 1223 } 1224 } 1225 1226 if (strcmp (rx_lex_start, "%gpreg") == 0) 1227 { 1228 { 1229 rx_lval.regno = rx_gp_register; 1230 *e = save; 1231 rx_lex_start = e; 1232 rx_last_token = REG; 1233 return REG; 1234 } 1235 } 1236 1237 if (rx_last_token == 0) 1238 for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++) 1239 if (check_condition (condition_opcode_table[ci].string)) 1240 { 1241 *e = save; 1242 rx_lex_start = e; 1243 rx_last_token = condition_opcode_table[ci].token; 1244 return condition_opcode_table[ci].token; 1245 } 1246 1247 for (i = 0; i < NUM_TOKENS; i++) 1248 if (strcasecmp (rx_lex_start, token_table[i].string) == 0 1249 && !(token_table[i].val == IS_OPCODE && rx_last_token != 0) 1250 && !(token_table[i].token == FLAG && !need_flag)) 1251 { 1252 rx_lval.regno = token_table[i].val; 1253 *e = save; 1254 rx_lex_start = e; 1255 rx_last_token = token_table[i].token; 1256 return token_table[i].token; 1257 } 1258 *e = save; 1259 } 1260 1261 if (rx_last_token == 0) 1262 { 1263 rx_last_token = UNKNOWN_OPCODE; 1264 return UNKNOWN_OPCODE; 1265 } 1266 1267 if (rx_last_token == UNKNOWN_OPCODE) 1268 return 0; 1269 1270 if (*rx_lex_start == '[') 1271 rx_in_brackets = 1; 1272 if (*rx_lex_start == ']') 1273 rx_in_brackets = 0; 1274 1275 if (rx_in_brackets 1276 || rx_last_token == REG 1277 || strchr ("[],#", *rx_lex_start)) 1278 { 1279 rx_last_token = *rx_lex_start; 1280 return *rx_lex_start ++; 1281 } 1282 1283 save_input_pointer = input_line_pointer; 1284 input_line_pointer = rx_lex_start; 1285 rx_lval.exp.X_md = 0; 1286 expression (&rx_lval.exp); 1287 1288 /* We parse but ignore any :<size> modifier on expressions. */ 1289 if (*input_line_pointer == ':') 1290 { 1291 char *cp; 1292 1293 for (cp = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++) 1294 if (!ISDIGIT (*cp)) 1295 break; 1296 if (cp > input_line_pointer+1) 1297 input_line_pointer = cp; 1298 } 1299 1300 rx_lex_start = input_line_pointer; 1301 input_line_pointer = save_input_pointer; 1302 rx_last_token = EXPR; 1303 return EXPR; 1304 } 1305 1306 int 1307 rx_error (const char * str) 1308 { 1309 int len; 1310 1311 len = rx_last_exp_start - rx_init_start; 1312 1313 as_bad ("%s", rx_init_start); 1314 as_bad ("%*s^ %s", len, "", str); 1315 return 0; 1316 } 1317 1318 static int 1319 rx_intop (expressionS exp, int nbits, int opbits) 1320 { 1321 long v; 1322 long mask, msb; 1323 1324 if (exp.X_op == O_big && nbits == 32) 1325 return 1; 1326 if (exp.X_op != O_constant) 1327 return 0; 1328 v = exp.X_add_number; 1329 1330 msb = 1UL << (opbits - 1); 1331 mask = (1UL << opbits) - 1; 1332 1333 if ((v & msb) && ! (v & ~mask)) 1334 v -= 1UL << opbits; 1335 1336 switch (nbits) 1337 { 1338 case 4: 1339 return -0x8 <= v && v <= 0x7; 1340 case 5: 1341 return -0x10 <= v && v <= 0x17; 1342 case 8: 1343 return -0x80 <= v && v <= 0x7f; 1344 case 16: 1345 return -0x8000 <= v && v <= 0x7fff; 1346 case 24: 1347 return -0x800000 <= v && v <= 0x7fffff; 1348 case 32: 1349 return 1; 1350 default: 1351 printf ("rx_intop passed %d\n", nbits); 1352 abort (); 1353 } 1354 return 1; 1355 } 1356 1357 static int 1358 rx_uintop (expressionS exp, int nbits) 1359 { 1360 unsigned long v; 1361 1362 if (exp.X_op != O_constant) 1363 return 0; 1364 v = exp.X_add_number; 1365 1366 switch (nbits) 1367 { 1368 case 4: 1369 return v <= 0xf; 1370 case 8: 1371 return v <= 0xff; 1372 case 16: 1373 return v <= 0xffff; 1374 case 24: 1375 return v <= 0xffffff; 1376 default: 1377 printf ("rx_uintop passed %d\n", nbits); 1378 abort (); 1379 } 1380 return 1; 1381 } 1382 1383 static int 1384 rx_disp3op (expressionS exp) 1385 { 1386 unsigned long v; 1387 1388 if (exp.X_op != O_constant) 1389 return 0; 1390 v = exp.X_add_number; 1391 if (v < 3 || v > 10) 1392 return 0; 1393 return 1; 1394 } 1395 1396 static int 1397 rx_disp5op (expressionS * exp, int msize) 1398 { 1399 long v; 1400 1401 if (exp->X_op != O_constant) 1402 return 0; 1403 v = exp->X_add_number; 1404 1405 switch (msize) 1406 { 1407 case BSIZE: 1408 if (0 < v && v <= 31) 1409 return 1; 1410 break; 1411 case WSIZE: 1412 if (v & 1) 1413 return 0; 1414 if (0 < v && v <= 63) 1415 { 1416 exp->X_add_number >>= 1; 1417 return 1; 1418 } 1419 break; 1420 case LSIZE: 1421 if (v & 3) 1422 return 0; 1423 if (0 < v && v <= 127) 1424 { 1425 exp->X_add_number >>= 2; 1426 return 1; 1427 } 1428 break; 1429 } 1430 return 0; 1431 } 1432 1433 /* Just like the above, but allows a zero displacement. */ 1434 1435 static int 1436 rx_disp5op0 (expressionS * exp, int msize) 1437 { 1438 if (exp->X_op != O_constant) 1439 return 0; 1440 if (exp->X_add_number == 0) 1441 return 1; 1442 return rx_disp5op (exp, msize); 1443 } 1444 1445 static int 1446 exp_val (expressionS exp) 1447 { 1448 if (exp.X_op != O_constant) 1449 { 1450 rx_error (_("constant expected")); 1451 return 0; 1452 } 1453 return exp.X_add_number; 1454 } 1455 1456 static expressionS 1457 zero_expr (void) 1458 { 1459 /* Static, so program load sets it to all zeros, which is what we want. */ 1460 static expressionS zero; 1461 zero.X_op = O_constant; 1462 return zero; 1463 } 1464 1465 static int 1466 immediate (expressionS exp, int type, int pos, int bits) 1467 { 1468 /* We will emit constants ourself here, so negate them. */ 1469 if (type == RXREL_NEGATIVE && exp.X_op == O_constant) 1470 exp.X_add_number = - exp.X_add_number; 1471 if (type == RXREL_NEGATIVE_BORROW) 1472 { 1473 if (exp.X_op == O_constant) 1474 exp.X_add_number = - exp.X_add_number - 1; 1475 else 1476 rx_error (_("sbb cannot use symbolic immediates")); 1477 } 1478 1479 if (rx_intop (exp, 8, bits)) 1480 { 1481 rx_op (exp, 1, type); 1482 return 1; 1483 } 1484 else if (rx_intop (exp, 16, bits)) 1485 { 1486 rx_op (exp, 2, type); 1487 return 2; 1488 } 1489 else if (rx_uintop (exp, 16) && bits == 16) 1490 { 1491 rx_op (exp, 2, type); 1492 return 2; 1493 } 1494 else if (rx_intop (exp, 24, bits)) 1495 { 1496 rx_op (exp, 3, type); 1497 return 3; 1498 } 1499 else if (rx_intop (exp, 32, bits)) 1500 { 1501 rx_op (exp, 4, type); 1502 return 0; 1503 } 1504 else if (type == RXREL_SIGNED) 1505 { 1506 /* This is a symbolic immediate, we will relax it later. */ 1507 rx_relax (RX_RELAX_IMM, pos); 1508 rx_op (exp, linkrelax ? 4 : 1, type); 1509 return 1; 1510 } 1511 else 1512 { 1513 /* Let the linker deal with it. */ 1514 rx_op (exp, 4, type); 1515 return 0; 1516 } 1517 } 1518 1519 static int 1520 displacement (expressionS exp, int msize) 1521 { 1522 int val; 1523 int vshift = 0; 1524 1525 if (exp.X_op == O_symbol 1526 && exp.X_md) 1527 { 1528 switch (exp.X_md) 1529 { 1530 case BFD_RELOC_GPREL16: 1531 switch (msize) 1532 { 1533 case BSIZE: 1534 exp.X_md = BFD_RELOC_RX_GPRELB; 1535 break; 1536 case WSIZE: 1537 exp.X_md = BFD_RELOC_RX_GPRELW; 1538 break; 1539 case LSIZE: 1540 exp.X_md = BFD_RELOC_RX_GPRELL; 1541 break; 1542 } 1543 O2 (exp); 1544 return 2; 1545 } 1546 } 1547 1548 if (exp.X_op == O_subtract) 1549 { 1550 exp.X_md = BFD_RELOC_RX_DIFF; 1551 O2 (exp); 1552 return 2; 1553 } 1554 1555 if (exp.X_op != O_constant) 1556 { 1557 rx_error (_("displacements must be constants")); 1558 return -1; 1559 } 1560 val = exp.X_add_number; 1561 1562 if (val == 0) 1563 return 0; 1564 1565 switch (msize) 1566 { 1567 case BSIZE: 1568 break; 1569 case WSIZE: 1570 if (val & 1) 1571 rx_error (_("word displacement not word-aligned")); 1572 vshift = 1; 1573 break; 1574 case LSIZE: 1575 if (val & 3) 1576 rx_error (_("long displacement not long-aligned")); 1577 vshift = 2; 1578 break; 1579 default: 1580 as_bad (_("displacement with unknown size (internal bug?)\n")); 1581 break; 1582 } 1583 1584 val >>= vshift; 1585 exp.X_add_number = val; 1586 1587 if (0 <= val && val <= 255 ) 1588 { 1589 O1 (exp); 1590 return 1; 1591 } 1592 1593 if (0 <= val && val <= 65535) 1594 { 1595 O2 (exp); 1596 return 2; 1597 } 1598 if (val < 0) 1599 rx_error (_("negative displacements not allowed")); 1600 else 1601 rx_error (_("displacement too large")); 1602 return -1; 1603 } 1604 1605 static void 1606 rtsd_immediate (expressionS exp) 1607 { 1608 int val; 1609 1610 if (exp.X_op != O_constant) 1611 { 1612 rx_error (_("rtsd size must be constant")); 1613 return; 1614 } 1615 val = exp.X_add_number; 1616 if (val & 3) 1617 rx_error (_("rtsd size must be multiple of 4")); 1618 1619 if (val < 0 || val > 1020) 1620 rx_error (_("rtsd size must be 0..1020")); 1621 1622 val >>= 2; 1623 exp.X_add_number = val; 1624 O1 (exp); 1625 } 1626 1627 static void 1628 rx_range (expressionS exp, int minv, int maxv) 1629 { 1630 int val; 1631 1632 if (exp.X_op != O_constant) 1633 return; 1634 1635 val = exp.X_add_number; 1636 if (val < minv || val > maxv) 1637 as_warn (_("Value %d out of range %d..%d"), val, minv, maxv); 1638 } 1639 1640 static void 1641 rx_check_float_support (void) 1642 { 1643 if (rx_cpu == RX100 || rx_cpu == RX200) 1644 rx_error (_("target CPU type does not support floating point instructions")); 1645 } 1646