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