1 /* Print IBM RS/6000 instructions for GNU software.
2 Copyright 1991 Free Software Foundation, Inc.
3 Contributed by IBM Corporation.
5 This file is part of GDB and the GNU binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #include "opcode/rs6k.h"
24 /* Print the rs6k instruction at address MEMADDR in debugged memory,
25 on STREAM. Returns length of the instruction, in bytes. */
28 print_insn (memaddr
, stream
)
32 int pop
, eop
, probable_eop
; /* primary and extended opcodes */
34 int best
= -1; /* found best opcode index */
36 unsigned int the_insn
;
38 read_memory (memaddr
, &the_insn
, sizeof (the_insn
));
39 pop
= (unsigned)(the_insn
>> 26);
40 min
= 0, max
= NOPCODES
-1;
43 best
= (min
+ max
) / 2;
45 /* see if we are running in loops */
50 if (pop
< rs6k_ops
[best
].p_opcode
)
53 else if (pop
> rs6k_ops
[best
].p_opcode
)
57 /* Opcode matched, check extended opcode. */
59 if (rs6k_ops
[best
].e_opcode
== -1) {
60 /* there is no valid extended opcode, what we've got is
65 /* Largest possible value of extended opcode. */
66 probable_eop
= ((the_insn
) >> 1) & 0x3ff;
68 eop
= probable_eop
& eopMask
[rs6k_ops
[best
].format
];
70 if (eop
< rs6k_ops
[best
].e_opcode
) {
72 while (pop
== rs6k_ops
[best
].p_opcode
) {
73 if (eop
== rs6k_ops
[best
].e_opcode
) /* found it! */
76 eop
= probable_eop
& eopMask
[rs6k_ops
[best
].format
];
81 else if (eop
> rs6k_ops
[best
].e_opcode
) {
83 while (pop
== rs6k_ops
[best
].p_opcode
) {
84 if (eop
== rs6k_ops
[best
].e_opcode
) /* found it! */
87 eop
= probable_eop
& eopMask
[rs6k_ops
[best
].format
];
92 else /* eop == rs6k_ops [best].e_opcode */
98 if (pop
== rs6k_ops
[best
].p_opcode
&&
99 (rs6k_ops
[best
].e_opcode
== -1 || rs6k_ops
[best
].e_opcode
== eop
))
107 print_operator (stream
, memaddr
, the_insn
, best
);
111 fprintf_unfiltered (stream
, "0x%08x", the_insn
);
117 /* condition code names */
118 static char *cond_code
[] = {
119 "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", "nl", "ng", "z", "nz" };
122 print_operator (stream
, memaddr
, insn_word
, insn_no
)
130 char *pp
= rs6k_ops
[insn_no
].opr_ext
;
132 int nocomma
= 0; /* true if no comma needed */
149 if ((insn_word
& 0x03e00000) == 0x01800000)
154 if ((insn_word
& 0x03e00000) == 0x00800000)
164 if (insn_word
& 0x4000)
168 case '1': /* exception #1 for bb/bc ambiguity */
169 tmp
= (insn_word
>> 21) & 0x1f; /* extract BO */
170 if (tmp
!= 0xc && tmp
!= 0x4) {
171 /* you can't use `bb' now. switch to `bc' */
174 pp
= rs6k_ops
[insn_no
].opr_ext
;
187 fprintf_unfiltered (stream
, "%s%s\t", rs6k_ops
[insn_no
].operator, buf
);
189 /* parse the operand now. */
190 pp
= rs6k_ops
[insn_no
].oprnd_format
;
195 fprintf_unfiltered (stream
, "%d", (insn_word
>> 21) & 0x1f);
200 fprintf_unfiltered (stream
, "r%d", (insn_word
>> 21) & 0x1f);
204 tmp
= (insn_word
>> 16) & 0x1f;
206 /* This is wrong, wrong, wrong. The condition code only goes
207 from 0 to 3 (for the instructions which can use extended
208 mnemonics of this type), and the XX (lt, gt, eq etc.) goes
209 into the mnemonic, not as an operand.
211 Probably the best way to get this right in both assembler
212 and disassembler is to switch to a match/lose style opcode
213 table like the sparc. */
215 fprintf_unfiltered (stream
, "{unknown cond code: 0x%x}", insn_word
);
218 fprintf_unfiltered (stream
, "%s", cond_code
[tmp
]);
220 /* So for just always use the "bbf/bbt" form. This is perfectly
221 correct, just not necessarily as legible.
223 If tmp is not in the range 0-3, we can't use an XX form anyway. */
224 fprintf_unfiltered (stream
, "%d", tmp
);
230 tmp
= (insn_word
& 0xfffc);
231 if (tmp
& 0x8000) /* fix sign extension */
234 if ((insn_word
& 0x2) == 0) /* if AA not set */
237 print_address (tmp
, stream
);
241 tmp
= insn_word
& 0x03fffffc;
245 if ((insn_word
& 0x2) == 0) /* if no AA bit set */
248 print_address (tmp
, stream
);
251 case LEV
: /* for svc only */
252 if (insn_word
& 0x2) { /* SA is set */
256 fprintf_unfiltered (stream
, "%d", (insn_word
>> 5) & 0x7f);
259 case FL1
: /* for svc only */
260 if (insn_word
& 0x2) { /* SA is set */
264 fprintf_unfiltered (stream
, "%d", (insn_word
>> 12) & 0xf);
267 case FL2
: /* for svc only */
269 if (insn_word
& 0x2) /* SA is set */
270 fprintf_unfiltered (stream
, "%d", (insn_word
>> 2) & 0x3fff);
272 fprintf_unfiltered (stream
, "%d", (insn_word
>> 2) & 0x7);
277 fprintf_unfiltered (stream
, "r%d)", (insn_word
>> 16) & 0x1f);
281 fprintf_unfiltered (stream
, "r%d", (insn_word
>> 16) & 0x1f);
285 fprintf_unfiltered (stream
, "r%d", (insn_word
>> 11) & 0x1f);
289 tmp
= insn_word
& 0xffff;
292 fprintf_unfiltered (stream
, "%d", tmp
);
296 fprintf_unfiltered (stream
, "%d", insn_word
& 0xffff);
300 fprintf_unfiltered (stream
, "%d", (insn_word
>> 23) & 0x7);
304 fprintf_unfiltered (stream
, "%d", (insn_word
>> 18) & 0x7);
308 fprintf_unfiltered (stream
, "%d", (insn_word
>> 21) & 0x1f);
312 fprintf_unfiltered (stream
, "%d", (insn_word
>> 16) & 0x1f);
316 fprintf_unfiltered (stream
, "%d", (insn_word
>> 11) & 0x1f);
320 fprintf_unfiltered (stream
, "%d", (insn_word
>> 21) & 0x1f);
324 fprintf_unfiltered (stream
, "%d", (insn_word
>> 16) & 0x1f);
328 fprintf_unfiltered (stream
, "%d", (insn_word
>> 11) & 0x1f);
332 fprintf_unfiltered (stream
, "0x%x", (insn_word
>> 6) & 0x1f);
336 fprintf_unfiltered (stream
, "0x%x", (insn_word
>> 1) & 0x1f);
340 fprintf_unfiltered (stream
, "%d", (insn_word
>> 16) & 0x1f);
345 tmp
= insn_word
& 0xffff;
348 fprintf_unfiltered (stream
, "%d(", tmp
);
352 fprintf_unfiltered (stream
, "0x%x", (insn_word
>> 12) & 0xff);
357 fprintf_unfiltered (stream
, "f%d", (insn_word
>> 21) & 0x1f);
361 fprintf_unfiltered (stream
, "f%d", (insn_word
>> 16) & 0x1f);
365 fprintf_unfiltered (stream
, "f%d", (insn_word
>> 11) & 0x1f);
369 fprintf_unfiltered (stream
, "f%d", (insn_word
>> 6) & 0x1f);
373 fprintf_unfiltered (stream
, "0x%x", (insn_word
>> 17) & 0xff);
377 fprintf_unfiltered (stream
, "%d", (insn_word
>> 11) & 0x1f);
381 fprintf_unfiltered (stream
, "%d", (insn_word
>> 12) & 0xf);
385 fprintf_unfiltered (stream
,
386 "{Internal error: Unknown operand format identifier %d}",
391 if (*pp
!= '\0' && !nocomma
)
392 fputc_unfiltered(',', stream
);
This page took 0.038484 seconds and 4 git commands to generate.