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