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