S12Z: opcodes: Separate the decoding of operations from their display.
[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         if (mo->base_offset != 0)
286           {
287             (*info->fprintf_func) (info->stream, "%d", mo->base_offset);
288           }
289         else if (mo->n_regs > 0)
290           {
291             const char *fmt;
292             switch (mo->mutation)
293               {
294               case OPND_RM_PRE_DEC:
295                 fmt = "-%s";
296                 break;
297               case OPND_RM_PRE_INC:
298                 fmt = "+%s";
299                 break;
300               case OPND_RM_POST_DEC:
301                 fmt = "%s-";
302                 break;
303               case OPND_RM_POST_INC:
304                 fmt = "%s+";
305                 break;
306               case OPND_RM_NONE:
307               default:
308                 fmt = "%s";
309                 break;
310               }
311             (*info->fprintf_func) (info->stream, fmt,
312                                    registers[mo->regs[0]].name);
313             used_reg = 1;
314           }
315
316         if (mo->n_regs > used_reg)
317           {
318             (*info->fprintf_func) (info->stream, ",%s",
319                                    registers[mo->regs[used_reg]].name);
320           }
321
322         (*info->fprintf_func) (info->stream, "%c",
323                                mo->indirect ? ']' : ')');
324       }
325       break;
326     };
327 }
328
329 static const char shift_size_table[] = {
330   'b', 'w', 'p', 'l'
331 };
332
333 int
334 print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
335 {
336   int o;
337   enum operator operator = OP_INVALID;
338   int n_operands = 0;
339
340   /* The longest instruction in S12Z can have 6 operands.
341      (Most have 3 or less.  Only PSH and PUL have so many.  */
342   struct operand *operands[6];
343
344   struct mem_read_abstraction mra;
345   mra.base.read = (void *) abstract_read_memory ;
346   mra.base.advance = advance ;
347   mra.base.posn = posn;
348   mra.memaddr = memaddr;
349   mra.info = info;
350
351   short osize = -1;
352   int n_bytes =
353     decode_s12z (&operator, &osize, &n_operands, operands,
354                  (struct mem_read_abstraction_base *) &mra);
355
356   (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
357   
358   /* Ship out size sufficies for those instructions which
359      need them.  */
360   if (osize == -1)
361     {
362       bool suffix = false;
363       for (o = 0; o < n_operands; ++o)
364         {
365           if (operands[o]->osize != -1)
366             {
367               if (!suffix)
368                 {
369                   (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
370                   suffix = true;
371                 }
372               (*mra.info->fprintf_func) (mra.info->stream, "%c",
373                                      shift_size_table[operands[o]->osize]);
374             }
375         }
376     }
377   else
378     {
379       (*mra.info->fprintf_func) (mra.info->stream, ".%c",
380                              shift_size_table[osize]);
381     }
382
383
384   /* Ship out the operands.  */
385   for (o = 0; o < n_operands; ++o)
386     {
387       if (operands[o])
388         opr_emit_disassembly (operands[o], mra.info);
389       free (operands[o]);
390     }
391
392   return n_bytes;
393 }