S12Z: Fix disassembly of indexed OPR operands with zero index.
[deliverable/binutils-gdb.git] / opcodes / s12z-dis.c
CommitLineData
7b4ae824 1/* s12z-dis.c -- Freescale S12Z disassembly
82704155 2 Copyright (C) 2018-2019 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
29#include "bfd.h"
30#include "dis-asm.h"
31
7b4ae824
JD
32#include "disassemble.h"
33
ef1ad42b 34#include "s12z-opc.h"
7b4ae824 35
ef1ad42b 36struct mem_read_abstraction
7b4ae824 37{
ef1ad42b
JD
38 struct mem_read_abstraction_base base;
39 bfd_vma memaddr;
40 struct disassemble_info* info;
7b4ae824
JD
41};
42
ef1ad42b
JD
43static void
44advance (struct mem_read_abstraction_base *b)
7b4ae824 45{
ef1ad42b
JD
46 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
47 mra->memaddr ++;
7b4ae824
JD
48}
49
ef1ad42b
JD
50static bfd_vma
51posn (struct mem_read_abstraction_base *b)
7b4ae824 52{
ef1ad42b
JD
53 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
54 return mra->memaddr;
7b4ae824
JD
55}
56
57static int
ef1ad42b
JD
58abstract_read_memory (struct mem_read_abstraction_base *b,
59 int offset,
60 size_t n, bfd_byte *bytes)
7b4ae824 61{
ef1ad42b 62 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
7b4ae824 63
ef1ad42b
JD
64 int status =
65 (*mra->info->read_memory_func) (mra->memaddr + offset,
66 bytes, n, mra->info);
7b4ae824 67
ef1ad42b 68 if (status != 0)
7b4ae824 69 {
ef1ad42b
JD
70 (*mra->info->memory_error_func) (status, mra->memaddr, mra->info);
71 return -1;
7b4ae824 72 }
ef1ad42b 73 return 0;
7b4ae824
JD
74}
75
ef1ad42b 76/* Start of disassembly file. */
7b4ae824
JD
77const 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
ef1ad42b
JD
99static 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
7b4ae824 198
ef1ad42b
JD
199static void
200operand_separator (struct disassemble_info *info)
7b4ae824 201{
ef1ad42b
JD
202 if ((info->flags & 0x2))
203 (*info->fprintf_func) (info->stream, ",");
204
205 (*info->fprintf_func) (info->stream, " ");
206
207 info->flags |= 0x2;
7b4ae824
JD
208}
209
ef1ad42b
JD
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. */
7b4ae824 213static void
ef1ad42b
JD
214decode_possible_symbol (bfd_vma addr, bfd_vma base,
215 struct disassemble_info *info, bool relative)
7b4ae824 216{
ef1ad42b
JD
217 const char *fmt = relative ? "*%+" BFD_VMA_FMT "d" : "%" BFD_VMA_FMT "d";
218 if (!info->symbol_at_address_func (addr + base, info))
7b4ae824 219 {
ef1ad42b 220 (*info->fprintf_func) (info->stream, fmt, addr);
7b4ae824
JD
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];
ef1ad42b 229 if (bfd_asymbol_value (sym) == addr + base)
7b4ae824
JD
230 {
231 break;
232 }
233 }
234 if (j < info->symtab_size)
235 (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
192c2bfb 236 else
ef1ad42b 237 (*info->fprintf_func) (info->stream, fmt, addr);
7b4ae824
JD
238 }
239}
240
7b4ae824 241
ef1ad42b 242/* Emit the disassembled text for OPR */
7b4ae824 243static void
ef1ad42b
JD
244opr_emit_disassembly (const struct operand *opr,
245 struct disassemble_info *info)
7b4ae824 246{
7b4ae824 247 operand_separator (info);
7b4ae824 248
ef1ad42b 249 switch (opr->cl)
7b4ae824 250 {
ef1ad42b
JD
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:
7b4ae824 256 {
ef1ad42b
JD
257 int r = ((struct register_operand*) opr)->reg;
258 (*info->fprintf_func) (info->stream, "%s", registers[r].name);
7b4ae824 259 }
ef1ad42b
JD
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:
7b4ae824 273 {
ef1ad42b
JD
274 struct simple_memory_operand *mo =
275 (struct simple_memory_operand *) opr;
276 decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
7b4ae824 277 }
ef1ad42b
JD
278 break;
279 case OPND_CL_MEMORY:
7b4ae824 280 {
ef1ad42b
JD
281 int used_reg = 0;
282 struct memory_operand *mo = (struct memory_operand *) opr;
283 (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
7b4ae824 284
39f286cd
JD
285 const char *fmt;
286 assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
287 switch (mo->mutation)
288 {
289 case OPND_RM_PRE_DEC:
290 fmt = "-%s";
291 break;
292 case OPND_RM_PRE_INC:
293 fmt = "+%s";
294 break;
295 case OPND_RM_POST_DEC:
296 fmt = "%s-";
297 break;
298 case OPND_RM_POST_INC:
299 fmt = "%s+";
300 break;
301 case OPND_RM_NONE:
302 default:
303 if (mo->n_regs < 2)
304 (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
305 fmt = "%s";
306 break;
307 }
308 if (mo->n_regs > 0)
309 (*info->fprintf_func) (info->stream, fmt,
310 registers[mo->regs[0]].name);
311 used_reg = 1;
7b4ae824 312
ef1ad42b
JD
313 if (mo->n_regs > used_reg)
314 {
315 (*info->fprintf_func) (info->stream, ",%s",
316 registers[mo->regs[used_reg]].name);
317 }
7b4ae824 318
ef1ad42b
JD
319 (*info->fprintf_func) (info->stream, "%c",
320 mo->indirect ? ']' : ')');
7b4ae824 321 }
ef1ad42b
JD
322 break;
323 };
7b4ae824
JD
324}
325
ef1ad42b
JD
326static const char shift_size_table[] = {
327 'b', 'w', 'p', 'l'
328};
7b4ae824 329
ef1ad42b
JD
330int
331print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
7b4ae824 332{
ef1ad42b
JD
333 int o;
334 enum operator operator = OP_INVALID;
335 int n_operands = 0;
336
337 /* The longest instruction in S12Z can have 6 operands.
338 (Most have 3 or less. Only PSH and PUL have so many. */
339 struct operand *operands[6];
340
341 struct mem_read_abstraction mra;
342 mra.base.read = (void *) abstract_read_memory ;
343 mra.base.advance = advance ;
344 mra.base.posn = posn;
345 mra.memaddr = memaddr;
346 mra.info = info;
347
348 short osize = -1;
349 int n_bytes =
350 decode_s12z (&operator, &osize, &n_operands, operands,
351 (struct mem_read_abstraction_base *) &mra);
352
353 (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
354
355 /* Ship out size sufficies for those instructions which
356 need them. */
357 if (osize == -1)
358 {
359 bool suffix = false;
360 for (o = 0; o < n_operands; ++o)
361 {
362 if (operands[o]->osize != -1)
363 {
364 if (!suffix)
365 {
366 (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
367 suffix = true;
368 }
369 (*mra.info->fprintf_func) (mra.info->stream, "%c",
370 shift_size_table[operands[o]->osize]);
371 }
372 }
373 }
374 else
375 {
376 (*mra.info->fprintf_func) (mra.info->stream, ".%c",
377 shift_size_table[osize]);
378 }
7b4ae824 379
7b4ae824 380
ef1ad42b
JD
381 /* Ship out the operands. */
382 for (o = 0; o < n_operands; ++o)
7b4ae824 383 {
ef1ad42b
JD
384 if (operands[o])
385 opr_emit_disassembly (operands[o], mra.info);
386 free (operands[o]);
7b4ae824
JD
387 }
388
ef1ad42b 389 return n_bytes;
7b4ae824 390}
This page took 0.071873 seconds and 4 git commands to generate.