xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/s12z-dis.c (revision 901e7e84758515fbf39dfc064cb0b45ab146d8b0)
1 /* s12z-dis.c -- Freescale S12Z disassembly
2    Copyright (C) 2018-2020 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 #include "bfd_stdint.h"
24 #include <stdbool.h>
25 #include <assert.h>
26 
27 #include "opcode/s12z.h"
28 #include "bfd.h"
29 #include "dis-asm.h"
30 #include "disassemble.h"
31 #include "s12z-opc.h"
32 #include "opintl.h"
33 
34 struct mem_read_abstraction
35 {
36   struct mem_read_abstraction_base base;
37   bfd_vma memaddr;
38   struct disassemble_info* info;
39 };
40 
41 static void
42 advance (struct mem_read_abstraction_base *b)
43 {
44   struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
45   mra->memaddr ++;
46 }
47 
48 static bfd_vma
49 posn (struct mem_read_abstraction_base *b)
50 {
51   struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
52   return mra->memaddr;
53 }
54 
55 static int
56 abstract_read_memory (struct mem_read_abstraction_base *b,
57 		      int offset,
58 		      size_t n, bfd_byte *bytes)
59 {
60   struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
61 
62   int status =
63     (*mra->info->read_memory_func) (mra->memaddr + offset,
64 				    bytes, n, mra->info);
65 
66   if (status != 0)
67     {
68       (*mra->info->memory_error_func) (status, mra->memaddr, mra->info);
69       return -1;
70     }
71   return 0;
72 }
73 
74 /* Start of disassembly file.  */
75 const struct reg registers[S12Z_N_REGISTERS] =
76   {
77     {"d2", 2},
78     {"d3", 2},
79     {"d4", 2},
80     {"d5", 2},
81 
82     {"d0", 1},
83     {"d1", 1},
84 
85     {"d6", 4},
86     {"d7", 4},
87 
88     {"x", 3},
89     {"y", 3},
90     {"s", 3},
91     {"p", 3},
92     {"cch", 1},
93     {"ccl", 1},
94     {"ccw", 2}
95   };
96 
97 static const char *mnemonics[] =
98   {
99     "!!invalid!!",
100     "psh",
101     "pul",
102     "tbne", "tbeq", "tbpl", "tbmi", "tbgt", "tble",
103     "dbne", "dbeq", "dbpl", "dbmi", "dbgt", "dble",
104     "sex",
105     "exg",
106     "lsl", "lsr",
107     "asl", "asr",
108     "rol", "ror",
109     "bfins", "bfext",
110 
111     "trap",
112 
113     "ld",
114     "st",
115     "cmp",
116 
117     "stop",
118     "wai",
119     "sys",
120 
121     "minu",
122     "mins",
123     "maxu",
124     "maxs",
125 
126     "abs",
127     "adc",
128     "bit",
129     "sbc",
130     "rti",
131     "clb",
132     "eor",
133 
134     "sat",
135 
136     "nop",
137     "bgnd",
138     "brclr",
139     "brset",
140     "rts",
141     "lea",
142     "mov",
143 
144     "bra",
145     "bsr",
146     "bhi",
147     "bls",
148     "bcc",
149     "bcs",
150     "bne",
151     "beq",
152     "bvc",
153     "bvs",
154     "bpl",
155     "bmi",
156     "bge",
157     "blt",
158     "bgt",
159     "ble",
160     "inc",
161     "clr",
162     "dec",
163 
164     "add",
165     "sub",
166     "and",
167     "or",
168 
169     "tfr",
170     "jmp",
171     "jsr",
172     "com",
173     "andcc",
174     "neg",
175     "orcc",
176     "bclr",
177     "bset",
178     "btgl",
179     "swi",
180 
181     "mulu",
182     "divu",
183     "modu",
184     "macu",
185     "qmulu",
186 
187     "muls",
188     "divs",
189     "mods",
190     "macs",
191     "qmuls",
192 
193     NULL
194   };
195 
196 
197 static void
198 operand_separator (struct disassemble_info *info)
199 {
200   if ((info->flags & 0x2))
201     (*info->fprintf_func) (info->stream, ",");
202 
203   (*info->fprintf_func) (info->stream, " ");
204 
205   info->flags |= 0x2;
206 }
207 
208 /* Render the symbol name whose value is ADDR + BASE or the adddress itself if
209    there is no symbol.  If BASE is non zero, then the a PC relative adddress is
210    assumend (ie BASE is the value in the PC.  */
211 static void
212 decode_possible_symbol (bfd_vma addr, bfd_vma base,
213                         struct disassemble_info *info, bool relative)
214 {
215   const char *fmt = relative  ? "*%+" BFD_VMA_FMT "d" : "%" BFD_VMA_FMT "d";
216   if (!info->symbol_at_address_func (addr + base, info))
217     {
218       (*info->fprintf_func) (info->stream, fmt, addr);
219     }
220   else
221     {
222       asymbol *sym = NULL;
223       int j;
224       for (j = 0; j < info->symtab_size; ++j)
225 	{
226 	  sym = info->symtab[j];
227 	  if (bfd_asymbol_value (sym) == addr + base)
228 	    {
229 	      break;
230 	    }
231 	}
232       if (j < info->symtab_size)
233 	(*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
234       else
235         (*info->fprintf_func) (info->stream, fmt, addr);
236     }
237 }
238 
239 
240 /* Emit the disassembled text for OPR */
241 static void
242 opr_emit_disassembly (const struct operand *opr,
243 		      struct disassemble_info *info)
244 {
245   operand_separator (info);
246 
247   switch (opr->cl)
248     {
249     case OPND_CL_IMMEDIATE:
250       (*info->fprintf_func) (info->stream, "#%d",
251 			     ((struct immediate_operand *) opr)->value);
252       break;
253     case OPND_CL_REGISTER:
254       {
255         int r = ((struct register_operand*) opr)->reg;
256 
257 	if (r < 0 || r >= S12Z_N_REGISTERS)
258 	  (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
259 	else
260 	  (*info->fprintf_func) (info->stream, "%s", registers[r].name);
261       }
262       break;
263     case OPND_CL_REGISTER_ALL16:
264       (*info->fprintf_func) (info->stream, "%s", "ALL16b");
265       break;
266     case OPND_CL_REGISTER_ALL:
267       (*info->fprintf_func) (info->stream, "%s", "ALL");
268       break;
269     case OPND_CL_BIT_FIELD:
270       (*info->fprintf_func) (info->stream, "#%d:%d",
271                              ((struct bitfield_operand*)opr)->width,
272                              ((struct bitfield_operand*)opr)->offset);
273       break;
274     case OPND_CL_SIMPLE_MEMORY:
275       {
276         struct simple_memory_operand *mo =
277 	  (struct simple_memory_operand *) opr;
278 	decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
279       }
280       break;
281     case OPND_CL_MEMORY:
282       {
283         int used_reg = 0;
284         struct memory_operand *mo = (struct memory_operand *) opr;
285 	(*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
286 
287 	const char *fmt;
288 	assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
289 	switch (mo->mutation)
290 	  {
291 	  case OPND_RM_PRE_DEC:
292 	    fmt = "-%s";
293 	    break;
294 	  case OPND_RM_PRE_INC:
295 	    fmt = "+%s";
296 	    break;
297 	  case OPND_RM_POST_DEC:
298 	    fmt = "%s-";
299 	    break;
300 	  case OPND_RM_POST_INC:
301 	    fmt = "%s+";
302 	    break;
303 	  case OPND_RM_NONE:
304 	  default:
305 	    if (mo->n_regs < 2)
306 	      (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
307 	    fmt = "%s";
308 	    break;
309 	  }
310 	if (mo->n_regs > 0)
311 	  {
312 	    int r = mo->regs[0];
313 
314 	    if (r < 0 || r >= S12Z_N_REGISTERS)
315 	      (*info->fprintf_func) (info->stream, fmt, _("<illegal reg num>"));
316 	    else
317 	      (*info->fprintf_func) (info->stream, fmt, registers[r].name);
318 	  }
319 	used_reg = 1;
320 
321         if (mo->n_regs > used_reg)
322           {
323 	    int r = mo->regs[used_reg];
324 
325 	    if (r < 0 || r >= S12Z_N_REGISTERS)
326 	      (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
327 	    else
328 	      (*info->fprintf_func) (info->stream, ",%s",
329 				     registers[r].name);
330           }
331 
332 	(*info->fprintf_func) (info->stream, "%c",
333 			       mo->indirect ? ']' : ')');
334       }
335       break;
336     };
337 }
338 
339 #define S12Z_N_SIZES 4
340 static const char shift_size_table[S12Z_N_SIZES] =
341 {
342   'b', 'w', 'p', 'l'
343 };
344 
345 int
346 print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
347 {
348   int o;
349   enum optr operator = OP_INVALID;
350   int n_operands = 0;
351 
352   /* The longest instruction in S12Z can have 6 operands.
353      (Most have 3 or less.  Only PSH and PUL have so many.  */
354   struct operand *operands[6];
355 
356   struct mem_read_abstraction mra;
357   mra.base.read = (void *) abstract_read_memory ;
358   mra.base.advance = advance ;
359   mra.base.posn = posn;
360   mra.memaddr = memaddr;
361   mra.info = info;
362 
363   short osize = -1;
364   int n_bytes =
365     decode_s12z (&operator, &osize, &n_operands, operands,
366 		 (struct mem_read_abstraction_base *) &mra);
367 
368   (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
369 
370   /* Ship out size sufficies for those instructions which
371      need them.  */
372   if (osize == -1)
373     {
374       bool suffix = false;
375 
376       for (o = 0; o < n_operands; ++o)
377 	{
378 	  if (operands[o] && operands[o]->osize != -1)
379 	    {
380 	      if (!suffix)
381 		{
382 		  (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
383 		  suffix = true;
384 		}
385 
386 	      osize = operands[o]->osize;
387 
388 	      if (osize < 0 || osize >= S12Z_N_SIZES)
389 		(*mra.info->fprintf_func) (mra.info->stream, _("<bad>"));
390 	      else
391 		(*mra.info->fprintf_func) (mra.info->stream, "%c",
392 					   shift_size_table[osize]);
393 
394 	    }
395 	}
396     }
397   else
398     {
399       if (osize < 0 || osize >= S12Z_N_SIZES)
400 	(*mra.info->fprintf_func) (mra.info->stream, _(".<bad>"));
401       else
402 	(*mra.info->fprintf_func) (mra.info->stream, ".%c",
403 				   shift_size_table[osize]);
404     }
405 
406   /* Ship out the operands.  */
407   for (o = 0; o < n_operands; ++o)
408     {
409       if (operands[o])
410 	opr_emit_disassembly (operands[o], mra.info);
411       free (operands[o]);
412     }
413 
414   return n_bytes;
415 }
416