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