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