| 1 | /* itbl-parse.y |
| 2 | Copyright (C) 1997-2018 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 | |
| 23 | /* |
| 24 | |
| 25 | Yacc grammar for instruction table entries. |
| 26 | |
| 27 | ======================================================================= |
| 28 | Original Instruction table specification document: |
| 29 | |
| 30 | MIPS Coprocessor Table Specification |
| 31 | ==================================== |
| 32 | |
| 33 | This document describes the format of the MIPS coprocessor table. The |
| 34 | table specifies a list of valid functions, data registers and control |
| 35 | registers that can be used in coprocessor instructions. This list, |
| 36 | together with the coprocessor instruction classes listed below, |
| 37 | specifies the complete list of coprocessor instructions that will |
| 38 | be recognized and assembled by the GNU assembler. In effect, |
| 39 | this makes the GNU assembler table-driven, where the table is |
| 40 | specified by the programmer. |
| 41 | |
| 42 | The table is an ordinary text file that the GNU assembler reads when |
| 43 | it starts. Using the information in the table, the assembler |
| 44 | generates an internal list of valid coprocessor registers and |
| 45 | functions. The assembler uses this internal list in addition to the |
| 46 | standard MIPS registers and instructions which are built-in to the |
| 47 | assembler during code generation. |
| 48 | |
| 49 | To specify the coprocessor table when invoking the GNU assembler, use |
| 50 | the command line option "--itbl file", where file is the |
| 51 | complete name of the table, including path and extension. |
| 52 | |
| 53 | Examples: |
| 54 | |
| 55 | gas -t cop.tbl test.s -o test.o |
| 56 | gas -t /usr/local/lib/cop.tbl test.s -o test.o |
| 57 | gas --itbl d:\gnu\data\cop.tbl test.s -o test.o |
| 58 | |
| 59 | Only one table may be supplied during a single invocation of |
| 60 | the assembler. |
| 61 | |
| 62 | |
| 63 | Instruction classes |
| 64 | =================== |
| 65 | |
| 66 | Below is a list of the valid coprocessor instruction classes for |
| 67 | any given coprocessor "z". These instructions are already recognized |
| 68 | by the assembler, and are listed here only for reference. |
| 69 | |
| 70 | Class format instructions |
| 71 | ------------------------------------------------- |
| 72 | Class1: |
| 73 | op base rt offset |
| 74 | LWCz rt,offset (base) |
| 75 | SWCz rt,offset (base) |
| 76 | Class2: |
| 77 | COPz sub rt rd 0 |
| 78 | MTCz rt,rd |
| 79 | MFCz rt,rd |
| 80 | CTCz rt,rd |
| 81 | CFCz rt,rd |
| 82 | Class3: |
| 83 | COPz CO cofun |
| 84 | COPz cofun |
| 85 | Class4: |
| 86 | COPz BC br offset |
| 87 | BCzT offset |
| 88 | BCzF offset |
| 89 | Class5: |
| 90 | COPz sub rt rd 0 |
| 91 | DMFCz rt,rd |
| 92 | DMTCz rt,rd |
| 93 | Class6: |
| 94 | op base rt offset |
| 95 | LDCz rt,offset (base) |
| 96 | SDCz rt,offset (base) |
| 97 | Class7: |
| 98 | COPz BC br offset |
| 99 | BCzTL offset |
| 100 | BCzFL offset |
| 101 | |
| 102 | The coprocessor table defines coprocessor-specific registers that can |
| 103 | be used with all of the above classes of instructions, where |
| 104 | appropriate. It also defines additional coprocessor-specific |
| 105 | functions for Class3 (COPz cofun) instructions, Thus, the table allows |
| 106 | the programmer to use convenient mnemonics and operands for these |
| 107 | functions, instead of the COPz mmenmonic and cofun operand. |
| 108 | |
| 109 | The names of the MIPS general registers and their aliases are defined |
| 110 | by the assembler and will be recognized as valid register names by the |
| 111 | assembler when used (where allowed) in coprocessor instructions. |
| 112 | However, the names and values of all coprocessor data and control |
| 113 | register mnemonics must be specified in the coprocessor table. |
| 114 | |
| 115 | |
| 116 | Table Grammar |
| 117 | ============= |
| 118 | |
| 119 | Here is the grammar for the coprocessor table: |
| 120 | |
| 121 | table -> entry* |
| 122 | |
| 123 | entry -> [z entrydef] [comment] '\n' |
| 124 | |
| 125 | entrydef -> type name val |
| 126 | entrydef -> 'insn' name val funcdef ; type of entry (instruction) |
| 127 | |
| 128 | z -> 'p'['0'..'3'] ; processor number |
| 129 | type -> ['dreg' | 'creg' | 'greg' ] ; type of entry (register) |
| 130 | ; 'dreg', 'creg' or 'greg' specifies a data, control, or general |
| 131 | ; register mnemonic, respectively |
| 132 | name -> [ltr|dec]* ; mnemonic of register/function |
| 133 | val -> [dec|hex] ; register/function number (integer constant) |
| 134 | |
| 135 | funcdef -> frange flags fields |
| 136 | ; bitfield range for opcode |
| 137 | ; list of fields' formats |
| 138 | fields -> field* |
| 139 | field -> [','] ftype frange flags |
| 140 | flags -> ['*' flagexpr] |
| 141 | flagexpr -> '[' flagexpr ']' |
| 142 | flagexpr -> val '|' flagexpr |
| 143 | ftype -> [ type | 'immed' | 'addr' ] |
| 144 | ; 'immed' specifies an immediate value; see grammar for "val" above |
| 145 | ; 'addr' specifies a C identifier; name of symbol to be resolved at |
| 146 | ; link time |
| 147 | frange -> ':' val '-' val ; starting to ending bit positions, where |
| 148 | ; where 0 is least significant bit |
| 149 | frange -> (null) ; default range of 31-0 will be assumed |
| 150 | |
| 151 | comment -> [';'|'#'] [char]* |
| 152 | char -> any printable character |
| 153 | ltr -> ['a'..'z'|'A'..'Z'] |
| 154 | dec -> ['0'..'9']* ; value in decimal |
| 155 | hex -> '0x'['0'..'9' | 'a'..'f' | 'A'..'F']* ; value in hexadecimal |
| 156 | |
| 157 | |
| 158 | Examples |
| 159 | ======== |
| 160 | |
| 161 | Example 1: |
| 162 | |
| 163 | The table: |
| 164 | |
| 165 | p1 dreg d1 1 ; data register "d1" for COP1 has value 1 |
| 166 | p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3 |
| 167 | p3 func fill 0x1f:24-20 ; function "fill" for COP3 has value 31 and |
| 168 | ; no fields |
| 169 | |
| 170 | will allow the assembler to accept the following coprocessor instructions: |
| 171 | |
| 172 | LWC1 d1,0x100 ($2) |
| 173 | fill |
| 174 | |
| 175 | Here, the general purpose register "$2", and instruction "LWC1", are standard |
| 176 | mnemonics built-in to the MIPS assembler. |
| 177 | |
| 178 | |
| 179 | Example 2: |
| 180 | |
| 181 | The table: |
| 182 | |
| 183 | p3 dreg d3 3 ; data register "d3" for COP3 has value 3 |
| 184 | p3 creg c2 22 ; control register "c2" for COP3 has value 22 |
| 185 | p3 func fee 0x1f:24-20 dreg:17-13 creg:12-8 immed:7-0 |
| 186 | ; function "fee" for COP3 has value 31, and 3 fields |
| 187 | ; consisting of a data register, a control register, |
| 188 | ; and an immediate value. |
| 189 | |
| 190 | will allow the assembler to accept the following coprocessor instruction: |
| 191 | |
| 192 | fee d3,c2,0x1 |
| 193 | |
| 194 | and will emit the object code: |
| 195 | |
| 196 | 31-26 25 24-20 19-18 17-13 12-8 7-0 |
| 197 | COPz CO fun dreg creg immed |
| 198 | 010011 1 11111 00 00011 10110 00000001 |
| 199 | |
| 200 | 0x4ff07601 |
| 201 | |
| 202 | |
| 203 | Example 3: |
| 204 | |
| 205 | The table: |
| 206 | |
| 207 | p3 dreg d3 3 ; data register "d3" for COP3 has value 3 |
| 208 | p3 creg c2 22 ; control register "c2" for COP3 has value 22 |
| 209 | p3 func fuu 0x01f00001 dreg:17-13 creg:12-8 |
| 210 | |
| 211 | will allow the assembler to accept the following coprocessor |
| 212 | instruction: |
| 213 | |
| 214 | fuu d3,c2 |
| 215 | |
| 216 | and will emit the object code: |
| 217 | |
| 218 | 31-26 25 24-20 19-18 17-13 12-8 7-0 |
| 219 | COPz CO fun dreg creg |
| 220 | 010011 1 11111 00 00011 10110 00000001 |
| 221 | |
| 222 | 0x4ff07601 |
| 223 | |
| 224 | In this way, the programmer can force arbitrary bits of an instruction |
| 225 | to have predefined values. |
| 226 | |
| 227 | ======================================================================= |
| 228 | Additional notes: |
| 229 | |
| 230 | Encoding of ranges: |
| 231 | To handle more than one bit position range within an instruction, |
| 232 | use 0s to mask out the ranges which don't apply. |
| 233 | May decide to modify the syntax to allow commas separate multiple |
| 234 | ranges within an instruction (range','range). |
| 235 | |
| 236 | Changes in grammar: |
| 237 | The number of parms argument to the function entry |
| 238 | was deleted from the original format such that we now count the fields. |
| 239 | |
| 240 | ---- |
| 241 | FIXME! should really change lexical analyzer |
| 242 | to recognize 'dreg' etc. in context sensitive way. |
| 243 | Currently function names or mnemonics may be incorrectly parsed as keywords |
| 244 | |
| 245 | FIXME! hex is ambiguous with any digit |
| 246 | |
| 247 | */ |
| 248 | |
| 249 | #include "as.h" |
| 250 | #include "itbl-lex.h" |
| 251 | #include "itbl-ops.h" |
| 252 | |
| 253 | /* #define DEBUG */ |
| 254 | |
| 255 | #ifdef DEBUG |
| 256 | #ifndef DBG_LVL |
| 257 | #define DBG_LVL 1 |
| 258 | #endif |
| 259 | #else |
| 260 | #define DBG_LVL 0 |
| 261 | #endif |
| 262 | |
| 263 | #if DBG_LVL >= 1 |
| 264 | #define DBG(x) printf x |
| 265 | #else |
| 266 | #define DBG(x) |
| 267 | #endif |
| 268 | |
| 269 | #if DBG_LVL >= 2 |
| 270 | #define DBGL2(x) printf x |
| 271 | #else |
| 272 | #define DBGL2(x) |
| 273 | #endif |
| 274 | |
| 275 | static int sbit, ebit; |
| 276 | static struct itbl_entry *insn=0; |
| 277 | static int yyerror (const char *); |
| 278 | |
| 279 | %} |
| 280 | |
| 281 | %union |
| 282 | { |
| 283 | char *str; |
| 284 | int num; |
| 285 | int processor; |
| 286 | unsigned long val; |
| 287 | } |
| 288 | |
| 289 | %token DREG CREG GREG IMMED ADDR INSN NUM ID NL PNUM |
| 290 | %type <val> value flags flagexpr |
| 291 | %type <num> number NUM ftype regtype pnum PNUM |
| 292 | %type <str> ID name |
| 293 | |
| 294 | %start insntbl |
| 295 | |
| 296 | %% |
| 297 | |
| 298 | insntbl: |
| 299 | entrys |
| 300 | ; |
| 301 | |
| 302 | entrys: |
| 303 | entry entrys |
| 304 | | |
| 305 | ; |
| 306 | |
| 307 | entry: |
| 308 | pnum regtype name value NL |
| 309 | { |
| 310 | DBG (("line %d: entry pnum=%d type=%d name=%s value=x%x\n", |
| 311 | insntbl_line, $1, $2, $3, $4)); |
| 312 | itbl_add_reg ($1, $2, $3, $4); |
| 313 | } |
| 314 | | pnum INSN name value range flags |
| 315 | { |
| 316 | DBG (("line %d: entry pnum=%d type=INSN name=%s value=x%x", |
| 317 | insntbl_line, $1, $3, $4)); |
| 318 | DBG ((" sbit=%d ebit=%d flags=0x%x\n", sbit, ebit, $6)); |
| 319 | insn=itbl_add_insn ($1, $3, $4, sbit, ebit, $6); |
| 320 | } |
| 321 | fieldspecs NL |
| 322 | {} |
| 323 | | NL |
| 324 | | error NL |
| 325 | ; |
| 326 | |
| 327 | fieldspecs: |
| 328 | ',' fieldspec fieldspecs |
| 329 | | fieldspec fieldspecs |
| 330 | | |
| 331 | ; |
| 332 | |
| 333 | ftype: |
| 334 | regtype |
| 335 | { |
| 336 | DBGL2 (("ftype\n")); |
| 337 | $$ = $1; |
| 338 | } |
| 339 | | ADDR |
| 340 | { |
| 341 | DBGL2 (("addr\n")); |
| 342 | $$ = ADDR; |
| 343 | } |
| 344 | | IMMED |
| 345 | { |
| 346 | DBGL2 (("immed\n")); |
| 347 | $$ = IMMED; |
| 348 | } |
| 349 | ; |
| 350 | |
| 351 | fieldspec: |
| 352 | ftype range flags |
| 353 | { |
| 354 | DBG (("line %d: field type=%d sbit=%d ebit=%d, flags=0x%x\n", |
| 355 | insntbl_line, $1, sbit, ebit, $3)); |
| 356 | itbl_add_operand (insn, $1, sbit, ebit, $3); |
| 357 | } |
| 358 | ; |
| 359 | |
| 360 | flagexpr: |
| 361 | NUM '|' flagexpr |
| 362 | { |
| 363 | $$ = $1 | $3; |
| 364 | } |
| 365 | | '[' flagexpr ']' |
| 366 | { |
| 367 | $$ = $2; |
| 368 | } |
| 369 | | NUM |
| 370 | { |
| 371 | $$ = $1; |
| 372 | } |
| 373 | ; |
| 374 | |
| 375 | flags: |
| 376 | '*' flagexpr |
| 377 | { |
| 378 | DBGL2 (("flags=%d\n", $2)); |
| 379 | $$ = $2; |
| 380 | } |
| 381 | | |
| 382 | { |
| 383 | $$ = 0; |
| 384 | } |
| 385 | ; |
| 386 | |
| 387 | range: |
| 388 | ':' NUM '-' NUM |
| 389 | { |
| 390 | DBGL2 (("range %d %d\n", $2, $4)); |
| 391 | sbit = $2; |
| 392 | ebit = $4; |
| 393 | } |
| 394 | | |
| 395 | { |
| 396 | sbit = 31; |
| 397 | ebit = 0; |
| 398 | } |
| 399 | ; |
| 400 | |
| 401 | pnum: |
| 402 | PNUM |
| 403 | { |
| 404 | DBGL2 (("pnum=%d\n",$1)); |
| 405 | $$ = $1; |
| 406 | } |
| 407 | ; |
| 408 | |
| 409 | regtype: |
| 410 | DREG |
| 411 | { |
| 412 | DBGL2 (("dreg\n")); |
| 413 | $$ = DREG; |
| 414 | } |
| 415 | | CREG |
| 416 | { |
| 417 | DBGL2 (("creg\n")); |
| 418 | $$ = CREG; |
| 419 | } |
| 420 | | GREG |
| 421 | { |
| 422 | DBGL2 (("greg\n")); |
| 423 | $$ = GREG; |
| 424 | } |
| 425 | ; |
| 426 | |
| 427 | name: |
| 428 | ID |
| 429 | { |
| 430 | DBGL2 (("name=%s\n",$1)); |
| 431 | $$ = $1; |
| 432 | } |
| 433 | ; |
| 434 | |
| 435 | number: |
| 436 | NUM |
| 437 | { |
| 438 | DBGL2 (("num=%d\n",$1)); |
| 439 | $$ = $1; |
| 440 | } |
| 441 | ; |
| 442 | |
| 443 | value: |
| 444 | NUM |
| 445 | { |
| 446 | DBGL2 (("val=x%x\n",$1)); |
| 447 | $$ = $1; |
| 448 | } |
| 449 | ; |
| 450 | %% |
| 451 | |
| 452 | static int |
| 453 | yyerror (const char *msg) |
| 454 | { |
| 455 | printf ("line %d: %s\n", insntbl_line, msg); |
| 456 | return 0; |
| 457 | } |