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