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