m88k native support
[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 }
f4e56031 289 fputs_filtered ( "\t", stream, 0 );
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;
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
f4e56031 400 fprintf_filtered ( stream, "%s\t", mem_tab[i].name );
dd3b648e
RP
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 );
f4e56031 412 fprintf_filtered ( stream, ",%s", reg1 );
dd3b648e
RP
413 } else { /* MEMA FORMAT */
414 fprintf( stream, "0x%x", offset );
415 if (mode & 8) {
f4e56031 416 fprintf_filtered ( stream, "(%s)", reg2 );
dd3b648e 417 }
f4e56031 418 fprintf_filtered ( stream, ",%s", reg1 );
dd3b648e
RP
419 }
420 break;
421
422 case -2: /* STORE INSTRUCTION */
423 if ( mode & 4 ){ /* MEMB FORMAT */
f4e56031 424 fprintf_filtered ( stream, "%s,", reg1 );
dd3b648e
RP
425 ea( memaddr, mode, reg2, reg3, word1, word2 );
426 } else { /* MEMA FORMAT */
f4e56031 427 fprintf_filtered ( stream, "%s,0x%x", reg1, offset );
dd3b648e 428 if (mode & 8) {
f4e56031 429 fprintf_filtered ( stream, "(%s)", reg2 );
dd3b648e
RP
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 */
f4e56031 438 fprintf_filtered ( stream, "0x%x", offset );
dd3b648e 439 if (mode & 8) {
f4e56031 440 fprintf_filtered( stream, "(%s)", reg2 );
dd3b648e
RP
441 }
442 }
443 break;
444 }
445
446 return len;
447}
448
449/****************************************/
450/* REG format */
451/****************************************/
452static void
453reg( 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
f4e56031 655 fputs_filtered( mnemp, stream );
dd3b648e
RP
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 ){
f4e56031 667 fputs_filtered( "\t", stream, 0 );
dd3b648e
RP
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 );
f4e56031 678 fputs_filtered( ",", stream );
dd3b648e
RP
679 regop( m2, s2, src2, fp );
680 break;
681 case -2:
682 regop( m1, s1, src, fp );
f4e56031 683 fputs_filtered( ",", stream );
dd3b648e
RP
684 dstop( m3, dst, fp );
685 break;
686 case 3:
687 regop( m1, s1, src, fp );
f4e56031 688 fputs_filtered( ",", stream );
dd3b648e 689 regop( m2, s2, src2, fp );
f4e56031 690 fputs_filtered( ",", stream );
dd3b648e
RP
691 dstop( m3, dst, fp );
692 break;
693 }
694 }
695}
696
697
698/*
699 * Print out effective address for memb instructions.
700 */
701static void
702ea( 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) */
f4e56031 720 fprintf_filtered( stream, "(%s)", reg2 );
dd3b648e
RP
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) {
f4e56031 727 fprintf_filtered( stream, "(%s)[%s]", reg2, reg3 );
dd3b648e 728 } else {
f4e56031 729 fprintf_filtered( stream, "(%s)[%s*%d]",reg2,reg3,scale);
dd3b648e
RP
730 }
731 break;
732 case 12: /* displacement */
733 print_addr( word2 );
734 break;
735 case 13: /* displ(reg) */
736 print_addr( word2 );
f4e56031 737 fprintf_filtered( stream, "(%s)", reg2 );
dd3b648e
RP
738 break;
739 case 14: /* displ[index*scale] */
740 print_addr( word2 );
741 if (scale == 1) {
f4e56031 742 fprintf_filtered( stream, "[%s]", reg3 );
dd3b648e 743 } else {
f4e56031 744 fprintf_filtered( stream, "[%s*%d]", reg3, scale );
dd3b648e
RP
745 }
746 break;
747 case 15: /* displ(reg)[index*scale] */
748 print_addr( word2 );
749 if (scale == 1) {
f4e56031 750 fprintf_filtered( stream, "(%s)[%s]", reg2, reg3 );
dd3b648e 751 } else {
f4e56031 752 fprintf_filtered( stream, "(%s)[%s*%d]",reg2,reg3,scale );
dd3b648e
RP
753 }
754 break;
755 default:
756 invalid( word1 );
757 return;
758 }
759}
760
761
762/************************************************/
763/* Register Instruction Operand */
764/************************************************/
765static void
766regop( 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 ){
f4e56031
KR
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;
dd3b648e
RP
779 }
780 } else { /* Non-FP register */
f4e56031 781 fputs_filtered( reg_names[reg], stream );
dd3b648e
RP
782 }
783 } else { /* NOT FLOATING POINT */
784 if ( mode == 1 ){ /* Literal */
f4e56031 785 fprintf_filtered( stream, "%d", reg );
dd3b648e
RP
786 } else { /* Register */
787 if ( spec == 0 ){
f4e56031 788 fputs_filtered( reg_names[reg], stream );
dd3b648e 789 } else {
f4e56031 790 fprintf_filtered( stream, "sf%d", reg );
dd3b648e
RP
791 }
792 }
793 }
794}
795
796/************************************************/
797/* Register Instruction Destination Operand */
798/************************************************/
799static void
800dstop( 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
815static void
816invalid( word1 )
817 int word1;
818{
f4e56031 819 fprintf_filtered( stream, ".word\t0x%08x", word1 );
dd3b648e
RP
820}
821
822static void
823print_addr(a)
824{
7eec00ed 825 print_address (a, stream);
dd3b648e
RP
826}
827
828static void
829put_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 ){
f4e56031 852 fprintf_filtered( stream, "%08x %08x\t", word1, word2 );
dd3b648e 853 } else {
f4e56031 854 fprintf_filtered( stream, "%08x \t", word1 );
dd3b648e
RP
855 }
856;
857
858#endif
859}
This page took 0.100235 seconds and 4 git commands to generate.