1 /* rx-parse.y Renesas RX parser 2 Copyright 2008, 2009 3 Free Software Foundation, Inc. 4 5 This file is part of GAS, the GNU Assembler. 6 7 GAS is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GAS is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GAS; see the file COPYING. If not, write to the Free 19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20 02110-1301, USA. */ 21 %{ 22 23 #include "as.h" 24 #include "safe-ctype.h" 25 #include "rx-defs.h" 26 27 static int rx_lex (void); 28 29 #define COND_EQ 0 30 #define COND_NE 1 31 32 #define MEMEX 0x06 33 34 #define BSIZE 0 35 #define WSIZE 1 36 #define LSIZE 2 37 38 /* .sb .sw .l .uw */ 39 static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE }; 40 41 /* Ok, here are the rules for using these macros... 42 43 B*() is used to specify the base opcode bytes. Fields to be filled 44 in later, leave zero. Call this first. 45 46 F() and FE() are used to fill in fields within the base opcode bytes. You MUST 47 call B*() before any F() or FE(). 48 49 [UN]*O*(), PC*() appends operands to the end of the opcode. You 50 must call P() and B*() before any of these, so that the fixups 51 have the right byte location. 52 O = signed, UO = unsigned, NO = negated, PC = pcrel 53 54 IMM() adds an immediate and fills in the field for it. 55 NIMM() same, but negates the immediate. 56 NBIMM() same, but negates the immediate, for sbb. 57 DSP() adds a displacement, and fills in the field for it. 58 59 Note that order is significant for the O, IMM, and DSP macros, as 60 they append their data to the operand buffer in the order that you 61 call them. 62 63 Use "disp" for displacements whenever possible; this handles the 64 "0" case properly. */ 65 66 #define B1(b1) rx_base1 (b1) 67 #define B2(b1, b2) rx_base2 (b1, b2) 68 #define B3(b1, b2, b3) rx_base3 (b1, b2, b3) 69 #define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4) 70 71 /* POS is bits from the MSB of the first byte to the LSB of the last byte. */ 72 #define F(val,pos,sz) rx_field (val, pos, sz) 73 #define FE(exp,pos,sz) rx_field (exp_val (exp), pos, sz); 74 75 #define O1(v) rx_op (v, 1, RXREL_SIGNED); rx_range (v, -128, 255) 76 #define O2(v) rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536) 77 #define O3(v) rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216) 78 #define O4(v) rx_op (v, 4, RXREL_SIGNED) 79 80 #define UO1(v) rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255) 81 #define UO2(v) rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536) 82 #define UO3(v) rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216) 83 #define UO4(v) rx_op (v, 4, RXREL_UNSIGNED) 84 85 #define NO1(v) rx_op (v, 1, RXREL_NEGATIVE) 86 #define NO2(v) rx_op (v, 2, RXREL_NEGATIVE) 87 #define NO3(v) rx_op (v, 3, RXREL_NEGATIVE) 88 #define NO4(v) rx_op (v, 4, RXREL_NEGATIVE) 89 90 #define PC1(v) rx_op (v, 1, RXREL_PCREL) 91 #define PC2(v) rx_op (v, 2, RXREL_PCREL) 92 #define PC3(v) rx_op (v, 3, RXREL_PCREL) 93 94 #define IMM_(v,pos,size) F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \ 95 if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos) 96 #define IMM(v,pos) IMM_ (v, pos, 32) 97 #define IMMW(v,pos) IMM_ (v, pos, 16); rx_range (v, -32768, 65536) 98 #define IMMB(v,pos) IMM_ (v, pos, 8); rx_range (v, -128, 255) 99 #define NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2) 100 #define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2) 101 #define DSP(v,pos,msz) if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \ 102 else rx_linkrelax_dsp (pos); \ 103 F (displacement (v, msz), pos, 2) 104 105 #define id24(a,b2,b3) B3 (0xfb+a, b2, b3) 106 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 ']' DOT_B 640 { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } 641 | BCLR REG ',' disp '[' REG ']' DOT_B 642 { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } 643 | BTST REG ',' disp '[' REG ']' DOT_B 644 { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } 645 | BNOT REG ',' disp '[' REG ']' DOT_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 ']' DOT_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 ']' DOT_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 885 float2_op 886 : '#' EXPR ',' REG 887 { id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); } 888 | float2_op_ni 889 ; 890 float2_op_ni 891 : REG ',' REG 892 { id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); } 893 | disp '[' REG ']' opt_l ',' REG 894 { id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); } 895 ; 896 897 /* ====================================================================== */ 898 899 disp : { $$ = zero_expr (); } 900 | EXPR { $$ = $1; } 901 ; 902 903 flag : { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; } 904 ; 905 906 /* DOT_UB is not listed here, it's handled with a separate pattern. */ 907 /* Use sizemap[$n] to get LSIZE etc. */ 908 memex : DOT_B { $$ = 0; } 909 | DOT_W { $$ = 1; } 910 | { $$ = 2; } 911 | DOT_L { $$ = 2; } 912 | DOT_UW { $$ = 3; } 913 ; 914 915 bwl : { $$ = LSIZE; } 916 | DOT_B { $$ = BSIZE; } 917 | DOT_W { $$ = WSIZE; } 918 | DOT_L { $$ = LSIZE; } 919 ; 920 921 bw : { $$ = 1; } 922 | DOT_B { $$ = 0; } 923 | DOT_W { $$ = 1; } 924 ; 925 926 opt_l : {} 927 | DOT_L {} 928 ; 929 930 %% 931 /* ====================================================================== */ 932 933 static struct 934 { 935 const char * string; 936 int token; 937 int val; 938 } 939 token_table[] = 940 { 941 { "r0", REG, 0 }, 942 { "r1", REG, 1 }, 943 { "r2", REG, 2 }, 944 { "r3", REG, 3 }, 945 { "r4", REG, 4 }, 946 { "r5", REG, 5 }, 947 { "r6", REG, 6 }, 948 { "r7", REG, 7 }, 949 { "r8", REG, 8 }, 950 { "r9", REG, 9 }, 951 { "r10", REG, 10 }, 952 { "r11", REG, 11 }, 953 { "r12", REG, 12 }, 954 { "r13", REG, 13 }, 955 { "r14", REG, 14 }, 956 { "r15", REG, 15 }, 957 958 { "psw", CREG, 0 }, 959 { "pc", CREG, 1 }, 960 { "usp", CREG, 2 }, 961 { "fpsw", CREG, 3 }, 962 /* reserved */ 963 /* reserved */ 964 /* reserved */ 965 { "wr", CREG, 7 }, 966 967 { "bpsw", CREG, 8 }, 968 { "bpc", CREG, 9 }, 969 { "isp", CREG, 10 }, 970 { "fintv", CREG, 11 }, 971 { "intb", CREG, 12 }, 972 973 { "pbp", CREG, 16 }, 974 { "pben", CREG, 17 }, 975 976 { "bbpsw", CREG, 24 }, 977 { "bbpc", CREG, 25 }, 978 979 { ".s", DOT_S, 0 }, 980 { ".b", DOT_B, 0 }, 981 { ".w", DOT_W, 0 }, 982 { ".l", DOT_L, 0 }, 983 { ".a", DOT_A , 0}, 984 { ".ub", DOT_UB, 0 }, 985 { ".uw", DOT_UW , 0}, 986 987 { "c", FLAG, 0 }, 988 { "z", FLAG, 1 }, 989 { "s", FLAG, 2 }, 990 { "o", FLAG, 3 }, 991 { "i", FLAG, 8 }, 992 { "u", FLAG, 9 }, 993 994 #define OPC(x) { #x, x, IS_OPCODE } 995 OPC(ABS), 996 OPC(ADC), 997 OPC(ADD), 998 { "and", AND_, IS_OPCODE }, 999 OPC(BCLR), 1000 OPC(BCND), 1001 OPC(BMCND), 1002 OPC(BNOT), 1003 OPC(BRA), 1004 OPC(BRK), 1005 OPC(BSET), 1006 OPC(BSR), 1007 OPC(BTST), 1008 OPC(CLRPSW), 1009 OPC(CMP), 1010 OPC(DBT), 1011 OPC(DIV), 1012 OPC(DIVU), 1013 OPC(EDIV), 1014 OPC(EDIVU), 1015 OPC(EMUL), 1016 OPC(EMULU), 1017 OPC(FADD), 1018 OPC(FCMP), 1019 OPC(FDIV), 1020 OPC(FMUL), 1021 OPC(FREIT), 1022 OPC(FSUB), 1023 OPC(FTOI), 1024 OPC(INT), 1025 OPC(ITOF), 1026 OPC(JMP), 1027 OPC(JSR), 1028 OPC(MVFACHI), 1029 OPC(MVFACMI), 1030 OPC(MVFACLO), 1031 OPC(MVFC), 1032 OPC(MVTACHI), 1033 OPC(MVTACLO), 1034 OPC(MVTC), 1035 OPC(MVTIPL), 1036 OPC(MACHI), 1037 OPC(MACLO), 1038 OPC(MAX), 1039 OPC(MIN), 1040 OPC(MOV), 1041 OPC(MOVU), 1042 OPC(MUL), 1043 OPC(MULHI), 1044 OPC(MULLO), 1045 OPC(MULU), 1046 OPC(NEG), 1047 OPC(NOP), 1048 OPC(NOT), 1049 OPC(OR), 1050 OPC(POP), 1051 OPC(POPC), 1052 OPC(POPM), 1053 OPC(PUSH), 1054 OPC(PUSHA), 1055 OPC(PUSHC), 1056 OPC(PUSHM), 1057 OPC(RACW), 1058 OPC(REIT), 1059 OPC(REVL), 1060 OPC(REVW), 1061 OPC(RMPA), 1062 OPC(ROLC), 1063 OPC(RORC), 1064 OPC(ROTL), 1065 OPC(ROTR), 1066 OPC(ROUND), 1067 OPC(RTE), 1068 OPC(RTFI), 1069 OPC(RTS), 1070 OPC(RTSD), 1071 OPC(SAT), 1072 OPC(SATR), 1073 OPC(SBB), 1074 OPC(SCCND), 1075 OPC(SCMPU), 1076 OPC(SETPSW), 1077 OPC(SHAR), 1078 OPC(SHLL), 1079 OPC(SHLR), 1080 OPC(SMOVB), 1081 OPC(SMOVF), 1082 OPC(SMOVU), 1083 OPC(SSTR), 1084 OPC(STNZ), 1085 OPC(STOP), 1086 OPC(STZ), 1087 OPC(SUB), 1088 OPC(SUNTIL), 1089 OPC(SWHILE), 1090 OPC(TST), 1091 OPC(WAIT), 1092 OPC(XCHG), 1093 OPC(XOR), 1094 }; 1095 1096 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0])) 1097 1098 static struct 1099 { 1100 char * string; 1101 int token; 1102 } 1103 condition_opcode_table[] = 1104 { 1105 { "b", BCND }, 1106 { "bm", BMCND }, 1107 { "sc", SCCND }, 1108 }; 1109 1110 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0])) 1111 1112 static struct 1113 { 1114 char * string; 1115 int val; 1116 } 1117 condition_table[] = 1118 { 1119 { "z", 0 }, 1120 { "eq", 0 }, 1121 { "geu", 2 }, 1122 { "c", 2 }, 1123 { "gtu", 4 }, 1124 { "pz", 6 }, 1125 { "ge", 8 }, 1126 { "gt", 10 }, 1127 { "o", 12}, 1128 /* always = 14 */ 1129 { "nz", 1 }, 1130 { "ne", 1 }, 1131 { "ltu", 3 }, 1132 { "nc", 3 }, 1133 { "leu", 5 }, 1134 { "n", 7 }, 1135 { "lt", 9 }, 1136 { "le", 11 }, 1137 { "no", 13 } 1138 /* never = 15 */ 1139 }; 1140 1141 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0])) 1142 1143 void 1144 rx_lex_init (char * beginning, char * ending) 1145 { 1146 rx_init_start = beginning; 1147 rx_lex_start = beginning; 1148 rx_lex_end = ending; 1149 rx_in_brackets = 0; 1150 rx_last_token = 0; 1151 1152 setbuf (stdout, 0); 1153 } 1154 1155 static int 1156 check_condition (char * base) 1157 { 1158 char * cp; 1159 unsigned int i; 1160 1161 if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1) 1162 return 0; 1163 if (memcmp (rx_lex_start, base, strlen (base))) 1164 return 0; 1165 cp = rx_lex_start + strlen (base); 1166 for (i = 0; i < NUM_CONDITIONS; i ++) 1167 { 1168 if (strcasecmp (cp, condition_table[i].string) == 0) 1169 { 1170 rx_lval.regno = condition_table[i].val; 1171 return 1; 1172 } 1173 } 1174 return 0; 1175 } 1176 1177 static int 1178 rx_lex (void) 1179 { 1180 unsigned int ci; 1181 char * save_input_pointer; 1182 1183 while (ISSPACE (*rx_lex_start) 1184 && rx_lex_start != rx_lex_end) 1185 rx_lex_start ++; 1186 1187 rx_last_exp_start = rx_lex_start; 1188 1189 if (rx_lex_start == rx_lex_end) 1190 return 0; 1191 1192 if (ISALPHA (*rx_lex_start) 1193 || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0) 1194 || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0) 1195 || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1]))) 1196 { 1197 unsigned int i; 1198 char * e; 1199 char save; 1200 1201 for (e = rx_lex_start + 1; 1202 e < rx_lex_end && ISALNUM (*e); 1203 e ++) 1204 ; 1205 save = *e; 1206 *e = 0; 1207 1208 if (strcmp (rx_lex_start, "%pidreg") == 0) 1209 { 1210 { 1211 rx_lval.regno = rx_pid_register; 1212 *e = save; 1213 rx_lex_start = e; 1214 rx_last_token = REG; 1215 return REG; 1216 } 1217 } 1218 1219 if (strcmp (rx_lex_start, "%gpreg") == 0) 1220 { 1221 { 1222 rx_lval.regno = rx_gp_register; 1223 *e = save; 1224 rx_lex_start = e; 1225 rx_last_token = REG; 1226 return REG; 1227 } 1228 } 1229 1230 if (rx_last_token == 0) 1231 for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++) 1232 if (check_condition (condition_opcode_table[ci].string)) 1233 { 1234 *e = save; 1235 rx_lex_start = e; 1236 rx_last_token = condition_opcode_table[ci].token; 1237 return condition_opcode_table[ci].token; 1238 } 1239 1240 for (i = 0; i < NUM_TOKENS; i++) 1241 if (strcasecmp (rx_lex_start, token_table[i].string) == 0 1242 && !(token_table[i].val == IS_OPCODE && rx_last_token != 0) 1243 && !(token_table[i].token == FLAG && !need_flag)) 1244 { 1245 rx_lval.regno = token_table[i].val; 1246 *e = save; 1247 rx_lex_start = e; 1248 rx_last_token = token_table[i].token; 1249 return token_table[i].token; 1250 } 1251 *e = save; 1252 } 1253 1254 if (rx_last_token == 0) 1255 { 1256 rx_last_token = UNKNOWN_OPCODE; 1257 return UNKNOWN_OPCODE; 1258 } 1259 1260 if (rx_last_token == UNKNOWN_OPCODE) 1261 return 0; 1262 1263 if (*rx_lex_start == '[') 1264 rx_in_brackets = 1; 1265 if (*rx_lex_start == ']') 1266 rx_in_brackets = 0; 1267 1268 if (rx_in_brackets 1269 || rx_last_token == REG 1270 || strchr ("[],#", *rx_lex_start)) 1271 { 1272 rx_last_token = *rx_lex_start; 1273 return *rx_lex_start ++; 1274 } 1275 1276 save_input_pointer = input_line_pointer; 1277 input_line_pointer = rx_lex_start; 1278 rx_lval.exp.X_md = 0; 1279 expression (&rx_lval.exp); 1280 1281 /* We parse but ignore any :<size> modifier on expressions. */ 1282 if (*input_line_pointer == ':') 1283 { 1284 char *cp; 1285 1286 for (cp = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++) 1287 if (!ISDIGIT (*cp)) 1288 break; 1289 if (cp > input_line_pointer+1) 1290 input_line_pointer = cp; 1291 } 1292 1293 rx_lex_start = input_line_pointer; 1294 input_line_pointer = save_input_pointer; 1295 rx_last_token = EXPR; 1296 return EXPR; 1297 } 1298 1299 int 1300 rx_error (const char * str) 1301 { 1302 int len; 1303 1304 len = rx_last_exp_start - rx_init_start; 1305 1306 as_bad ("%s", rx_init_start); 1307 as_bad ("%*s^ %s", len, "", str); 1308 return 0; 1309 } 1310 1311 static int 1312 rx_intop (expressionS exp, int nbits, int opbits) 1313 { 1314 long v; 1315 long mask, msb; 1316 1317 if (exp.X_op == O_big && nbits == 32) 1318 return 1; 1319 if (exp.X_op != O_constant) 1320 return 0; 1321 v = exp.X_add_number; 1322 1323 msb = 1UL << (opbits - 1); 1324 mask = (1UL << opbits) - 1; 1325 1326 if ((v & msb) && ! (v & ~mask)) 1327 v -= 1UL << opbits; 1328 1329 switch (nbits) 1330 { 1331 case 4: 1332 return -0x8 <= v && v <= 0x7; 1333 case 5: 1334 return -0x10 <= v && v <= 0x17; 1335 case 8: 1336 return -0x80 <= v && v <= 0x7f; 1337 case 16: 1338 return -0x8000 <= v && v <= 0x7fff; 1339 case 24: 1340 return -0x800000 <= v && v <= 0x7fffff; 1341 case 32: 1342 return 1; 1343 default: 1344 printf ("rx_intop passed %d\n", nbits); 1345 abort (); 1346 } 1347 return 1; 1348 } 1349 1350 static int 1351 rx_uintop (expressionS exp, int nbits) 1352 { 1353 unsigned long v; 1354 1355 if (exp.X_op != O_constant) 1356 return 0; 1357 v = exp.X_add_number; 1358 1359 switch (nbits) 1360 { 1361 case 4: 1362 return v <= 0xf; 1363 case 8: 1364 return v <= 0xff; 1365 case 16: 1366 return v <= 0xffff; 1367 case 24: 1368 return v <= 0xffffff; 1369 default: 1370 printf ("rx_uintop passed %d\n", nbits); 1371 abort (); 1372 } 1373 return 1; 1374 } 1375 1376 static int 1377 rx_disp3op (expressionS exp) 1378 { 1379 unsigned long v; 1380 1381 if (exp.X_op != O_constant) 1382 return 0; 1383 v = exp.X_add_number; 1384 if (v < 3 || v > 10) 1385 return 0; 1386 return 1; 1387 } 1388 1389 static int 1390 rx_disp5op (expressionS * exp, int msize) 1391 { 1392 long v; 1393 1394 if (exp->X_op != O_constant) 1395 return 0; 1396 v = exp->X_add_number; 1397 1398 switch (msize) 1399 { 1400 case BSIZE: 1401 if (0 < v && v <= 31) 1402 return 1; 1403 break; 1404 case WSIZE: 1405 if (v & 1) 1406 return 0; 1407 if (0 < v && v <= 63) 1408 { 1409 exp->X_add_number >>= 1; 1410 return 1; 1411 } 1412 break; 1413 case LSIZE: 1414 if (v & 3) 1415 return 0; 1416 if (0 < v && v <= 127) 1417 { 1418 exp->X_add_number >>= 2; 1419 return 1; 1420 } 1421 break; 1422 } 1423 return 0; 1424 } 1425 1426 /* Just like the above, but allows a zero displacement. */ 1427 1428 static int 1429 rx_disp5op0 (expressionS * exp, int msize) 1430 { 1431 if (exp->X_op != O_constant) 1432 return 0; 1433 if (exp->X_add_number == 0) 1434 return 1; 1435 return rx_disp5op (exp, msize); 1436 } 1437 1438 static int 1439 exp_val (expressionS exp) 1440 { 1441 if (exp.X_op != O_constant) 1442 { 1443 rx_error (_("constant expected")); 1444 return 0; 1445 } 1446 return exp.X_add_number; 1447 } 1448 1449 static expressionS 1450 zero_expr (void) 1451 { 1452 /* Static, so program load sets it to all zeros, which is what we want. */ 1453 static expressionS zero; 1454 zero.X_op = O_constant; 1455 return zero; 1456 } 1457 1458 static int 1459 immediate (expressionS exp, int type, int pos, int bits) 1460 { 1461 /* We will emit constants ourself here, so negate them. */ 1462 if (type == RXREL_NEGATIVE && exp.X_op == O_constant) 1463 exp.X_add_number = - exp.X_add_number; 1464 if (type == RXREL_NEGATIVE_BORROW) 1465 { 1466 if (exp.X_op == O_constant) 1467 exp.X_add_number = - exp.X_add_number - 1; 1468 else 1469 rx_error (_("sbb cannot use symbolic immediates")); 1470 } 1471 1472 if (rx_intop (exp, 8, bits)) 1473 { 1474 rx_op (exp, 1, type); 1475 return 1; 1476 } 1477 else if (rx_intop (exp, 16, bits)) 1478 { 1479 rx_op (exp, 2, type); 1480 return 2; 1481 } 1482 else if (rx_uintop (exp, 16) && bits == 16) 1483 { 1484 rx_op (exp, 2, type); 1485 return 2; 1486 } 1487 else if (rx_intop (exp, 24, bits)) 1488 { 1489 rx_op (exp, 3, type); 1490 return 3; 1491 } 1492 else if (rx_intop (exp, 32, bits)) 1493 { 1494 rx_op (exp, 4, type); 1495 return 0; 1496 } 1497 else if (type == RXREL_SIGNED) 1498 { 1499 /* This is a symbolic immediate, we will relax it later. */ 1500 rx_relax (RX_RELAX_IMM, pos); 1501 rx_op (exp, linkrelax ? 4 : 1, type); 1502 return 1; 1503 } 1504 else 1505 { 1506 /* Let the linker deal with it. */ 1507 rx_op (exp, 4, type); 1508 return 0; 1509 } 1510 } 1511 1512 static int 1513 displacement (expressionS exp, int msize) 1514 { 1515 int val; 1516 int vshift = 0; 1517 1518 if (exp.X_op == O_symbol 1519 && exp.X_md) 1520 { 1521 switch (exp.X_md) 1522 { 1523 case BFD_RELOC_GPREL16: 1524 switch (msize) 1525 { 1526 case BSIZE: 1527 exp.X_md = BFD_RELOC_RX_GPRELB; 1528 break; 1529 case WSIZE: 1530 exp.X_md = BFD_RELOC_RX_GPRELW; 1531 break; 1532 case LSIZE: 1533 exp.X_md = BFD_RELOC_RX_GPRELL; 1534 break; 1535 } 1536 O2 (exp); 1537 return 2; 1538 } 1539 } 1540 1541 if (exp.X_op == O_subtract) 1542 { 1543 exp.X_md = BFD_RELOC_RX_DIFF; 1544 O2 (exp); 1545 return 2; 1546 } 1547 1548 if (exp.X_op != O_constant) 1549 { 1550 rx_error (_("displacements must be constants")); 1551 return -1; 1552 } 1553 val = exp.X_add_number; 1554 1555 if (val == 0) 1556 return 0; 1557 1558 switch (msize) 1559 { 1560 case BSIZE: 1561 break; 1562 case WSIZE: 1563 if (val & 1) 1564 rx_error (_("word displacement not word-aligned")); 1565 vshift = 1; 1566 break; 1567 case LSIZE: 1568 if (val & 3) 1569 rx_error (_("long displacement not long-aligned")); 1570 vshift = 2; 1571 break; 1572 default: 1573 as_bad (_("displacement with unknown size (internal bug?)\n")); 1574 break; 1575 } 1576 1577 val >>= vshift; 1578 exp.X_add_number = val; 1579 1580 if (0 <= val && val <= 255 ) 1581 { 1582 O1 (exp); 1583 return 1; 1584 } 1585 1586 if (0 <= val && val <= 65535) 1587 { 1588 O2 (exp); 1589 return 2; 1590 } 1591 if (val < 0) 1592 rx_error (_("negative displacements not allowed")); 1593 else 1594 rx_error (_("displacement too large")); 1595 return -1; 1596 } 1597 1598 static void 1599 rtsd_immediate (expressionS exp) 1600 { 1601 int val; 1602 1603 if (exp.X_op != O_constant) 1604 { 1605 rx_error (_("rtsd size must be constant")); 1606 return; 1607 } 1608 val = exp.X_add_number; 1609 if (val & 3) 1610 rx_error (_("rtsd size must be multiple of 4")); 1611 1612 if (val < 0 || val > 1020) 1613 rx_error (_("rtsd size must be 0..1020")); 1614 1615 val >>= 2; 1616 exp.X_add_number = val; 1617 O1 (exp); 1618 } 1619 1620 static void 1621 rx_range (expressionS exp, int minv, int maxv) 1622 { 1623 int val; 1624 1625 if (exp.X_op != O_constant) 1626 return; 1627 1628 val = exp.X_add_number; 1629 if (val < minv || val > maxv) 1630 as_warn (_("Value %d out of range %d..%d"), val, minv, maxv); 1631 } 1632