visium-dis.c revision 1.1.1.8 1 1.1 christos /* Single instruction disassembler for the Visium.
2 1.1 christos
3 1.1.1.8 christos Copyright (C) 2002-2026 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of the GNU opcodes library.
6 1.1 christos
7 1.1 christos This library 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 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 christos 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 christos along with this program; if not, write to the Free Software
19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "sysdep.h"
23 1.1.1.3 christos #include "disassemble.h"
24 1.1 christos #include "opcode/visium.h"
25 1.1 christos
26 1.1 christos #include <string.h>
27 1.1 christos #include <stdlib.h>
28 1.1 christos #include <stdio.h>
29 1.1 christos #include <ctype.h>
30 1.1 christos #include <setjmp.h>
31 1.1 christos
32 1.1 christos /* Maximum length of an instruction. */
33 1.1 christos #define MAXLEN 4
34 1.1 christos
35 1.1 christos struct private
36 1.1 christos {
37 1.1 christos /* Points to first byte not fetched. */
38 1.1 christos bfd_byte *max_fetched;
39 1.1 christos bfd_byte the_buffer[MAXLEN];
40 1.1 christos bfd_vma insn_start;
41 1.1 christos jmp_buf bailout;
42 1.1 christos };
43 1.1 christos
44 1.1 christos /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
45 1.1 christos to ADDR (exclusive) are valid. Returns 1 for success, longjmps
46 1.1 christos on error. */
47 1.1 christos #define FETCH_DATA(info, addr) \
48 1.1 christos ((addr) <= ((struct private *)(info->private_data))->max_fetched \
49 1.1 christos ? 1 : fetch_data ((info), (addr)))
50 1.1 christos
51 1.1 christos static int fetch_data (struct disassemble_info *info, bfd_byte * addr);
52 1.1 christos
53 1.1 christos static int
54 1.1 christos fetch_data (struct disassemble_info *info, bfd_byte *addr)
55 1.1 christos {
56 1.1 christos int status;
57 1.1 christos struct private *priv = (struct private *) info->private_data;
58 1.1 christos bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
59 1.1 christos
60 1.1 christos status = (*info->read_memory_func) (start,
61 1.1 christos priv->max_fetched,
62 1.1 christos addr - priv->max_fetched, info);
63 1.1 christos if (status != 0)
64 1.1 christos {
65 1.1 christos (*info->memory_error_func) (status, start, info);
66 1.1 christos longjmp (priv->bailout, 1);
67 1.1 christos }
68 1.1 christos else
69 1.1 christos priv->max_fetched = addr;
70 1.1 christos return 1;
71 1.1 christos }
72 1.1 christos
73 1.1 christos static char *size_names[] = { "?", "b", "w", "?", "l", "?", "?", "?" };
74 1.1 christos
75 1.1 christos static char *cc_names[] =
76 1.1 christos {
77 1.1 christos "fa", "eq", "cs", "os", "ns", "ne", "cc", "oc",
78 1.1 christos "nc", "ge", "gt", "hi", "le", "ls", "lt", "tr"
79 1.1 christos };
80 1.1 christos
81 1.1 christos /* Disassemble non-storage relative instructions. */
82 1.1 christos
83 1.1 christos static int
84 1.1 christos disassem_class0 (disassemble_info *info, unsigned int ins)
85 1.1 christos {
86 1.1 christos int opcode = (ins >> 21) & 0x000f;
87 1.1 christos
88 1.1 christos if (ins & CLASS0_UNUSED_MASK)
89 1.1 christos goto illegal_opcode;
90 1.1 christos
91 1.1 christos switch (opcode)
92 1.1 christos {
93 1.1 christos case 0:
94 1.1 christos /* BRR instruction. */
95 1.1 christos {
96 1.1 christos unsigned cbf = (ins >> 27) & 0x000f;
97 1.1.1.4 christos int displacement = ((ins & 0xffff) ^ 0x8000) - 0x8000;
98 1.1 christos
99 1.1 christos if (ins == 0)
100 1.1 christos (*info->fprintf_func) (info->stream, "nop");
101 1.1 christos else
102 1.1 christos (*info->fprintf_func) (info->stream, "brr %s,%+d",
103 1.1 christos cc_names[cbf], displacement);
104 1.1 christos }
105 1.1 christos break;
106 1.1 christos case 1:
107 1.1 christos /* Illegal opcode. */
108 1.1 christos goto illegal_opcode;
109 1.1 christos break;
110 1.1 christos case 2:
111 1.1 christos /* Illegal opcode. */
112 1.1 christos goto illegal_opcode;
113 1.1 christos break;
114 1.1 christos case 3:
115 1.1 christos /* Illegal opcode. */
116 1.1 christos goto illegal_opcode;
117 1.1 christos break;
118 1.1 christos case 4:
119 1.1 christos /* Illegal opcode. */
120 1.1 christos goto illegal_opcode;
121 1.1 christos break;
122 1.1 christos case 5:
123 1.1 christos /* Illegal opcode. */
124 1.1 christos goto illegal_opcode;
125 1.1 christos break;
126 1.1 christos case 6:
127 1.1 christos /* Illegal opcode. */
128 1.1 christos goto illegal_opcode;
129 1.1 christos break;
130 1.1 christos case 7:
131 1.1 christos /* Illegal opcode. */
132 1.1 christos goto illegal_opcode;
133 1.1 christos break;
134 1.1 christos case 8:
135 1.1 christos /* Illegal opcode. */
136 1.1 christos goto illegal_opcode;
137 1.1 christos break;
138 1.1 christos case 9:
139 1.1 christos /* Illegal opcode. */
140 1.1 christos goto illegal_opcode;
141 1.1 christos break;
142 1.1 christos case 10:
143 1.1 christos /* Illegal opcode. */
144 1.1 christos goto illegal_opcode;
145 1.1 christos break;
146 1.1 christos case 11:
147 1.1 christos /* Illegal opcode. */
148 1.1 christos goto illegal_opcode;
149 1.1 christos break;
150 1.1 christos case 12:
151 1.1 christos /* Illegal opcode. */
152 1.1 christos goto illegal_opcode;
153 1.1 christos break;
154 1.1 christos case 13:
155 1.1 christos /* Illegal opcode. */
156 1.1 christos goto illegal_opcode;
157 1.1 christos break;
158 1.1 christos case 14:
159 1.1 christos /* Illegal opcode. */
160 1.1 christos goto illegal_opcode;
161 1.1 christos break;
162 1.1 christos case 15:
163 1.1 christos /* Illegal opcode. */
164 1.1 christos goto illegal_opcode;
165 1.1 christos break;
166 1.1 christos }
167 1.1 christos return 0;
168 1.1 christos
169 1.1.1.5 christos illegal_opcode:
170 1.1 christos return -1;
171 1.1 christos }
172 1.1 christos
173 1.1 christos /* Disassemble non-storage register class instructions. */
174 1.1 christos
175 1.1 christos static int
176 1.1 christos disassem_class1 (disassemble_info *info, unsigned int ins)
177 1.1 christos {
178 1.1 christos int opcode = (ins >> 21) & 0xf;
179 1.1 christos int source_a = (ins >> 16) & 0x1f;
180 1.1 christos int source_b = (ins >> 4) & 0x1f;
181 1.1 christos int indx = (ins >> 10) & 0x1f;
182 1.1 christos
183 1.1 christos int size = ins & 0x7;
184 1.1 christos
185 1.1 christos if (ins & CLASS1_UNUSED_MASK)
186 1.1 christos goto illegal_opcode;
187 1.1 christos
188 1.1 christos switch (opcode)
189 1.1 christos {
190 1.1 christos case 0:
191 1.1 christos /* Stop. */
192 1.1.1.3 christos (*info->fprintf_func) (info->stream, "stop %d,r%d", indx, source_a);
193 1.1 christos break;
194 1.1 christos case 1:
195 1.1 christos /* BMI - Block Move Indirect. */
196 1.1 christos if (ins != BMI)
197 1.1 christos goto illegal_opcode;
198 1.1 christos
199 1.1 christos (*info->fprintf_func) (info->stream, "bmi r1,r2,r3");
200 1.1 christos break;
201 1.1 christos case 2:
202 1.1 christos /* Illegal opcode. */
203 1.1 christos goto illegal_opcode;
204 1.1 christos break;
205 1.1 christos case 3:
206 1.1 christos /* BMD - Block Move Direct. */
207 1.1 christos if (ins != BMD)
208 1.1 christos goto illegal_opcode;
209 1.1 christos
210 1.1 christos (*info->fprintf_func) (info->stream, "bmd r1,r2,r3");
211 1.1 christos break;
212 1.1 christos case 4:
213 1.1 christos /* DSI - Disable Interrupts. */
214 1.1 christos if (ins != DSI)
215 1.1 christos goto illegal_opcode;
216 1.1 christos
217 1.1 christos (*info->fprintf_func) (info->stream, "dsi");
218 1.1 christos break;
219 1.1 christos
220 1.1 christos case 5:
221 1.1 christos /* ENI - Enable Interrupts. */
222 1.1 christos if (ins != ENI)
223 1.1 christos goto illegal_opcode;
224 1.1 christos
225 1.1 christos (*info->fprintf_func) (info->stream, "eni");
226 1.1 christos break;
227 1.1 christos
228 1.1 christos case 6:
229 1.1 christos /* Illegal opcode (was EUT). */
230 1.1 christos goto illegal_opcode;
231 1.1 christos break;
232 1.1 christos case 7:
233 1.1 christos /* RFI - Return from Interrupt. */
234 1.1 christos if (ins != RFI)
235 1.1 christos goto illegal_opcode;
236 1.1 christos
237 1.1 christos (*info->fprintf_func) (info->stream, "rfi");
238 1.1 christos break;
239 1.1 christos case 8:
240 1.1 christos /* Illegal opcode. */
241 1.1 christos goto illegal_opcode;
242 1.1 christos break;
243 1.1 christos case 9:
244 1.1 christos /* Illegal opcode. */
245 1.1 christos goto illegal_opcode;
246 1.1 christos break;
247 1.1 christos case 10:
248 1.1 christos /* Illegal opcode. */
249 1.1 christos goto illegal_opcode;
250 1.1 christos break;
251 1.1 christos case 11:
252 1.1 christos /* Illegal opcode. */
253 1.1 christos goto illegal_opcode;
254 1.1 christos break;
255 1.1 christos case 12:
256 1.1 christos /* Illegal opcode. */
257 1.1 christos goto illegal_opcode;
258 1.1 christos break;
259 1.1 christos case 13:
260 1.1 christos goto illegal_opcode;
261 1.1 christos break;
262 1.1 christos case 14:
263 1.1 christos goto illegal_opcode;
264 1.1 christos break;
265 1.1 christos case 15:
266 1.1 christos if (ins & EAM_SELECT_MASK)
267 1.1 christos {
268 1.1 christos /* Extension arithmetic module write */
269 1.1 christos int fp_ins = (ins >> 27) & 0xf;
270 1.1 christos
271 1.1 christos if (size != 4)
272 1.1 christos goto illegal_opcode;
273 1.1 christos
274 1.1 christos if (ins & FP_SELECT_MASK)
275 1.1 christos {
276 1.1 christos /* Which floating point instructions don't need a fsrcB
277 1.1 christos register. */
278 1.1 christos const int no_fsrcb[16] = { 1, 0, 0, 0, 0, 1, 1, 1,
279 1.1 christos 1, 1, 0, 0, 1, 0, 0, 0
280 1.1 christos };
281 1.1 christos if (no_fsrcb[fp_ins] && source_b)
282 1.1 christos goto illegal_opcode;
283 1.1 christos
284 1.1 christos /* Check that none of the floating register register numbers
285 1.1 christos is higher than 15. (If this is fload, then srcA is a
286 1.1 christos general register. */
287 1.1 christos if (ins & ((1 << 14) | (1 << 8)) || (fp_ins && ins & (1 << 20)))
288 1.1 christos goto illegal_opcode;
289 1.1 christos
290 1.1 christos switch (fp_ins)
291 1.1 christos {
292 1.1 christos case 0:
293 1.1 christos (*info->fprintf_func) (info->stream, "fload f%d,r%d",
294 1.1 christos indx, source_a);
295 1.1 christos break;
296 1.1 christos case 1:
297 1.1 christos (*info->fprintf_func) (info->stream, "fadd f%d,f%d,f%d",
298 1.1 christos indx, source_a, source_b);
299 1.1 christos break;
300 1.1 christos case 2:
301 1.1 christos (*info->fprintf_func) (info->stream, "fsub f%d,f%d,f%d",
302 1.1 christos indx, source_a, source_b);
303 1.1 christos break;
304 1.1 christos case 3:
305 1.1 christos (*info->fprintf_func) (info->stream, "fmult f%d,f%d,f%d",
306 1.1 christos indx, source_a, source_b);
307 1.1 christos break;
308 1.1 christos case 4:
309 1.1 christos (*info->fprintf_func) (info->stream, "fdiv f%d,f%d,f%d",
310 1.1 christos indx, source_a, source_b);
311 1.1 christos break;
312 1.1 christos case 5:
313 1.1 christos (*info->fprintf_func) (info->stream, "fsqrt f%d,f%d",
314 1.1 christos indx, source_a);
315 1.1 christos break;
316 1.1 christos case 6:
317 1.1 christos (*info->fprintf_func) (info->stream, "fneg f%d,f%d",
318 1.1 christos indx, source_a);
319 1.1 christos break;
320 1.1 christos case 7:
321 1.1 christos (*info->fprintf_func) (info->stream, "fabs f%d,f%d",
322 1.1 christos indx, source_a);
323 1.1 christos break;
324 1.1 christos case 8:
325 1.1 christos (*info->fprintf_func) (info->stream, "ftoi f%d,f%d",
326 1.1 christos indx, source_a);
327 1.1 christos break;
328 1.1 christos case 9:
329 1.1 christos (*info->fprintf_func) (info->stream, "itof f%d,f%d",
330 1.1 christos indx, source_a);
331 1.1 christos break;
332 1.1 christos case 12:
333 1.1 christos (*info->fprintf_func) (info->stream, "fmove f%d,f%d",
334 1.1 christos indx, source_a);
335 1.1 christos break;
336 1.1 christos default:
337 1.1 christos (*info->fprintf_func) (info->stream,
338 1.1 christos "fpinst %d,f%d,f%d,f%d", fp_ins,
339 1.1 christos indx, source_a, source_b);
340 1.1 christos break;
341 1.1 christos }
342 1.1 christos }
343 1.1 christos else
344 1.1 christos {
345 1.1 christos /* Which EAM operations do not need a srcB register. */
346 1.1 christos const int no_srcb[32] =
347 1.1 christos { 0, 0, 1, 1, 0, 1, 1, 1,
348 1.1 christos 0, 1, 1, 1, 0, 0, 0, 0,
349 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0,
350 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0
351 1.1 christos };
352 1.1 christos
353 1.1 christos if (no_srcb[indx] && source_b)
354 1.1 christos goto illegal_opcode;
355 1.1 christos
356 1.1 christos if (fp_ins)
357 1.1 christos goto illegal_opcode;
358 1.1 christos
359 1.1 christos switch (indx)
360 1.1 christos {
361 1.1 christos case 0:
362 1.1 christos (*info->fprintf_func) (info->stream, "mults r%d,r%d",
363 1.1 christos source_a, source_b);
364 1.1 christos break;
365 1.1 christos case 1:
366 1.1 christos (*info->fprintf_func) (info->stream, "multu r%d,r%d",
367 1.1 christos source_a, source_b);
368 1.1 christos break;
369 1.1 christos case 2:
370 1.1 christos (*info->fprintf_func) (info->stream, "divs r%d",
371 1.1 christos source_a);
372 1.1 christos break;
373 1.1 christos case 3:
374 1.1 christos (*info->fprintf_func) (info->stream, "divu r%d",
375 1.1 christos source_a);
376 1.1 christos break;
377 1.1 christos case 4:
378 1.1 christos (*info->fprintf_func) (info->stream, "writemd r%d,r%d",
379 1.1 christos source_a, source_b);
380 1.1 christos break;
381 1.1 christos case 5:
382 1.1 christos (*info->fprintf_func) (info->stream, "writemdc r%d",
383 1.1 christos source_a);
384 1.1 christos break;
385 1.1 christos case 6:
386 1.1 christos (*info->fprintf_func) (info->stream, "divds r%d",
387 1.1 christos source_a);
388 1.1 christos break;
389 1.1 christos case 7:
390 1.1 christos (*info->fprintf_func) (info->stream, "divdu r%d",
391 1.1 christos source_a);
392 1.1 christos break;
393 1.1 christos case 9:
394 1.1 christos (*info->fprintf_func) (info->stream, "asrd r%d",
395 1.1 christos source_a);
396 1.1 christos break;
397 1.1 christos case 10:
398 1.1 christos (*info->fprintf_func) (info->stream, "lsrd r%d",
399 1.1 christos source_a);
400 1.1 christos break;
401 1.1 christos case 11:
402 1.1 christos (*info->fprintf_func) (info->stream, "asld r%d",
403 1.1 christos source_a);
404 1.1 christos break;
405 1.1 christos default:
406 1.1 christos (*info->fprintf_func) (info->stream,
407 1.1 christos "eamwrite %d,r%d,r%d", indx,
408 1.1 christos source_a, source_b);
409 1.1 christos break;
410 1.1 christos }
411 1.1 christos }
412 1.1 christos }
413 1.1 christos else
414 1.1 christos {
415 1.1 christos /* WRITE - write to memory. */
416 1.1 christos (*info->fprintf_func) (info->stream, "write.%s %d(r%d),r%d",
417 1.1 christos size_names[size], indx, source_a, source_b);
418 1.1 christos }
419 1.1 christos break;
420 1.1 christos }
421 1.1 christos
422 1.1 christos return 0;
423 1.1 christos
424 1.1.1.5 christos illegal_opcode:
425 1.1 christos return -1;
426 1.1 christos }
427 1.1 christos
428 1.1 christos /* Disassemble storage immediate class instructions. */
429 1.1 christos
430 1.1 christos static int
431 1.1 christos disassem_class2 (disassemble_info *info, unsigned int ins)
432 1.1 christos {
433 1.1 christos int opcode = (ins >> 21) & 0xf;
434 1.1 christos int source_a = (ins >> 16) & 0x1f;
435 1.1 christos unsigned immediate = ins & 0x0000ffff;
436 1.1 christos
437 1.1 christos if (ins & CC_MASK)
438 1.1 christos goto illegal_opcode;
439 1.1 christos
440 1.1 christos switch (opcode)
441 1.1 christos {
442 1.1 christos case 0:
443 1.1 christos /* ADDI instruction. */
444 1.1 christos (*info->fprintf_func) (info->stream, "addi r%d,%d", source_a,
445 1.1 christos immediate);
446 1.1 christos break;
447 1.1 christos case 1:
448 1.1 christos /* Illegal opcode. */
449 1.1 christos goto illegal_opcode;
450 1.1 christos break;
451 1.1 christos case 2:
452 1.1 christos /* SUBI instruction. */
453 1.1 christos (*info->fprintf_func) (info->stream, "subi r%d,%d", source_a,
454 1.1 christos immediate);
455 1.1 christos break;
456 1.1 christos case 3:
457 1.1 christos /* Illegal opcode. */
458 1.1 christos goto illegal_opcode;
459 1.1 christos break;
460 1.1 christos case 4:
461 1.1 christos /* MOVIL instruction. */
462 1.1 christos (*info->fprintf_func) (info->stream, "movil r%d,0x%04X", source_a,
463 1.1 christos immediate);
464 1.1 christos break;
465 1.1 christos case 5:
466 1.1 christos /* MOVIU instruction. */
467 1.1 christos (*info->fprintf_func) (info->stream, "moviu r%d,0x%04X", source_a,
468 1.1 christos immediate);
469 1.1 christos break;
470 1.1 christos case 6:
471 1.1 christos /* MOVIQ instruction. */
472 1.1 christos (*info->fprintf_func) (info->stream, "moviq r%d,%u", source_a,
473 1.1 christos immediate);
474 1.1 christos break;
475 1.1 christos case 7:
476 1.1 christos /* Illegal opcode. */
477 1.1 christos goto illegal_opcode;
478 1.1 christos break;
479 1.1 christos case 8:
480 1.1 christos /* WRTL instruction. */
481 1.1 christos if (source_a != 0)
482 1.1 christos goto illegal_opcode;
483 1.1 christos
484 1.1 christos (*info->fprintf_func) (info->stream, "wrtl 0x%04X", immediate);
485 1.1 christos break;
486 1.1 christos case 9:
487 1.1 christos /* WRTU instruction. */
488 1.1 christos if (source_a != 0)
489 1.1 christos goto illegal_opcode;
490 1.1 christos
491 1.1 christos (*info->fprintf_func) (info->stream, "wrtu 0x%04X", immediate);
492 1.1 christos break;
493 1.1 christos case 10:
494 1.1 christos /* Illegal opcode. */
495 1.1 christos goto illegal_opcode;
496 1.1 christos break;
497 1.1 christos case 11:
498 1.1 christos /* Illegal opcode. */
499 1.1 christos goto illegal_opcode;
500 1.1 christos break;
501 1.1 christos case 12:
502 1.1 christos /* Illegal opcode. */
503 1.1 christos goto illegal_opcode;
504 1.1 christos break;
505 1.1 christos case 13:
506 1.1 christos /* Illegal opcode. */
507 1.1 christos goto illegal_opcode;
508 1.1 christos break;
509 1.1 christos case 14:
510 1.1 christos /* Illegal opcode. */
511 1.1 christos goto illegal_opcode;
512 1.1 christos break;
513 1.1 christos case 15:
514 1.1 christos /* Illegal opcode. */
515 1.1 christos goto illegal_opcode;
516 1.1 christos break;
517 1.1 christos }
518 1.1 christos
519 1.1 christos return 0;
520 1.1 christos
521 1.1.1.5 christos illegal_opcode:
522 1.1 christos return -1;
523 1.1 christos }
524 1.1 christos
525 1.1 christos /* Disassemble storage register class instructions. */
526 1.1 christos
527 1.1 christos static int
528 1.1 christos disassem_class3 (disassemble_info *info, unsigned int ins)
529 1.1 christos {
530 1.1 christos int opcode = (ins >> 21) & 0xf;
531 1.1 christos int source_b = (ins >> 4) & 0x1f;
532 1.1 christos int source_a = (ins >> 16) & 0x1f;
533 1.1 christos int size = ins & 0x7;
534 1.1 christos int dest = (ins >> 10) & 0x1f;
535 1.1 christos
536 1.1 christos /* Those instructions that don't have a srcB register. */
537 1.1 christos const int no_srcb[16] =
538 1.1 christos { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 };
539 1.1 christos
540 1.1 christos /* These are instructions which can take an immediate srcB value. */
541 1.1 christos const int srcb_immed[16] =
542 1.1 christos { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 };
543 1.1 christos
544 1.1 christos /* User opcodes should not provide a non-zero srcB register
545 1.1 christos when none is required. Only a BRA or floating point
546 1.1 christos instruction should have a non-zero condition code field.
547 1.1 christos Only a WRITE or EAMWRITE (opcode 15) should select an EAM
548 1.1 christos or floating point operation. Note that FP_SELECT_MASK is
549 1.1 christos the same bit (bit 3) as the interrupt bit which
550 1.1 christos distinguishes SYS1 from BRA and SYS2 from RFLAG. */
551 1.1 christos if ((no_srcb[opcode] && source_b)
552 1.1 christos || (!srcb_immed[opcode] && ins & CLASS3_SOURCEB_IMMED)
553 1.1 christos || (opcode != 12 && opcode != 15 && ins & CC_MASK)
554 1.1 christos || (opcode != 15 && ins & (EAM_SELECT_MASK | FP_SELECT_MASK)))
555 1.1 christos goto illegal_opcode;
556 1.1 christos
557 1.1 christos
558 1.1 christos switch (opcode)
559 1.1 christos {
560 1.1 christos case 0:
561 1.1 christos /* ADD instruction. */
562 1.1 christos (*info->fprintf_func) (info->stream, "add.%s r%d,r%d,r%d",
563 1.1 christos size_names[size], dest, source_a, source_b);
564 1.1 christos break;
565 1.1 christos case 1:
566 1.1 christos /* ADC instruction. */
567 1.1 christos (*info->fprintf_func) (info->stream, "adc.%s r%d,r%d,r%d",
568 1.1 christos size_names[size], dest, source_a, source_b);
569 1.1 christos break;
570 1.1 christos case 2:
571 1.1 christos /* SUB instruction. */
572 1.1 christos if (dest == 0)
573 1.1 christos (*info->fprintf_func) (info->stream, "cmp.%s r%d,r%d",
574 1.1 christos size_names[size], source_a, source_b);
575 1.1 christos else
576 1.1 christos (*info->fprintf_func) (info->stream, "sub.%s r%d,r%d,r%d",
577 1.1 christos size_names[size], dest, source_a, source_b);
578 1.1 christos break;
579 1.1 christos case 3:
580 1.1 christos /* SUBC instruction. */
581 1.1 christos if (dest == 0)
582 1.1 christos (*info->fprintf_func) (info->stream, "cmpc.%s r%d,r%d",
583 1.1 christos size_names[size], source_a, source_b);
584 1.1 christos else
585 1.1 christos (*info->fprintf_func) (info->stream, "subc.%s r%d,r%d,r%d",
586 1.1 christos size_names[size], dest, source_a, source_b);
587 1.1 christos break;
588 1.1 christos case 4:
589 1.1 christos /* EXTW instruction. */
590 1.1 christos if (size == 1)
591 1.1 christos goto illegal_opcode;
592 1.1 christos
593 1.1 christos (*info->fprintf_func) (info->stream, "extw.%s r%d,r%d",
594 1.1 christos size_names[size], dest, source_a);
595 1.1 christos break;
596 1.1 christos case 5:
597 1.1 christos /* ASR instruction. */
598 1.1 christos if (ins & CLASS3_SOURCEB_IMMED)
599 1.1 christos (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,%d",
600 1.1 christos size_names[size], dest, source_a, source_b);
601 1.1 christos else
602 1.1 christos (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,r%d",
603 1.1 christos size_names[size], dest, source_a, source_b);
604 1.1 christos break;
605 1.1 christos case 6:
606 1.1 christos /* LSR instruction. */
607 1.1 christos if (ins & CLASS3_SOURCEB_IMMED)
608 1.1 christos (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,%d",
609 1.1 christos size_names[size], dest, source_a, source_b);
610 1.1 christos else
611 1.1 christos (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,r%d",
612 1.1 christos size_names[size], dest, source_a, source_b);
613 1.1 christos break;
614 1.1 christos case 7:
615 1.1 christos /* ASL instruction. */
616 1.1 christos if (ins & CLASS3_SOURCEB_IMMED)
617 1.1 christos (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,%d",
618 1.1 christos size_names[size], dest, source_a, source_b);
619 1.1 christos else
620 1.1 christos (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,r%d",
621 1.1 christos size_names[size], dest, source_a, source_b);
622 1.1 christos break;
623 1.1 christos case 8:
624 1.1 christos /* XOR instruction. */
625 1.1 christos (*info->fprintf_func) (info->stream, "xor.%s r%d,r%d,r%d",
626 1.1 christos size_names[size], dest, source_a, source_b);
627 1.1 christos break;
628 1.1 christos case 9:
629 1.1 christos /* OR instruction. */
630 1.1 christos if (source_b == 0)
631 1.1 christos (*info->fprintf_func) (info->stream, "move.%s r%d,r%d",
632 1.1 christos size_names[size], dest, source_a);
633 1.1 christos else
634 1.1 christos (*info->fprintf_func) (info->stream, "or.%s r%d,r%d,r%d",
635 1.1 christos size_names[size], dest, source_a, source_b);
636 1.1 christos break;
637 1.1 christos case 10:
638 1.1 christos /* AND instruction. */
639 1.1 christos (*info->fprintf_func) (info->stream, "and.%s r%d,r%d,r%d",
640 1.1 christos size_names[size], dest, source_a, source_b);
641 1.1 christos break;
642 1.1 christos case 11:
643 1.1 christos /* NOT instruction. */
644 1.1 christos (*info->fprintf_func) (info->stream, "not.%s r%d,r%d",
645 1.1 christos size_names[size], dest, source_a);
646 1.1 christos break;
647 1.1 christos case 12:
648 1.1 christos /* BRA instruction. */
649 1.1 christos {
650 1.1 christos unsigned cbf = (ins >> 27) & 0x000f;
651 1.1 christos
652 1.1 christos if (size != 4)
653 1.1 christos goto illegal_opcode;
654 1.1 christos
655 1.1 christos (*info->fprintf_func) (info->stream, "bra %s,r%d,r%d",
656 1.1 christos cc_names[cbf], source_a, dest);
657 1.1 christos }
658 1.1 christos break;
659 1.1 christos case 13:
660 1.1 christos /* RFLAG instruction. */
661 1.1 christos if (source_a || size != 4)
662 1.1 christos goto illegal_opcode;
663 1.1 christos
664 1.1 christos (*info->fprintf_func) (info->stream, "rflag r%d", dest);
665 1.1 christos break;
666 1.1 christos case 14:
667 1.1 christos /* EXTB instruction. */
668 1.1 christos (*info->fprintf_func) (info->stream, "extb.%s r%d,r%d",
669 1.1 christos size_names[size], dest, source_a);
670 1.1 christos break;
671 1.1 christos case 15:
672 1.1 christos if (!(ins & CLASS3_SOURCEB_IMMED))
673 1.1 christos goto illegal_opcode;
674 1.1 christos
675 1.1 christos if (ins & EAM_SELECT_MASK)
676 1.1 christos {
677 1.1 christos /* Extension arithmetic module read. */
678 1.1 christos int fp_ins = (ins >> 27) & 0xf;
679 1.1 christos
680 1.1 christos if (size != 4)
681 1.1 christos goto illegal_opcode;
682 1.1 christos
683 1.1 christos if (ins & FP_SELECT_MASK)
684 1.1 christos {
685 1.1 christos /* Check fsrcA <= 15 and fsrcB <= 15. */
686 1.1 christos if (ins & ((1 << 20) | (1 << 8)))
687 1.1 christos goto illegal_opcode;
688 1.1 christos
689 1.1 christos switch (fp_ins)
690 1.1 christos {
691 1.1 christos case 0:
692 1.1 christos if (source_b)
693 1.1 christos goto illegal_opcode;
694 1.1 christos
695 1.1 christos (*info->fprintf_func) (info->stream, "fstore r%d,f%d",
696 1.1 christos dest, source_a);
697 1.1 christos break;
698 1.1 christos case 10:
699 1.1 christos (*info->fprintf_func) (info->stream, "fcmp r%d,f%d,f%d",
700 1.1 christos dest, source_a, source_b);
701 1.1 christos break;
702 1.1 christos case 11:
703 1.1 christos (*info->fprintf_func) (info->stream, "fcmpe r%d,f%d,f%d",
704 1.1 christos dest, source_a, source_b);
705 1.1 christos break;
706 1.1 christos default:
707 1.1 christos (*info->fprintf_func) (info->stream,
708 1.1 christos "fpuread %d,r%d,f%d,f%d", fp_ins,
709 1.1 christos dest, source_a, source_b);
710 1.1 christos break;
711 1.1 christos }
712 1.1 christos }
713 1.1 christos else
714 1.1 christos {
715 1.1 christos if (fp_ins || source_a)
716 1.1 christos goto illegal_opcode;
717 1.1 christos
718 1.1 christos switch (source_b)
719 1.1 christos {
720 1.1 christos case 0:
721 1.1 christos (*info->fprintf_func) (info->stream, "readmda r%d", dest);
722 1.1 christos break;
723 1.1 christos case 1:
724 1.1 christos (*info->fprintf_func) (info->stream, "readmdb r%d", dest);
725 1.1 christos break;
726 1.1 christos case 2:
727 1.1 christos (*info->fprintf_func) (info->stream, "readmdc r%d", dest);
728 1.1 christos break;
729 1.1 christos default:
730 1.1 christos (*info->fprintf_func) (info->stream, "eamread r%d,%d",
731 1.1 christos dest, source_b);
732 1.1 christos break;
733 1.1 christos }
734 1.1 christos }
735 1.1 christos }
736 1.1 christos else
737 1.1 christos {
738 1.1 christos if (ins & FP_SELECT_MASK)
739 1.1 christos goto illegal_opcode;
740 1.1 christos
741 1.1 christos /* READ instruction. */
742 1.1 christos (*info->fprintf_func) (info->stream, "read.%s r%d,%d(r%d)",
743 1.1 christos size_names[size], dest, source_b, source_a);
744 1.1 christos }
745 1.1 christos break;
746 1.1 christos }
747 1.1 christos
748 1.1 christos return 0;
749 1.1 christos
750 1.1.1.5 christos illegal_opcode:
751 1.1 christos return -1;
752 1.1 christos
753 1.1 christos }
754 1.1 christos
755 1.1 christos /* Print the visium instruction at address addr in debugged memory,
756 1.1 christos on info->stream. Return length of the instruction, in bytes. */
757 1.1 christos
758 1.1 christos int
759 1.1 christos print_insn_visium (bfd_vma addr, disassemble_info *info)
760 1.1 christos {
761 1.1 christos unsigned ins;
762 1.1 christos unsigned p1, p2;
763 1.1 christos int ans;
764 1.1 christos int i;
765 1.1 christos
766 1.1 christos /* Stuff copied from m68k-dis.c. */
767 1.1 christos struct private priv;
768 1.1 christos bfd_byte *buffer = priv.the_buffer;
769 1.1.1.5 christos info->private_data = &priv;
770 1.1 christos priv.max_fetched = priv.the_buffer;
771 1.1 christos priv.insn_start = addr;
772 1.1 christos if (setjmp (priv.bailout) != 0)
773 1.1 christos {
774 1.1 christos /* Error return. */
775 1.1 christos return -1;
776 1.1 christos }
777 1.1 christos
778 1.1 christos /* We do return this info. */
779 1.1 christos info->insn_info_valid = 1;
780 1.1 christos
781 1.1 christos /* Assume non branch insn. */
782 1.1 christos info->insn_type = dis_nonbranch;
783 1.1 christos
784 1.1 christos /* Assume no delay. */
785 1.1 christos info->branch_delay_insns = 0;
786 1.1 christos
787 1.1 christos /* Assume no target known. */
788 1.1 christos info->target = 0;
789 1.1 christos
790 1.1 christos /* Get 32-bit instruction word. */
791 1.1 christos FETCH_DATA (info, buffer + 4);
792 1.1.1.4 christos ins = (unsigned) buffer[0] << 24;
793 1.1 christos ins |= buffer[1] << 16;
794 1.1 christos ins |= buffer[2] << 8;
795 1.1 christos ins |= buffer[3];
796 1.1 christos
797 1.1 christos ans = 0;
798 1.1 christos
799 1.1 christos p1 = buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3];
800 1.1 christos p2 = 0;
801 1.1 christos for (i = 0; i < 8; i++)
802 1.1 christos {
803 1.1 christos p2 += p1 & 1;
804 1.1 christos p1 >>= 1;
805 1.1 christos }
806 1.1 christos
807 1.1 christos /* Decode the instruction. */
808 1.1 christos if (p2 & 1)
809 1.1 christos ans = -1;
810 1.1 christos else
811 1.1 christos {
812 1.1 christos switch ((ins >> 25) & 0x3)
813 1.1 christos {
814 1.1 christos case 0:
815 1.1 christos ans = disassem_class0 (info, ins);
816 1.1 christos break;
817 1.1 christos case 1:
818 1.1 christos ans = disassem_class1 (info, ins);
819 1.1 christos break;
820 1.1 christos case 2:
821 1.1 christos ans = disassem_class2 (info, ins);
822 1.1 christos break;
823 1.1 christos case 3:
824 1.1 christos ans = disassem_class3 (info, ins);
825 1.1 christos break;
826 1.1 christos }
827 1.1 christos }
828 1.1 christos
829 1.1 christos if (ans != 0)
830 1.1 christos (*info->fprintf_func) (info->stream, "err");
831 1.1 christos
832 1.1 christos /* Return number of bytes consumed (always 4 for the Visium). */
833 1.1 christos return 4;
834 1.1 christos }
835