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