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