gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / s12z-dis.c
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 }
This page took 0.036824 seconds and 4 git commands to generate.