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