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