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