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