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