or1k: Implement relocation R_OR1K_GOT_AHI16 for gotha()
[deliverable/binutils-gdb.git] / opcodes / s12z-dis.c
1 /* s12z-dis.c -- Freescale S12Z disassembly
2 Copyright (C) 2018-2021 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 <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 asymbol *sym = info->symbol_at_address_func (addr + base, info);
210
211 if (!sym)
212 (*info->fprintf_func) (info->stream, fmt, addr);
213 else
214 (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
215 }
216
217
218 /* Emit the disassembled text for OPR */
219 static void
220 opr_emit_disassembly (const struct operand *opr,
221 struct disassemble_info *info)
222 {
223 operand_separator (info);
224
225 switch (opr->cl)
226 {
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:
232 {
233 int r = ((struct register_operand*) opr)->reg;
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);
239 }
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:
253 {
254 struct simple_memory_operand *mo =
255 (struct simple_memory_operand *) opr;
256 decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
257 }
258 break;
259 case OPND_CL_MEMORY:
260 {
261 int used_reg = 0;
262 struct memory_operand *mo = (struct memory_operand *) opr;
263 (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
264
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)
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 }
297 used_reg = 1;
298
299 if (mo->n_regs > used_reg)
300 {
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);
308 }
309
310 (*info->fprintf_func) (info->stream, "%c",
311 mo->indirect ? ']' : ')');
312 }
313 break;
314 };
315 }
316
317 #define S12Z_N_SIZES 4
318 static const char shift_size_table[S12Z_N_SIZES] =
319 {
320 'b', 'w', 'p', 'l'
321 };
322
323 int
324 print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
325 {
326 int o;
327 enum optr operator = OP_INVALID;
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]);
347
348 /* Ship out size sufficies for those instructions which
349 need them. */
350 if (osize == -1)
351 {
352 bool suffix = false;
353
354 for (o = 0; o < n_operands; ++o)
355 {
356 if (operands[o] && operands[o]->osize != -1)
357 {
358 if (!suffix)
359 {
360 (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
361 suffix = true;
362 }
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]);
371 }
372 }
373 }
374 else
375 {
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]);
381 }
382
383 /* Ship out the operands. */
384 for (o = 0; o < n_operands; ++o)
385 {
386 if (operands[o])
387 opr_emit_disassembly (operands[o], mra.info);
388 free (operands[o]);
389 }
390
391 return n_bytes;
392 }
This page took 0.036304 seconds and 4 git commands to generate.