mmix-dis.c revision 1.1.1.2 1 1.1 skrll /* mmix-dis.c -- Disassemble MMIX instructions.
2 1.1.1.2 christos Copyright 2000, 2001, 2002, 2005, 2007 Free Software Foundation, Inc.
3 1.1 skrll Written by Hans-Peter Nilsson (hp (at) bitrange.com)
4 1.1 skrll
5 1.1 skrll This file is part of the GNU opcodes library.
6 1.1 skrll
7 1.1 skrll This library is free software; you can redistribute it and/or modify
8 1.1 skrll it under the terms of the GNU General Public License as published by
9 1.1 skrll the Free Software Foundation; either version 3, or (at your option)
10 1.1 skrll any later version.
11 1.1 skrll
12 1.1 skrll It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 skrll ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 skrll or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 skrll License for more details.
16 1.1 skrll
17 1.1 skrll You should have received a copy of the GNU General Public License
18 1.1 skrll along with this file; see the file COPYING. If not, write to the Free
19 1.1 skrll Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 1.1 skrll MA 02110-1301, USA. */
21 1.1 skrll
22 1.1 skrll #include <stdio.h>
23 1.1 skrll #include <string.h>
24 1.1 skrll #include <stdlib.h>
25 1.1 skrll #include "opcode/mmix.h"
26 1.1 skrll #include "dis-asm.h"
27 1.1 skrll #include "libiberty.h"
28 1.1 skrll #include "bfd.h"
29 1.1 skrll #include "opintl.h"
30 1.1 skrll
31 1.1 skrll #define BAD_CASE(x) \
32 1.1 skrll do \
33 1.1 skrll { \
34 1.1 skrll fprintf (stderr, \
35 1.1 skrll _("Bad case %d (%s) in %s:%d\n"), \
36 1.1 skrll x, #x, __FILE__, __LINE__); \
37 1.1 skrll abort (); \
38 1.1 skrll } \
39 1.1 skrll while (0)
40 1.1 skrll
41 1.1 skrll #define FATAL_DEBUG \
42 1.1 skrll do \
43 1.1 skrll { \
44 1.1 skrll fprintf (stderr, \
45 1.1 skrll _("Internal: Non-debugged code (test-case missing): %s:%d"),\
46 1.1 skrll __FILE__, __LINE__); \
47 1.1 skrll abort (); \
48 1.1 skrll } \
49 1.1 skrll while (0)
50 1.1 skrll
51 1.1 skrll #define ROUND_MODE(n) \
52 1.1 skrll ((n) == 1 ? "ROUND_OFF" : (n) == 2 ? "ROUND_UP" : \
53 1.1 skrll (n) == 3 ? "ROUND_DOWN" : (n) == 4 ? "ROUND_NEAR" : \
54 1.1 skrll _("(unknown)"))
55 1.1 skrll
56 1.1 skrll #define INSN_IMMEDIATE_BIT (IMM_OFFSET_BIT << 24)
57 1.1 skrll #define INSN_BACKWARD_OFFSET_BIT (1 << 24)
58 1.1 skrll
59 1.1 skrll struct mmix_dis_info
60 1.1 skrll {
61 1.1 skrll const char *reg_name[256];
62 1.1 skrll const char *spec_reg_name[32];
63 1.1 skrll
64 1.1 skrll /* Waste a little memory so we don't have to allocate each separately.
65 1.1 skrll We could have an array with static contents for these, but on the
66 1.1 skrll other hand, we don't have to. */
67 1.1 skrll char basic_reg_name[256][sizeof ("$255")];
68 1.1 skrll };
69 1.1 skrll
70 1.1 skrll /* Initialize a target-specific array in INFO. */
71 1.1 skrll
72 1.1 skrll static bfd_boolean
73 1.1 skrll initialize_mmix_dis_info (struct disassemble_info *info)
74 1.1 skrll {
75 1.1 skrll struct mmix_dis_info *minfop = malloc (sizeof (struct mmix_dis_info));
76 1.1.1.2 christos long i;
77 1.1 skrll
78 1.1 skrll if (minfop == NULL)
79 1.1 skrll return FALSE;
80 1.1 skrll
81 1.1 skrll memset (minfop, 0, sizeof (*minfop));
82 1.1 skrll
83 1.1 skrll /* Initialize register names from register symbols. If there's no
84 1.1 skrll register section, then there are no register symbols. */
85 1.1 skrll if ((info->section != NULL && info->section->owner != NULL)
86 1.1 skrll || (info->symbols != NULL
87 1.1 skrll && info->symbols[0] != NULL
88 1.1 skrll && bfd_asymbol_bfd (info->symbols[0]) != NULL))
89 1.1 skrll {
90 1.1 skrll bfd *abfd = info->section && info->section->owner != NULL
91 1.1 skrll ? info->section->owner
92 1.1 skrll : bfd_asymbol_bfd (info->symbols[0]);
93 1.1 skrll asection *reg_section = bfd_get_section_by_name (abfd, "*REG*");
94 1.1 skrll
95 1.1 skrll if (reg_section != NULL)
96 1.1 skrll {
97 1.1 skrll /* The returned symcount *does* include the ending NULL. */
98 1.1 skrll long symsize = bfd_get_symtab_upper_bound (abfd);
99 1.1 skrll asymbol **syms = malloc (symsize);
100 1.1 skrll long nsyms;
101 1.1 skrll
102 1.1 skrll if (syms == NULL)
103 1.1 skrll {
104 1.1 skrll FATAL_DEBUG;
105 1.1 skrll free (minfop);
106 1.1 skrll return FALSE;
107 1.1 skrll }
108 1.1 skrll nsyms = bfd_canonicalize_symtab (abfd, syms);
109 1.1 skrll
110 1.1 skrll /* We use the first name for a register. If this is MMO, then
111 1.1 skrll it's the name with the first sequence number, presumably the
112 1.1 skrll first in the source. */
113 1.1 skrll for (i = 0; i < nsyms && syms[i] != NULL; i++)
114 1.1 skrll {
115 1.1 skrll if (syms[i]->section == reg_section
116 1.1 skrll && syms[i]->value < 256
117 1.1 skrll && minfop->reg_name[syms[i]->value] == NULL)
118 1.1 skrll minfop->reg_name[syms[i]->value] = syms[i]->name;
119 1.1 skrll }
120 1.1 skrll }
121 1.1 skrll }
122 1.1 skrll
123 1.1 skrll /* Fill in the rest with the canonical names. */
124 1.1 skrll for (i = 0; i < 256; i++)
125 1.1 skrll if (minfop->reg_name[i] == NULL)
126 1.1 skrll {
127 1.1.1.2 christos sprintf (minfop->basic_reg_name[i], "$%ld", i);
128 1.1 skrll minfop->reg_name[i] = minfop->basic_reg_name[i];
129 1.1 skrll }
130 1.1 skrll
131 1.1 skrll /* We assume it's actually a one-to-one mapping of number-to-name. */
132 1.1 skrll for (i = 0; mmix_spec_regs[i].name != NULL; i++)
133 1.1 skrll minfop->spec_reg_name[mmix_spec_regs[i].number] = mmix_spec_regs[i].name;
134 1.1 skrll
135 1.1 skrll info->private_data = (void *) minfop;
136 1.1 skrll return TRUE;
137 1.1 skrll }
138 1.1 skrll
139 1.1 skrll /* A table indexed by the first byte is constructed as we disassemble each
140 1.1 skrll tetrabyte. The contents is a pointer into mmix_insns reflecting the
141 1.1 skrll first found entry with matching match-bits and lose-bits. Further
142 1.1 skrll entries are considered one after one until the operand constraints
143 1.1 skrll match or the match-bits and lose-bits do not match. Normally a
144 1.1 skrll "further entry" will just show that there was no other match. */
145 1.1 skrll
146 1.1 skrll static const struct mmix_opcode *
147 1.1 skrll get_opcode (unsigned long insn)
148 1.1 skrll {
149 1.1 skrll static const struct mmix_opcode **opcodes = NULL;
150 1.1 skrll const struct mmix_opcode *opcodep = mmix_opcodes;
151 1.1 skrll unsigned int opcode_part = (insn >> 24) & 255;
152 1.1 skrll
153 1.1 skrll if (opcodes == NULL)
154 1.1 skrll opcodes = xcalloc (256, sizeof (struct mmix_opcode *));
155 1.1 skrll
156 1.1 skrll opcodep = opcodes[opcode_part];
157 1.1 skrll if (opcodep == NULL
158 1.1 skrll || (opcodep->match & insn) != opcodep->match
159 1.1 skrll || (opcodep->lose & insn) != 0)
160 1.1 skrll {
161 1.1 skrll /* Search through the table. */
162 1.1 skrll for (opcodep = mmix_opcodes; opcodep->name != NULL; opcodep++)
163 1.1 skrll {
164 1.1 skrll /* FIXME: Break out this into an initialization function. */
165 1.1 skrll if ((opcodep->match & (opcode_part << 24)) == opcode_part
166 1.1 skrll && (opcodep->lose & (opcode_part << 24)) == 0)
167 1.1 skrll opcodes[opcode_part] = opcodep;
168 1.1 skrll
169 1.1 skrll if ((opcodep->match & insn) == opcodep->match
170 1.1 skrll && (opcodep->lose & insn) == 0)
171 1.1 skrll break;
172 1.1 skrll }
173 1.1 skrll }
174 1.1 skrll
175 1.1 skrll if (opcodep->name == NULL)
176 1.1 skrll return NULL;
177 1.1 skrll
178 1.1 skrll /* Check constraints. If they don't match, loop through the next opcode
179 1.1 skrll entries. */
180 1.1 skrll do
181 1.1 skrll {
182 1.1 skrll switch (opcodep->operands)
183 1.1 skrll {
184 1.1 skrll /* These have no restraint on what can be in the lower three
185 1.1 skrll bytes. */
186 1.1 skrll case mmix_operands_regs:
187 1.1 skrll case mmix_operands_reg_yz:
188 1.1 skrll case mmix_operands_regs_z_opt:
189 1.1 skrll case mmix_operands_regs_z:
190 1.1 skrll case mmix_operands_jmp:
191 1.1 skrll case mmix_operands_pushgo:
192 1.1 skrll case mmix_operands_pop:
193 1.1 skrll case mmix_operands_sync:
194 1.1 skrll case mmix_operands_x_regs_z:
195 1.1 skrll case mmix_operands_neg:
196 1.1 skrll case mmix_operands_pushj:
197 1.1 skrll case mmix_operands_regaddr:
198 1.1 skrll case mmix_operands_get:
199 1.1 skrll case mmix_operands_set:
200 1.1 skrll case mmix_operands_save:
201 1.1 skrll case mmix_operands_unsave:
202 1.1 skrll case mmix_operands_xyz_opt:
203 1.1 skrll return opcodep;
204 1.1 skrll
205 1.1 skrll /* For a ROUND_MODE, the middle byte must be 0..4. */
206 1.1 skrll case mmix_operands_roundregs_z:
207 1.1 skrll case mmix_operands_roundregs:
208 1.1 skrll {
209 1.1 skrll int midbyte = (insn >> 8) & 255;
210 1.1 skrll
211 1.1 skrll if (midbyte <= 4)
212 1.1 skrll return opcodep;
213 1.1 skrll }
214 1.1 skrll break;
215 1.1 skrll
216 1.1 skrll case mmix_operands_put:
217 1.1 skrll /* A "PUT". If it is "immediate", then no restrictions,
218 1.1 skrll otherwise we have to make sure the register number is < 32. */
219 1.1 skrll if ((insn & INSN_IMMEDIATE_BIT)
220 1.1 skrll || ((insn >> 16) & 255) < 32)
221 1.1 skrll return opcodep;
222 1.1 skrll break;
223 1.1 skrll
224 1.1 skrll case mmix_operands_resume:
225 1.1 skrll /* Middle bytes must be zero. */
226 1.1 skrll if ((insn & 0x00ffff00) == 0)
227 1.1 skrll return opcodep;
228 1.1 skrll break;
229 1.1 skrll
230 1.1 skrll default:
231 1.1 skrll BAD_CASE (opcodep->operands);
232 1.1 skrll }
233 1.1 skrll
234 1.1 skrll opcodep++;
235 1.1 skrll }
236 1.1 skrll while ((opcodep->match & insn) == opcodep->match
237 1.1 skrll && (opcodep->lose & insn) == 0);
238 1.1 skrll
239 1.1 skrll /* If we got here, we had no match. */
240 1.1 skrll return NULL;
241 1.1 skrll }
242 1.1 skrll
243 1.1 skrll /* The main disassembly function. */
244 1.1 skrll
245 1.1 skrll int
246 1.1 skrll print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info)
247 1.1 skrll {
248 1.1 skrll unsigned char buffer[4];
249 1.1 skrll unsigned long insn;
250 1.1 skrll unsigned int x, y, z;
251 1.1 skrll const struct mmix_opcode *opcodep;
252 1.1 skrll int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
253 1.1 skrll struct mmix_dis_info *minfop;
254 1.1 skrll
255 1.1 skrll if (status != 0)
256 1.1 skrll {
257 1.1 skrll (*info->memory_error_func) (status, memaddr, info);
258 1.1 skrll return -1;
259 1.1 skrll }
260 1.1 skrll
261 1.1 skrll /* FIXME: Is -1 suitable? */
262 1.1 skrll if (info->private_data == NULL
263 1.1 skrll && ! initialize_mmix_dis_info (info))
264 1.1 skrll return -1;
265 1.1 skrll
266 1.1 skrll minfop = (struct mmix_dis_info *) info->private_data;
267 1.1 skrll x = buffer[1];
268 1.1 skrll y = buffer[2];
269 1.1 skrll z = buffer[3];
270 1.1 skrll
271 1.1 skrll insn = bfd_getb32 (buffer);
272 1.1 skrll
273 1.1 skrll opcodep = get_opcode (insn);
274 1.1 skrll
275 1.1 skrll if (opcodep == NULL)
276 1.1 skrll {
277 1.1 skrll (*info->fprintf_func) (info->stream, _("*unknown*"));
278 1.1 skrll return 4;
279 1.1 skrll }
280 1.1 skrll
281 1.1 skrll (*info->fprintf_func) (info->stream, "%s ", opcodep->name);
282 1.1 skrll
283 1.1 skrll /* Present bytes in the order they are laid out in memory. */
284 1.1 skrll info->display_endian = BFD_ENDIAN_BIG;
285 1.1 skrll
286 1.1 skrll info->insn_info_valid = 1;
287 1.1 skrll info->bytes_per_chunk = 4;
288 1.1 skrll info->branch_delay_insns = 0;
289 1.1 skrll info->target = 0;
290 1.1 skrll switch (opcodep->type)
291 1.1 skrll {
292 1.1 skrll case mmix_type_normal:
293 1.1 skrll case mmix_type_memaccess_block:
294 1.1 skrll info->insn_type = dis_nonbranch;
295 1.1 skrll break;
296 1.1 skrll
297 1.1 skrll case mmix_type_branch:
298 1.1 skrll info->insn_type = dis_branch;
299 1.1 skrll break;
300 1.1 skrll
301 1.1 skrll case mmix_type_condbranch:
302 1.1 skrll info->insn_type = dis_condbranch;
303 1.1 skrll break;
304 1.1 skrll
305 1.1 skrll case mmix_type_memaccess_octa:
306 1.1 skrll info->insn_type = dis_dref;
307 1.1 skrll info->data_size = 8;
308 1.1 skrll break;
309 1.1 skrll
310 1.1 skrll case mmix_type_memaccess_tetra:
311 1.1 skrll info->insn_type = dis_dref;
312 1.1 skrll info->data_size = 4;
313 1.1 skrll break;
314 1.1 skrll
315 1.1 skrll case mmix_type_memaccess_wyde:
316 1.1 skrll info->insn_type = dis_dref;
317 1.1 skrll info->data_size = 2;
318 1.1 skrll break;
319 1.1 skrll
320 1.1 skrll case mmix_type_memaccess_byte:
321 1.1 skrll info->insn_type = dis_dref;
322 1.1 skrll info->data_size = 1;
323 1.1 skrll break;
324 1.1 skrll
325 1.1 skrll case mmix_type_jsr:
326 1.1 skrll info->insn_type = dis_jsr;
327 1.1 skrll break;
328 1.1 skrll
329 1.1 skrll default:
330 1.1 skrll BAD_CASE(opcodep->type);
331 1.1 skrll }
332 1.1 skrll
333 1.1 skrll switch (opcodep->operands)
334 1.1 skrll {
335 1.1 skrll case mmix_operands_regs:
336 1.1 skrll /* All registers: "$X,$Y,$Z". */
337 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s,%s",
338 1.1 skrll minfop->reg_name[x],
339 1.1 skrll minfop->reg_name[y],
340 1.1 skrll minfop->reg_name[z]);
341 1.1 skrll break;
342 1.1 skrll
343 1.1 skrll case mmix_operands_reg_yz:
344 1.1 skrll /* Like SETH - "$X,YZ". */
345 1.1 skrll (*info->fprintf_func) (info->stream, "%s,0x%x",
346 1.1 skrll minfop->reg_name[x], y * 256 + z);
347 1.1 skrll break;
348 1.1 skrll
349 1.1 skrll case mmix_operands_regs_z_opt:
350 1.1 skrll case mmix_operands_regs_z:
351 1.1 skrll case mmix_operands_pushgo:
352 1.1 skrll /* The regular "$X,$Y,$Z|Z". */
353 1.1 skrll if (insn & INSN_IMMEDIATE_BIT)
354 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s,%d",
355 1.1 skrll minfop->reg_name[x], minfop->reg_name[y], z);
356 1.1 skrll else
357 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s,%s",
358 1.1 skrll minfop->reg_name[x],
359 1.1 skrll minfop->reg_name[y],
360 1.1 skrll minfop->reg_name[z]);
361 1.1 skrll break;
362 1.1 skrll
363 1.1 skrll case mmix_operands_jmp:
364 1.1 skrll /* Address; only JMP. */
365 1.1 skrll {
366 1.1 skrll bfd_signed_vma offset = (x * 65536 + y * 256 + z) * 4;
367 1.1 skrll
368 1.1 skrll if (insn & INSN_BACKWARD_OFFSET_BIT)
369 1.1 skrll offset -= (256 * 65536) * 4;
370 1.1 skrll
371 1.1 skrll info->target = memaddr + offset;
372 1.1 skrll (*info->print_address_func) (memaddr + offset, info);
373 1.1 skrll }
374 1.1 skrll break;
375 1.1 skrll
376 1.1 skrll case mmix_operands_roundregs_z:
377 1.1 skrll /* Two registers, like FLOT, possibly with rounding: "$X,$Z|Z"
378 1.1 skrll "$X,ROUND_MODE,$Z|Z". */
379 1.1 skrll if (y != 0)
380 1.1 skrll {
381 1.1 skrll if (insn & INSN_IMMEDIATE_BIT)
382 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s,%d",
383 1.1 skrll minfop->reg_name[x],
384 1.1 skrll ROUND_MODE (y), z);
385 1.1 skrll else
386 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s,%s",
387 1.1 skrll minfop->reg_name[x],
388 1.1 skrll ROUND_MODE (y),
389 1.1 skrll minfop->reg_name[z]);
390 1.1 skrll }
391 1.1 skrll else
392 1.1 skrll {
393 1.1 skrll if (insn & INSN_IMMEDIATE_BIT)
394 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%d",
395 1.1 skrll minfop->reg_name[x], z);
396 1.1 skrll else
397 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s",
398 1.1 skrll minfop->reg_name[x],
399 1.1 skrll minfop->reg_name[z]);
400 1.1 skrll }
401 1.1 skrll break;
402 1.1 skrll
403 1.1 skrll case mmix_operands_pop:
404 1.1 skrll /* Like POP - "X,YZ". */
405 1.1 skrll (*info->fprintf_func) (info->stream, "%d,%d", x, y*256 + z);
406 1.1 skrll break;
407 1.1 skrll
408 1.1 skrll case mmix_operands_roundregs:
409 1.1 skrll /* Two registers, possibly with rounding: "$X,$Z" or
410 1.1 skrll "$X,ROUND_MODE,$Z". */
411 1.1 skrll if (y != 0)
412 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s,%s",
413 1.1 skrll minfop->reg_name[x],
414 1.1 skrll ROUND_MODE (y),
415 1.1 skrll minfop->reg_name[z]);
416 1.1 skrll else
417 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s",
418 1.1 skrll minfop->reg_name[x],
419 1.1 skrll minfop->reg_name[z]);
420 1.1 skrll break;
421 1.1 skrll
422 1.1 skrll case mmix_operands_sync:
423 1.1 skrll /* Like SYNC - "XYZ". */
424 1.1 skrll (*info->fprintf_func) (info->stream, "%u",
425 1.1 skrll x * 65536 + y * 256 + z);
426 1.1 skrll break;
427 1.1 skrll
428 1.1 skrll case mmix_operands_x_regs_z:
429 1.1 skrll /* Like SYNCD - "X,$Y,$Z|Z". */
430 1.1 skrll if (insn & INSN_IMMEDIATE_BIT)
431 1.1 skrll (*info->fprintf_func) (info->stream, "%d,%s,%d",
432 1.1 skrll x, minfop->reg_name[y], z);
433 1.1 skrll else
434 1.1 skrll (*info->fprintf_func) (info->stream, "%d,%s,%s",
435 1.1 skrll x, minfop->reg_name[y],
436 1.1 skrll minfop->reg_name[z]);
437 1.1 skrll break;
438 1.1 skrll
439 1.1 skrll case mmix_operands_neg:
440 1.1 skrll /* Like NEG and NEGU - "$X,Y,$Z|Z". */
441 1.1 skrll if (insn & INSN_IMMEDIATE_BIT)
442 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%d,%d",
443 1.1 skrll minfop->reg_name[x], y, z);
444 1.1 skrll else
445 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%d,%s",
446 1.1 skrll minfop->reg_name[x], y,
447 1.1 skrll minfop->reg_name[z]);
448 1.1 skrll break;
449 1.1 skrll
450 1.1 skrll case mmix_operands_pushj:
451 1.1 skrll case mmix_operands_regaddr:
452 1.1 skrll /* Like GETA or branches - "$X,Address". */
453 1.1 skrll {
454 1.1 skrll bfd_signed_vma offset = (y * 256 + z) * 4;
455 1.1 skrll
456 1.1 skrll if (insn & INSN_BACKWARD_OFFSET_BIT)
457 1.1 skrll offset -= 65536 * 4;
458 1.1 skrll
459 1.1 skrll info->target = memaddr + offset;
460 1.1 skrll
461 1.1 skrll (*info->fprintf_func) (info->stream, "%s,", minfop->reg_name[x]);
462 1.1 skrll (*info->print_address_func) (memaddr + offset, info);
463 1.1 skrll }
464 1.1 skrll break;
465 1.1 skrll
466 1.1 skrll case mmix_operands_get:
467 1.1 skrll /* GET - "X,spec_reg". */
468 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s",
469 1.1 skrll minfop->reg_name[x],
470 1.1 skrll minfop->spec_reg_name[z]);
471 1.1 skrll break;
472 1.1 skrll
473 1.1 skrll case mmix_operands_put:
474 1.1 skrll /* PUT - "spec_reg,$Z|Z". */
475 1.1 skrll if (insn & INSN_IMMEDIATE_BIT)
476 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%d",
477 1.1 skrll minfop->spec_reg_name[x], z);
478 1.1 skrll else
479 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s",
480 1.1 skrll minfop->spec_reg_name[x],
481 1.1 skrll minfop->reg_name[z]);
482 1.1 skrll break;
483 1.1 skrll
484 1.1 skrll case mmix_operands_set:
485 1.1 skrll /* Two registers, "$X,$Y". */
486 1.1 skrll (*info->fprintf_func) (info->stream, "%s,%s",
487 1.1 skrll minfop->reg_name[x],
488 1.1 skrll minfop->reg_name[y]);
489 1.1 skrll break;
490 1.1 skrll
491 1.1 skrll case mmix_operands_save:
492 1.1 skrll /* SAVE - "$X,0". */
493 1.1 skrll (*info->fprintf_func) (info->stream, "%s,0", minfop->reg_name[x]);
494 1.1 skrll break;
495 1.1 skrll
496 1.1 skrll case mmix_operands_unsave:
497 1.1 skrll /* UNSAVE - "0,$Z". */
498 1.1 skrll (*info->fprintf_func) (info->stream, "0,%s", minfop->reg_name[z]);
499 1.1 skrll break;
500 1.1 skrll
501 1.1 skrll case mmix_operands_xyz_opt:
502 1.1 skrll /* Like SWYM or TRAP - "X,Y,Z". */
503 1.1 skrll (*info->fprintf_func) (info->stream, "%d,%d,%d", x, y, z);
504 1.1 skrll break;
505 1.1 skrll
506 1.1 skrll case mmix_operands_resume:
507 1.1 skrll /* Just "Z", like RESUME. */
508 1.1 skrll (*info->fprintf_func) (info->stream, "%d", z);
509 1.1 skrll break;
510 1.1 skrll
511 1.1 skrll default:
512 1.1 skrll (*info->fprintf_func) (info->stream, _("*unknown operands type: %d*"),
513 1.1 skrll opcodep->operands);
514 1.1 skrll break;
515 1.1 skrll }
516 1.1 skrll
517 1.1 skrll return 4;
518 1.1 skrll }
519