1 1.1 christos /* This is the machine dependent code of the Visium Assembler. 2 1.1 christos 3 1.1.1.8 christos Copyright (C) 2005-2026 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos This file is part of GAS, the GNU Assembler. 6 1.1 christos 7 1.1 christos GAS is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 2, or (at your option) 10 1.1 christos any later version. 11 1.1 christos 12 1.1 christos GAS is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1.1.3 christos along with this program; if not, write to the Free Software 19 1.1.1.3 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 1.1.1.3 christos MA 02110-1301, USA. */ 21 1.1 christos 22 1.1 christos #include "as.h" 23 1.1 christos #include "safe-ctype.h" 24 1.1 christos #include "subsegs.h" 25 1.1 christos #include "obstack.h" 26 1.1 christos 27 1.1 christos #include "opcode/visium.h" 28 1.1 christos #include "elf/visium.h" 29 1.1 christos #include "dwarf2dbg.h" 30 1.1 christos #include "dw2gencfi.h" 31 1.1 christos 32 1.1 christos /* Relocations and fixups: 33 1.1 christos 34 1.1 christos There are two different cases where an instruction or data 35 1.1 christos directive operand requires relocation, or fixup. 36 1.1 christos 37 1.1 christos 1. Relative branch instructions, take an 16-bit signed word 38 1.1 christos offset. The formula for computing the offset is this: 39 1.1 christos 40 1.1 christos offset = (destination - pc) / 4 41 1.1 christos 42 1.1 christos Branch instructions never branch to a label not declared 43 1.1 christos locally, so the actual offset can always be computed by the assembler. 44 1.1 christos However, we provide a relocation type to support this. 45 1.1 christos 46 1.1 christos 2. Load literal instructions, such as MOVIU, which take a 16-bit 47 1.1 christos literal operand. The literal may be the top or bottom half of 48 1.1 christos a 32-bit value computed by the assembler, or by the linker. We provide 49 1.1 christos two relocation types here. 50 1.1 christos 51 1.1 christos 3. Data items (long, word and byte) preset with a value computed by 52 1.1 christos the linker. */ 53 1.1 christos 54 1.1 christos 55 1.1 christos /* This string holds the chars that always start a comment. If the 56 1.1.1.7 christos pre-processor is disabled, these aren't very useful. */ 57 1.1.1.7 christos const char comment_chars[] = "!;"; 58 1.1 christos 59 1.1 christos /* This array holds the chars that only start a comment at the beginning 60 1.1 christos of a line. If the line seems to have the form '# 123 filename' .line 61 1.1 christos and .file directives will appear in the pre-processed output. Note that 62 1.1 christos input_file.c hand checks for '#' at the beginning of the first line of 63 1.1 christos the input file. This is because the compiler outputs #NO_APP at the 64 1.1 christos beginning of its output. Also note that comments like this one will 65 1.1 christos always work. */ 66 1.1 christos const char line_comment_chars[] = "#!;"; 67 1.1 christos const char line_separator_chars[] = ""; 68 1.1 christos 69 1.1 christos /* Chars that can be used to separate mantissa from exponent in floating point 70 1.1 christos numbers. */ 71 1.1 christos const char EXP_CHARS[] = "eE"; 72 1.1 christos 73 1.1 christos /* Chars that mean this number is a floating point constant, as in 74 1.1 christos "0f12.456" or "0d1.2345e12". 75 1.1 christos 76 1.1 christos ...Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be 77 1.1 christos changed in read.c. Ideally it shouldn't have to know about it at all, 78 1.1 christos but nothing is ideal around here. */ 79 1.1 christos const char FLT_CHARS[] = "rRsSfFdDxXeE"; 80 1.1 christos 81 1.1 christos /* The size of a relocation record. */ 82 1.1 christos const int md_reloc_size = 8; 83 1.1 christos 84 1.1 christos /* The architecture for which we are assembling. */ 85 1.1 christos enum visium_arch_val 86 1.1 christos { 87 1.1 christos VISIUM_ARCH_DEF, 88 1.1 christos VISIUM_ARCH_MCM24, 89 1.1 christos VISIUM_ARCH_MCM, 90 1.1 christos VISIUM_ARCH_GR6 91 1.1 christos }; 92 1.1 christos 93 1.1 christos static enum visium_arch_val visium_arch = VISIUM_ARCH_DEF; 94 1.1 christos 95 1.1 christos /* The opcode architecture for which we are assembling. In contrast to the 96 1.1 christos previous one, this only determines which instructions are supported. */ 97 1.1 christos static enum visium_opcode_arch_val visium_opcode_arch = VISIUM_OPCODE_ARCH_DEF; 98 1.1 christos 99 1.1 christos /* Flags to set in the ELF header e_flags field. */ 100 1.1 christos static flagword visium_flags = 0; 101 1.1 christos 102 1.1 christos /* More than this number of nops in an alignment op gets a branch instead. */ 103 1.1 christos static unsigned int nop_limit = 5; 104 1.1 christos 105 1.1 christos 106 1.1 christos /* Translate internal representation of relocation info to BFD target 107 1.1 christos format. */ 108 1.1 christos arelent * 109 1.1 christos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) 110 1.1 christos { 111 1.1 christos arelent *reloc; 112 1.1 christos bfd_reloc_code_real_type code; 113 1.1 christos 114 1.1.1.7 christos reloc = notes_alloc (sizeof (arelent)); 115 1.1.1.7 christos reloc->sym_ptr_ptr = notes_alloc (sizeof (asymbol *)); 116 1.1 christos *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 117 1.1 christos reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 118 1.1 christos 119 1.1 christos switch (fixp->fx_r_type) 120 1.1 christos { 121 1.1 christos case BFD_RELOC_8: 122 1.1 christos case BFD_RELOC_16: 123 1.1 christos case BFD_RELOC_32: 124 1.1 christos case BFD_RELOC_8_PCREL: 125 1.1 christos case BFD_RELOC_16_PCREL: 126 1.1 christos case BFD_RELOC_32_PCREL: 127 1.1 christos case BFD_RELOC_VISIUM_HI16: 128 1.1 christos case BFD_RELOC_VISIUM_LO16: 129 1.1 christos case BFD_RELOC_VISIUM_IM16: 130 1.1 christos case BFD_RELOC_VISIUM_REL16: 131 1.1 christos case BFD_RELOC_VISIUM_HI16_PCREL: 132 1.1 christos case BFD_RELOC_VISIUM_LO16_PCREL: 133 1.1 christos case BFD_RELOC_VISIUM_IM16_PCREL: 134 1.1 christos case BFD_RELOC_VTABLE_INHERIT: 135 1.1 christos case BFD_RELOC_VTABLE_ENTRY: 136 1.1 christos code = fixp->fx_r_type; 137 1.1 christos break; 138 1.1 christos default: 139 1.1 christos as_bad_where (fixp->fx_file, fixp->fx_line, 140 1.1 christos "internal error: unknown relocation type %d (`%s')", 141 1.1 christos fixp->fx_r_type, 142 1.1 christos bfd_get_reloc_code_name (fixp->fx_r_type)); 143 1.1 christos return 0; 144 1.1 christos } 145 1.1 christos 146 1.1 christos reloc->howto = bfd_reloc_type_lookup (stdoutput, code); 147 1.1 christos if (reloc->howto == 0) 148 1.1 christos { 149 1.1 christos as_bad_where (fixp->fx_file, fixp->fx_line, 150 1.1 christos "internal error: can't export reloc type %d (`%s')", 151 1.1 christos fixp->fx_r_type, bfd_get_reloc_code_name (code)); 152 1.1 christos return 0; 153 1.1 christos } 154 1.1 christos 155 1.1 christos /* Write the addend. */ 156 1.1 christos if (reloc->howto->pc_relative == 0) 157 1.1 christos reloc->addend = fixp->fx_addnumber; 158 1.1 christos else 159 1.1 christos reloc->addend = fixp->fx_offset; 160 1.1 christos 161 1.1 christos return reloc; 162 1.1 christos } 163 1.1 christos 164 1.1 christos static void visium_rdata (int); 165 1.1 christos 166 1.1 christos static void visium_update_parity_bit (char *); 167 1.1 christos static char *parse_exp (char *, expressionS *); 168 1.1 christos 169 1.1 christos /* This table describes all the machine specific pseudo-ops the assembler 170 1.1.1.6 christos has to support, and that aren't handled elsewhere. The fields are: 171 1.1 christos 172 1.1 christos 1: Pseudo-op name without dot. 173 1.1 christos 2: Function to call to execute this pseudo-op. 174 1.1 christos 3: Integer arg to pass to the function. */ 175 1.1 christos const pseudo_typeS md_pseudo_table[] = 176 1.1 christos { 177 1.1 christos {"align", s_align_bytes, 0}, 178 1.1 christos {"noopt", s_ignore, 0}, 179 1.1 christos {"optim", s_ignore, 0}, 180 1.1 christos {"rdata", visium_rdata, 0}, 181 1.1 christos {"rodata", visium_rdata, 0}, 182 1.1 christos {0, 0, 0} 183 1.1 christos }; 184 1.1 christos 185 1.1 christos 186 1.1 christos static void 187 1.1 christos visium_rdata (int xxx) 188 1.1 christos { 189 1.1 christos char *save_line = input_line_pointer; 190 1.1 christos static char section[] = ".rodata\n"; 191 1.1 christos 192 1.1 christos /* Just pretend this is .section .rodata */ 193 1.1 christos input_line_pointer = section; 194 1.1 christos obj_elf_section (xxx); 195 1.1 christos input_line_pointer = save_line; 196 1.1 christos } 197 1.1 christos 198 1.1 christos /* Align a section. */ 199 1.1 christos valueT 200 1.1 christos md_section_align (asection *seg, valueT addr) 201 1.1 christos { 202 1.1.1.4 christos int align = bfd_section_alignment (seg); 203 1.1 christos 204 1.1.1.7 christos return (addr + ((valueT) 1 << align) - 1) & -((valueT) 1 << align); 205 1.1 christos } 206 1.1 christos 207 1.1 christos void 208 1.1 christos md_number_to_chars (char *buf, valueT val, int n) 209 1.1 christos { 210 1.1 christos number_to_chars_bigendian (buf, val, n); 211 1.1 christos } 212 1.1 christos 213 1.1 christos symbolS * 214 1.1 christos md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 215 1.1 christos { 216 1.1 christos return 0; 217 1.1 christos } 218 1.1 christos 219 1.1 christos /* The parse options. */ 220 1.1.1.7 christos const char md_shortopts[] = "m:"; 221 1.1 christos 222 1.1.1.7 christos const struct option md_longopts[] = 223 1.1 christos { 224 1.1 christos {NULL, no_argument, NULL, 0} 225 1.1 christos }; 226 1.1 christos 227 1.1.1.7 christos const size_t md_longopts_size = sizeof (md_longopts); 228 1.1 christos 229 1.1 christos struct visium_option_table 230 1.1 christos { 231 1.1 christos char *option; /* Option name to match. */ 232 1.1 christos char *help; /* Help information. */ 233 1.1 christos int *var; /* Variable to change. */ 234 1.1 christos int value; /* To what to change it. */ 235 1.1 christos char *deprecated; /* If non-null, print this message. */ 236 1.1 christos }; 237 1.1 christos 238 1.1 christos static struct visium_option_table visium_opts[] = 239 1.1 christos { 240 1.1 christos {NULL, NULL, NULL, 0, NULL} 241 1.1 christos }; 242 1.1 christos 243 1.1 christos struct visium_arch_option_table 244 1.1 christos { 245 1.1.1.2 christos const char *name; 246 1.1 christos enum visium_arch_val value; 247 1.1 christos }; 248 1.1 christos 249 1.1 christos static struct visium_arch_option_table visium_archs[] = 250 1.1 christos { 251 1.1 christos {"mcm24", VISIUM_ARCH_MCM24}, 252 1.1 christos {"mcm", VISIUM_ARCH_MCM}, 253 1.1 christos {"gr5", VISIUM_ARCH_MCM}, 254 1.1 christos {"gr6", VISIUM_ARCH_GR6}, 255 1.1 christos }; 256 1.1 christos 257 1.1 christos struct visium_long_option_table 258 1.1 christos { 259 1.1.1.2 christos const char *option; /* Substring to match. */ 260 1.1.1.2 christos const char *help; /* Help information. */ 261 1.1.1.2 christos int (*func) (const char *subopt); /* Function to decode sub-option. */ 262 1.1.1.2 christos const char *deprecated; /* If non-null, print this message. */ 263 1.1 christos }; 264 1.1 christos 265 1.1 christos static int 266 1.1.1.2 christos visium_parse_arch (const char *str) 267 1.1 christos { 268 1.1.1.2 christos unsigned int i; 269 1.1 christos 270 1.1 christos if (strlen (str) == 0) 271 1.1 christos { 272 1.1 christos as_bad ("missing architecture name `%s'", str); 273 1.1 christos return 0; 274 1.1 christos } 275 1.1 christos 276 1.1.1.2 christos for (i = 0; i < ARRAY_SIZE (visium_archs); i++) 277 1.1.1.2 christos if (strcmp (visium_archs[i].name, str) == 0) 278 1.1 christos { 279 1.1.1.2 christos visium_arch = visium_archs[i].value; 280 1.1 christos return 1; 281 1.1 christos } 282 1.1 christos 283 1.1 christos as_bad ("unknown architecture `%s'\n", str); 284 1.1 christos return 0; 285 1.1 christos } 286 1.1 christos 287 1.1 christos static struct visium_long_option_table visium_long_opts[] = 288 1.1 christos { 289 1.1 christos {"mtune=", "<arch_name>\t assemble for architecture <arch name>", 290 1.1 christos visium_parse_arch, NULL}, 291 1.1 christos {NULL, NULL, NULL, NULL} 292 1.1 christos }; 293 1.1 christos 294 1.1 christos int 295 1.1.1.2 christos md_parse_option (int c, const char *arg) 296 1.1 christos { 297 1.1 christos struct visium_option_table *opt; 298 1.1 christos struct visium_long_option_table *lopt; 299 1.1 christos 300 1.1 christos switch (c) 301 1.1 christos { 302 1.1 christos case 'a': 303 1.1 christos /* Listing option. Just ignore these, we don't support additional 304 1.1 christos ones. */ 305 1.1 christos return 0; 306 1.1 christos 307 1.1 christos default: 308 1.1 christos for (opt = visium_opts; opt->option != NULL; opt++) 309 1.1 christos { 310 1.1 christos if (c == opt->option[0] 311 1.1 christos && ((arg == NULL && opt->option[1] == 0) 312 1.1 christos || strcmp (arg, opt->option + 1) == 0)) 313 1.1 christos { 314 1.1 christos /* If the option is deprecated, tell the user. */ 315 1.1 christos if (opt->deprecated != NULL) 316 1.1 christos as_tsktsk ("option `-%c%s' is deprecated: %s", c, 317 1.1 christos arg ? arg : "", opt->deprecated); 318 1.1 christos 319 1.1 christos if (opt->var != NULL) 320 1.1 christos *opt->var = opt->value; 321 1.1 christos 322 1.1 christos return 1; 323 1.1 christos } 324 1.1 christos } 325 1.1 christos 326 1.1 christos for (lopt = visium_long_opts; lopt->option != NULL; lopt++) 327 1.1 christos { 328 1.1 christos /* These options are expected to have an argument. */ 329 1.1 christos if (c == lopt->option[0] 330 1.1 christos && arg != NULL 331 1.1 christos && strncmp (arg, lopt->option + 1, 332 1.1 christos strlen (lopt->option + 1)) == 0) 333 1.1 christos { 334 1.1 christos /* If the option is deprecated, tell the user. */ 335 1.1 christos if (lopt->deprecated != NULL) 336 1.1 christos as_tsktsk ("option `-%c%s' is deprecated: %s", c, arg, 337 1.1 christos lopt->deprecated); 338 1.1 christos 339 1.1 christos /* Call the sup-option parser. */ 340 1.1 christos return lopt->func (arg + strlen (lopt->option) - 1); 341 1.1 christos } 342 1.1 christos } 343 1.1 christos 344 1.1 christos return 0; 345 1.1 christos } 346 1.1 christos 347 1.1 christos return 1; 348 1.1 christos } 349 1.1 christos 350 1.1 christos void 351 1.1 christos md_show_usage (FILE * fp) 352 1.1 christos { 353 1.1 christos struct visium_option_table *opt; 354 1.1 christos struct visium_long_option_table *lopt; 355 1.1 christos 356 1.1 christos fprintf (fp, " Visium-specific assembler options:\n"); 357 1.1 christos 358 1.1 christos for (opt = visium_opts; opt->option != NULL; opt++) 359 1.1 christos if (opt->help != NULL) 360 1.1 christos fprintf (fp, " -%-23s%s\n", opt->option, opt->help); 361 1.1 christos 362 1.1 christos for (lopt = visium_long_opts; lopt->option != NULL; lopt++) 363 1.1 christos if (lopt->help != NULL) 364 1.1 christos fprintf (fp, " -%s%s\n", lopt->option, lopt->help); 365 1.1 christos 366 1.1 christos } 367 1.1 christos 368 1.1 christos /* Interface to relax_segment. */ 369 1.1 christos 370 1.1 christos /* Return the estimate of the size of a machine dependent frag 371 1.1 christos before any relaxing is done. It may also create any necessary 372 1.1 christos relocations. */ 373 1.1 christos int 374 1.1 christos md_estimate_size_before_relax (fragS * fragP, 375 1.1 christos segT segment ATTRIBUTE_UNUSED) 376 1.1 christos { 377 1.1 christos fragP->fr_var = 4; 378 1.1 christos return 4; 379 1.1 christos } 380 1.1 christos 381 1.1 christos /* Get the address of a symbol during relaxation. From tc-arm.c. */ 382 1.1 christos static addressT 383 1.1 christos relaxed_symbol_addr (fragS *fragp, long stretch) 384 1.1 christos { 385 1.1 christos fragS *sym_frag; 386 1.1 christos addressT addr; 387 1.1 christos symbolS *sym; 388 1.1 christos 389 1.1 christos sym = fragp->fr_symbol; 390 1.1 christos sym_frag = symbol_get_frag (sym); 391 1.1 christos know (S_GET_SEGMENT (sym) != absolute_section 392 1.1 christos || sym_frag == &zero_address_frag); 393 1.1 christos addr = S_GET_VALUE (sym) + fragp->fr_offset; 394 1.1 christos 395 1.1 christos /* If frag has yet to be reached on this pass, assume it will 396 1.1 christos move by STRETCH just as we did. If this is not so, it will 397 1.1 christos be because some frag between grows, and that will force 398 1.1 christos another pass. */ 399 1.1 christos if (stretch != 0 400 1.1 christos && sym_frag->relax_marker != fragp->relax_marker) 401 1.1 christos { 402 1.1 christos fragS *f; 403 1.1 christos 404 1.1 christos /* Adjust stretch for any alignment frag. Note that if have 405 1.1 christos been expanding the earlier code, the symbol may be 406 1.1 christos defined in what appears to be an earlier frag. FIXME: 407 1.1 christos This doesn't handle the fr_subtype field, which specifies 408 1.1 christos a maximum number of bytes to skip when doing an 409 1.1 christos alignment. */ 410 1.1 christos for (f = fragp; f != NULL && f != sym_frag; f = f->fr_next) 411 1.1 christos { 412 1.1 christos if (f->fr_type == rs_align || f->fr_type == rs_align_code) 413 1.1 christos { 414 1.1 christos if (stretch < 0) 415 1.1.1.7 christos stretch = -(-stretch & ~((1ul << f->fr_offset) - 1)); 416 1.1 christos else 417 1.1.1.7 christos stretch &= ~((1ul << f->fr_offset) - 1); 418 1.1 christos if (stretch == 0) 419 1.1 christos break; 420 1.1 christos } 421 1.1 christos } 422 1.1 christos if (f != NULL) 423 1.1 christos addr += stretch; 424 1.1 christos } 425 1.1 christos 426 1.1 christos return addr; 427 1.1 christos } 428 1.1 christos 429 1.1 christos /* Relax a machine dependent frag. This returns the amount by which 430 1.1 christos the current size of the frag should change. */ 431 1.1 christos int 432 1.1 christos visium_relax_frag (asection *sec, fragS *fragP, long stretch) 433 1.1 christos { 434 1.1 christos int old_size, new_size; 435 1.1 christos addressT addr; 436 1.1 christos 437 1.1 christos /* We only handle relaxation for the BRR instruction. */ 438 1.1 christos gas_assert (fragP->fr_subtype == mode_ci); 439 1.1 christos 440 1.1 christos if (!S_IS_DEFINED (fragP->fr_symbol) 441 1.1 christos || sec != S_GET_SEGMENT (fragP->fr_symbol) 442 1.1 christos || S_IS_WEAK (fragP->fr_symbol)) 443 1.1 christos return 0; 444 1.1 christos 445 1.1 christos old_size = fragP->fr_var; 446 1.1 christos addr = relaxed_symbol_addr (fragP, stretch); 447 1.1 christos 448 1.1 christos /* If the target is the address of the instruction, we'll insert a NOP. */ 449 1.1 christos if (addr == fragP->fr_address + fragP->fr_fix) 450 1.1 christos new_size = 8; 451 1.1 christos else 452 1.1 christos new_size = 4; 453 1.1 christos 454 1.1 christos fragP->fr_var = new_size; 455 1.1 christos return new_size - old_size; 456 1.1 christos } 457 1.1 christos 458 1.1 christos /* Convert a machine dependent frag. */ 459 1.1 christos void 460 1.1 christos md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, 461 1.1 christos fragS * fragP) 462 1.1 christos { 463 1.1.1.5 christos char *buf = &fragP->fr_literal[0] + fragP->fr_fix; 464 1.1 christos expressionS exp; 465 1.1 christos fixS *fixP; 466 1.1 christos 467 1.1 christos /* We only handle relaxation for the BRR instruction. */ 468 1.1 christos gas_assert (fragP->fr_subtype == mode_ci); 469 1.1 christos 470 1.1 christos /* Insert the NOP if requested. */ 471 1.1 christos if (fragP->fr_var == 8) 472 1.1 christos { 473 1.1 christos memcpy (buf + 4, buf, 4); 474 1.1 christos memset (buf, 0, 4); 475 1.1 christos fragP->fr_fix += 4; 476 1.1 christos } 477 1.1 christos 478 1.1 christos exp.X_op = O_symbol; 479 1.1 christos exp.X_add_symbol = fragP->fr_symbol; 480 1.1 christos exp.X_add_number = fragP->fr_offset; 481 1.1 christos 482 1.1 christos /* Now we can create the relocation at the correct offset. */ 483 1.1 christos fixP = fix_new_exp (fragP, fragP->fr_fix, 4, &exp, 1, BFD_RELOC_VISIUM_REL16); 484 1.1 christos fixP->fx_file = fragP->fr_file; 485 1.1 christos fixP->fx_line = fragP->fr_line; 486 1.1 christos fragP->fr_fix += 4; 487 1.1 christos fragP->fr_var = 0; 488 1.1 christos } 489 1.1 christos 490 1.1 christos /* The location from which a PC relative jump should be calculated, 491 1.1 christos given a PC relative jump reloc. */ 492 1.1 christos long 493 1.1 christos visium_pcrel_from_section (fixS *fixP, segT sec) 494 1.1 christos { 495 1.1.1.7 christos if (fixP->fx_addsy != NULL 496 1.1 christos && (!S_IS_DEFINED (fixP->fx_addsy) 497 1.1 christos || S_GET_SEGMENT (fixP->fx_addsy) != sec)) 498 1.1 christos { 499 1.1 christos /* The symbol is undefined (or is defined but not in this section). 500 1.1 christos Let the linker figure it out. */ 501 1.1 christos return 0; 502 1.1 christos } 503 1.1 christos 504 1.1 christos /* Return the address of the instruction. */ 505 1.1 christos return fixP->fx_where + fixP->fx_frag->fr_address; 506 1.1 christos } 507 1.1 christos 508 1.1 christos /* Indicate whether a fixup against a locally defined 509 1.1 christos symbol should be adjusted to be against the section 510 1.1 christos symbol. */ 511 1.1.1.5 christos bool 512 1.1 christos visium_fix_adjustable (fixS *fix) 513 1.1 christos { 514 1.1 christos /* We need the symbol name for the VTABLE entries. */ 515 1.1 christos return (fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT 516 1.1 christos && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY); 517 1.1 christos } 518 1.1 christos 519 1.1 christos /* Update the parity bit of the 4-byte instruction in BUF. */ 520 1.1 christos static void 521 1.1 christos visium_update_parity_bit (char *buf) 522 1.1 christos { 523 1.1 christos int p1 = (buf[0] & 0x7f) ^ buf[1] ^ buf[2] ^ buf[3]; 524 1.1 christos int p2 = 0; 525 1.1 christos int i; 526 1.1 christos 527 1.1 christos for (i = 1; i <= 8; i++) 528 1.1 christos { 529 1.1 christos p2 ^= (p1 & 1); 530 1.1 christos p1 >>= 1; 531 1.1 christos } 532 1.1 christos 533 1.1 christos buf[0] = (buf[0] & 0x7f) | ((p2 << 7) & 0x80); 534 1.1 christos } 535 1.1 christos 536 1.1 christos /* This is called from HANDLE_ALIGN in write.c. Fill in the contents 537 1.1 christos of an rs_align_code fragment. */ 538 1.1 christos void 539 1.1 christos visium_handle_align (fragS *fragP) 540 1.1 christos { 541 1.1 christos valueT count 542 1.1 christos = fragP->fr_next->fr_address - (fragP->fr_address + fragP->fr_fix); 543 1.1 christos valueT fix = count & 3; 544 1.1 christos char *p = fragP->fr_literal + fragP->fr_fix; 545 1.1 christos 546 1.1 christos if (fix) 547 1.1 christos { 548 1.1 christos memset (p, 0, fix); 549 1.1 christos p += fix; 550 1.1 christos count -= fix; 551 1.1 christos fragP->fr_fix += fix; 552 1.1 christos } 553 1.1 christos 554 1.1 christos if (count == 0) 555 1.1 christos return; 556 1.1 christos 557 1.1 christos if (count > 4 * nop_limit && count <= 131068) 558 1.1 christos { 559 1.1.1.7 christos /* Make a branch, then follow with nops. */ 560 1.1 christos md_number_to_chars (p, 0x78000000 + (count >> 2), 4); 561 1.1 christos visium_update_parity_bit (p); 562 1.1.1.7 christos p += 4; 563 1.1.1.7 christos fragP->fr_fix += 4; 564 1.1 christos } 565 1.1 christos 566 1.1.1.7 christos *p = 0; 567 1.1 christos } 568 1.1 christos 569 1.1 christos /* Apply a fixS to the frags, now that we know the value it ought to 570 1.1 christos hold. */ 571 1.1 christos void 572 1.1 christos md_apply_fix (fixS * fixP, valueT * value, segT segment) 573 1.1 christos { 574 1.1 christos char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 575 1.1 christos offsetT val; 576 1.1 christos long insn; 577 1.1 christos 578 1.1 christos val = *value; 579 1.1 christos 580 1.1 christos gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED); 581 1.1 christos 582 1.1 christos /* Remember value for tc_gen_reloc. */ 583 1.1 christos fixP->fx_addnumber = val; 584 1.1 christos 585 1.1 christos /* Since DIFF_EXPR_OK is defined, .-foo gets turned into PC 586 1.1 christos relative relocs. If this has happened, a non-PC relative 587 1.1 christos reloc must be reinstalled with its PC relative version here. */ 588 1.1 christos if (fixP->fx_pcrel) 589 1.1 christos { 590 1.1 christos switch (fixP->fx_r_type) 591 1.1 christos { 592 1.1 christos case BFD_RELOC_8: 593 1.1 christos fixP->fx_r_type = BFD_RELOC_8_PCREL; 594 1.1 christos break; 595 1.1 christos case BFD_RELOC_16: 596 1.1 christos fixP->fx_r_type = BFD_RELOC_16_PCREL; 597 1.1 christos break; 598 1.1 christos case BFD_RELOC_32: 599 1.1 christos fixP->fx_r_type = BFD_RELOC_32_PCREL; 600 1.1 christos break; 601 1.1 christos case BFD_RELOC_VISIUM_HI16: 602 1.1 christos fixP->fx_r_type = BFD_RELOC_VISIUM_HI16_PCREL; 603 1.1 christos break; 604 1.1 christos case BFD_RELOC_VISIUM_LO16: 605 1.1 christos fixP->fx_r_type = BFD_RELOC_VISIUM_LO16_PCREL; 606 1.1 christos break; 607 1.1 christos case BFD_RELOC_VISIUM_IM16: 608 1.1 christos fixP->fx_r_type = BFD_RELOC_VISIUM_IM16_PCREL; 609 1.1 christos break; 610 1.1 christos default: 611 1.1 christos break; 612 1.1 christos } 613 1.1 christos } 614 1.1 christos 615 1.1 christos /* If this is a data relocation, just output VAL. */ 616 1.1 christos switch (fixP->fx_r_type) 617 1.1 christos { 618 1.1 christos case BFD_RELOC_8: 619 1.1 christos case BFD_RELOC_8_PCREL: 620 1.1 christos md_number_to_chars (buf, val, 1); 621 1.1 christos break; 622 1.1 christos case BFD_RELOC_16: 623 1.1 christos case BFD_RELOC_16_PCREL: 624 1.1 christos md_number_to_chars (buf, val, 2); 625 1.1 christos break; 626 1.1 christos case BFD_RELOC_32: 627 1.1 christos case BFD_RELOC_32_PCREL: 628 1.1 christos md_number_to_chars (buf, val, 4); 629 1.1 christos break; 630 1.1 christos case BFD_RELOC_VTABLE_INHERIT: 631 1.1 christos case BFD_RELOC_VTABLE_ENTRY: 632 1.1 christos fixP->fx_done = 0; 633 1.1 christos break; 634 1.1 christos default: 635 1.1 christos /* It's a relocation against an instruction. */ 636 1.1.1.7 christos insn = bfd_getb32 (buf); 637 1.1 christos 638 1.1 christos switch (fixP->fx_r_type) 639 1.1 christos { 640 1.1 christos case BFD_RELOC_VISIUM_REL16: 641 1.1 christos if (fixP->fx_addsy == NULL 642 1.1 christos || (S_IS_DEFINED (fixP->fx_addsy) 643 1.1 christos && S_GET_SEGMENT (fixP->fx_addsy) == segment)) 644 1.1 christos { 645 1.1 christos if (val > 0x1fffc || val < -0x20000) 646 1.1 christos as_bad_where 647 1.1 christos (fixP->fx_file, fixP->fx_line, 648 1.1 christos "16-bit word displacement out of range: value = %d", 649 1.1 christos (int) val); 650 1.1 christos val = (val >> 2); 651 1.1 christos 652 1.1 christos insn = (insn & 0xffff0000) | (val & 0x0000ffff); 653 1.1 christos } 654 1.1 christos break; 655 1.1 christos 656 1.1 christos case BFD_RELOC_VISIUM_HI16: 657 1.1 christos case BFD_RELOC_VISIUM_HI16_PCREL: 658 1.1 christos if (fixP->fx_addsy == NULL) 659 1.1 christos insn = (insn & 0xffff0000) | ((val >> 16) & 0x0000ffff); 660 1.1 christos break; 661 1.1 christos 662 1.1 christos case BFD_RELOC_VISIUM_LO16: 663 1.1 christos case BFD_RELOC_VISIUM_LO16_PCREL: 664 1.1 christos if (fixP->fx_addsy == NULL) 665 1.1 christos insn = (insn & 0xffff0000) | (val & 0x0000ffff); 666 1.1 christos break; 667 1.1 christos 668 1.1 christos case BFD_RELOC_VISIUM_IM16: 669 1.1 christos case BFD_RELOC_VISIUM_IM16_PCREL: 670 1.1 christos if (fixP->fx_addsy == NULL) 671 1.1 christos { 672 1.1 christos if ((val & 0xffff0000) != 0) 673 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line, 674 1.1 christos "16-bit immediate out of range: value = %d", 675 1.1 christos (int) val); 676 1.1 christos 677 1.1 christos insn = (insn & 0xffff0000) | val; 678 1.1 christos } 679 1.1 christos break; 680 1.1 christos 681 1.1 christos case BFD_RELOC_NONE: 682 1.1 christos default: 683 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line, 684 1.1 christos "bad or unhandled relocation type: 0x%02x", 685 1.1.1.7 christos (unsigned int) fixP->fx_r_type); 686 1.1 christos break; 687 1.1 christos } 688 1.1 christos 689 1.1.1.7 christos bfd_putb32 (insn, buf); 690 1.1 christos visium_update_parity_bit (buf); 691 1.1 christos break; 692 1.1 christos } 693 1.1 christos 694 1.1 christos /* Are we finished with this relocation now? */ 695 1.1 christos if (fixP->fx_addsy == NULL) 696 1.1 christos fixP->fx_done = 1; 697 1.1 christos } 698 1.1 christos 699 1.1 christos char * 700 1.1 christos parse_exp (char *s, expressionS * op) 701 1.1 christos { 702 1.1 christos char *save = input_line_pointer; 703 1.1 christos char *new; 704 1.1 christos 705 1.1 christos if (!s) 706 1.1 christos { 707 1.1 christos return s; 708 1.1 christos } 709 1.1 christos 710 1.1 christos input_line_pointer = s; 711 1.1 christos expression (op); 712 1.1 christos new = input_line_pointer; 713 1.1 christos input_line_pointer = save; 714 1.1 christos return new; 715 1.1 christos } 716 1.1 christos 717 1.1 christos /* If the given string is a Visium opcode mnemonic return the code 718 1.1 christos otherwise return -1. Use binary chop to find matching entry. */ 719 1.1 christos static int 720 1.1 christos get_opcode (int *code, enum addressing_mode *mode, char *flags, char *mnem) 721 1.1 christos { 722 1.1 christos int l = 0; 723 1.1 christos int r = sizeof (opcode_table) / sizeof (struct opcode_entry) - 1; 724 1.1 christos 725 1.1 christos do 726 1.1 christos { 727 1.1 christos int mid = (l + r) / 2; 728 1.1 christos int ans = strcmp (mnem, opcode_table[mid].mnem); 729 1.1 christos 730 1.1 christos if (ans < 0) 731 1.1 christos r = mid - 1; 732 1.1 christos else if (ans > 0) 733 1.1 christos l = mid + 1; 734 1.1 christos else 735 1.1 christos { 736 1.1 christos *code = opcode_table[mid].code; 737 1.1 christos *mode = opcode_table[mid].mode; 738 1.1 christos *flags = opcode_table[mid].flags; 739 1.1 christos 740 1.1 christos return 0; 741 1.1 christos } 742 1.1 christos } 743 1.1 christos while (l <= r); 744 1.1 christos 745 1.1 christos return -1; 746 1.1 christos } 747 1.1 christos 748 1.1 christos /* This function is called when the assembler starts up. It is called 749 1.1 christos after the options have been parsed and the output file has been 750 1.1 christos opened. */ 751 1.1 christos void 752 1.1 christos md_begin (void) 753 1.1 christos { 754 1.1 christos switch (visium_arch) 755 1.1 christos { 756 1.1 christos case VISIUM_ARCH_DEF: 757 1.1 christos break; 758 1.1 christos case VISIUM_ARCH_MCM24: 759 1.1 christos visium_opcode_arch = VISIUM_OPCODE_ARCH_GR5; 760 1.1 christos visium_flags |= EF_VISIUM_ARCH_MCM24; 761 1.1 christos break; 762 1.1 christos case VISIUM_ARCH_MCM: 763 1.1 christos visium_opcode_arch = VISIUM_OPCODE_ARCH_GR5; 764 1.1 christos visium_flags |= EF_VISIUM_ARCH_MCM; 765 1.1 christos break; 766 1.1 christos case VISIUM_ARCH_GR6: 767 1.1 christos visium_opcode_arch = VISIUM_OPCODE_ARCH_GR6; 768 1.1 christos visium_flags |= EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_GR6; 769 1.1 christos nop_limit = 2; 770 1.1 christos break; 771 1.1 christos default: 772 1.1 christos gas_assert (0); 773 1.1 christos } 774 1.1 christos 775 1.1 christos bfd_set_private_flags (stdoutput, visium_flags); 776 1.1 christos } 777 1.1 christos 778 1.1 christos /* This is identical to the md_atof in m68k.c. I think this is right, 779 1.1 christos but I'm not sure. 780 1.1 christos 781 1.1 christos Turn a string in input_line_pointer into a floating point constant of type 782 1.1 christos type, and store the appropriate bytes in *litP. The number of LITTLENUMS 783 1.1 christos emitted is stored in *sizeP . An error message is returned, 784 1.1 christos or NULL on OK. */ 785 1.1 christos 786 1.1.1.2 christos const char * 787 1.1 christos md_atof (int type, char *litP, int *sizeP) 788 1.1 christos { 789 1.1 christos int i, prec; 790 1.1 christos LITTLENUM_TYPE words[MAX_LITTLENUMS]; 791 1.1 christos char *t; 792 1.1 christos 793 1.1 christos switch (type) 794 1.1 christos { 795 1.1 christos case 'f': 796 1.1 christos case 'F': 797 1.1 christos case 's': 798 1.1 christos case 'S': 799 1.1 christos prec = 2; 800 1.1 christos break; 801 1.1 christos 802 1.1 christos case 'd': 803 1.1 christos case 'D': 804 1.1 christos case 'r': 805 1.1 christos case 'R': 806 1.1 christos prec = 4; 807 1.1 christos break; 808 1.1 christos 809 1.1 christos case 'x': 810 1.1 christos case 'X': 811 1.1 christos prec = 6; 812 1.1 christos break; 813 1.1 christos 814 1.1 christos case 'p': 815 1.1 christos case 'P': 816 1.1 christos prec = 6; 817 1.1 christos break; 818 1.1 christos 819 1.1 christos default: 820 1.1 christos *sizeP = 0; 821 1.1.1.2 christos return _("Bad call to MD_ATOF()"); 822 1.1 christos } 823 1.1 christos 824 1.1 christos t = atof_ieee (input_line_pointer, type, words); 825 1.1 christos if (t) 826 1.1 christos input_line_pointer = t; 827 1.1 christos *sizeP = prec * sizeof (LITTLENUM_TYPE); 828 1.1 christos 829 1.1 christos if (target_big_endian) 830 1.1 christos { 831 1.1 christos for (i = 0; i < prec; i++) 832 1.1 christos { 833 1.1.1.7 christos md_number_to_chars (litP, words[i], sizeof (LITTLENUM_TYPE)); 834 1.1 christos litP += sizeof (LITTLENUM_TYPE); 835 1.1 christos } 836 1.1 christos } 837 1.1 christos else 838 1.1 christos { 839 1.1 christos for (i = prec - 1; i >= 0; i--) 840 1.1 christos { 841 1.1.1.7 christos md_number_to_chars (litP, words[i], sizeof (LITTLENUM_TYPE)); 842 1.1 christos litP += sizeof (LITTLENUM_TYPE); 843 1.1 christos } 844 1.1 christos } 845 1.1 christos 846 1.1 christos return 0; 847 1.1 christos } 848 1.1 christos 849 1.1 christos static inline char * 850 1.1 christos skip_space (char *s) 851 1.1 christos { 852 1.1.1.7 christos while (is_whitespace (*s)) 853 1.1 christos ++s; 854 1.1 christos 855 1.1 christos return s; 856 1.1 christos } 857 1.1 christos 858 1.1 christos static int 859 1.1 christos parse_gen_reg (char **sptr, int *rptr) 860 1.1 christos { 861 1.1 christos char *s = skip_space (*sptr); 862 1.1 christos char buf[10]; 863 1.1 christos int cnt; 864 1.1 christos int l, r; 865 1.1 christos 866 1.1 christos cnt = 0; 867 1.1 christos memset (buf, '\0', 10); 868 1.1 christos while ((ISALNUM (*s)) && cnt < 10) 869 1.1 christos buf[cnt++] = TOLOWER (*s++); 870 1.1 christos 871 1.1 christos l = 0; 872 1.1 christos r = sizeof (gen_reg_table) / sizeof (struct reg_entry) - 1; 873 1.1 christos 874 1.1 christos do 875 1.1 christos { 876 1.1 christos int mid = (l + r) / 2; 877 1.1 christos int ans = strcmp (buf, gen_reg_table[mid].name); 878 1.1 christos 879 1.1 christos if (ans < 0) 880 1.1 christos r = mid - 1; 881 1.1 christos else if (ans > 0) 882 1.1 christos l = mid + 1; 883 1.1 christos else 884 1.1 christos { 885 1.1 christos *rptr = gen_reg_table[mid].code; 886 1.1 christos *sptr = s; 887 1.1 christos return 0; 888 1.1 christos } 889 1.1 christos } 890 1.1 christos while (l <= r); 891 1.1 christos 892 1.1 christos return -1; 893 1.1 christos } 894 1.1 christos 895 1.1 christos static int 896 1.1 christos parse_fp_reg (char **sptr, int *rptr) 897 1.1 christos { 898 1.1 christos char *s = skip_space (*sptr); 899 1.1 christos char buf[10]; 900 1.1 christos int cnt; 901 1.1 christos int l, r; 902 1.1 christos 903 1.1 christos cnt = 0; 904 1.1 christos memset (buf, '\0', 10); 905 1.1 christos while ((ISALNUM (*s)) && cnt < 10) 906 1.1 christos buf[cnt++] = TOLOWER (*s++); 907 1.1 christos 908 1.1 christos l = 0; 909 1.1 christos r = sizeof (fp_reg_table) / sizeof (struct reg_entry) - 1; 910 1.1 christos 911 1.1 christos do 912 1.1 christos { 913 1.1 christos int mid = (l + r) / 2; 914 1.1 christos int ans = strcmp (buf, fp_reg_table[mid].name); 915 1.1 christos 916 1.1 christos if (ans < 0) 917 1.1 christos r = mid - 1; 918 1.1 christos else if (ans > 0) 919 1.1 christos l = mid + 1; 920 1.1 christos else 921 1.1 christos { 922 1.1 christos *rptr = fp_reg_table[mid].code; 923 1.1 christos *sptr = s; 924 1.1 christos return 0; 925 1.1 christos } 926 1.1 christos } 927 1.1 christos while (l <= r); 928 1.1 christos 929 1.1 christos return -1; 930 1.1 christos } 931 1.1 christos 932 1.1 christos static int 933 1.1 christos parse_cc (char **sptr, int *rptr) 934 1.1 christos { 935 1.1 christos char *s = skip_space (*sptr); 936 1.1 christos char buf[10]; 937 1.1 christos int cnt; 938 1.1 christos int l, r; 939 1.1 christos 940 1.1 christos cnt = 0; 941 1.1 christos memset (buf, '\0', 10); 942 1.1 christos while ((ISALNUM (*s)) && cnt < 10) 943 1.1 christos buf[cnt++] = TOLOWER (*s++); 944 1.1 christos 945 1.1 christos l = 0; 946 1.1 christos r = sizeof (cc_table) / sizeof (struct cc_entry) - 1; 947 1.1 christos 948 1.1 christos do 949 1.1 christos { 950 1.1 christos int mid = (l + r) / 2; 951 1.1 christos int ans = strcmp (buf, cc_table[mid].name); 952 1.1 christos 953 1.1 christos if (ans < 0) 954 1.1 christos r = mid - 1; 955 1.1 christos else if (ans > 0) 956 1.1 christos l = mid + 1; 957 1.1 christos else 958 1.1 christos { 959 1.1 christos *rptr = cc_table[mid].code; 960 1.1 christos *sptr = s; 961 1.1 christos return 0; 962 1.1 christos } 963 1.1 christos } 964 1.1 christos while (l <= r); 965 1.1 christos 966 1.1 christos return -1; 967 1.1 christos } 968 1.1 christos 969 1.1 christos /* Previous dest is the destination register number of the instruction 970 1.1 christos before the current one. */ 971 1.1 christos static int previous_dest = 0; 972 1.1 christos static int previous_mode = 0; 973 1.1 christos static int condition_code = 0; 974 1.1 christos static int this_dest = 0; 975 1.1 christos static int this_mode = 0; 976 1.1 christos 977 1.1 christos 978 1.1 christos /* This is the main function in this file. It takes a line of assembly language 979 1.1 christos source code and assembles it. Note, labels and pseudo ops have already 980 1.1 christos been removed, so too has leading white space. */ 981 1.1 christos void 982 1.1 christos md_assemble (char *str0) 983 1.1 christos { 984 1.1 christos char *str = str0; 985 1.1 christos int cnt; 986 1.1 christos char mnem[10]; 987 1.1 christos int opcode; 988 1.1 christos enum addressing_mode amode; 989 1.1 christos char arch_flags; 990 1.1 christos int ans; 991 1.1 christos 992 1.1 christos char *output; 993 1.1 christos int reloc = 0; 994 1.1 christos relax_substateT relax = 0; 995 1.1 christos expressionS e1; 996 1.1 christos int r1, r2, r3; 997 1.1 christos int cc; 998 1.1 christos int indx; 999 1.1 christos 1000 1.1 christos /* Initialize the expression. */ 1001 1.1 christos e1.X_op = O_absent; 1002 1.1 christos 1003 1.1 christos /* Initialize destination register. 1004 1.1 christos If the instruction we just looked at is in the delay slot of an 1005 1.1 christos unconditional branch, then there is no index hazard. */ 1006 1.1 christos if ((previous_mode == mode_cad || previous_mode == mode_ci) 1007 1.1 christos && condition_code == 15) 1008 1.1 christos this_dest = 0; 1009 1.1 christos 1010 1.1 christos previous_dest = this_dest; 1011 1.1 christos previous_mode = this_mode; 1012 1.1 christos this_dest = 0; 1013 1.1 christos 1014 1.1 christos /* Drop leading whitespace (probably not required). */ 1015 1.1.1.7 christos while (is_whitespace (*str)) 1016 1.1 christos str++; 1017 1.1 christos 1018 1.1 christos /* Get opcode mnemonic and make sure it's in lower case. */ 1019 1.1 christos cnt = 0; 1020 1.1 christos memset (mnem, '\0', 10); 1021 1.1 christos while ((ISALNUM (*str) || *str == '.' || *str == '_') && cnt < 10) 1022 1.1 christos mnem[cnt++] = TOLOWER (*str++); 1023 1.1 christos 1024 1.1 christos /* Look up mnemonic in opcode table, and get the code, 1025 1.1 christos the instruction format, and the flags that indicate 1026 1.1.1.3 christos which family members support this mnemonic. */ 1027 1.1 christos if (get_opcode (&opcode, &amode, &arch_flags, mnem) < 0) 1028 1.1 christos { 1029 1.1.1.3 christos as_bad ("Unknown instruction mnemonic `%s'", mnem); 1030 1.1 christos return; 1031 1.1 christos } 1032 1.1 christos 1033 1.1 christos if ((VISIUM_OPCODE_ARCH_MASK (visium_opcode_arch) & arch_flags) == 0) 1034 1.1 christos { 1035 1.1 christos as_bad ("Architecture mismatch on `%s'", mnem); 1036 1.1 christos return; 1037 1.1 christos } 1038 1.1 christos 1039 1.1 christos this_mode = amode; 1040 1.1 christos 1041 1.1 christos switch (amode) 1042 1.1 christos { 1043 1.1 christos case mode_d: 1044 1.1 christos /* register := 1045 1.1 christos Example: 1046 1.1 christos readmda r1 */ 1047 1.1 christos ans = parse_gen_reg (&str, &r1); 1048 1.1 christos if (ans < 0) 1049 1.1 christos { 1050 1.1 christos as_bad ("Dest register required"); 1051 1.1 christos return; 1052 1.1 christos } 1053 1.1 christos opcode |= (r1 << 10); 1054 1.1 christos this_dest = r1; 1055 1.1 christos break; 1056 1.1 christos 1057 1.1 christos case mode_a: 1058 1.1 christos /* op= register 1059 1.1 christos Example: asld r1 */ 1060 1.1 christos ans = parse_gen_reg (&str, &r1); 1061 1.1 christos if (ans < 0) 1062 1.1 christos { 1063 1.1 christos as_bad ("SourceA register required"); 1064 1.1 christos return; 1065 1.1 christos } 1066 1.1 christos opcode |= (r1 << 16); 1067 1.1 christos break; 1068 1.1 christos 1069 1.1 christos case mode_ab: 1070 1.1 christos /* register * register 1071 1.1 christos Example: 1072 1.1 christos mults r1,r2 */ 1073 1.1 christos ans = parse_gen_reg (&str, &r1); 1074 1.1 christos if (ans < 0) 1075 1.1 christos { 1076 1.1 christos as_bad ("SourceA register required"); 1077 1.1 christos return; 1078 1.1 christos } 1079 1.1 christos str = skip_space (str); 1080 1.1 christos if (*str == ',') 1081 1.1 christos { 1082 1.1 christos str++; 1083 1.1 christos ans = parse_gen_reg (&str, &r2); 1084 1.1 christos if (ans < 0) 1085 1.1 christos { 1086 1.1 christos as_bad ("SourceB register required"); 1087 1.1 christos return; 1088 1.1 christos } 1089 1.1 christos opcode |= (r1 << 16) | (r2 << 4); 1090 1.1 christos } 1091 1.1 christos else 1092 1.1 christos { 1093 1.1 christos as_bad ("SourceB register required"); 1094 1.1 christos return; 1095 1.1 christos } 1096 1.1 christos break; 1097 1.1 christos 1098 1.1 christos case mode_da: 1099 1.1 christos /* register := register 1100 1.1 christos Example: 1101 1.1 christos extb.l r1,r2 */ 1102 1.1 christos ans = parse_gen_reg (&str, &r1); 1103 1.1 christos if (ans < 0) 1104 1.1 christos { 1105 1.1 christos as_bad ("Dest register required"); 1106 1.1 christos return; 1107 1.1 christos } 1108 1.1 christos str = skip_space (str); 1109 1.1 christos if (*str == ',') 1110 1.1 christos { 1111 1.1 christos str++; 1112 1.1 christos ans = parse_gen_reg (&str, &r2); 1113 1.1 christos if (ans < 0) 1114 1.1 christos { 1115 1.1 christos as_bad ("SourceA register required"); 1116 1.1 christos return; 1117 1.1 christos } 1118 1.1 christos opcode |= (r1 << 10) | (r2 << 16); 1119 1.1 christos } 1120 1.1 christos else 1121 1.1 christos { 1122 1.1 christos as_bad ("SourceB register required"); 1123 1.1 christos return; 1124 1.1 christos } 1125 1.1 christos this_dest = r1; 1126 1.1 christos break; 1127 1.1 christos 1128 1.1 christos case mode_dab: 1129 1.1 christos /* register := register * register 1130 1.1 christos Example: 1131 1.1 christos add.l r1,r2,r3 */ 1132 1.1 christos ans = parse_gen_reg (&str, &r1); 1133 1.1 christos if (ans < 0) 1134 1.1 christos { 1135 1.1 christos as_bad ("Dest register required"); 1136 1.1 christos return; 1137 1.1 christos } 1138 1.1 christos str = skip_space (str); 1139 1.1 christos if (*str == ',') 1140 1.1 christos { 1141 1.1 christos str++; 1142 1.1 christos ans = parse_gen_reg (&str, &r2); 1143 1.1 christos if (ans < 0) 1144 1.1 christos { 1145 1.1 christos as_bad ("SourceA register required"); 1146 1.1 christos return; 1147 1.1 christos } 1148 1.1 christos str = skip_space (str); 1149 1.1 christos if (*str == ',') 1150 1.1 christos { 1151 1.1 christos str++; 1152 1.1 christos ans = parse_gen_reg (&str, &r3); 1153 1.1 christos if (ans < 0) 1154 1.1 christos { 1155 1.1 christos as_bad ("SourceB register required"); 1156 1.1 christos return; 1157 1.1 christos } 1158 1.1 christos 1159 1.1 christos /* Got three regs, assemble instruction. */ 1160 1.1 christos opcode |= (r1 << 10) | (r2 << 16) | (r3 << 4); 1161 1.1 christos } 1162 1.1 christos else 1163 1.1 christos { 1164 1.1 christos as_bad ("SourceA register required"); 1165 1.1 christos return; 1166 1.1 christos } 1167 1.1 christos } 1168 1.1 christos else 1169 1.1 christos { 1170 1.1 christos as_bad ("Dest register required"); 1171 1.1 christos return; 1172 1.1 christos } 1173 1.1 christos this_dest = r1; 1174 1.1 christos break; 1175 1.1 christos 1176 1.1 christos case mode_iab: 1177 1.1 christos /* 5-bit immediate * register * register 1178 1.1 christos Example: 1179 1.1 christos eamwrite 3,r1,r2 */ 1180 1.1 christos str = parse_exp (str, &e1); 1181 1.1 christos str = skip_space (str); 1182 1.1 christos if (e1.X_op != O_absent && *str == ',') 1183 1.1 christos { 1184 1.1 christos int eam_op = e1.X_add_number; 1185 1.1 christos 1186 1.1 christos str = skip_space (str + 1); 1187 1.1 christos ans = parse_gen_reg (&str, &r2); 1188 1.1 christos if (ans < 0) 1189 1.1 christos { 1190 1.1 christos as_bad ("SourceA register required"); 1191 1.1 christos return; 1192 1.1 christos } 1193 1.1 christos str = skip_space (str); 1194 1.1 christos if (*str == ',') 1195 1.1 christos { 1196 1.1 christos str++; 1197 1.1 christos ans = parse_gen_reg (&str, &r3); 1198 1.1 christos if (ans < 0) 1199 1.1 christos { 1200 1.1 christos as_bad ("SourceB register required"); 1201 1.1 christos return; 1202 1.1 christos } 1203 1.1 christos 1204 1.1 christos /* Got three operands, assemble instruction. */ 1205 1.1 christos if (eam_op < 0 || eam_op > 31) 1206 1.1 christos { 1207 1.1 christos as_bad ("eam_op out of range"); 1208 1.1 christos } 1209 1.1 christos opcode |= ((eam_op & 0x1f) << 10) | (r2 << 16) | (r3 << 4); 1210 1.1 christos } 1211 1.1 christos } 1212 1.1 christos else 1213 1.1 christos { 1214 1.1 christos as_bad ("EAM_OP required"); 1215 1.1 christos return; 1216 1.1 christos } 1217 1.1 christos break; 1218 1.1 christos 1219 1.1 christos case mode_0ab: 1220 1.1 christos /* zero * register * register 1221 1.1 christos Example: 1222 1.1 christos cmp.l r1,r2 */ 1223 1.1 christos ans = parse_gen_reg (&str, &r1); 1224 1.1 christos if (ans < 0) 1225 1.1 christos { 1226 1.1 christos as_bad ("SourceA register required"); 1227 1.1 christos return; 1228 1.1 christos } 1229 1.1 christos str = skip_space (str); 1230 1.1 christos if (*str == ',') 1231 1.1 christos { 1232 1.1 christos str++; 1233 1.1 christos ans = parse_gen_reg (&str, &r2); 1234 1.1 christos if (ans < 0) 1235 1.1 christos { 1236 1.1 christos as_bad ("SourceB register required"); 1237 1.1 christos return; 1238 1.1 christos } 1239 1.1 christos opcode |= (r1 << 16) | (r2 << 4); 1240 1.1 christos } 1241 1.1 christos else 1242 1.1 christos { 1243 1.1 christos as_bad ("SourceB register required"); 1244 1.1 christos return; 1245 1.1 christos } 1246 1.1 christos break; 1247 1.1 christos 1248 1.1 christos case mode_da0: 1249 1.1 christos /* register * register * zero 1250 1.1 christos Example: 1251 1.1 christos move.l r1,r2 */ 1252 1.1 christos ans = parse_gen_reg (&str, &r1); 1253 1.1 christos if (ans < 0) 1254 1.1 christos { 1255 1.1 christos as_bad ("Dest register required"); 1256 1.1 christos return; 1257 1.1 christos } 1258 1.1 christos str = skip_space (str); 1259 1.1 christos if (*str == ',') 1260 1.1 christos { 1261 1.1 christos str++; 1262 1.1 christos ans = parse_gen_reg (&str, &r2); 1263 1.1 christos if (ans < 0) 1264 1.1 christos { 1265 1.1 christos as_bad ("SourceA register required"); 1266 1.1 christos return; 1267 1.1 christos } 1268 1.1 christos opcode |= (r1 << 10) | (r2 << 16); 1269 1.1 christos } 1270 1.1 christos else 1271 1.1 christos { 1272 1.1 christos as_bad ("SourceA register required"); 1273 1.1 christos return; 1274 1.1 christos } 1275 1.1 christos this_dest = r1; 1276 1.1 christos break; 1277 1.1 christos 1278 1.1 christos case mode_cad: 1279 1.1 christos /* condition * register * register 1280 1.1 christos Example: 1281 1.1 christos bra tr,r1,r2 */ 1282 1.1 christos ans = parse_cc (&str, &cc); 1283 1.1 christos if (ans < 0) 1284 1.1 christos { 1285 1.1 christos as_bad ("condition code required"); 1286 1.1 christos return; 1287 1.1 christos } 1288 1.1 christos 1289 1.1 christos str = skip_space (str); 1290 1.1 christos if (*str == ',') 1291 1.1 christos { 1292 1.1 christos str = skip_space (str + 1); 1293 1.1 christos ans = parse_gen_reg (&str, &r2); 1294 1.1 christos if (ans < 0) 1295 1.1 christos { 1296 1.1 christos as_bad ("SourceA register required"); 1297 1.1 christos return; 1298 1.1 christos } 1299 1.1 christos str = skip_space (str); 1300 1.1 christos if (*str == ',') 1301 1.1 christos { 1302 1.1 christos str++; 1303 1.1 christos ans = parse_gen_reg (&str, &r3); 1304 1.1 christos if (ans < 0) 1305 1.1 christos { 1306 1.1 christos as_bad ("Dest register required"); 1307 1.1 christos return; 1308 1.1 christos } 1309 1.1 christos 1310 1.1 christos /* Got three operands, assemble instruction. */ 1311 1.1 christos opcode |= (cc << 27) | (r2 << 16) | (r3 << 10); 1312 1.1 christos } 1313 1.1 christos else 1314 1.1 christos { 1315 1.1 christos as_bad ("Dest register required"); 1316 1.1 christos return; 1317 1.1 christos } 1318 1.1 christos } 1319 1.1 christos else 1320 1.1 christos { 1321 1.1 christos as_bad ("SourceA register required"); 1322 1.1 christos return; 1323 1.1 christos } 1324 1.1 christos 1325 1.1 christos if (previous_mode == mode_cad || previous_mode == mode_ci) 1326 1.1 christos as_bad ("branch instruction in delay slot"); 1327 1.1 christos 1328 1.1.1.4 christos /* For the GR6, BRA insns must be aligned on 64-bit boundaries. */ 1329 1.1.1.4 christos if (visium_arch == VISIUM_ARCH_GR6) 1330 1.1.1.4 christos do_align (3, NULL, 0, 0); 1331 1.1.1.4 christos 1332 1.1 christos this_dest = r3; 1333 1.1 christos condition_code = cc; 1334 1.1 christos break; 1335 1.1 christos 1336 1.1 christos case mode_das: 1337 1.1.1.3 christos /* register := register * 5-bit immediate/register shift count 1338 1.1 christos Example: 1339 1.1 christos asl.l r1,r2,4 */ 1340 1.1 christos ans = parse_gen_reg (&str, &r1); 1341 1.1 christos if (ans < 0) 1342 1.1 christos { 1343 1.1 christos as_bad ("Dest register required"); 1344 1.1 christos return; 1345 1.1 christos } 1346 1.1 christos str = skip_space (str); 1347 1.1 christos if (*str == ',') 1348 1.1 christos { 1349 1.1 christos str++; 1350 1.1 christos ans = parse_gen_reg (&str, &r2); 1351 1.1 christos if (ans < 0) 1352 1.1 christos { 1353 1.1 christos as_bad ("SourceA register required"); 1354 1.1 christos return; 1355 1.1 christos } 1356 1.1 christos str = skip_space (str); 1357 1.1 christos if (*str == ',') 1358 1.1 christos { 1359 1.1 christos str++; 1360 1.1 christos ans = parse_gen_reg (&str, &r3); 1361 1.1 christos if (ans == 0) 1362 1.1 christos { 1363 1.1 christos opcode |= (r1 << 10) | (r2 << 16) | (r3 << 4); 1364 1.1 christos } 1365 1.1 christos else 1366 1.1 christos { 1367 1.1 christos str = parse_exp (str, &e1); 1368 1.1 christos if (e1.X_op == O_constant) 1369 1.1 christos { 1370 1.1 christos int imm = e1.X_add_number; 1371 1.1 christos 1372 1.1 christos if (imm < 0 || imm > 31) 1373 1.1 christos as_bad ("immediate value out of range"); 1374 1.1 christos 1375 1.1.1.7 christos opcode |= ((r1 << 10) | (r2 << 16) | (1 << 9) 1376 1.1.1.7 christos | ((imm & 0x1f) << 4)); 1377 1.1 christos } 1378 1.1 christos else 1379 1.1 christos { 1380 1.1 christos as_bad ("immediate operand required"); 1381 1.1 christos return; 1382 1.1 christos } 1383 1.1 christos } 1384 1.1 christos } 1385 1.1 christos } 1386 1.1 christos else 1387 1.1 christos { 1388 1.1 christos as_bad ("SourceA register required"); 1389 1.1 christos return; 1390 1.1 christos } 1391 1.1 christos this_dest = r1; 1392 1.1 christos break; 1393 1.1 christos 1394 1.1 christos case mode_di: 1395 1.1 christos /* register := 5-bit immediate 1396 1.1 christos Example: 1397 1.1 christos eamread r1,3 */ 1398 1.1 christos ans = parse_gen_reg (&str, &r1); 1399 1.1 christos if (ans < 0) 1400 1.1 christos { 1401 1.1 christos as_bad ("Dest register required"); 1402 1.1 christos return; 1403 1.1 christos } 1404 1.1 christos str = skip_space (str); 1405 1.1 christos if (*str == ',') 1406 1.1 christos { 1407 1.1 christos str++; 1408 1.1 christos str = parse_exp (str, &e1); 1409 1.1 christos if (e1.X_op == O_constant) 1410 1.1 christos { 1411 1.1 christos int opnd2 = e1.X_add_number; 1412 1.1 christos 1413 1.1 christos if (opnd2 < 0 || opnd2 > 31) 1414 1.1 christos { 1415 1.1 christos as_bad ("immediate operand out of range"); 1416 1.1 christos return; 1417 1.1 christos } 1418 1.1 christos opcode |= (r1 << 10) | ((opnd2 & 0x1f) << 4); 1419 1.1 christos } 1420 1.1 christos else 1421 1.1 christos { 1422 1.1 christos as_bad ("immediate operand required"); 1423 1.1 christos return; 1424 1.1 christos } 1425 1.1 christos } 1426 1.1 christos else 1427 1.1 christos { 1428 1.1 christos as_bad ("immediate operand required"); 1429 1.1 christos return; 1430 1.1 christos } 1431 1.1 christos this_dest = r1; 1432 1.1 christos break; 1433 1.1 christos 1434 1.1 christos case mode_ir: 1435 1.1 christos /* 5-bit immediate * register, e.g. trace 1,r1 */ 1436 1.1 christos str = parse_exp (str, &e1); 1437 1.1 christos str = skip_space (str); 1438 1.1 christos if (e1.X_op == O_constant && *str == ',') 1439 1.1 christos { 1440 1.1 christos int opnd1 = e1.X_add_number; 1441 1.1 christos 1442 1.1 christos str = skip_space (str + 1); 1443 1.1 christos ans = parse_gen_reg (&str, &r2); 1444 1.1 christos if (ans < 0) 1445 1.1 christos { 1446 1.1 christos as_bad ("SourceA register required"); 1447 1.1 christos return; 1448 1.1 christos } 1449 1.1 christos 1450 1.1 christos /* Got two operands, assemble instruction. */ 1451 1.1 christos if (opnd1 < 0 || opnd1 > 31) 1452 1.1 christos { 1453 1.1 christos as_bad ("1st operand out of range"); 1454 1.1 christos } 1455 1.1 christos opcode |= ((opnd1 & 0x1f) << 10) | (r2 << 16); 1456 1.1 christos } 1457 1.1 christos else 1458 1.1 christos { 1459 1.1 christos as_bad ("Immediate operand required"); 1460 1.1 christos return; 1461 1.1 christos } 1462 1.1 christos break; 1463 1.1 christos 1464 1.1 christos case mode_ai: 1465 1.1 christos /* register *= 16-bit unsigned immediate 1466 1.1 christos Example: 1467 1.1 christos addi r1,123 */ 1468 1.1 christos ans = parse_gen_reg (&str, &r1); 1469 1.1 christos if (ans < 0) 1470 1.1 christos { 1471 1.1 christos as_bad ("Dest register required"); 1472 1.1 christos return; 1473 1.1 christos } 1474 1.1 christos opcode |= (r1 << 16); 1475 1.1 christos 1476 1.1 christos str = skip_space (str); 1477 1.1 christos if (*str != ',') 1478 1.1 christos { 1479 1.1 christos as_bad ("immediate value missing"); 1480 1.1 christos return; 1481 1.1 christos } 1482 1.1 christos this_dest = r1; 1483 1.1.1.3 christos /* Fall through. */ 1484 1.1 christos 1485 1.1 christos case mode_i: 1486 1.1 christos /* MOVIL/WRTL traditionally get an implicit "%l" applied 1487 1.1 christos to their immediate value. For other opcodes, unless 1488 1.1 christos the immediate value is decorated with "%u" or "%l" 1489 1.1 christos it must be in the range 0 .. 65535. */ 1490 1.1 christos if ((opcode & 0x7fe00000) == 0x04800000 1491 1.1 christos || (opcode & 0x7fe00000) == 0x05000000) 1492 1.1 christos reloc = BFD_RELOC_VISIUM_LO16; 1493 1.1 christos else 1494 1.1 christos reloc = BFD_RELOC_VISIUM_IM16; 1495 1.1 christos 1496 1.1 christos str = skip_space (str + 1); 1497 1.1 christos 1498 1.1 christos if (*str == '%') 1499 1.1 christos { 1500 1.1 christos if (str[1] == 'u') 1501 1.1 christos reloc = BFD_RELOC_VISIUM_HI16; 1502 1.1 christos else if (str[1] == 'l') 1503 1.1 christos reloc = BFD_RELOC_VISIUM_LO16; 1504 1.1 christos else 1505 1.1 christos { 1506 1.1 christos as_bad ("bad char after %%"); 1507 1.1 christos return; 1508 1.1 christos } 1509 1.1 christos 1510 1.1 christos str += 2; 1511 1.1 christos } 1512 1.1 christos str = parse_exp (str, &e1); 1513 1.1 christos if (e1.X_op != O_absent) 1514 1.1 christos { 1515 1.1 christos if (e1.X_op == O_constant) 1516 1.1 christos { 1517 1.1 christos int imm = e1.X_add_number; 1518 1.1 christos 1519 1.1 christos if (reloc == BFD_RELOC_VISIUM_HI16) 1520 1.1 christos opcode |= ((imm >> 16) & 0xffff); 1521 1.1 christos else if (reloc == BFD_RELOC_VISIUM_LO16) 1522 1.1 christos opcode |= (imm & 0xffff); 1523 1.1 christos else 1524 1.1 christos { 1525 1.1 christos if (imm < 0 || imm > 0xffff) 1526 1.1 christos as_bad ("immediate value out of range"); 1527 1.1 christos 1528 1.1 christos opcode |= (imm & 0xffff); 1529 1.1 christos } 1530 1.1 christos /* No relocation is needed. */ 1531 1.1 christos reloc = 0; 1532 1.1 christos } 1533 1.1 christos } 1534 1.1 christos else 1535 1.1 christos { 1536 1.1 christos as_bad ("immediate value missing"); 1537 1.1 christos return; 1538 1.1 christos } 1539 1.1 christos break; 1540 1.1 christos 1541 1.1 christos case mode_bax: 1542 1.1 christos /* register * register * 5-bit immediate, 1543 1.1 christos SourceB * SourceA * Index 1544 1.1 christos Examples 1545 1.1 christos write.l (r1),r2 1546 1.1 christos write.l 3(r1),r2 */ 1547 1.1 christos str = skip_space (str); 1548 1.1 christos 1549 1.1 christos indx = 0; 1550 1.1 christos if (*str != '(') 1551 1.1 christos { 1552 1.1 christos str = parse_exp (str, &e1); 1553 1.1 christos if (e1.X_op == O_constant) 1554 1.1 christos { 1555 1.1 christos indx = e1.X_add_number; 1556 1.1 christos 1557 1.1 christos if (indx < 0 || indx > 31) 1558 1.1 christos { 1559 1.1 christos as_bad ("Index out of range"); 1560 1.1 christos return; 1561 1.1 christos } 1562 1.1 christos } 1563 1.1 christos else 1564 1.1 christos { 1565 1.1 christos as_bad ("Index(SourceA) required"); 1566 1.1 christos return; 1567 1.1 christos } 1568 1.1 christos } 1569 1.1 christos 1570 1.1 christos str = skip_space (str); 1571 1.1 christos 1572 1.1 christos if (*str != '(') 1573 1.1 christos { 1574 1.1 christos as_bad ("Index(SourceA) required"); 1575 1.1 christos return; 1576 1.1 christos } 1577 1.1 christos 1578 1.1 christos str = skip_space (str + 1); 1579 1.1 christos 1580 1.1 christos ans = parse_gen_reg (&str, &r1); 1581 1.1 christos if (ans < 0) 1582 1.1 christos { 1583 1.1 christos as_bad ("SourceA register required"); 1584 1.1 christos return; 1585 1.1 christos } 1586 1.1 christos str = skip_space (str); 1587 1.1 christos if (*str != ')') 1588 1.1 christos { 1589 1.1 christos as_bad ("(SourceA) required"); 1590 1.1 christos return; 1591 1.1 christos } 1592 1.1 christos str = skip_space (str + 1); 1593 1.1 christos 1594 1.1 christos if (*str == ',') 1595 1.1 christos { 1596 1.1 christos str = skip_space (str + 1); 1597 1.1 christos ans = parse_gen_reg (&str, &r2); 1598 1.1 christos if (ans < 0) 1599 1.1 christos { 1600 1.1 christos as_bad ("SourceB register required"); 1601 1.1 christos return; 1602 1.1 christos } 1603 1.1 christos } 1604 1.1 christos else 1605 1.1 christos { 1606 1.1 christos as_bad ("SourceB register required"); 1607 1.1 christos return; 1608 1.1 christos } 1609 1.1 christos 1610 1.1 christos opcode |= (r1 << 16) | (r2 << 4) | ((indx & 0x1f) << 10); 1611 1.1 christos 1612 1.1 christos if (indx != 0 && previous_mode == mode_cad) 1613 1.1 christos { 1614 1.1 christos /* We're in a delay slot. 1615 1.1 christos If the base reg is the destination of the branch, then issue 1616 1.1 christos an error message. 1617 1.1 christos Otherwise it is safe to use the base and index. */ 1618 1.1 christos if (previous_dest != 0 && r1 == previous_dest) 1619 1.1 christos { 1620 1.1 christos as_bad ("base register not ready"); 1621 1.1 christos return; 1622 1.1 christos } 1623 1.1 christos } 1624 1.1 christos else if (previous_dest != 0 1625 1.1 christos && r1 == previous_dest 1626 1.1 christos && (visium_arch == VISIUM_ARCH_MCM 1627 1.1 christos || visium_arch == VISIUM_ARCH_MCM24 1628 1.1 christos || (visium_arch == VISIUM_ARCH_DEF && indx != 0))) 1629 1.1 christos { 1630 1.1 christos as_warn ("base register not ready, NOP inserted."); 1631 1.1 christos /* Insert a NOP before the write instruction. */ 1632 1.1 christos output = frag_more (4); 1633 1.1 christos memset (output, 0, 4); 1634 1.1 christos } 1635 1.1 christos break; 1636 1.1 christos 1637 1.1 christos case mode_dax: 1638 1.1 christos /* register := register * 5-bit immediate 1639 1.1 christos Examples: 1640 1.1 christos read.b r1,(r2) 1641 1.1 christos read.w r1,3(r2) */ 1642 1.1 christos ans = parse_gen_reg (&str, &r1); 1643 1.1 christos if (ans < 0) 1644 1.1 christos { 1645 1.1 christos as_bad ("Dest register required"); 1646 1.1 christos return; 1647 1.1 christos } 1648 1.1 christos str = skip_space (str); 1649 1.1 christos if (*str != ',') 1650 1.1 christos { 1651 1.1 christos as_bad ("SourceA required"); 1652 1.1 christos return; 1653 1.1 christos } 1654 1.1 christos str = skip_space (str + 1); 1655 1.1 christos 1656 1.1 christos indx = 0; 1657 1.1 christos if (*str != '(') 1658 1.1 christos { 1659 1.1 christos str = parse_exp (str, &e1); 1660 1.1 christos if (e1.X_op == O_constant) 1661 1.1 christos { 1662 1.1 christos indx = e1.X_add_number; 1663 1.1 christos 1664 1.1 christos if (indx < 0 || indx > 31) 1665 1.1 christos { 1666 1.1 christos as_bad ("Index out of range"); 1667 1.1 christos return; 1668 1.1 christos } 1669 1.1 christos } 1670 1.1 christos else 1671 1.1 christos { 1672 1.1 christos as_bad ("Immediate 0 to 31 required"); 1673 1.1 christos return; 1674 1.1 christos } 1675 1.1 christos } 1676 1.1 christos if (*str != '(') 1677 1.1 christos { 1678 1.1 christos as_bad ("(SourceA) required"); 1679 1.1 christos return; 1680 1.1 christos } 1681 1.1 christos str++; 1682 1.1 christos ans = parse_gen_reg (&str, &r2); 1683 1.1 christos if (ans < 0) 1684 1.1 christos { 1685 1.1 christos as_bad ("SourceA register required"); 1686 1.1 christos return; 1687 1.1 christos } 1688 1.1 christos str = skip_space (str); 1689 1.1 christos if (*str != ')') 1690 1.1 christos { 1691 1.1 christos as_bad ("(SourceA) required"); 1692 1.1 christos return; 1693 1.1 christos } 1694 1.1 christos str++; 1695 1.1 christos opcode |= (r1 << 10) | (r2 << 16) | ((indx & 0x1f) << 4); 1696 1.1 christos this_dest = r1; 1697 1.1 christos 1698 1.1 christos if (indx != 0 && previous_mode == mode_cad) 1699 1.1 christos { 1700 1.1 christos /* We're in a delay slot. 1701 1.1 christos If the base reg is the destination of the branch, then issue 1702 1.1 christos an error message. 1703 1.1 christos Otherwise it is safe to use the base and index. */ 1704 1.1 christos if (previous_dest != 0 && r2 == previous_dest) 1705 1.1 christos { 1706 1.1 christos as_bad ("base register not ready"); 1707 1.1 christos return; 1708 1.1 christos } 1709 1.1 christos } 1710 1.1 christos else if (previous_dest != 0 1711 1.1 christos && r2 == previous_dest 1712 1.1 christos && (visium_arch == VISIUM_ARCH_MCM 1713 1.1 christos || visium_arch == VISIUM_ARCH_MCM24 1714 1.1 christos || (visium_arch == VISIUM_ARCH_DEF && indx != 0))) 1715 1.1 christos { 1716 1.1 christos as_warn ("base register not ready, NOP inserted."); 1717 1.1 christos /* Insert a NOP before the read instruction. */ 1718 1.1 christos output = frag_more (4); 1719 1.1 christos memset (output, 0, 4); 1720 1.1 christos } 1721 1.1 christos break; 1722 1.1 christos 1723 1.1 christos case mode_s: 1724 1.1 christos /* special mode 1725 1.1 christos Example: 1726 1.1 christos nop */ 1727 1.1 christos str = skip_space (str); 1728 1.1 christos break; 1729 1.1 christos 1730 1.1 christos case mode_ci: 1731 1.1 christos /* condition * 16-bit signed word displacement 1732 1.1 christos Example: 1733 1.1 christos brr L1 */ 1734 1.1 christos ans = parse_cc (&str, &cc); 1735 1.1 christos if (ans < 0) 1736 1.1 christos { 1737 1.1 christos as_bad ("condition code required"); 1738 1.1 christos return; 1739 1.1 christos } 1740 1.1 christos opcode |= (cc << 27); 1741 1.1 christos 1742 1.1 christos str = skip_space (str); 1743 1.1 christos if (*str == ',') 1744 1.1 christos { 1745 1.1 christos str = skip_space (str + 1); 1746 1.1 christos str = parse_exp (str, &e1); 1747 1.1 christos if (e1.X_op != O_absent) 1748 1.1 christos { 1749 1.1 christos if (e1.X_op == O_constant) 1750 1.1 christos { 1751 1.1 christos int imm = e1.X_add_number; 1752 1.1 christos 1753 1.1 christos if (imm < -32768 || imm > 32767) 1754 1.1 christos as_bad ("immediate value out of range"); 1755 1.1 christos 1756 1.1 christos /* The GR6 doesn't correctly handle a 0 displacement 1757 1.1 christos so we insert a NOP and change it to -1. */ 1758 1.1 christos if (imm == 0 && cc != 0 && visium_arch == VISIUM_ARCH_GR6) 1759 1.1 christos { 1760 1.1 christos output = frag_more (4); 1761 1.1 christos memset (output, 0, 4); 1762 1.1 christos imm = -1; 1763 1.1 christos } 1764 1.1 christos 1765 1.1 christos opcode |= (imm & 0xffff); 1766 1.1 christos } 1767 1.1 christos else if (e1.X_op == O_symbol) 1768 1.1 christos { 1769 1.1 christos /* The GR6 doesn't correctly handle a 0 displacement 1770 1.1 christos so the instruction requires relaxation. */ 1771 1.1 christos if (cc != 0 && visium_arch == VISIUM_ARCH_GR6) 1772 1.1 christos relax = amode; 1773 1.1 christos else 1774 1.1 christos reloc = BFD_RELOC_VISIUM_REL16; 1775 1.1 christos } 1776 1.1 christos else 1777 1.1 christos { 1778 1.1 christos as_bad ("immediate value missing"); 1779 1.1 christos return; 1780 1.1 christos } 1781 1.1 christos } 1782 1.1 christos else 1783 1.1 christos { 1784 1.1 christos as_bad ("immediate value missing"); 1785 1.1 christos return; 1786 1.1 christos } 1787 1.1 christos } 1788 1.1 christos else 1789 1.1 christos { 1790 1.1 christos as_bad ("immediate value missing"); 1791 1.1 christos return; 1792 1.1 christos } 1793 1.1 christos 1794 1.1 christos if (previous_mode == mode_cad || previous_mode == mode_ci) 1795 1.1 christos as_bad ("branch instruction in delay slot"); 1796 1.1 christos 1797 1.1 christos condition_code = cc; 1798 1.1 christos break; 1799 1.1 christos 1800 1.1 christos case mode_fdab: 1801 1.1 christos /* float := float * float 1802 1.1 christos Example 1803 1.1 christos fadd f4,f3,f2 */ 1804 1.1 christos ans = parse_fp_reg (&str, &r1); 1805 1.1 christos if (ans < 0) 1806 1.1 christos { 1807 1.1 christos as_bad ("floating point destination register required"); 1808 1.1 christos return; 1809 1.1 christos } 1810 1.1 christos str = skip_space (str); 1811 1.1 christos if (*str == ',') 1812 1.1 christos { 1813 1.1 christos str++; 1814 1.1 christos ans = parse_fp_reg (&str, &r2); 1815 1.1 christos if (ans < 0) 1816 1.1 christos { 1817 1.1 christos as_bad ("floating point SourceA register required"); 1818 1.1 christos return; 1819 1.1 christos } 1820 1.1 christos str = skip_space (str); 1821 1.1 christos if (*str == ',') 1822 1.1 christos { 1823 1.1 christos str++; 1824 1.1 christos ans = parse_fp_reg (&str, &r3); 1825 1.1 christos if (ans < 0) 1826 1.1 christos { 1827 1.1 christos as_bad ("floating point SourceB register required"); 1828 1.1 christos return; 1829 1.1 christos } 1830 1.1 christos 1831 1.1 christos /* Got 3 floating regs, assemble instruction. */ 1832 1.1 christos opcode |= (r1 << 10) | (r2 << 16) | (r3 << 4); 1833 1.1 christos } 1834 1.1 christos else 1835 1.1 christos { 1836 1.1 christos as_bad ("floating point SourceB register required"); 1837 1.1 christos return; 1838 1.1 christos } 1839 1.1 christos } 1840 1.1 christos else 1841 1.1 christos { 1842 1.1 christos as_bad ("floating point SourceA register required"); 1843 1.1 christos return; 1844 1.1 christos } 1845 1.1 christos break; 1846 1.1 christos 1847 1.1 christos case mode_ifdab: 1848 1.1 christos /* 4-bit immediate * float * float * float 1849 1.1 christos Example 1850 1.1 christos fpinst 10,f1,f2,f3 */ 1851 1.1 christos str = parse_exp (str, &e1); 1852 1.1 christos str = skip_space (str); 1853 1.1 christos if (e1.X_op != O_absent && *str == ',') 1854 1.1 christos { 1855 1.1 christos int finst = e1.X_add_number; 1856 1.1 christos 1857 1.1 christos str = skip_space (str + 1); 1858 1.1 christos ans = parse_fp_reg (&str, &r1); 1859 1.1 christos if (ans < 0) 1860 1.1 christos { 1861 1.1 christos as_bad ("floating point destination register required"); 1862 1.1 christos return; 1863 1.1 christos } 1864 1.1 christos str = skip_space (str); 1865 1.1 christos if (*str == ',') 1866 1.1 christos { 1867 1.1 christos str++; 1868 1.1 christos ans = parse_fp_reg (&str, &r2); 1869 1.1 christos if (ans < 0) 1870 1.1 christos { 1871 1.1 christos as_bad ("floating point SourceA register required"); 1872 1.1 christos return; 1873 1.1 christos } 1874 1.1 christos str = skip_space (str); 1875 1.1 christos if (*str == ',') 1876 1.1 christos { 1877 1.1 christos str++; 1878 1.1 christos ans = parse_fp_reg (&str, &r3); 1879 1.1 christos if (ans < 0) 1880 1.1 christos { 1881 1.1 christos as_bad ("floating point SourceB register required"); 1882 1.1 christos return; 1883 1.1 christos } 1884 1.1 christos 1885 1.1 christos /* Got immediate and 3 floating regs, 1886 1.1 christos assemble instruction. */ 1887 1.1 christos if (finst < 0 || finst > 15) 1888 1.1 christos as_bad ("finst out of range"); 1889 1.1 christos 1890 1.1.1.7 christos opcode |= (((finst & 0xf) << 27) 1891 1.1.1.7 christos | (r1 << 10) | (r2 << 16) | (r3 << 4)); 1892 1.1 christos } 1893 1.1 christos else 1894 1.1 christos { 1895 1.1 christos as_bad ("floating point SourceB register required"); 1896 1.1 christos return; 1897 1.1 christos } 1898 1.1 christos } 1899 1.1 christos else 1900 1.1 christos { 1901 1.1 christos as_bad ("floating point SourceA register required"); 1902 1.1 christos return; 1903 1.1 christos } 1904 1.1 christos } 1905 1.1 christos else 1906 1.1 christos { 1907 1.1 christos as_bad ("finst missing"); 1908 1.1 christos return; 1909 1.1 christos } 1910 1.1 christos break; 1911 1.1 christos 1912 1.1 christos case mode_idfab: 1913 1.1 christos /* 4-bit immediate * register * float * float 1914 1.1 christos Example 1915 1.1 christos fpuread 4,r25,f2,f3 */ 1916 1.1 christos str = parse_exp (str, &e1); 1917 1.1 christos str = skip_space (str); 1918 1.1 christos if (e1.X_op != O_absent && *str == ',') 1919 1.1 christos { 1920 1.1 christos int finst = e1.X_add_number; 1921 1.1 christos 1922 1.1 christos str = skip_space (str + 1); 1923 1.1 christos ans = parse_gen_reg (&str, &r1); 1924 1.1 christos if (ans < 0) 1925 1.1 christos { 1926 1.1 christos as_bad ("destination general register required"); 1927 1.1 christos return; 1928 1.1 christos } 1929 1.1 christos str = skip_space (str); 1930 1.1 christos if (*str == ',') 1931 1.1 christos { 1932 1.1 christos str++; 1933 1.1 christos ans = parse_fp_reg (&str, &r2); 1934 1.1 christos if (ans < 0) 1935 1.1 christos { 1936 1.1 christos as_bad ("floating point SourceA register required"); 1937 1.1 christos return; 1938 1.1 christos } 1939 1.1 christos str = skip_space (str); 1940 1.1 christos if (*str == ',') 1941 1.1 christos { 1942 1.1 christos str++; 1943 1.1 christos ans = parse_fp_reg (&str, &r3); 1944 1.1 christos if (ans < 0) 1945 1.1 christos { 1946 1.1 christos as_bad ("floating point SourceB register required"); 1947 1.1 christos return; 1948 1.1 christos } 1949 1.1 christos 1950 1.1 christos /* Got immediate and 3 floating regs, 1951 1.1 christos assemble instruction. */ 1952 1.1 christos if (finst < 0 || finst > 15) 1953 1.1 christos as_bad ("finst out of range"); 1954 1.1 christos 1955 1.1.1.7 christos opcode |= (((finst & 0xf) << 27) 1956 1.1.1.7 christos | (r1 << 10) | (r2 << 16) | (r3 << 4)); 1957 1.1 christos } 1958 1.1 christos else 1959 1.1 christos { 1960 1.1 christos as_bad ("floating point SourceB register required"); 1961 1.1 christos return; 1962 1.1 christos } 1963 1.1 christos } 1964 1.1 christos else 1965 1.1 christos { 1966 1.1 christos as_bad ("floating point SourceA register required"); 1967 1.1 christos return; 1968 1.1 christos } 1969 1.1 christos } 1970 1.1 christos else 1971 1.1 christos { 1972 1.1 christos as_bad ("finst missing"); 1973 1.1 christos return; 1974 1.1 christos } 1975 1.1 christos break; 1976 1.1 christos 1977 1.1 christos case mode_fda: 1978 1.1 christos /* float := float 1979 1.1 christos Example 1980 1.1 christos fsqrt f4,f3 */ 1981 1.1 christos ans = parse_fp_reg (&str, &r1); 1982 1.1 christos if (ans < 0) 1983 1.1 christos { 1984 1.1 christos as_bad ("floating point destination register required"); 1985 1.1 christos return; 1986 1.1 christos } 1987 1.1 christos str = skip_space (str); 1988 1.1 christos if (*str == ',') 1989 1.1 christos { 1990 1.1 christos str++; 1991 1.1 christos ans = parse_fp_reg (&str, &r2); 1992 1.1 christos if (ans < 0) 1993 1.1 christos { 1994 1.1 christos as_bad ("floating point source register required"); 1995 1.1 christos return; 1996 1.1 christos } 1997 1.1 christos 1998 1.1 christos /* Got 2 floating regs, assemble instruction. */ 1999 1.1 christos opcode |= (r1 << 10) | (r2 << 16); 2000 1.1 christos } 2001 1.1 christos else 2002 1.1 christos { 2003 1.1 christos as_bad ("floating point source register required"); 2004 1.1 christos return; 2005 1.1 christos } 2006 1.1 christos break; 2007 1.1 christos 2008 1.1 christos case mode_fdra: 2009 1.1 christos /* float := register 2010 1.1 christos Example 2011 1.1 christos fload f15,r6 */ 2012 1.1 christos ans = parse_fp_reg (&str, &r1); 2013 1.1 christos if (ans < 0) 2014 1.1 christos { 2015 1.1 christos as_bad ("floating point destination register required"); 2016 1.1 christos return; 2017 1.1 christos } 2018 1.1 christos str = skip_space (str); 2019 1.1 christos if (*str == ',') 2020 1.1 christos { 2021 1.1 christos str++; 2022 1.1 christos ans = parse_gen_reg (&str, &r2); 2023 1.1 christos if (ans < 0) 2024 1.1 christos { 2025 1.1 christos as_bad ("SourceA general register required"); 2026 1.1 christos return; 2027 1.1 christos } 2028 1.1 christos 2029 1.1 christos /* Got 2 regs, assemble instruction. */ 2030 1.1 christos opcode |= (r1 << 10) | (r2 << 16); 2031 1.1 christos } 2032 1.1 christos else 2033 1.1 christos { 2034 1.1 christos as_bad ("SourceA general register required"); 2035 1.1 christos return; 2036 1.1 christos } 2037 1.1 christos break; 2038 1.1 christos 2039 1.1 christos case mode_rdfab: 2040 1.1 christos /* register := float * float 2041 1.1 christos Example 2042 1.1 christos fcmp r0,f4,f8 2043 1.1 christos For the GR6, register must be r0 and can be omitted. */ 2044 1.1 christos ans = parse_gen_reg (&str, &r1); 2045 1.1 christos if (ans < 0) 2046 1.1 christos { 2047 1.1 christos if (visium_opcode_arch == VISIUM_OPCODE_ARCH_GR5) 2048 1.1 christos { 2049 1.1 christos as_bad ("Dest general register required"); 2050 1.1 christos return; 2051 1.1 christos } 2052 1.1 christos r1 = 0; 2053 1.1 christos } 2054 1.1 christos else 2055 1.1 christos { 2056 1.1 christos if (r1 != 0 && visium_opcode_arch != VISIUM_OPCODE_ARCH_GR5) 2057 1.1 christos { 2058 1.1 christos as_bad ("FCMP/FCMPE can only use r0 as Dest register"); 2059 1.1 christos return; 2060 1.1 christos } 2061 1.1 christos 2062 1.1 christos str = skip_space (str); 2063 1.1 christos if (*str == ',') 2064 1.1 christos str++; 2065 1.1 christos else 2066 1.1 christos { 2067 1.1 christos as_bad ("floating point SourceA register required"); 2068 1.1 christos return; 2069 1.1 christos } 2070 1.1 christos } 2071 1.1 christos 2072 1.1 christos ans = parse_fp_reg (&str, &r2); 2073 1.1 christos if (ans < 0) 2074 1.1 christos { 2075 1.1 christos as_bad ("floating point SourceA register required"); 2076 1.1 christos return; 2077 1.1 christos } 2078 1.1 christos str = skip_space (str); 2079 1.1 christos if (*str == ',') 2080 1.1 christos { 2081 1.1 christos str++; 2082 1.1 christos ans = parse_fp_reg (&str, &r3); 2083 1.1 christos if (ans < 0) 2084 1.1 christos { 2085 1.1 christos as_bad ("floating point SourceB register required"); 2086 1.1 christos return; 2087 1.1 christos } 2088 1.1 christos 2089 1.1 christos /* Got 3 regs, assemble instruction. */ 2090 1.1 christos opcode |= (r1 << 10) | (r2 << 16) | (r3 << 4); 2091 1.1 christos } 2092 1.1 christos 2093 1.1 christos this_dest = r1; 2094 1.1 christos break; 2095 1.1 christos 2096 1.1 christos case mode_rdfa: 2097 1.1 christos /* register := float 2098 1.1 christos Example 2099 1.1 christos fstore r5,f12 */ 2100 1.1 christos ans = parse_gen_reg (&str, &r1); 2101 1.1 christos if (ans < 0) 2102 1.1 christos { 2103 1.1 christos as_bad ("Dest general register required"); 2104 1.1 christos return; 2105 1.1 christos } 2106 1.1 christos str = skip_space (str); 2107 1.1 christos if (*str == ',') 2108 1.1 christos { 2109 1.1 christos str++; 2110 1.1 christos ans = parse_fp_reg (&str, &r2); 2111 1.1 christos if (ans < 0) 2112 1.1 christos { 2113 1.1 christos as_bad ("floating point source register required"); 2114 1.1 christos return; 2115 1.1 christos } 2116 1.1 christos 2117 1.1 christos /* Got 2 regs, assemble instruction. */ 2118 1.1 christos opcode |= (r1 << 10) | (r2 << 16); 2119 1.1 christos } 2120 1.1 christos else 2121 1.1 christos { 2122 1.1 christos as_bad ("floating point source register required"); 2123 1.1 christos return; 2124 1.1 christos } 2125 1.1 christos 2126 1.1 christos this_dest = r1; 2127 1.1 christos break; 2128 1.1 christos 2129 1.1 christos case mode_rrr: 2130 1.1 christos /* register register register, all sources and destinations 2131 1.1 christos Example: 2132 1.1 christos bmd r1,r2,r3 */ 2133 1.1 christos 2134 1.1 christos ans = parse_gen_reg (&str, &r1); 2135 1.1 christos if (ans < 0) 2136 1.1 christos { 2137 1.1 christos as_bad ("destination address register required"); 2138 1.1 christos return; 2139 1.1 christos } 2140 1.1 christos str = skip_space (str); 2141 1.1 christos if (*str == ',') 2142 1.1 christos { 2143 1.1 christos str++; 2144 1.1 christos ans = parse_gen_reg (&str, &r2); 2145 1.1 christos if (ans < 0) 2146 1.1 christos { 2147 1.1 christos as_bad ("source address register required"); 2148 1.1 christos return; 2149 1.1 christos } 2150 1.1 christos str = skip_space (str); 2151 1.1 christos if (*str == ',') 2152 1.1 christos { 2153 1.1 christos str++; 2154 1.1 christos ans = parse_gen_reg (&str, &r3); 2155 1.1 christos if (ans < 0) 2156 1.1 christos { 2157 1.1 christos as_bad ("count register required"); 2158 1.1 christos return; 2159 1.1 christos } 2160 1.1 christos 2161 1.1 christos /* We insist on three registers but the opcode can only use 2162 1.1 christos r1,r2,r3. */ 2163 1.1 christos if (r1 != 1 || r2 != 2 || r3 != 3) 2164 1.1 christos { 2165 1.1 christos as_bad ("BMI/BMD can only use format op r1,r2,r3"); 2166 1.1 christos return; 2167 1.1 christos } 2168 1.1 christos 2169 1.1 christos /* Opcode is unmodified by what comes out of the table. */ 2170 1.1 christos } 2171 1.1 christos else 2172 1.1 christos { 2173 1.1 christos as_bad ("register required"); 2174 1.1 christos return; 2175 1.1 christos } 2176 1.1 christos } 2177 1.1 christos else 2178 1.1 christos { 2179 1.1 christos as_bad ("register required"); 2180 1.1 christos return; 2181 1.1 christos } 2182 1.1 christos 2183 1.1 christos this_dest = r1; 2184 1.1 christos break; 2185 1.1 christos 2186 1.1 christos default: 2187 1.1 christos break; 2188 1.1 christos } 2189 1.1 christos 2190 1.1 christos if (relax) 2191 1.1 christos output = frag_var (rs_machine_dependent, 8, 4, relax, e1.X_add_symbol, 2192 1.1 christos e1.X_add_number, NULL); 2193 1.1 christos else 2194 1.1 christos output = frag_more (4); 2195 1.1 christos 2196 1.1 christos /* Build the 32-bit instruction in a host-endian-neutral fashion. */ 2197 1.1 christos output[0] = (opcode >> 24) & 0xff; 2198 1.1 christos output[1] = (opcode >> 16) & 0xff; 2199 1.1 christos output[2] = (opcode >> 8) & 0xff; 2200 1.1 christos output[3] = (opcode >> 0) & 0xff; 2201 1.1 christos 2202 1.1 christos if (relax) 2203 1.1 christos /* The size of the instruction is unknown, so tie the debug info to the 2204 1.1 christos start of the instruction. */ 2205 1.1 christos dwarf2_emit_insn (0); 2206 1.1 christos else 2207 1.1 christos { 2208 1.1 christos if (reloc) 2209 1.1 christos fix_new_exp (frag_now, output - frag_now->fr_literal, 4, &e1, 2210 1.1 christos reloc == BFD_RELOC_VISIUM_REL16, reloc); 2211 1.1 christos else 2212 1.1 christos visium_update_parity_bit (output); 2213 1.1 christos 2214 1.1 christos dwarf2_emit_insn (4); 2215 1.1 christos } 2216 1.1 christos 2217 1.1 christos if (*str != '\0') 2218 1.1 christos as_bad ("junk after instruction"); 2219 1.1 christos } 2220 1.1 christos 2221 1.1 christos void 2222 1.1 christos visium_cfi_frame_initial_instructions (void) 2223 1.1 christos { 2224 1.1 christos /* The CFA is in SP on function entry. */ 2225 1.1 christos cfi_add_CFA_def_cfa (23, 0); 2226 1.1 christos } 2227 1.1 christos 2228 1.1 christos int 2229 1.1 christos visium_regname_to_dw2regnum (char *regname) 2230 1.1 christos { 2231 1.1 christos if (!regname[0]) 2232 1.1 christos return -1; 2233 1.1 christos 2234 1.1 christos if (regname[0] == 'f' && regname[1] == 'p' && !regname[2]) 2235 1.1 christos return 22; 2236 1.1 christos 2237 1.1 christos if (regname[0] == 's' && regname[1] == 'p' && !regname[2]) 2238 1.1 christos return 23; 2239 1.1 christos 2240 1.1 christos if (regname[0] == 'm' && regname[1] == 'd' && !regname[3]) 2241 1.1 christos switch (regname[2]) 2242 1.1 christos { 2243 1.1 christos case 'b': return 32; 2244 1.1 christos case 'a': return 33; 2245 1.1 christos case 'c': return 34; 2246 1.1 christos default : return -1; 2247 1.1 christos } 2248 1.1 christos 2249 1.1 christos if (regname[0] == 'f' || regname[0] == 'r') 2250 1.1 christos { 2251 1.1 christos char *p; 2252 1.1 christos unsigned int regnum = strtoul (regname + 1, &p, 10); 2253 1.1 christos if (*p) 2254 1.1 christos return -1; 2255 1.1 christos if (regnum >= (regname[0] == 'f' ? 16 : 32)) 2256 1.1 christos return -1; 2257 1.1 christos if (regname[0] == 'f') 2258 1.1 christos regnum += 35; 2259 1.1 christos return regnum; 2260 1.1 christos } 2261 1.1 christos 2262 1.1 christos return -1; 2263 1.1 christos } 2264