gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / s12z-dis.c
CommitLineData
7b4ae824 1/* s12z-dis.c -- Freescale S12Z disassembly
b3adc24a 2 Copyright (C) 2018-2020 Free Software Foundation, Inc.
7b4ae824
JD
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>
2d5d5a8f 23#include "bfd_stdint.h"
7b4ae824
JD
24#include <stdbool.h>
25#include <assert.h>
26
7ba3ba91 27#include "opcode/s12z.h"
7b4ae824
JD
28#include "bfd.h"
29#include "dis-asm.h"
7b4ae824 30#include "disassemble.h"
ef1ad42b 31#include "s12z-opc.h"
66a66a17 32#include "opintl.h"
7b4ae824 33
ef1ad42b 34struct mem_read_abstraction
7b4ae824 35{
ef1ad42b
JD
36 struct mem_read_abstraction_base base;
37 bfd_vma memaddr;
38 struct disassemble_info* info;
7b4ae824
JD
39};
40
ef1ad42b
JD
41static void
42advance (struct mem_read_abstraction_base *b)
7b4ae824 43{
ef1ad42b
JD
44 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
45 mra->memaddr ++;
7b4ae824
JD
46}
47
ef1ad42b
JD
48static bfd_vma
49posn (struct mem_read_abstraction_base *b)
7b4ae824 50{
ef1ad42b
JD
51 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
52 return mra->memaddr;
7b4ae824
JD
53}
54
55static int
ef1ad42b
JD
56abstract_read_memory (struct mem_read_abstraction_base *b,
57 int offset,
58 size_t n, bfd_byte *bytes)
7b4ae824 59{
ef1ad42b 60 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
7b4ae824 61
d1023b5d
AM
62 int status = (*mra->info->read_memory_func) (mra->memaddr + offset,
63 bytes, n, mra->info);
64 return status != 0 ? -1 : 0;
7b4ae824
JD
65}
66
ef1ad42b 67/* Start of disassembly file. */
7b4ae824
JD
68const 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
ef1ad42b
JD
90static 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
7b4ae824 189
ef1ad42b
JD
190static void
191operand_separator (struct disassemble_info *info)
7b4ae824 192{
ef1ad42b
JD
193 if ((info->flags & 0x2))
194 (*info->fprintf_func) (info->stream, ",");
195
196 (*info->fprintf_func) (info->stream, " ");
197
198 info->flags |= 0x2;
7b4ae824
JD
199}
200
ef1ad42b
JD
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. */
7b4ae824 204static void
ef1ad42b
JD
205decode_possible_symbol (bfd_vma addr, bfd_vma base,
206 struct disassemble_info *info, bool relative)
7b4ae824 207{
ef1ad42b
JD
208 const char *fmt = relative ? "*%+" BFD_VMA_FMT "d" : "%" BFD_VMA_FMT "d";
209 if (!info->symbol_at_address_func (addr + base, info))
7b4ae824 210 {
ef1ad42b 211 (*info->fprintf_func) (info->stream, fmt, addr);
7b4ae824
JD
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];
ef1ad42b 220 if (bfd_asymbol_value (sym) == addr + base)
7b4ae824
JD
221 {
222 break;
223 }
224 }
225 if (j < info->symtab_size)
226 (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
192c2bfb 227 else
ef1ad42b 228 (*info->fprintf_func) (info->stream, fmt, addr);
7b4ae824
JD
229 }
230}
231
7b4ae824 232
ef1ad42b 233/* Emit the disassembled text for OPR */
7b4ae824 234static void
ef1ad42b
JD
235opr_emit_disassembly (const struct operand *opr,
236 struct disassemble_info *info)
7b4ae824 237{
7b4ae824 238 operand_separator (info);
7b4ae824 239
ef1ad42b 240 switch (opr->cl)
7b4ae824 241 {
ef1ad42b
JD
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:
7b4ae824 247 {
ef1ad42b 248 int r = ((struct register_operand*) opr)->reg;
66a66a17
NC
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);
7b4ae824 254 }
ef1ad42b
JD
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:
7b4ae824 268 {
ef1ad42b
JD
269 struct simple_memory_operand *mo =
270 (struct simple_memory_operand *) opr;
271 decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
7b4ae824 272 }
ef1ad42b
JD
273 break;
274 case OPND_CL_MEMORY:
7b4ae824 275 {
ef1ad42b
JD
276 int used_reg = 0;
277 struct memory_operand *mo = (struct memory_operand *) opr;
278 (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
7b4ae824 279
39f286cd
JD
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)
66a66a17
NC
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 }
39f286cd 312 used_reg = 1;
7b4ae824 313
ef1ad42b
JD
314 if (mo->n_regs > used_reg)
315 {
66a66a17
NC
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);
ef1ad42b 323 }
7b4ae824 324
ef1ad42b
JD
325 (*info->fprintf_func) (info->stream, "%c",
326 mo->indirect ? ']' : ')');
7b4ae824 327 }
ef1ad42b
JD
328 break;
329 };
7b4ae824
JD
330}
331
66a66a17
NC
332#define S12Z_N_SIZES 4
333static const char shift_size_table[S12Z_N_SIZES] =
334{
ef1ad42b
JD
335 'b', 'w', 'p', 'l'
336};
7b4ae824 337
ef1ad42b
JD
338int
339print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
7b4ae824 340{
ef1ad42b 341 int o;
e5a557ac 342 enum optr operator = OP_INVALID;
ef1ad42b
JD
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]);
448b8ca8 362
ef1ad42b
JD
363 /* Ship out size sufficies for those instructions which
364 need them. */
365 if (osize == -1)
366 {
367 bool suffix = false;
66a66a17 368
ef1ad42b
JD
369 for (o = 0; o < n_operands; ++o)
370 {
448b8ca8 371 if (operands[o] && operands[o]->osize != -1)
ef1ad42b
JD
372 {
373 if (!suffix)
374 {
375 (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
376 suffix = true;
377 }
66a66a17
NC
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]);
ef1ad42b
JD
386 }
387 }
388 }
389 else
390 {
66a66a17
NC
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]);
ef1ad42b 396 }
7b4ae824 397
ef1ad42b
JD
398 /* Ship out the operands. */
399 for (o = 0; o < n_operands; ++o)
7b4ae824 400 {
ef1ad42b
JD
401 if (operands[o])
402 opr_emit_disassembly (operands[o], mra.info);
403 free (operands[o]);
7b4ae824
JD
404 }
405
ef1ad42b 406 return n_bytes;
7b4ae824 407}
This page took 0.15002 seconds and 4 git commands to generate.