S12Z: Don't crash when disassembling invalid instructions.
[external/binutils.git] / opcodes / s12z-dis.c
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 }