Commit | Line | Data |
---|---|---|
20135e4c NC |
1 | /* Disassemble moxie instructions. |
2 | Copyright 2009 | |
3 | Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of the GNU opcodes library. | |
6 | ||
7 | This library is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
11 | ||
12 | It is distributed in the hope that it will be useful, but WITHOUT | |
13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | |
20 | MA 02110-1301, USA. */ | |
21 | ||
22 | #include <stdio.h> | |
23 | #include "sysdep.h" | |
24 | #define STATIC_TABLE | |
25 | #define DEFINE_TABLE | |
26 | ||
27 | #include "opcode/moxie.h" | |
28 | #include "dis-asm.h" | |
29 | ||
30 | static fprintf_ftype fpr; | |
31 | static void *stream; | |
32 | ||
33 | /* Macros to extract operands from the instruction word. */ | |
34 | #define OP_A(i) ((i >> 4) & 0xf) | |
35 | #define OP_B(i) (i & 0xf) | |
36 | ||
37 | static const char * reg_names[16] = | |
38 | { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", | |
39 | "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" }; | |
40 | ||
41 | int | |
42 | print_insn_moxie (bfd_vma addr, struct disassemble_info * info) | |
43 | { | |
44 | int length = 2; | |
45 | int status; | |
46 | stream = info->stream; | |
47 | const moxie_opc_info_t * opcode; | |
48 | bfd_byte buffer[4]; | |
49 | unsigned short iword; | |
50 | fpr = info->fprintf_func; | |
51 | ||
52 | if ((status = info->read_memory_func (addr, buffer, 2, info))) | |
53 | goto fail; | |
54 | iword = bfd_getb16 (buffer); | |
55 | ||
56 | /* Form 1 instructions have the high bit set to 0. */ | |
57 | if ((iword & (1<<15)) == 0) | |
58 | { | |
59 | /* Extract the Form 1 opcode. */ | |
60 | opcode = &moxie_form1_opc_info[iword >> 8]; | |
61 | switch (opcode->itype) | |
62 | { | |
63 | case MOXIE_F1_NARG: | |
64 | fpr (stream, "%s", opcode->name); | |
65 | break; | |
66 | case MOXIE_F1_A: | |
67 | fpr (stream, "%s\t%s", opcode->name, | |
68 | reg_names[OP_A(iword)]); | |
69 | break; | |
70 | case MOXIE_F1_AB: | |
71 | fpr (stream, "%s\t%s, %s", opcode->name, | |
72 | reg_names[OP_A(iword)], | |
73 | reg_names[OP_B(iword)]); | |
74 | break; | |
75 | case MOXIE_F1_A4: | |
76 | { | |
77 | unsigned imm; | |
78 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
79 | goto fail; | |
80 | imm = bfd_getb32 (buffer); | |
81 | fpr (stream, "%s\t%s, 0x%x", opcode->name, | |
82 | reg_names[OP_A(iword)], imm); | |
83 | length = 6; | |
84 | } | |
85 | break; | |
86 | case MOXIE_F1_4: | |
87 | { | |
88 | unsigned imm; | |
89 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
90 | goto fail; | |
91 | imm = bfd_getb32 (buffer); | |
92 | fpr (stream, "%s\t0x%x", opcode->name, imm); | |
93 | length = 6; | |
94 | } | |
95 | break; | |
96 | case MOXIE_F1_AiB: | |
97 | fpr (stream, "%s\t(%s), %s", opcode->name, | |
98 | reg_names[OP_A(iword)], reg_names[OP_B(iword)]); | |
99 | break; | |
100 | case MOXIE_F1_ABi: | |
101 | fpr (stream, "%s\t%s, (%s)", opcode->name, | |
102 | reg_names[OP_A(iword)], reg_names[OP_B(iword)]); | |
103 | break; | |
104 | case MOXIE_F1_4A: | |
105 | { | |
106 | unsigned imm; | |
107 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
108 | goto fail; | |
109 | imm = bfd_getb32 (buffer); | |
110 | fpr (stream, "%s\t0x%x, %s", | |
111 | opcode->name, imm, reg_names[OP_A(iword)]); | |
112 | length = 6; | |
113 | } | |
114 | break; | |
115 | case MOXIE_F1_AiB4: | |
116 | { | |
117 | unsigned imm; | |
118 | if ((status = info->read_memory_func (addr+2, buffer, 4, info))) | |
119 | goto fail; | |
120 | imm = bfd_getb32 (buffer); | |
121 | fpr (stream, "%s\t0x%x(%s), %s", opcode->name, | |
122 | imm, | |
123 | reg_names[OP_A(iword)], | |
124 | reg_names[OP_B(iword)]); | |
125 | length = 6; | |
126 | } | |
127 | break; | |
128 | case MOXIE_F1_ABi4: | |
129 | { | |
130 | unsigned imm; | |
131 | if ((status = info->read_memory_func (addr+2, buffer, 4, info))) | |
132 | goto fail; | |
133 | imm = bfd_getb32 (buffer); | |
134 | fpr (stream, "%s\t%s, 0x%x(%s)", | |
135 | opcode->name, | |
136 | reg_names[OP_A(iword)], | |
137 | imm, | |
138 | reg_names[OP_B(iword)]); | |
139 | length = 6; | |
140 | } | |
141 | break; | |
142 | default: | |
143 | abort (); | |
144 | } | |
145 | } | |
146 | else if ((iword & (1<<14)) == 0) | |
147 | { | |
148 | /* Extract the Form 2 opcode. */ | |
149 | opcode = &moxie_form2_opc_info[(iword >> 12) & 3]; | |
150 | switch (opcode->itype) | |
151 | { | |
152 | case MOXIE_F2_A8V: | |
153 | fpr (stream, "%s\t%s, 0x%x", | |
154 | opcode->name, | |
155 | reg_names[(iword >> 8) & 0xf], | |
156 | iword & ((1 << 8) - 1)); | |
157 | break; | |
158 | case MOXIE_F2_NARG: | |
159 | fpr (stream, "%s", opcode->name); | |
160 | break; | |
161 | default: | |
162 | abort(); | |
163 | } | |
164 | } | |
165 | else | |
166 | { | |
167 | /* Extract the Form 3 opcode. */ | |
168 | opcode = &moxie_form2_opc_info[(iword >> 12) & 3]; | |
169 | switch (opcode->itype) | |
170 | { | |
171 | case MOXIE_F3_NARG: | |
172 | fpr (stream, "%s", opcode->name); | |
173 | break; | |
174 | default: | |
175 | abort(); | |
176 | } | |
177 | } | |
178 | ||
179 | return length; | |
180 | ||
181 | fail: | |
182 | info->memory_error_func (status, addr, info); | |
183 | return -1; | |
184 | } |