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