Automatic date update in version.in
[deliverable/binutils-gdb.git] / opcodes / s12z-dis.c
CommitLineData
7b4ae824 1/* s12z-dis.c -- Freescale S12Z disassembly
250d07de 2 Copyright (C) 2018-2021 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>
3dfb1b6d 23#include <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 208 const char *fmt = relative ? "*%+" BFD_VMA_FMT "d" : "%" BFD_VMA_FMT "d";
a2e66773
AM
209 asymbol *sym = info->symbol_at_address_func (addr + base, info);
210
211 if (!sym)
212 (*info->fprintf_func) (info->stream, fmt, addr);
7b4ae824 213 else
a2e66773 214 (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
7b4ae824
JD
215}
216
7b4ae824 217
ef1ad42b 218/* Emit the disassembled text for OPR */
7b4ae824 219static void
ef1ad42b
JD
220opr_emit_disassembly (const struct operand *opr,
221 struct disassemble_info *info)
7b4ae824 222{
7b4ae824 223 operand_separator (info);
7b4ae824 224
ef1ad42b 225 switch (opr->cl)
7b4ae824 226 {
ef1ad42b
JD
227 case OPND_CL_IMMEDIATE:
228 (*info->fprintf_func) (info->stream, "#%d",
229 ((struct immediate_operand *) opr)->value);
230 break;
231 case OPND_CL_REGISTER:
7b4ae824 232 {
ef1ad42b 233 int r = ((struct register_operand*) opr)->reg;
66a66a17
NC
234
235 if (r < 0 || r >= S12Z_N_REGISTERS)
236 (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
237 else
238 (*info->fprintf_func) (info->stream, "%s", registers[r].name);
7b4ae824 239 }
ef1ad42b
JD
240 break;
241 case OPND_CL_REGISTER_ALL16:
242 (*info->fprintf_func) (info->stream, "%s", "ALL16b");
243 break;
244 case OPND_CL_REGISTER_ALL:
245 (*info->fprintf_func) (info->stream, "%s", "ALL");
246 break;
247 case OPND_CL_BIT_FIELD:
248 (*info->fprintf_func) (info->stream, "#%d:%d",
249 ((struct bitfield_operand*)opr)->width,
250 ((struct bitfield_operand*)opr)->offset);
251 break;
252 case OPND_CL_SIMPLE_MEMORY:
7b4ae824 253 {
ef1ad42b
JD
254 struct simple_memory_operand *mo =
255 (struct simple_memory_operand *) opr;
256 decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
7b4ae824 257 }
ef1ad42b
JD
258 break;
259 case OPND_CL_MEMORY:
7b4ae824 260 {
ef1ad42b
JD
261 int used_reg = 0;
262 struct memory_operand *mo = (struct memory_operand *) opr;
263 (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
7b4ae824 264
39f286cd
JD
265 const char *fmt;
266 assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
267 switch (mo->mutation)
268 {
269 case OPND_RM_PRE_DEC:
270 fmt = "-%s";
271 break;
272 case OPND_RM_PRE_INC:
273 fmt = "+%s";
274 break;
275 case OPND_RM_POST_DEC:
276 fmt = "%s-";
277 break;
278 case OPND_RM_POST_INC:
279 fmt = "%s+";
280 break;
281 case OPND_RM_NONE:
282 default:
283 if (mo->n_regs < 2)
284 (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
285 fmt = "%s";
286 break;
287 }
288 if (mo->n_regs > 0)
66a66a17
NC
289 {
290 int r = mo->regs[0];
291
292 if (r < 0 || r >= S12Z_N_REGISTERS)
293 (*info->fprintf_func) (info->stream, fmt, _("<illegal reg num>"));
294 else
295 (*info->fprintf_func) (info->stream, fmt, registers[r].name);
296 }
39f286cd 297 used_reg = 1;
7b4ae824 298
ef1ad42b
JD
299 if (mo->n_regs > used_reg)
300 {
66a66a17
NC
301 int r = mo->regs[used_reg];
302
303 if (r < 0 || r >= S12Z_N_REGISTERS)
304 (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
305 else
306 (*info->fprintf_func) (info->stream, ",%s",
307 registers[r].name);
ef1ad42b 308 }
7b4ae824 309
ef1ad42b
JD
310 (*info->fprintf_func) (info->stream, "%c",
311 mo->indirect ? ']' : ')');
7b4ae824 312 }
ef1ad42b
JD
313 break;
314 };
7b4ae824
JD
315}
316
66a66a17
NC
317#define S12Z_N_SIZES 4
318static const char shift_size_table[S12Z_N_SIZES] =
319{
ef1ad42b
JD
320 'b', 'w', 'p', 'l'
321};
7b4ae824 322
ef1ad42b
JD
323int
324print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
7b4ae824 325{
ef1ad42b 326 int o;
e5a557ac 327 enum optr operator = OP_INVALID;
ef1ad42b
JD
328 int n_operands = 0;
329
330 /* The longest instruction in S12Z can have 6 operands.
331 (Most have 3 or less. Only PSH and PUL have so many. */
332 struct operand *operands[6];
333
334 struct mem_read_abstraction mra;
335 mra.base.read = (void *) abstract_read_memory ;
336 mra.base.advance = advance ;
337 mra.base.posn = posn;
338 mra.memaddr = memaddr;
339 mra.info = info;
340
341 short osize = -1;
342 int n_bytes =
343 decode_s12z (&operator, &osize, &n_operands, operands,
344 (struct mem_read_abstraction_base *) &mra);
345
346 (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
448b8ca8 347
ef1ad42b
JD
348 /* Ship out size sufficies for those instructions which
349 need them. */
350 if (osize == -1)
351 {
352 bool suffix = false;
66a66a17 353
ef1ad42b
JD
354 for (o = 0; o < n_operands; ++o)
355 {
448b8ca8 356 if (operands[o] && operands[o]->osize != -1)
ef1ad42b
JD
357 {
358 if (!suffix)
359 {
360 (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
361 suffix = true;
362 }
66a66a17
NC
363
364 osize = operands[o]->osize;
365
366 if (osize < 0 || osize >= S12Z_N_SIZES)
367 (*mra.info->fprintf_func) (mra.info->stream, _("<bad>"));
368 else
369 (*mra.info->fprintf_func) (mra.info->stream, "%c",
370 shift_size_table[osize]);
ef1ad42b
JD
371 }
372 }
373 }
374 else
375 {
66a66a17
NC
376 if (osize < 0 || osize >= S12Z_N_SIZES)
377 (*mra.info->fprintf_func) (mra.info->stream, _(".<bad>"));
378 else
379 (*mra.info->fprintf_func) (mra.info->stream, ".%c",
380 shift_size_table[osize]);
ef1ad42b 381 }
7b4ae824 382
ef1ad42b
JD
383 /* Ship out the operands. */
384 for (o = 0; o < n_operands; ++o)
7b4ae824 385 {
ef1ad42b
JD
386 if (operands[o])
387 opr_emit_disassembly (operands[o], mra.info);
388 free (operands[o]);
7b4ae824
JD
389 }
390
ef1ad42b 391 return n_bytes;
7b4ae824 392}
This page took 0.265117 seconds and 4 git commands to generate.