Add "info connections" command, "info inferiors" connection number/string
[deliverable/binutils-gdb.git] / opcodes / s12z-dis.c
1 /* s12z-dis.c -- Freescale S12Z disassembly
2 Copyright (C) 2018-2020 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 "bfd_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 =
63 (*mra->info->read_memory_func) (mra->memaddr + offset,
64 bytes, n, mra->info);
65
66 if (status != 0)
67 {
68 (*mra->info->memory_error_func) (status, mra->memaddr, mra->info);
69 return -1;
70 }
71 return 0;
72 }
73
74 /* Start of disassembly file. */
75 const 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
97 static 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
196
197 static void
198 operand_separator (struct disassemble_info *info)
199 {
200 if ((info->flags & 0x2))
201 (*info->fprintf_func) (info->stream, ",");
202
203 (*info->fprintf_func) (info->stream, " ");
204
205 info->flags |= 0x2;
206 }
207
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. */
211 static void
212 decode_possible_symbol (bfd_vma addr, bfd_vma base,
213 struct disassemble_info *info, bool relative)
214 {
215 const char *fmt = relative ? "*%+" BFD_VMA_FMT "d" : "%" BFD_VMA_FMT "d";
216 if (!info->symbol_at_address_func (addr + base, info))
217 {
218 (*info->fprintf_func) (info->stream, fmt, addr);
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];
227 if (bfd_asymbol_value (sym) == addr + base)
228 {
229 break;
230 }
231 }
232 if (j < info->symtab_size)
233 (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
234 else
235 (*info->fprintf_func) (info->stream, fmt, addr);
236 }
237 }
238
239
240 /* Emit the disassembled text for OPR */
241 static void
242 opr_emit_disassembly (const struct operand *opr,
243 struct disassemble_info *info)
244 {
245 operand_separator (info);
246
247 switch (opr->cl)
248 {
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:
254 {
255 int r = ((struct register_operand*) opr)->reg;
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);
261 }
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:
275 {
276 struct simple_memory_operand *mo =
277 (struct simple_memory_operand *) opr;
278 decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
279 }
280 break;
281 case OPND_CL_MEMORY:
282 {
283 int used_reg = 0;
284 struct memory_operand *mo = (struct memory_operand *) opr;
285 (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
286
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)
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 }
319 used_reg = 1;
320
321 if (mo->n_regs > used_reg)
322 {
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);
330 }
331
332 (*info->fprintf_func) (info->stream, "%c",
333 mo->indirect ? ']' : ')');
334 }
335 break;
336 };
337 }
338
339 #define S12Z_N_SIZES 4
340 static const char shift_size_table[S12Z_N_SIZES] =
341 {
342 'b', 'w', 'p', 'l'
343 };
344
345 int
346 print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
347 {
348 int o;
349 enum optr operator = OP_INVALID;
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]);
369
370 /* Ship out size sufficies for those instructions which
371 need them. */
372 if (osize == -1)
373 {
374 bool suffix = false;
375
376 for (o = 0; o < n_operands; ++o)
377 {
378 if (operands[o] && operands[o]->osize != -1)
379 {
380 if (!suffix)
381 {
382 (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
383 suffix = true;
384 }
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
394 }
395 }
396 }
397 else
398 {
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]);
404 }
405
406 /* Ship out the operands. */
407 for (o = 0; o < n_operands; ++o)
408 {
409 if (operands[o])
410 opr_emit_disassembly (operands[o], mra.info);
411 free (operands[o]);
412 }
413
414 return n_bytes;
415 }
This page took 0.038083 seconds and 4 git commands to generate.