* symtab.c (find_pc_symtab): some object file formats, notably mips,
[deliverable/binutils-gdb.git] / gdb / i960-pinsn.c
CommitLineData
609756e2 1/* i80960 instruction disassembler for GDB.
609f87d4 2 Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
609756e2
JG
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
dd3b648e 19
dd3b648e 20#include "defs.h"
dd3b648e
RP
21#include "frame.h"
22#include "inferior.h"
23
dd3b648e
RP
24static FILE *stream; /* Output goes here */
25static void print_addr();
26static void ctrl();
27static void cobr();
28static void reg();
29static int mem();
30static void ea();
31static void dstop();
32static void regop();
33static void invalid();
34static int pinsn();
35static 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. */
40int
41print_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
60CORE_ADDR
61next_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
120struct tabent {
121 char *name;
122 char numops;
123};
124
125static int
126pinsn( 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/****************************************/
169static void
170ctrl( 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
f4e56031 216 fputs_filtered( ctrl_tab[i].name, stream );
dd3b648e 217 if ( word1 & 2 ){ /* Predicts branch not taken */
f4e56031 218 fputs_filtered ( ".f", stream );
dd3b648e
RP
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 }
f4e56031 227 fputs_filtered ( "\t", stream );
dd3b648e
RP
228 print_addr( word1 + memaddr );
229 }
230}
231
232/****************************************/
233/* COBR format */
234/****************************************/
235static void
236cobr( 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 */
f4e56031 287 fputs_filtered ( ".f", stream );
dd3b648e 288 }
36e0df23 289 fputs_filtered ( "\t", stream );
dd3b648e
RP
290
291 src1 = (word1 >> 19) & 0x1f;
292 src2 = (word1 >> 14) & 0x1f;
293
294 if ( word1 & 0x02000 ){ /* M1 is 1 */
f4e56031 295 fprintf_filtered ( stream, "%d", src1 );
dd3b648e 296 } else { /* M1 is 0 */
f4e56031 297 fputs_filtered ( reg_names[src1], stream );
dd3b648e
RP
298 }
299
300 if ( cobr_tab[i].numops > 1 ){
301 if ( word1 & 1 ){ /* S2 is 1 */
f4e56031 302 fprintf_filtered ( stream, ",sf%d,", src2 );
dd3b648e 303 } else { /* S1 is 0 */
f4e56031 304 fprintf_filtered ( stream, ",%s,", reg_names[src2] );
dd3b648e
RP
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/****************************************/
320static int /* returns instruction length: 4 or 8 */
321mem( 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;
b52373a2 331 const char *reg1, *reg2, *reg3;
dd3b648e
RP
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;
8a96d79b 344/* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table. */
dd3b648e 345#define MEM_MIN 0x80
8a96d79b
JG
346#define MEM_MAX 0xcf
347#define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
348
349 static struct { int opcode; char *name; char numops; } mem_init[] = {
dd3b648e
RP
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,
dd3b648e
RP
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
f4e56031 402 fprintf_filtered ( stream, "%s\t", mem_tab[i].name );
dd3b648e
RP
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 );
f4e56031 414 fprintf_filtered ( stream, ",%s", reg1 );
dd3b648e
RP
415 } else { /* MEMA FORMAT */
416 fprintf( stream, "0x%x", offset );
417 if (mode & 8) {
f4e56031 418 fprintf_filtered ( stream, "(%s)", reg2 );
dd3b648e 419 }
f4e56031 420 fprintf_filtered ( stream, ",%s", reg1 );
dd3b648e
RP
421 }
422 break;
423
424 case -2: /* STORE INSTRUCTION */
425 if ( mode & 4 ){ /* MEMB FORMAT */
f4e56031 426 fprintf_filtered ( stream, "%s,", reg1 );
dd3b648e
RP
427 ea( memaddr, mode, reg2, reg3, word1, word2 );
428 } else { /* MEMA FORMAT */
f4e56031 429 fprintf_filtered ( stream, "%s,0x%x", reg1, offset );
dd3b648e 430 if (mode & 8) {
f4e56031 431 fprintf_filtered ( stream, "(%s)", reg2 );
dd3b648e
RP
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 */
f4e56031 440 fprintf_filtered ( stream, "0x%x", offset );
dd3b648e 441 if (mode & 8) {
f4e56031 442 fprintf_filtered( stream, "(%s)", reg2 );
dd3b648e
RP
443 }
444 }
445 break;
446 }
447
448 return len;
449}
450
451/****************************************/
452/* REG format */
453/****************************************/
454static void
455reg( 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
f4e56031 657 fputs_filtered( mnemp, stream );
dd3b648e
RP
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 ){
36e0df23 669 fputs_filtered( "\t", stream );
dd3b648e
RP
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 );
f4e56031 680 fputs_filtered( ",", stream );
dd3b648e
RP
681 regop( m2, s2, src2, fp );
682 break;
683 case -2:
684 regop( m1, s1, src, fp );
f4e56031 685 fputs_filtered( ",", stream );
dd3b648e
RP
686 dstop( m3, dst, fp );
687 break;
688 case 3:
689 regop( m1, s1, src, fp );
f4e56031 690 fputs_filtered( ",", stream );
dd3b648e 691 regop( m2, s2, src2, fp );
f4e56031 692 fputs_filtered( ",", stream );
dd3b648e
RP
693 dstop( m3, dst, fp );
694 break;
695 }
696 }
697}
698
699
700/*
701 * Print out effective address for memb instructions.
702 */
703static void
704ea( 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) */
f4e56031 722 fprintf_filtered( stream, "(%s)", reg2 );
dd3b648e
RP
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) {
f4e56031 729 fprintf_filtered( stream, "(%s)[%s]", reg2, reg3 );
dd3b648e 730 } else {
f4e56031 731 fprintf_filtered( stream, "(%s)[%s*%d]",reg2,reg3,scale);
dd3b648e
RP
732 }
733 break;
734 case 12: /* displacement */
735 print_addr( word2 );
736 break;
737 case 13: /* displ(reg) */
738 print_addr( word2 );
f4e56031 739 fprintf_filtered( stream, "(%s)", reg2 );
dd3b648e
RP
740 break;
741 case 14: /* displ[index*scale] */
742 print_addr( word2 );
743 if (scale == 1) {
f4e56031 744 fprintf_filtered( stream, "[%s]", reg3 );
dd3b648e 745 } else {
f4e56031 746 fprintf_filtered( stream, "[%s*%d]", reg3, scale );
dd3b648e
RP
747 }
748 break;
749 case 15: /* displ(reg)[index*scale] */
750 print_addr( word2 );
751 if (scale == 1) {
f4e56031 752 fprintf_filtered( stream, "(%s)[%s]", reg2, reg3 );
dd3b648e 753 } else {
f4e56031 754 fprintf_filtered( stream, "(%s)[%s*%d]",reg2,reg3,scale );
dd3b648e
RP
755 }
756 break;
757 default:
758 invalid( word1 );
759 return;
760 }
761}
762
763
764/************************************************/
765/* Register Instruction Operand */
766/************************************************/
767static void
768regop( 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 ){
f4e56031
KR
774 case 0: fputs_filtered( "fp0", stream ); break;
775 case 1: fputs_filtered( "fp1", stream ); break;
776 case 2: fputs_filtered( "fp2", stream ); break;
777 case 3: fputs_filtered( "fp3", stream ); break;
778 case 16: fputs_filtered( "0f0.0", stream ); break;
779 case 22: fputs_filtered( "0f1.0", stream ); break;
780 default: fputs_filtered( "?", stream ); break;
dd3b648e
RP
781 }
782 } else { /* Non-FP register */
f4e56031 783 fputs_filtered( reg_names[reg], stream );
dd3b648e
RP
784 }
785 } else { /* NOT FLOATING POINT */
786 if ( mode == 1 ){ /* Literal */
f4e56031 787 fprintf_filtered( stream, "%d", reg );
dd3b648e
RP
788 } else { /* Register */
789 if ( spec == 0 ){
f4e56031 790 fputs_filtered( reg_names[reg], stream );
dd3b648e 791 } else {
f4e56031 792 fprintf_filtered( stream, "sf%d", reg );
dd3b648e
RP
793 }
794 }
795 }
796}
797
798/************************************************/
799/* Register Instruction Destination Operand */
800/************************************************/
801static void
802dstop( 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
817static void
818invalid( word1 )
819 int word1;
820{
f4e56031 821 fprintf_filtered( stream, ".word\t0x%08x", word1 );
dd3b648e
RP
822}
823
824static void
825print_addr(a)
826{
7eec00ed 827 print_address (a, stream);
dd3b648e
RP
828}
829
830static void
831put_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 ){
f4e56031 854 fprintf_filtered( stream, "%08x %08x\t", word1, word2 );
dd3b648e 855 } else {
f4e56031 856 fprintf_filtered( stream, "%08x \t", word1 );
dd3b648e
RP
857 }
858;
859
860#endif
861}
This page took 0.114205 seconds and 4 git commands to generate.