* copy.c (main): Even if is_strip, accept -d argument indicating alternate
[binutils-gdb.git] / binutils / i960-pinsn.c
1 /* Disassemble i80960 instructions.
2 Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Diddler.
5
6 BFD is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 BFD is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with BFD; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "bucomm.h"
23
24 static char *reg_names[] = {
25 /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7",
26 /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
27 /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
28 /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp",
29 /* 32 */ "pc", "ac", "ip", "tc", "fp0", "fp1", "fp2", "fp3"
30 };
31
32
33 static FILE *stream; /* Output goes here */
34 static void print_addr();
35 static void ctrl();
36 static void cobr();
37 static void reg();
38 static int mem();
39 static void ea();
40 static void dstop();
41 static void regop();
42 static void invalid();
43 static int pinsn();
44 static void put_abs();
45
46
47 /* Print the i960 instruction at address 'memaddr' in debugged memory,
48 * on stream 's'. Returns length of the instruction, in bytes.
49 */
50 int
51 print_insn_i960( memaddr, buffer, s )
52 bfd_vma memaddr;
53 uint8e_type *buffer;
54 FILE *s;
55 {
56 unsigned int word1, word2;
57
58 stream = s;
59 word1 =buffer [0] |( buffer[1]<< 8) | (buffer[2] << 16) | ( buffer[3] <<24);
60 word2 =buffer [4] |( buffer[5]<< 8) | (buffer[6] << 16) | ( buffer[7] <<24);
61 return pinsn( memaddr, word1, word2 );
62 }
63 \f
64 #define IN_GDB
65
66 /*****************************************************************************
67 * All code below this point should be identical with that of
68 * the disassembler in gdmp960.
69 *****************************************************************************/
70
71 struct tabent {
72 char *name;
73 char numops;
74 };
75
76 static int
77 pinsn( memaddr, word1, word2 )
78 unsigned long memaddr;
79 unsigned long word1, word2;
80 {
81 int instr_len;
82
83 instr_len = 4;
84 put_abs( word1, word2 );
85
86 /* Divide instruction set into classes based on high 4 bits of opcode*/
87 switch ( (word1 >> 28) & 0xf ){
88 case 0x0:
89 case 0x1:
90 ctrl( memaddr, word1, word2 );
91 break;
92 case 0x2:
93 case 0x3:
94 cobr( memaddr, word1, word2 );
95 break;
96 case 0x5:
97 case 0x6:
98 case 0x7:
99 reg( word1 );
100 break;
101 case 0x8:
102 case 0x9:
103 case 0xa:
104 case 0xb:
105 case 0xc:
106 instr_len = mem( memaddr, word1, word2, 0 );
107 break;
108 default:
109 /* invalid instruction, print as data word */
110 invalid( word1 );
111 break;
112 }
113 return instr_len;
114 }
115
116 /****************************************/
117 /* CTRL format */
118 /****************************************/
119 static void
120 ctrl( memaddr, word1, word2 )
121 unsigned long memaddr;
122 unsigned long word1, word2;
123 {
124 int i;
125 static struct tabent ctrl_tab[] = {
126 NULL, 0, /* 0x00 */
127 NULL, 0, /* 0x01 */
128 NULL, 0, /* 0x02 */
129 NULL, 0, /* 0x03 */
130 NULL, 0, /* 0x04 */
131 NULL, 0, /* 0x05 */
132 NULL, 0, /* 0x06 */
133 NULL, 0, /* 0x07 */
134 "b", 1, /* 0x08 */
135 "call", 1, /* 0x09 */
136 "ret", 0, /* 0x0a */
137 "bal", 1, /* 0x0b */
138 NULL, 0, /* 0x0c */
139 NULL, 0, /* 0x0d */
140 NULL, 0, /* 0x0e */
141 NULL, 0, /* 0x0f */
142 "bno", 1, /* 0x10 */
143 "bg", 1, /* 0x11 */
144 "be", 1, /* 0x12 */
145 "bge", 1, /* 0x13 */
146 "bl", 1, /* 0x14 */
147 "bne", 1, /* 0x15 */
148 "ble", 1, /* 0x16 */
149 "bo", 1, /* 0x17 */
150 "faultno", 0, /* 0x18 */
151 "faultg", 0, /* 0x19 */
152 "faulte", 0, /* 0x1a */
153 "faultge", 0, /* 0x1b */
154 "faultl", 0, /* 0x1c */
155 "faultne", 0, /* 0x1d */
156 "faultle", 0, /* 0x1e */
157 "faulto", 0, /* 0x1f */
158 };
159
160 i = (word1 >> 24) & 0xff;
161 if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){
162 invalid( word1 );
163 return;
164 }
165
166 fputs( ctrl_tab[i].name, stream );
167 if ( word1 & 2 ){ /* Predicts branch not taken */
168 fputs( ".f", stream );
169 }
170
171 if ( ctrl_tab[i].numops == 1 ){
172 /* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */
173 word1 &= 0x00ffffff;
174 if ( word1 & 0x00800000 ){ /* Sign bit is set */
175 word1 |= (-1 & ~0xffffff); /* Sign extend */
176 }
177 putc( '\t', stream );
178 print_addr( word1 + memaddr );
179 }
180 }
181
182 /****************************************/
183 /* COBR format */
184 /****************************************/
185 static void
186 cobr( memaddr, word1, word2 )
187 unsigned long memaddr;
188 unsigned long word1, word2;
189 {
190 int src1;
191 int src2;
192 int i;
193
194 static struct tabent cobr_tab[] = {
195 "testno", 1, /* 0x20 */
196 "testg", 1, /* 0x21 */
197 "teste", 1, /* 0x22 */
198 "testge", 1, /* 0x23 */
199 "testl", 1, /* 0x24 */
200 "testne", 1, /* 0x25 */
201 "testle", 1, /* 0x26 */
202 "testo", 1, /* 0x27 */
203 NULL, 0, /* 0x28 */
204 NULL, 0, /* 0x29 */
205 NULL, 0, /* 0x2a */
206 NULL, 0, /* 0x2b */
207 NULL, 0, /* 0x2c */
208 NULL, 0, /* 0x2d */
209 NULL, 0, /* 0x2e */
210 NULL, 0, /* 0x2f */
211 "bbc", 3, /* 0x30 */
212 "cmpobg", 3, /* 0x31 */
213 "cmpobe", 3, /* 0x32 */
214 "cmpobge", 3, /* 0x33 */
215 "cmpobl", 3, /* 0x34 */
216 "cmpobne", 3, /* 0x35 */
217 "cmpoble", 3, /* 0x36 */
218 "bbs", 3, /* 0x37 */
219 "cmpibno", 3, /* 0x38 */
220 "cmpibg", 3, /* 0x39 */
221 "cmpibe", 3, /* 0x3a */
222 "cmpibge", 3, /* 0x3b */
223 "cmpibl", 3, /* 0x3c */
224 "cmpibne", 3, /* 0x3d */
225 "cmpible", 3, /* 0x3e */
226 "cmpibo", 3, /* 0x3f */
227 };
228
229 i = ((word1 >> 24) & 0xff) - 0x20;
230 if ( cobr_tab[i].name == NULL ){
231 invalid( word1 );
232 return;
233 }
234
235 fputs( cobr_tab[i].name, stream );
236 if ( word1 & 2 ){ /* Predicts branch not taken */
237 fputs( ".f", stream );
238 }
239 putc( '\t', stream );
240
241 src1 = (word1 >> 19) & 0x1f;
242 src2 = (word1 >> 14) & 0x1f;
243
244 if ( word1 & 0x02000 ){ /* M1 is 1 */
245 fprintf( stream, "%d", src1 );
246 } else { /* M1 is 0 */
247 fputs( reg_names[src1], stream );
248 }
249
250 if ( cobr_tab[i].numops > 1 ){
251 if ( word1 & 1 ){ /* S2 is 1 */
252 fprintf( stream, ",sf%d,", src2 );
253 } else { /* S1 is 0 */
254 fprintf( stream, ",%s,", reg_names[src2] );
255 }
256
257 /* Extract displacement and convert to address
258 */
259 word1 &= 0x00001ffc;
260 if ( word1 & 0x00001000 ){ /* Negative displacement */
261 word1 |= (-1 & ~0x1fff); /* Sign extend */
262 }
263 print_addr( memaddr + word1 );
264 }
265 }
266
267 /****************************************/
268 /* MEM format */
269 /****************************************/
270 static int /* returns instruction length: 4 or 8 */
271 mem( memaddr, word1, word2, noprint )
272 unsigned long memaddr;
273 unsigned long word1, word2;
274 int noprint; /* If TRUE, return instruction length, but
275 * don't output any text.
276 */
277 {
278 int i, j;
279 int len;
280 int mode;
281 int offset;
282 char *reg1, *reg2, *reg3;
283
284 /* This lookup table is too sparse to make it worth typing in, but not
285 * so large as to make a sparse array necessary. We allocate the
286 * table at runtime, initialize all entries to empty, and copy the
287 * real ones in from an initialization table.
288 *
289 * NOTE: In this table, the meaning of 'numops' is:
290 * 1: single operand
291 * 2: 2 operands, load instruction
292 * -2: 2 operands, store instruction
293 */
294 static struct tabent *mem_tab = NULL;
295 static struct { int opcode; char *name; char numops; } mem_init[] = {
296 #define MEM_MIN 0x80
297 0x80, "ldob", 2,
298 0x82, "stob", -2,
299 0x84, "bx", 1,
300 0x85, "balx", 2,
301 0x86, "callx", 1,
302 0x88, "ldos", 2,
303 0x8a, "stos", -2,
304 0x8c, "lda", 2,
305 0x90, "ld", 2,
306 0x92, "st", -2,
307 0x98, "ldl", 2,
308 0x9a, "stl", -2,
309 0xa0, "ldt", 2,
310 0xa2, "stt", -2,
311 0xb0, "ldq", 2,
312 0xb2, "stq", -2,
313 0xc0, "ldib", 2,
314 0xc2, "stib", -2,
315 0xc8, "ldis", 2,
316 0xca, "stis", -2,
317 #define MEM_MAX 0xca
318 #define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
319 0, NULL, 0
320 };
321
322 if ( mem_tab == NULL ){
323 mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
324 memset( (void *) mem_tab, 0, MEM_SIZ );
325 for ( i = 0; mem_init[i].opcode != 0; i++ ){
326 j = mem_init[i].opcode - MEM_MIN;
327 mem_tab[j].name = mem_init[i].name;
328 mem_tab[j].numops = mem_init[i].numops;
329 }
330 }
331
332 i = ((word1 >> 24) & 0xff) - MEM_MIN;
333 mode = (word1 >> 10) & 0xf;
334
335 if ( (mem_tab[i].name != NULL) /* Valid instruction */
336 && ((mode == 5) || (mode >=12)) ){ /* With 32-bit displacement */
337 len = 8;
338 } else {
339 len = 4;
340 }
341
342 if ( noprint ){
343 return len;
344 }
345
346 if ( (mem_tab[i].name == NULL) || (mode == 6) ){
347 invalid( word1 );
348 return len;
349 }
350
351 fprintf( stream, "%s\t", mem_tab[i].name );
352
353 reg1 = reg_names[ (word1 >> 19) & 0x1f ]; /* MEMB only */
354 reg2 = reg_names[ (word1 >> 14) & 0x1f ];
355 reg3 = reg_names[ word1 & 0x1f ]; /* MEMB only */
356 offset = word1 & 0xfff; /* MEMA only */
357
358 switch ( mem_tab[i].numops ){
359
360 case 2: /* LOAD INSTRUCTION */
361 if ( mode & 4 ){ /* MEMB FORMAT */
362 ea( memaddr, mode, reg2, reg3, word1, word2 );
363 fprintf( stream, ",%s", reg1 );
364 } else { /* MEMA FORMAT */
365 fprintf( stream, "0x%x", (unsigned) offset );
366 if (mode & 8) {
367 fprintf( stream, "(%s)", reg2 );
368 }
369 fprintf( stream, ",%s", reg1 );
370 }
371 break;
372
373 case -2: /* STORE INSTRUCTION */
374 if ( mode & 4 ){ /* MEMB FORMAT */
375 fprintf( stream, "%s,", reg1 );
376 ea( memaddr, mode, reg2, reg3, word1, word2 );
377 } else { /* MEMA FORMAT */
378 fprintf( stream, "%s,0x%x", reg1, (unsigned) offset );
379 if (mode & 8) {
380 fprintf( stream, "(%s)", reg2 );
381 }
382 }
383 break;
384
385 case 1: /* BX/CALLX INSTRUCTION */
386 if ( mode & 4 ){ /* MEMB FORMAT */
387 ea( memaddr, mode, reg2, reg3, word1, word2 );
388 } else { /* MEMA FORMAT */
389 fprintf( stream, "0x%x", (unsigned) offset );
390 if (mode & 8) {
391 fprintf( stream, "(%s)", reg2 );
392 }
393 }
394 break;
395 }
396
397 return len;
398 }
399
400 /****************************************/
401 /* REG format */
402 /****************************************/
403 static void
404 reg( word1 )
405 unsigned long word1;
406 {
407 int i, j;
408 int opcode;
409 int fp;
410 int m1, m2, m3;
411 int s1, s2;
412 int src, src2, dst;
413 char *mnemp;
414
415 /* This lookup table is too sparse to make it worth typing in, but not
416 * so large as to make a sparse array necessary. We allocate the
417 * table at runtime, initialize all entries to empty, and copy the
418 * real ones in from an initialization table.
419 *
420 * NOTE: In this table, the meaning of 'numops' is:
421 * 1: single operand, which is NOT a destination.
422 * -1: single operand, which IS a destination.
423 * 2: 2 operands, the 2nd of which is NOT a destination.
424 * -2: 2 operands, the 2nd of which IS a destination.
425 * 3: 3 operands
426 *
427 * If an opcode mnemonic begins with "F", it is a floating-point
428 * opcode (the "F" is not printed).
429 */
430
431 static struct tabent *reg_tab = NULL;
432 static struct { int opcode; char *name; char numops; } reg_init[] = {
433 #define REG_MIN 0x580
434 0x580, "notbit", 3,
435 0x581, "and", 3,
436 0x582, "andnot", 3,
437 0x583, "setbit", 3,
438 0x584, "notand", 3,
439 0x586, "xor", 3,
440 0x587, "or", 3,
441 0x588, "nor", 3,
442 0x589, "xnor", 3,
443 0x58a, "not", -2,
444 0x58b, "ornot", 3,
445 0x58c, "clrbit", 3,
446 0x58d, "notor", 3,
447 0x58e, "nand", 3,
448 0x58f, "alterbit", 3,
449 0x590, "addo", 3,
450 0x591, "addi", 3,
451 0x592, "subo", 3,
452 0x593, "subi", 3,
453 0x598, "shro", 3,
454 0x59a, "shrdi", 3,
455 0x59b, "shri", 3,
456 0x59c, "shlo", 3,
457 0x59d, "rotate", 3,
458 0x59e, "shli", 3,
459 0x5a0, "cmpo", 2,
460 0x5a1, "cmpi", 2,
461 0x5a2, "concmpo", 2,
462 0x5a3, "concmpi", 2,
463 0x5a4, "cmpinco", 3,
464 0x5a5, "cmpinci", 3,
465 0x5a6, "cmpdeco", 3,
466 0x5a7, "cmpdeci", 3,
467 0x5ac, "scanbyte", 2,
468 0x5ae, "chkbit", 2,
469 0x5b0, "addc", 3,
470 0x5b2, "subc", 3,
471 0x5cc, "mov", -2,
472 0x5d8, "eshro", 3,
473 0x5dc, "movl", -2,
474 0x5ec, "movt", -2,
475 0x5fc, "movq", -2,
476 0x600, "synmov", 2,
477 0x601, "synmovl", 2,
478 0x602, "synmovq", 2,
479 0x603, "cmpstr", 3,
480 0x604, "movqstr", 3,
481 0x605, "movstr", 3,
482 0x610, "atmod", 3,
483 0x612, "atadd", 3,
484 0x613, "inspacc", -2,
485 0x614, "ldphy", -2,
486 0x615, "synld", -2,
487 0x617, "fill", 3,
488 0x630, "sdma", 3,
489 0x631, "udma", 0,
490 0x640, "spanbit", -2,
491 0x641, "scanbit", -2,
492 0x642, "daddc", 3,
493 0x643, "dsubc", 3,
494 0x644, "dmovt", -2,
495 0x645, "modac", 3,
496 0x646, "condrec", -2,
497 0x650, "modify", 3,
498 0x651, "extract", 3,
499 0x654, "modtc", 3,
500 0x655, "modpc", 3,
501 0x656, "receive", -2,
502 0x659, "sysctl", 3,
503 0x660, "calls", 1,
504 0x662, "send", 3,
505 0x663, "sendserv", 1,
506 0x664, "resumprcs", 1,
507 0x665, "schedprcs", 1,
508 0x666, "saveprcs", 0,
509 0x668, "condwait", 1,
510 0x669, "wait", 1,
511 0x66a, "signal", 1,
512 0x66b, "mark", 0,
513 0x66c, "fmark", 0,
514 0x66d, "flushreg", 0,
515 0x66f, "syncf", 0,
516 0x670, "emul", 3,
517 0x671, "ediv", 3,
518 0x673, "ldtime", -1,
519 0x674, "Fcvtir", -2,
520 0x675, "Fcvtilr", -2,
521 0x676, "Fscalerl", 3,
522 0x677, "Fscaler", 3,
523 0x680, "Fatanr", 3,
524 0x681, "Flogepr", 3,
525 0x682, "Flogr", 3,
526 0x683, "Fremr", 3,
527 0x684, "Fcmpor", 2,
528 0x685, "Fcmpr", 2,
529 0x688, "Fsqrtr", -2,
530 0x689, "Fexpr", -2,
531 0x68a, "Flogbnr", -2,
532 0x68b, "Froundr", -2,
533 0x68c, "Fsinr", -2,
534 0x68d, "Fcosr", -2,
535 0x68e, "Ftanr", -2,
536 0x68f, "Fclassr", 1,
537 0x690, "Fatanrl", 3,
538 0x691, "Flogeprl", 3,
539 0x692, "Flogrl", 3,
540 0x693, "Fremrl", 3,
541 0x694, "Fcmporl", 2,
542 0x695, "Fcmprl", 2,
543 0x698, "Fsqrtrl", -2,
544 0x699, "Fexprl", -2,
545 0x69a, "Flogbnrl", -2,
546 0x69b, "Froundrl", -2,
547 0x69c, "Fsinrl", -2,
548 0x69d, "Fcosrl", -2,
549 0x69e, "Ftanrl", -2,
550 0x69f, "Fclassrl", 1,
551 0x6c0, "Fcvtri", -2,
552 0x6c1, "Fcvtril", -2,
553 0x6c2, "Fcvtzri", -2,
554 0x6c3, "Fcvtzril", -2,
555 0x6c9, "Fmovr", -2,
556 0x6d9, "Fmovrl", -2,
557 0x6e1, "Fmovre", -2,
558 0x6e2, "Fcpysre", 3,
559 0x6e3, "Fcpyrsre", 3,
560 0x701, "mulo", 3,
561 0x708, "remo", 3,
562 0x70b, "divo", 3,
563 0x741, "muli", 3,
564 0x748, "remi", 3,
565 0x749, "modi", 3,
566 0x74b, "divi", 3,
567 0x78b, "Fdivr", 3,
568 0x78c, "Fmulr", 3,
569 0x78d, "Fsubr", 3,
570 0x78f, "Faddr", 3,
571 0x79b, "Fdivrl", 3,
572 0x79c, "Fmulrl", 3,
573 0x79d, "Fsubrl", 3,
574 0x79f, "Faddrl", 3,
575 #define REG_MAX 0x79f
576 #define REG_SIZ ((REG_MAX-REG_MIN+1) * sizeof(struct tabent))
577 0, NULL, 0
578 };
579
580 if ( reg_tab == NULL ){
581 reg_tab = (struct tabent *) xmalloc( REG_SIZ );
582 memset( (void *) reg_tab, 0, REG_SIZ );
583 for ( i = 0; reg_init[i].opcode != 0; i++ ){
584 j = reg_init[i].opcode - REG_MIN;
585 reg_tab[j].name = reg_init[i].name;
586 reg_tab[j].numops = reg_init[i].numops;
587 }
588 }
589
590 opcode = ((word1 >> 20) & 0xff0) | ((word1 >> 7) & 0xf);
591 i = opcode - REG_MIN;
592
593 if ( (opcode<REG_MIN) || (opcode>REG_MAX) || (reg_tab[i].name==NULL) ){
594 invalid( word1 );
595 return;
596 }
597
598 mnemp = reg_tab[i].name;
599 if ( *mnemp == 'F' ){
600 fp = 1;
601 mnemp++;
602 } else {
603 fp = 0;
604 }
605
606 fputs( mnemp, stream );
607
608 s1 = (word1 >> 5) & 1;
609 s2 = (word1 >> 6) & 1;
610 m1 = (word1 >> 11) & 1;
611 m2 = (word1 >> 12) & 1;
612 m3 = (word1 >> 13) & 1;
613 src = word1 & 0x1f;
614 src2 = (word1 >> 14) & 0x1f;
615 dst = (word1 >> 19) & 0x1f;
616
617 if ( reg_tab[i].numops != 0 ){
618 putc( '\t', stream );
619
620 switch ( reg_tab[i].numops ){
621 case 1:
622 regop( m1, s1, src, fp );
623 break;
624 case -1:
625 dstop( m3, dst, fp );
626 break;
627 case 2:
628 regop( m1, s1, src, fp );
629 putc( ',', stream );
630 regop( m2, s2, src2, fp );
631 break;
632 case -2:
633 regop( m1, s1, src, fp );
634 putc( ',', stream );
635 dstop( m3, dst, fp );
636 break;
637 case 3:
638 regop( m1, s1, src, fp );
639 putc( ',', stream );
640 regop( m2, s2, src2, fp );
641 putc( ',', stream );
642 dstop( m3, dst, fp );
643 break;
644 }
645 }
646 }
647
648
649 /*
650 * Print out effective address for memb instructions.
651 */
652 static void
653 ea( memaddr, mode, reg2, reg3, word1, word2 )
654 unsigned long memaddr;
655 int mode;
656 char *reg2, *reg3;
657 int word1;
658 unsigned int word2;
659 {
660 int scale;
661 static int scale_tab[] = { 1, 2, 4, 8, 16 };
662
663 scale = (word1 >> 7) & 0x07;
664 if ( (scale > 4) || ((word1 >> 5) & 0x03 != 0) ){
665 invalid( word1 );
666 return;
667 }
668 scale = scale_tab[scale];
669
670 switch (mode) {
671 case 4: /* (reg) */
672 fprintf( stream, "(%s)", reg2 );
673 break;
674 case 5: /* displ+8(ip) */
675 print_addr( word2+8+memaddr );
676 break;
677 case 7: /* (reg)[index*scale] */
678 if (scale == 1) {
679 fprintf( stream, "(%s)[%s]", reg2, reg3 );
680 } else {
681 fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale);
682 }
683 break;
684 case 12: /* displacement */
685 print_addr( word2 );
686 break;
687 case 13: /* displ(reg) */
688 print_addr( word2 );
689 fprintf( stream, "(%s)", reg2 );
690 break;
691 case 14: /* displ[index*scale] */
692 print_addr( word2 );
693 if (scale == 1) {
694 fprintf( stream, "[%s]", reg3 );
695 } else {
696 fprintf( stream, "[%s*%d]", reg3, scale );
697 }
698 break;
699 case 15: /* displ(reg)[index*scale] */
700 print_addr( word2 );
701 if (scale == 1) {
702 fprintf( stream, "(%s)[%s]", reg2, reg3 );
703 } else {
704 fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale );
705 }
706 break;
707 default:
708 invalid( word1 );
709 return;
710 }
711 }
712
713
714 /************************************************/
715 /* Register Instruction Operand */
716 /************************************************/
717 static void
718 regop( mode, spec, reg, fp )
719 int mode, spec, reg, fp;
720 {
721 if ( fp ){ /* FLOATING POINT INSTRUCTION */
722 if ( mode == 1 ){ /* FP operand */
723 switch ( reg ){
724 case 0: fputs( "fp0", stream ); break;
725 case 1: fputs( "fp1", stream ); break;
726 case 2: fputs( "fp2", stream ); break;
727 case 3: fputs( "fp3", stream ); break;
728 case 16: fputs( "0f0.0", stream ); break;
729 case 22: fputs( "0f1.0", stream ); break;
730 default: putc( '?', stream ); break;
731 }
732 } else { /* Non-FP register */
733 fputs( reg_names[reg], stream );
734 }
735 } else { /* NOT FLOATING POINT */
736 if ( mode == 1 ){ /* Literal */
737 fprintf( stream, "%d", reg );
738 } else { /* Register */
739 if ( spec == 0 ){
740 fputs( reg_names[reg], stream );
741 } else {
742 fprintf( stream, "sf%d", reg );
743 }
744 }
745 }
746 }
747
748 /************************************************/
749 /* Register Instruction Destination Operand */
750 /************************************************/
751 static void
752 dstop( mode, reg, fp )
753 int mode, reg, fp;
754 {
755 /* 'dst' operand can't be a literal. On non-FP instructions, register
756 * mode is assumed and "m3" acts as if were "s3"; on FP-instructions,
757 * sf registers are not allowed so m3 acts normally.
758 */
759 if ( fp ){
760 regop( mode, 0, reg, fp );
761 } else {
762 regop( 0, mode, reg, fp );
763 }
764 }
765
766
767 static void
768 invalid( word1 )
769 int word1;
770 {
771 fprintf( stream, ".word\t0x%08x", (unsigned) word1 );
772 }
773
774 static void
775 print_addr(a)
776 int a;
777 {
778 fprintf( stream, "0x%x", (unsigned) a );
779 }
780
781 static void
782 put_abs( word1, word2 )
783 unsigned long word1, word2;
784 {
785 #ifdef IN_GDB
786 return;
787 #else
788 int len;
789
790 switch ( (word1 >> 28) & 0xf ){
791 case 0x8:
792 case 0x9:
793 case 0xa:
794 case 0xb:
795 case 0xc:
796 /* MEM format instruction */
797 len = mem( 0, word1, word2, 1 );
798 break;
799 default:
800 len = 4;
801 break;
802 }
803
804 if ( len == 8 ){
805 fprintf( stream, "%08x %08x\t", word1, word2 );
806 } else {
807 fprintf( stream, "%08x \t", word1 );
808 }
809 ;
810
811 #endif
812 }