Fix build with -DDEBUG=7
[deliverable/binutils-gdb.git] / opcodes / or32-dis.c
CommitLineData
3b16e843 1/* Instruction printing code for the OpenRISC 1000
9b201bb5 2 Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
3b16e843
NC
3 Contributed by Damjan Lampret <lampret@opencores.org>.
4 Modified from a29k port.
5
9b201bb5 6 This file is part of the GNU opcodes library.
3b16e843 7
9b201bb5 8 This library is free software; you can redistribute it and/or modify
3b16e843 9 it under the terms of the GNU General Public License as published by
9b201bb5
NC
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
3b16e843 12
9b201bb5
NC
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
3b16e843
NC
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
47b0e7ad
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
3b16e843 22
9ccb8af9 23#ifndef DEBUG
3b16e843 24#define DEBUG 0
9ccb8af9 25#endif
3b16e843
NC
26
27#include "dis-asm.h"
28#include "opcode/or32.h"
29#include "safe-ctype.h"
30#include <string.h>
5e37cc46 31#include <stdlib.h>
3b16e843 32
5e37cc46 33#define EXTEND29(x) ((x) & (unsigned long) 0x10000000 ? ((x) | (unsigned long) 0xf0000000) : ((x)))
3b16e843 34
3b16e843
NC
35/* Now find the four bytes of INSN_CH and put them in *INSN. */
36
37static void
47b0e7ad 38find_bytes_big (unsigned char *insn_ch, unsigned long *insn)
3b16e843
NC
39{
40 *insn =
41 ((unsigned long) insn_ch[0] << 24) +
42 ((unsigned long) insn_ch[1] << 16) +
43 ((unsigned long) insn_ch[2] << 8) +
44 ((unsigned long) insn_ch[3]);
45#if DEBUG
9ccb8af9 46 printf ("find_bytes_big3: %lx\n", *insn);
3b16e843
NC
47#endif
48}
49
50static void
47b0e7ad 51find_bytes_little (unsigned char *insn_ch, unsigned long *insn)
3b16e843
NC
52{
53 *insn =
54 ((unsigned long) insn_ch[3] << 24) +
55 ((unsigned long) insn_ch[2] << 16) +
56 ((unsigned long) insn_ch[1] << 8) +
57 ((unsigned long) insn_ch[0]);
58}
59
47b0e7ad 60typedef void (*find_byte_func_type) (unsigned char *, unsigned long *);
3b16e843
NC
61
62static unsigned long
47b0e7ad 63or32_extract (char param_ch, char *enc_initial, unsigned long insn)
3b16e843
NC
64{
65 char *enc;
66 unsigned long ret = 0;
67 int opc_pos = 0;
68 int param_pos = 0;
69
70 for (enc = enc_initial; *enc != '\0'; enc++)
71 if (*enc == param_ch)
5e37cc46
NC
72 {
73 if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
74 continue;
75 else
76 param_pos++;
77 }
3b16e843
NC
78
79#if DEBUG
80 printf ("or32_extract: %c %x ", param_ch, param_pos);
81#endif
82 opc_pos = 32;
83
84 for (enc = enc_initial; *enc != '\0'; )
85 if ((*enc == '0') && (*(enc + 1) == 'x'))
86 {
87 opc_pos -= 4;
88
89 if ((param_ch == '0') || (param_ch == '1'))
90 {
5e37cc46 91 unsigned long tmp = strtoul (enc, NULL, 16);
3b16e843 92#if DEBUG
9ccb8af9 93 printf (" enc=%s, tmp=%lx ", enc, tmp);
3b16e843
NC
94#endif
95 if (param_ch == '0')
96 tmp = 15 - tmp;
97 ret |= tmp << opc_pos;
98 }
99 enc += 3;
100 }
101 else if ((*enc == '0') || (*enc == '1'))
102 {
103 opc_pos--;
104 if (param_ch == *enc)
105 ret |= 1 << opc_pos;
106 enc++;
107 }
108 else if (*enc == param_ch)
109 {
110 opc_pos--;
111 param_pos--;
112#if DEBUG
9ccb8af9 113 printf ("\n ret=%lx opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
3b16e843
NC
114#endif
115 ret += ((insn >> opc_pos) & 0x1) << param_pos;
116
117 if (!param_pos
118 && letter_signed (param_ch)
5e37cc46 119 && ret >> (letter_range (param_ch) - 1))
3b16e843
NC
120 {
121#if DEBUG
9ccb8af9 122 printf ("\n ret=%lx opc_pos=%x, param_pos=%x\n",
3b16e843
NC
123 ret, opc_pos, param_pos);
124#endif
125 ret |= 0xffffffff << letter_range(param_ch);
126#if DEBUG
9ccb8af9 127 printf ("\n after conversion to signed: ret=%lx\n", ret);
3b16e843
NC
128#endif
129 }
130 enc++;
131 }
132 else if (ISALPHA (*enc))
133 {
134 opc_pos--;
135 enc++;
136 }
137 else if (*enc == '-')
138 {
139 opc_pos--;
140 enc++;
141 }
142 else
143 enc++;
144
145#if DEBUG
9ccb8af9 146 printf ("ret=%lx\n", ret);
3b16e843
NC
147#endif
148 return ret;
149}
150
151static int
47b0e7ad 152or32_opcode_match (unsigned long insn, char *encoding)
3b16e843
NC
153{
154 unsigned long ones, zeros;
155
156#if DEBUG
157 printf ("or32_opcode_match: %.8lx\n", insn);
158#endif
159 ones = or32_extract ('1', encoding, insn);
160 zeros = or32_extract ('0', encoding, insn);
161
162#if DEBUG
9ccb8af9
AM
163 printf ("ones: %lx \n", ones);
164 printf ("zeros: %lx \n", zeros);
3b16e843
NC
165#endif
166 if ((insn & ones) != ones)
167 {
168#if DEBUG
169 printf ("ret1\n");
170#endif
171 return 0;
172 }
173
174 if ((~insn & zeros) != zeros)
175 {
176#if DEBUG
177 printf ("ret2\n");
178#endif
179 return 0;
180 }
181
182#if DEBUG
183 printf ("ret3\n");
184#endif
185 return 1;
186}
187
188/* Print register to INFO->STREAM. Used only by print_insn. */
189
190static void
47b0e7ad
NC
191or32_print_register (char param_ch,
192 char *encoding,
193 unsigned long insn,
194 struct disassemble_info *info)
3b16e843
NC
195{
196 int regnum = or32_extract (param_ch, encoding, insn);
197
198#if DEBUG
9ccb8af9 199 printf ("or32_print_register: %c, %s, %lx\n", param_ch, encoding, insn);
3b16e843
NC
200#endif
201 if (param_ch == 'A')
202 (*info->fprintf_func) (info->stream, "r%d", regnum);
203 else if (param_ch == 'B')
204 (*info->fprintf_func) (info->stream, "r%d", regnum);
205 else if (param_ch == 'D')
206 (*info->fprintf_func) (info->stream, "r%d", regnum);
207 else if (regnum < 16)
208 (*info->fprintf_func) (info->stream, "r%d", regnum);
209 else if (regnum < 32)
210 (*info->fprintf_func) (info->stream, "r%d", regnum-16);
211 else
212 (*info->fprintf_func) (info->stream, "X%d", regnum);
213}
214
215/* Print immediate to INFO->STREAM. Used only by print_insn. */
216
217static void
47b0e7ad
NC
218or32_print_immediate (char param_ch,
219 char *encoding,
220 unsigned long insn,
221 struct disassemble_info *info)
3b16e843
NC
222{
223 int imm = or32_extract(param_ch, encoding, insn);
224
225 if (letter_signed(param_ch))
226 (*info->fprintf_func) (info->stream, "0x%x", imm);
227/* (*info->fprintf_func) (info->stream, "%d", imm); */
228 else
229 (*info->fprintf_func) (info->stream, "0x%x", imm);
230}
231
232/* Print one instruction from MEMADDR on INFO->STREAM.
233 Return the size of the instruction (always 4 on or32). */
234
235static int
47b0e7ad 236print_insn (bfd_vma memaddr, struct disassemble_info *info)
3b16e843
NC
237{
238 /* The raw instruction. */
239 unsigned char insn_ch[4];
240 /* Address. Will be sign extened 27-bit. */
5e37cc46 241 unsigned long addr;
3b16e843
NC
242 /* The four bytes of the instruction. */
243 unsigned long insn;
47b0e7ad 244 find_byte_func_type find_byte_func = (find_byte_func_type) info->private_data;
56da5fed 245 struct or32_opcode const * opcode;
3b16e843
NC
246
247 {
248 int status =
249 (*info->read_memory_func) (memaddr, (bfd_byte *) &insn_ch[0], 4, info);
250
251 if (status != 0)
252 {
253 (*info->memory_error_func) (status, memaddr, info);
254 return -1;
255 }
256 }
257
258 (*find_byte_func) (&insn_ch[0], &insn);
259
260 for (opcode = &or32_opcodes[0];
261 opcode < &or32_opcodes[or32_num_opcodes];
262 ++opcode)
263 {
264 if (or32_opcode_match (insn, opcode->encoding))
265 {
266 char *s;
267
268 (*info->fprintf_func) (info->stream, "%s ", opcode->name);
269
270 for (s = opcode->args; *s != '\0'; ++s)
271 {
272 switch (*s)
273 {
274 case '\0':
275 return 4;
276
277 case 'r':
278 or32_print_register (*++s, opcode->encoding, insn, info);
279 break;
280
281 case 'X':
282 addr = or32_extract ('X', opcode->encoding, insn) << 2;
283
284 /* Calulate the correct address. XXX is this really correct ?? */
285 addr = memaddr + EXTEND29 (addr);
286
287 (*info->print_address_func)
288 (addr, info);
289 break;
290
291 default:
292 if (strchr (opcode->encoding, *s))
293 or32_print_immediate (*s, opcode->encoding, insn, info);
294 else
295 (*info->fprintf_func) (info->stream, "%c", *s);
296 }
297 }
298
299 return 4;
300 }
301 }
302
303 /* This used to be %8x for binutils. */
304 (*info->fprintf_func)
0fd3a477 305 (info->stream, ".word 0x%08lx", insn);
3b16e843
NC
306 return 4;
307}
308
309/* Disassemble a big-endian or32 instruction. */
310
311int
47b0e7ad 312print_insn_big_or32 (bfd_vma memaddr, struct disassemble_info *info)
3b16e843 313{
47b0e7ad
NC
314 info->private_data = find_bytes_big;
315
3b16e843
NC
316 return print_insn (memaddr, info);
317}
318
319/* Disassemble a little-endian or32 instruction. */
320
321int
47b0e7ad 322print_insn_little_or32 (bfd_vma memaddr, struct disassemble_info *info)
3b16e843 323{
47b0e7ad 324 info->private_data = find_bytes_little;
3b16e843
NC
325 return print_insn (memaddr, info);
326}
This page took 0.410062 seconds and 4 git commands to generate.