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