tc-visium.c revision 1.1.1.8 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