xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/or32-dis.c (revision d2201f2f89f0be1a0be6f7568000ed297414a06d)
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