use byacc instead of bison.
[deliverable/binutils-gdb.git] / binutils / i960-pinsn.c
1 /* Disassemble i80960 instructions.
2 Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Diddler.
5
6 BFD is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 BFD is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with BFD; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /* $Id$ */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "bucomm.h"
25
26 static char *reg_names[] = {
27 /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7",
28 /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
29 /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
30 /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp",
31 /* 32 */ "pc", "ac", "ip", "tc", "fp0", "fp1", "fp2", "fp3"
32 };
33
34
35 static FILE *stream; /* Output goes here */
36 static void print_addr();
37 static void ctrl();
38 static void cobr();
39 static void reg();
40 static int mem();
41 static void ea();
42 static void dstop();
43 static void regop();
44 static void invalid();
45 static int pinsn();
46 static void put_abs();
47
48
49 /* Print the i960 instruction at address 'memaddr' in debugged memory,
50 * on stream 's'. Returns length of the instruction, in bytes.
51 */
52 int
53 print_insn_i960( memaddr, buffer, s )
54 bfd_vma memaddr;
55 uint8e_type *buffer;
56 FILE *s;
57 {
58 unsigned int word1, word2;
59
60 stream = s;
61 word1 =buffer [0] |( buffer[1]<< 8) | (buffer[2] << 16) | ( buffer[3] <<24);
62 word2 =buffer [4] |( buffer[5]<< 8) | (buffer[6] << 16) | ( buffer[7] <<24);
63 return pinsn( memaddr, word1, word2 );
64 }
65 \f
66 #define IN_GDB
67
68 /*****************************************************************************
69 * All code below this point should be identical with that of
70 * the disassembler in gdmp960.
71 *****************************************************************************/
72
73 struct tabent {
74 char *name;
75 char numops;
76 };
77
78 static int
79 pinsn( memaddr, word1, word2 )
80 unsigned long memaddr;
81 unsigned long word1, word2;
82 {
83 int instr_len;
84
85 instr_len = 4;
86 put_abs( word1, word2 );
87
88 /* Divide instruction set into classes based on high 4 bits of opcode*/
89 switch ( (word1 >> 28) & 0xf ){
90 case 0x0:
91 case 0x1:
92 ctrl( memaddr, word1, word2 );
93 break;
94 case 0x2:
95 case 0x3:
96 cobr( memaddr, word1, word2 );
97 break;
98 case 0x5:
99 case 0x6:
100 case 0x7:
101 reg( word1 );
102 break;
103 case 0x8:
104 case 0x9:
105 case 0xa:
106 case 0xb:
107 case 0xc:
108 instr_len = mem( memaddr, word1, word2, 0 );
109 break;
110 default:
111 /* invalid instruction, print as data word */
112 invalid( word1 );
113 break;
114 }
115 return instr_len;
116 }
117
118 /****************************************/
119 /* CTRL format */
120 /****************************************/
121 static void
122 ctrl( memaddr, word1, word2 )
123 unsigned long memaddr;
124 unsigned long word1, word2;
125 {
126 int i;
127 static struct tabent ctrl_tab[] = {
128 NULL, 0, /* 0x00 */
129 NULL, 0, /* 0x01 */
130 NULL, 0, /* 0x02 */
131 NULL, 0, /* 0x03 */
132 NULL, 0, /* 0x04 */
133 NULL, 0, /* 0x05 */
134 NULL, 0, /* 0x06 */
135 NULL, 0, /* 0x07 */
136 "b", 1, /* 0x08 */
137 "call", 1, /* 0x09 */
138 "ret", 0, /* 0x0a */
139 "bal", 1, /* 0x0b */
140 NULL, 0, /* 0x0c */
141 NULL, 0, /* 0x0d */
142 NULL, 0, /* 0x0e */
143 NULL, 0, /* 0x0f */
144 "bno", 1, /* 0x10 */
145 "bg", 1, /* 0x11 */
146 "be", 1, /* 0x12 */
147 "bge", 1, /* 0x13 */
148 "bl", 1, /* 0x14 */
149 "bne", 1, /* 0x15 */
150 "ble", 1, /* 0x16 */
151 "bo", 1, /* 0x17 */
152 "faultno", 0, /* 0x18 */
153 "faultg", 0, /* 0x19 */
154 "faulte", 0, /* 0x1a */
155 "faultge", 0, /* 0x1b */
156 "faultl", 0, /* 0x1c */
157 "faultne", 0, /* 0x1d */
158 "faultle", 0, /* 0x1e */
159 "faulto", 0, /* 0x1f */
160 };
161
162 i = (word1 >> 24) & 0xff;
163 if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){
164 invalid( word1 );
165 return;
166 }
167
168 fputs( ctrl_tab[i].name, stream );
169 if ( word1 & 2 ){ /* Predicts branch not taken */
170 fputs( ".f", stream );
171 }
172
173 if ( ctrl_tab[i].numops == 1 ){
174 /* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */
175 word1 &= 0x00ffffff;
176 if ( word1 & 0x00800000 ){ /* Sign bit is set */
177 word1 |= (-1 & ~0xffffff); /* Sign extend */
178 }
179 putc( '\t', stream );
180 print_addr( word1 + memaddr );
181 }
182 }
183
184 /****************************************/
185 /* COBR format */
186 /****************************************/
187 static void
188 cobr( memaddr, word1, word2 )
189 unsigned long memaddr;
190 unsigned long word1, word2;
191 {
192 int src1;
193 int src2;
194 int i;
195
196 static struct tabent cobr_tab[] = {
197 "testno", 1, /* 0x20 */
198 "testg", 1, /* 0x21 */
199 "teste", 1, /* 0x22 */
200 "testge", 1, /* 0x23 */
201 "testl", 1, /* 0x24 */
202 "testne", 1, /* 0x25 */
203 "testle", 1, /* 0x26 */
204 "testo", 1, /* 0x27 */
205 NULL, 0, /* 0x28 */
206 NULL, 0, /* 0x29 */
207 NULL, 0, /* 0x2a */
208 NULL, 0, /* 0x2b */
209 NULL, 0, /* 0x2c */
210 NULL, 0, /* 0x2d */
211 NULL, 0, /* 0x2e */
212 NULL, 0, /* 0x2f */
213 "bbc", 3, /* 0x30 */
214 "cmpobg", 3, /* 0x31 */
215 "cmpobe", 3, /* 0x32 */
216 "cmpobge", 3, /* 0x33 */
217 "cmpobl", 3, /* 0x34 */
218 "cmpobne", 3, /* 0x35 */
219 "cmpoble", 3, /* 0x36 */
220 "bbs", 3, /* 0x37 */
221 "cmpibno", 3, /* 0x38 */
222 "cmpibg", 3, /* 0x39 */
223 "cmpibe", 3, /* 0x3a */
224 "cmpibge", 3, /* 0x3b */
225 "cmpibl", 3, /* 0x3c */
226 "cmpibne", 3, /* 0x3d */
227 "cmpible", 3, /* 0x3e */
228 "cmpibo", 3, /* 0x3f */
229 };
230
231 i = ((word1 >> 24) & 0xff) - 0x20;
232 if ( cobr_tab[i].name == NULL ){
233 invalid( word1 );
234 return;
235 }
236
237 fputs( cobr_tab[i].name, stream );
238 if ( word1 & 2 ){ /* Predicts branch not taken */
239 fputs( ".f", stream );
240 }
241 putc( '\t', stream );
242
243 src1 = (word1 >> 19) & 0x1f;
244 src2 = (word1 >> 14) & 0x1f;
245
246 if ( word1 & 0x02000 ){ /* M1 is 1 */
247 fprintf( stream, "%d", src1 );
248 } else { /* M1 is 0 */
249 fputs( reg_names[src1], stream );
250 }
251
252 if ( cobr_tab[i].numops > 1 ){
253 if ( word1 & 1 ){ /* S2 is 1 */
254 fprintf( stream, ",sf%d,", src2 );
255 } else { /* S1 is 0 */
256 fprintf( stream, ",%s,", reg_names[src2] );
257 }
258
259 /* Extract displacement and convert to address
260 */
261 word1 &= 0x00001ffc;
262 if ( word1 & 0x00001000 ){ /* Negative displacement */
263 word1 |= (-1 & ~0x1fff); /* Sign extend */
264 }
265 print_addr( memaddr + word1 );
266 }
267 }
268
269 /****************************************/
270 /* MEM format */
271 /****************************************/
272 static int /* returns instruction length: 4 or 8 */
273 mem( memaddr, word1, word2, noprint )
274 unsigned long memaddr;
275 unsigned long word1, word2;
276 int noprint; /* If TRUE, return instruction length, but
277 * don't output any text.
278 */
279 {
280 int i, j;
281 int len;
282 int mode;
283 int offset;
284 char *reg1, *reg2, *reg3;
285
286 /* This lookup table is too sparse to make it worth typing in, but not
287 * so large as to make a sparse array necessary. We allocate the
288 * table at runtime, initialize all entries to empty, and copy the
289 * real ones in from an initialization table.
290 *
291 * NOTE: In this table, the meaning of 'numops' is:
292 * 1: single operand
293 * 2: 2 operands, load instruction
294 * -2: 2 operands, store instruction
295 */
296 static struct tabent *mem_tab = NULL;
297 static struct { int opcode; char *name; char numops; } mem_init[] = {
298 #define MEM_MIN 0x80
299 0x80, "ldob", 2,
300 0x82, "stob", -2,
301 0x84, "bx", 1,
302 0x85, "balx", 2,
303 0x86, "callx", 1,
304 0x88, "ldos", 2,
305 0x8a, "stos", -2,
306 0x8c, "lda", 2,
307 0x90, "ld", 2,
308 0x92, "st", -2,
309 0x98, "ldl", 2,
310 0x9a, "stl", -2,
311 0xa0, "ldt", 2,
312 0xa2, "stt", -2,
313 0xb0, "ldq", 2,
314 0xb2, "stq", -2,
315 0xc0, "ldib", 2,
316 0xc2, "stib", -2,
317 0xc8, "ldis", 2,
318 0xca, "stis", -2,
319 #define MEM_MAX 0xca
320 #define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
321 0, NULL, 0
322 };
323
324 if ( mem_tab == NULL ){
325 mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
326 bzero( (void *) mem_tab, MEM_SIZ );
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 /****************************************/
405 static void
406 reg( 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 );
584 bzero( (void *) reg_tab, REG_SIZ );
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 */
654 static void
655 ea( memaddr, mode, reg2, reg3, word1, word2 )
656 unsigned long memaddr;
657 int mode;
658 char *reg2, *reg3;
659 int 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 /************************************************/
719 static void
720 regop( 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 /************************************************/
753 static void
754 dstop( 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
769 static void
770 invalid( word1 )
771 int word1;
772 {
773 fprintf( stream, ".word\t0x%08x", (unsigned) word1 );
774 }
775
776 static void
777 print_addr(a)
778 int a;
779 {
780 fprintf( stream, "0x%x", (unsigned) a );
781 }
782
783 static void
784 put_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.047651 seconds and 4 git commands to generate.