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