S12Z: opcodes: Separate the decoding of operations from their display.
[deliverable/binutils-gdb.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 }
This page took 0.040571 seconds and 4 git commands to generate.