1 /* Disassemble h8500 instructions.
2    Copyright 1993, 1998, 2000, 2001, 2002, 2004, 2005, 2007, 2012
3    Free Software Foundation, Inc.
4 
5    This file is part of the GNU opcodes library.
6 
7    This library is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    It is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include <stdio.h>
24 
25 #define DISASSEMBLER_TABLE
26 #define DEFINE_TABLE
27 
28 #include "h8500-opc.h"
29 #include "dis-asm.h"
30 #include "opintl.h"
31 
32 /* Maximum length of an instruction.  */
33 #define MAXLEN 8
34 
35 #include <setjmp.h>
36 
37 struct private
38 {
39   /* Points to first byte not fetched.  */
40   bfd_byte *max_fetched;
41   bfd_byte the_buffer[MAXLEN];
42   bfd_vma insn_start;
43   jmp_buf bailout;
44 };
45 
46 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
47    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
48    on error.  */
49 #define FETCH_DATA(info, addr) \
50   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
51    ? 1 : fetch_data ((info), (addr)))
52 
53 static int
fetch_data(struct disassemble_info * info,bfd_byte * addr)54 fetch_data (struct disassemble_info *info, bfd_byte *addr)
55 {
56   int status;
57   struct private *priv = (struct private *) info->private_data;
58   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
59 
60   status = (*info->read_memory_func) (start,
61 				      priv->max_fetched,
62 				      addr - priv->max_fetched,
63 				      info);
64   if (status != 0)
65     {
66       (*info->memory_error_func) (status, start, info);
67       longjmp (priv->bailout, 1);
68     }
69   else
70     priv->max_fetched = addr;
71   return 1;
72 }
73 
74 static char *crname[] = { "sr", "ccr", "*", "br", "ep", "dp", "*", "tp" };
75 
76 int
print_insn_h8500(bfd_vma addr,disassemble_info * info)77 print_insn_h8500 (bfd_vma addr, disassemble_info *info)
78 {
79   const h8500_opcode_info *opcode;
80   void *stream = info->stream;
81   fprintf_ftype func = info->fprintf_func;
82   struct private priv;
83   bfd_byte *buffer = priv.the_buffer;
84 
85   info->private_data = (PTR) & priv;
86   priv.max_fetched = priv.the_buffer;
87   priv.insn_start = addr;
88   if (setjmp (priv.bailout) != 0)
89     /* Error return.  */
90     return -1;
91 
92   /* Run down the table to find the one which matches.  */
93   for (opcode = h8500_table; opcode->name; opcode++)
94     {
95       int byte;
96       int rn = 0;
97       int rd = 0;
98       int rs = 0;
99       int disp = 0;
100       int abs_val = 0;
101       int imm = 0;
102       int pcrel = 0;
103       int qim = 0;
104       int i;
105       int cr = 0;
106 
107       for (byte = 0; byte < opcode->length; byte++)
108 	{
109 	  FETCH_DATA (info, buffer + byte + 1);
110 	  if ((buffer[byte] & opcode->bytes[byte].mask)
111 	      != (opcode->bytes[byte].contents))
112 	    goto next;
113 
114 	  else
115 	    {
116 	      /* Extract any info parts.  */
117 	      switch (opcode->bytes[byte].insert)
118 		{
119 		case 0:
120 		case FP:
121 		  break;
122 		default:
123 		  /* xgettext:c-format */
124 		  func (stream, _("can't cope with insert %d\n"),
125 			opcode->bytes[byte].insert);
126 		  break;
127 		case RN:
128 		  rn = buffer[byte] & 0x7;
129 		  break;
130 		case RS:
131 		  rs = buffer[byte] & 0x7;
132 		  break;
133 		case CRB:
134 		  cr = buffer[byte] & 0x7;
135 		  if (cr == 0)
136 		    goto next;
137 		  break;
138 		case CRW:
139 		  cr = buffer[byte] & 0x7;
140 		  if (cr != 0)
141 		    goto next;
142 		  break;
143 		case DISP16:
144 		  FETCH_DATA (info, buffer + byte + 2);
145 		  disp = (buffer[byte] << 8) | (buffer[byte + 1]);
146 		  break;
147 		case FPIND_D8:
148 		case DISP8:
149 		  disp = ((char) (buffer[byte]));
150 		  break;
151 		case RD:
152 		case RDIND:
153 		  rd = buffer[byte] & 0x7;
154 		  break;
155 		case ABS24:
156 		  FETCH_DATA (info, buffer + byte + 3);
157 		  abs_val =
158 		    (buffer[byte] << 16)
159 		    | (buffer[byte + 1] << 8)
160 		    | (buffer[byte + 2]);
161 		  break;
162 		case ABS16:
163 		  FETCH_DATA (info, buffer + byte + 2);
164 		  abs_val = (buffer[byte] << 8) | (buffer[byte + 1]);
165 		  break;
166 		case ABS8:
167 		  abs_val = (buffer[byte]);
168 		  break;
169 		case IMM16:
170 		  FETCH_DATA (info, buffer + byte + 2);
171 		  imm = (buffer[byte] << 8) | (buffer[byte + 1]);
172 		  break;
173 		case IMM4:
174 		  imm = (buffer[byte]) & 0xf;
175 		  break;
176 		case IMM8:
177 		case RLIST:
178 		  imm = (buffer[byte]);
179 		  break;
180 		case PCREL16:
181 		  FETCH_DATA (info, buffer + byte + 2);
182 		  pcrel = (buffer[byte] << 8) | (buffer[byte + 1]);
183 		  break;
184 		case PCREL8:
185 		  pcrel = (buffer[byte]);
186 		  break;
187 		case QIM:
188 		  switch (buffer[byte] & 0x7)
189 		    {
190 		    case 0:
191 		      qim = 1;
192 		      break;
193 		    case 1:
194 		      qim = 2;
195 		      break;
196 		    case 4:
197 		      qim = -1;
198 		      break;
199 		    case 5:
200 		      qim = -2;
201 		      break;
202 		    }
203 		  break;
204 
205 		}
206 	    }
207 	}
208       /* We get here when all the masks have passed so we can output
209 	 the operands.  */
210       FETCH_DATA (info, buffer + opcode->length);
211       (func) (stream, "%s\t", opcode->name);
212       for (i = 0; i < opcode->nargs; i++)
213 	{
214 	  if (i)
215 	    (func) (stream, ",");
216 	  switch (opcode->arg_type[i])
217 	    {
218 	    case FP:
219 	      func (stream, "fp");
220 	      break;
221 	    case RNIND_D16:
222 	      func (stream, "@(0x%x:16,r%d)", disp, rn);
223 	      break;
224 	    case RNIND_D8:
225 	      func (stream, "@(0x%x:8 (%d),r%d)", disp & 0xff, disp, rn);
226 	      break;
227 	    case RDIND_D16:
228 	      func (stream, "@(0x%x:16,r%d)", disp, rd);
229 	      break;
230 	    case RDIND_D8:
231 	      func (stream, "@(0x%x:8 (%d), r%d)", disp & 0xff, disp, rd);
232 	      break;
233 	    case FPIND_D8:
234 	      func (stream, "@(0x%x:8 (%d), fp)", disp & 0xff, disp);
235 	      break;
236 	    case CRB:
237 	    case CRW:
238 	      func (stream, "%s", crname[cr]);
239 	      break;
240 	    case RN:
241 	      func (stream, "r%d", rn);
242 	      break;
243 	    case RD:
244 	      func (stream, "r%d", rd);
245 	      break;
246 	    case RS:
247 	      func (stream, "r%d", rs);
248 	      break;
249 	    case RNDEC:
250 	      func (stream, "@-r%d", rn);
251 	      break;
252 	    case RNINC:
253 	      func (stream, "@r%d+", rn);
254 	      break;
255 	    case RNIND:
256 	      func (stream, "@r%d", rn);
257 	      break;
258 	    case RDIND:
259 	      func (stream, "@r%d", rd);
260 	      break;
261 	    case SPINC:
262 	      func (stream, "@sp+");
263 	      break;
264 	    case SPDEC:
265 	      func (stream, "@-sp");
266 	      break;
267 	    case ABS24:
268 	      func (stream, "@0x%0x:24", abs_val);
269 	      break;
270 	    case ABS16:
271 	      func (stream, "@0x%0x:16", abs_val & 0xffff);
272 	      break;
273 	    case ABS8:
274 	      func (stream, "@0x%0x:8", abs_val & 0xff);
275 	      break;
276 	    case IMM16:
277 	      func (stream, "#0x%0x:16", imm & 0xffff);
278 	      break;
279 	    case RLIST:
280 	      {
281 		int j;
282 		int nc = 0;
283 
284 		func (stream, "(");
285 		for (j = 0; j < 8; j++)
286 		  {
287 		    if (imm & (1 << j))
288 		      {
289 			func (stream, "r%d", j);
290 			if (nc)
291 			  func (stream, ",");
292 			nc = 1;
293 		      }
294 		  }
295 		func (stream, ")");
296 	      }
297 	      break;
298 	    case IMM8:
299 	      func (stream, "#0x%0x:8", imm & 0xff);
300 	      break;
301 	    case PCREL16:
302 	      func (stream, "0x%0x:16",
303 		    (int)(pcrel + addr + opcode->length) & 0xffff);
304 	      break;
305 	    case PCREL8:
306 	      func (stream, "#0x%0x:8",
307 		    (int)((char) pcrel + addr + opcode->length) & 0xffff);
308 	      break;
309 	    case QIM:
310 	      func (stream, "#%d:q", qim);
311 	      break;
312 	    case IMM4:
313 	      func (stream, "#%d:4", imm);
314 	      break;
315 	    }
316 	}
317       return opcode->length;
318     next:
319       ;
320     }
321 
322   /* Couldn't understand anything.  */
323   /* xgettext:c-format */
324   func (stream, _("%02x\t\t*unknown*"), buffer[0]);
325   return 1;
326 }
327