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