Annotation of src/external/gpl3/binutils.old/dist/opcodes/rl78-dis.c, Revision 1.7
1.1 christos 1: /* Disassembler code for Renesas RL78.
1.7 ! christos 2: Copyright (C) 2011-2020 Free Software Foundation, Inc.
1.1 christos 3: Contributed by Red Hat.
4: Written by DJ Delorie.
5:
6: This file is part of the GNU opcodes library.
7:
8: This library is free software; you can redistribute it and/or modify
9: it under the terms of the GNU General Public License as published by
10: the Free Software Foundation; either version 3, or (at your option)
11: any later version.
12:
13: It is distributed in the hope that it will be useful, but WITHOUT
14: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16: License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21: MA 02110-1301, USA. */
22:
23: #include "sysdep.h"
24: #include <stdio.h>
25:
26: #include "bfd.h"
1.3 christos 27: #include "elf-bfd.h"
1.6 christos 28: #include "disassemble.h"
1.1 christos 29: #include "opcode/rl78.h"
1.3 christos 30: #include "elf/rl78.h"
1.1 christos 31:
1.6 christos 32: #include <setjmp.h>
33:
1.1 christos 34: #define DEBUG_SEMANTICS 0
35:
36: typedef struct
37: {
38: bfd_vma pc;
39: disassemble_info * dis;
40: } RL78_Data;
41:
1.6 christos 42: struct private
43: {
44: OPCODES_SIGJMP_BUF bailout;
45: };
46:
1.1 christos 47: static int
48: rl78_get_byte (void * vdata)
49: {
50: bfd_byte buf[1];
51: RL78_Data *rl78_data = (RL78_Data *) vdata;
1.6 christos 52: int status;
53:
54: status = rl78_data->dis->read_memory_func (rl78_data->pc,
55: buf,
56: 1,
57: rl78_data->dis);
58: if (status != 0)
59: {
60: struct private *priv = (struct private *) rl78_data->dis->private_data;
1.1 christos 61:
1.6 christos 62: rl78_data->dis->memory_error_func (status, rl78_data->pc,
63: rl78_data->dis);
64: OPCODES_SIGLONGJMP (priv->bailout, 1);
65: }
1.1 christos 66:
67: rl78_data->pc ++;
68: return buf[0];
69: }
70:
71: static char const *
72: register_names[] =
73: {
74: "",
75: "x", "a", "c", "b", "e", "d", "l", "h",
76: "ax", "bc", "de", "hl",
77: "sp", "psw", "cs", "es", "pmc", "mem"
78: };
79:
80: static char const *
81: condition_names[] =
82: {
83: "t", "f", "c", "nc", "h", "nh", "z", "nz"
84: };
85:
86: static int
87: indirect_type (int t)
88: {
89: switch (t)
90: {
91: case RL78_Operand_Indirect:
92: case RL78_Operand_BitIndirect:
93: case RL78_Operand_PostInc:
94: case RL78_Operand_PreDec:
95: return 1;
96: default:
97: return 0;
98: }
99: }
100:
1.3 christos 101: static int
102: print_insn_rl78_common (bfd_vma addr, disassemble_info * dis, RL78_Dis_Isa isa)
1.1 christos 103: {
104: int rv;
105: RL78_Data rl78_data;
106: RL78_Opcode_Decoded opcode;
107: const char * s;
108: #if DEBUG_SEMANTICS
109: static char buf[200];
110: #endif
1.6 christos 111: struct private priv;
1.1 christos 112:
1.6 christos 113: dis->private_data = (PTR) &priv;
1.1 christos 114: rl78_data.pc = addr;
115: rl78_data.dis = dis;
116:
1.6 christos 117: if (OPCODES_SIGSETJMP (priv.bailout) != 0)
118: {
119: /* Error return. */
120: return -1;
121: }
122:
1.3 christos 123: rv = rl78_decode_opcode (addr, &opcode, rl78_get_byte, &rl78_data, isa);
1.1 christos 124:
125: dis->bytes_per_line = 10;
126:
127: #define PR (dis->fprintf_func)
128: #define PS (dis->stream)
129: #define PC(c) PR (PS, "%c", c)
130:
131: s = opcode.syntax;
132:
133: #if DEBUG_SEMANTICS
134:
135: switch (opcode.id)
136: {
137: case RLO_unknown: s = "uknown"; break;
138: case RLO_add: s = "add: %e0%0 += %e1%1"; break;
139: case RLO_addc: s = "addc: %e0%0 += %e1%1 + CY"; break;
140: case RLO_and: s = "and: %e0%0 &= %e1%1"; break;
141: case RLO_branch: s = "branch: pc = %e0%0"; break;
142: case RLO_branch_cond: s = "branch_cond: pc = %e0%0 if %c1 / %e1%1"; break;
143: case RLO_branch_cond_clear: s = "branch_cond_clear: pc = %e0%0 if %c1 / %e1%1, %e1%1 = 0"; break;
144: case RLO_call: s = "call: pc = %e1%0"; break;
145: case RLO_cmp: s = "cmp: %e0%0 - %e1%1"; break;
146: case RLO_mov: s = "mov: %e0%0 = %e1%1"; break;
147: case RLO_or: s = "or: %e0%0 |= %e1%1"; break;
148: case RLO_rol: s = "rol: %e0%0 <<= %e1%1"; break;
149: case RLO_rolc: s = "rol: %e0%0 <<= %e1%1,CY"; break;
150: case RLO_ror: s = "ror: %e0%0 >>= %e1%1"; break;
151: case RLO_rorc: s = "ror: %e0%0 >>= %e1%1,CY"; break;
152: case RLO_sar: s = "sar: %e0%0 >>= %e1%1 signed"; break;
153: case RLO_sel: s = "sel: rb = %1"; break;
154: case RLO_shr: s = "shr: %e0%0 >>= %e1%1 unsigned"; break;
155: case RLO_shl: s = "shl: %e0%0 <<= %e1%1"; break;
156: case RLO_skip: s = "skip: if %c1"; break;
157: case RLO_sub: s = "sub: %e0%0 -= %e1%1"; break;
158: case RLO_subc: s = "subc: %e0%0 -= %e1%1 - CY"; break;
159: case RLO_xch: s = "xch: %e0%0 <-> %e1%1"; break;
160: case RLO_xor: s = "xor: %e0%0 ^= %e1%1"; break;
161: }
162:
163: sprintf(buf, "%s%%W%%f\t\033[32m%s\033[0m", s, opcode.syntax);
164: s = buf;
165:
166: #endif
167:
168: for (; *s; s++)
169: {
170: if (*s != '%')
171: {
172: PC (*s);
173: }
174: else
175: {
176: RL78_Opcode_Operand * oper;
177: int do_hex = 0;
178: int do_addr = 0;
179: int do_es = 0;
180: int do_sfr = 0;
181: int do_cond = 0;
182: int do_bang = 0;
183:
1.3 christos 184: while (1)
1.1 christos 185: {
1.3 christos 186: s ++;
187: switch (*s)
188: {
189: case 'x':
190: do_hex = 1;
191: break;
192: case '!':
193: do_bang = 1;
194: break;
195: case 'e':
196: do_es = 1;
197: break;
198: case 'a':
199: do_addr = 1;
200: break;
201: case 's':
202: do_sfr = 1;
203: break;
204: case 'c':
205: do_cond = 1;
206: break;
207: default:
208: goto no_more_modifiers;
209: }
1.1 christos 210: }
1.3 christos 211: no_more_modifiers:;
1.1 christos 212:
213: switch (*s)
214: {
215: case '%':
216: PC ('%');
217: break;
218:
219: #if DEBUG_SEMANTICS
220:
221: case 'W':
222: if (opcode.size == RL78_Word)
223: PR (PS, " \033[33mW\033[0m");
224: break;
225:
226: case 'f':
227: if (opcode.flags)
228: {
229: char *comma = "";
230: PR (PS, " \033[35m");
1.3 christos 231:
1.1 christos 232: if (opcode.flags & RL78_PSW_Z)
233: { PR (PS, "Z"); comma = ","; }
234: if (opcode.flags & RL78_PSW_AC)
235: { PR (PS, "%sAC", comma); comma = ","; }
236: if (opcode.flags & RL78_PSW_CY)
237: { PR (PS, "%sCY", comma); comma = ","; }
238: PR (PS, "\033[0m");
239: }
240: break;
241:
242: #endif
243:
244: case '0':
245: case '1':
1.3 christos 246: oper = *s == '0' ? &opcode.op[0] : &opcode.op[1];
247: if (do_es)
248: {
249: if (oper->use_es && indirect_type (oper->type))
250: PR (PS, "es:");
251: }
252:
253: if (do_bang)
1.5 christos 254: {
255: /* If we are going to display SP by name, we must omit the bang. */
256: if ((oper->type == RL78_Operand_Indirect
257: || oper->type == RL78_Operand_BitIndirect)
258: && oper->reg == RL78_Reg_None
259: && do_sfr
260: && ((oper->addend == 0xffff8 && opcode.size == RL78_Word)
261: || (oper->addend == 0x0fff8 && do_es && opcode.size == RL78_Word)))
262: ;
263: else
264: PC ('!');
265: }
1.3 christos 266:
267: if (do_cond)
268: {
269: PR (PS, "%s", condition_names[oper->condition]);
270: break;
271: }
272:
273: switch (oper->type)
274: {
275: case RL78_Operand_Immediate:
276: if (do_addr)
277: dis->print_address_func (oper->addend, dis);
278: else if (do_hex
279: || oper->addend > 999
280: || oper->addend < -999)
281: PR (PS, "%#x", oper->addend);
282: else
283: PR (PS, "%d", oper->addend);
284: break;
285:
286: case RL78_Operand_Register:
287: PR (PS, "%s", register_names[oper->reg]);
288: break;
289:
290: case RL78_Operand_Bit:
291: PR (PS, "%s.%d", register_names[oper->reg], oper->bit_number);
292: break;
293:
294: case RL78_Operand_Indirect:
295: case RL78_Operand_BitIndirect:
296: switch (oper->reg)
1.1 christos 297: {
1.3 christos 298: case RL78_Reg_None:
299: if (oper->addend == 0xffffa && do_sfr && opcode.size == RL78_Byte)
300: PR (PS, "psw");
301: else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Word)
302: PR (PS, "sp");
1.5 christos 303: else if (oper->addend == 0x0fff8 && do_sfr && do_es && opcode.size == RL78_Word)
304: PR (PS, "sp");
1.3 christos 305: else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Byte)
306: PR (PS, "spl");
307: else if (oper->addend == 0xffff9 && do_sfr && opcode.size == RL78_Byte)
308: PR (PS, "sph");
309: else if (oper->addend == 0xffffc && do_sfr && opcode.size == RL78_Byte)
310: PR (PS, "cs");
311: else if (oper->addend == 0xffffd && do_sfr && opcode.size == RL78_Byte)
312: PR (PS, "es");
313: else if (oper->addend == 0xffffe && do_sfr && opcode.size == RL78_Byte)
314: PR (PS, "pmc");
315: else if (oper->addend == 0xfffff && do_sfr && opcode.size == RL78_Byte)
316: PR (PS, "mem");
317: else if (oper->addend >= 0xffe20)
1.1 christos 318: PR (PS, "%#x", oper->addend);
319: else
1.3 christos 320: {
321: int faddr = oper->addend;
322: if (do_es && ! oper->use_es)
323: faddr += 0xf0000;
324: dis->print_address_func (faddr, dis);
325: }
1.1 christos 326: break;
327:
1.3 christos 328: case RL78_Reg_B:
329: case RL78_Reg_C:
330: case RL78_Reg_BC:
331: PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]);
1.1 christos 332: break;
333:
1.3 christos 334: default:
335: PR (PS, "[%s", register_names[oper->reg]);
336: if (oper->reg2 != RL78_Reg_None)
337: PR (PS, "+%s", register_names[oper->reg2]);
338: if (oper->addend || do_addr)
339: PR (PS, "+%d", oper->addend);
340: PC (']');
1.1 christos 341: break;
342:
1.3 christos 343: }
344: if (oper->type == RL78_Operand_BitIndirect)
345: PR (PS, ".%d", oper->bit_number);
346: break;
1.1 christos 347:
348: #if DEBUG_SEMANTICS
1.3 christos 349: /* Shouldn't happen - push and pop don't print
350: [SP] directly. But we *do* use them for
351: semantic debugging. */
352: case RL78_Operand_PostInc:
353: PR (PS, "[%s++]", register_names[oper->reg]);
354: break;
355: case RL78_Operand_PreDec:
356: PR (PS, "[--%s]", register_names[oper->reg]);
357: break;
1.1 christos 358: #endif
359:
1.3 christos 360: default:
361: /* If we ever print this, that means the
362: programmer tried to print an operand with a
363: type we don't expect. Print the line and
364: operand number from rl78-decode.opc for
365: them. */
366: PR (PS, "???%d.%d", opcode.lineno, *s - '0');
367: break;
368: }
1.1 christos 369: }
370: }
371: }
372:
373: #if DEBUG_SEMANTICS
374:
375: PR (PS, "\t\033[34m(line %d)\033[0m", opcode.lineno);
376:
377: #endif
378:
379: return rv;
380: }
1.3 christos 381:
382: int
383: print_insn_rl78 (bfd_vma addr, disassemble_info * dis)
384: {
385: return print_insn_rl78_common (addr, dis, RL78_ISA_DEFAULT);
386: }
387:
388: int
389: print_insn_rl78_g10 (bfd_vma addr, disassemble_info * dis)
390: {
391: return print_insn_rl78_common (addr, dis, RL78_ISA_G10);
392: }
393:
394: int
395: print_insn_rl78_g13 (bfd_vma addr, disassemble_info * dis)
396: {
397: return print_insn_rl78_common (addr, dis, RL78_ISA_G13);
398: }
399:
400: int
401: print_insn_rl78_g14 (bfd_vma addr, disassemble_info * dis)
402: {
403: return print_insn_rl78_common (addr, dis, RL78_ISA_G14);
404: }
405:
406: disassembler_ftype
407: rl78_get_disassembler (bfd *abfd)
408: {
1.6 christos 409: int cpu = E_FLAG_RL78_ANY_CPU;
410:
411: if (abfd != NULL)
412: cpu = abfd->tdata.elf_obj_data->elf_header->e_flags & E_FLAG_RL78_CPU_MASK;
413:
1.3 christos 414: switch (cpu)
415: {
416: case E_FLAG_RL78_G10:
417: return print_insn_rl78_g10;
418: case E_FLAG_RL78_G13:
419: return print_insn_rl78_g13;
420: case E_FLAG_RL78_G14:
421: return print_insn_rl78_g14;
422: default:
423: return print_insn_rl78;
424: }
425: }
CVSweb <webmaster@jp.NetBSD.org>