Commit | Line | Data |
---|---|---|
20135e4c | 1 | /* Disassemble moxie instructions. |
df7b86aa | 2 | Copyright 2009, 2012 |
20135e4c NC |
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 | ||
20135e4c | 22 | #include "sysdep.h" |
df7b86aa NC |
23 | #include <stdio.h> |
24 | ||
20135e4c NC |
25 | #define STATIC_TABLE |
26 | #define DEFINE_TABLE | |
27 | ||
28 | #include "opcode/moxie.h" | |
29 | #include "dis-asm.h" | |
30 | ||
31 | static fprintf_ftype fpr; | |
32 | static void *stream; | |
33 | ||
34 | /* Macros to extract operands from the instruction word. */ | |
35 | #define OP_A(i) ((i >> 4) & 0xf) | |
36 | #define OP_B(i) (i & 0xf) | |
f865a31d | 37 | #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1) |
20135e4c NC |
38 | |
39 | static const char * reg_names[16] = | |
40 | { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", | |
41 | "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" }; | |
42 | ||
43 | int | |
44 | print_insn_moxie (bfd_vma addr, struct disassemble_info * info) | |
45 | { | |
46 | int length = 2; | |
47 | int status; | |
48 | stream = info->stream; | |
49 | const moxie_opc_info_t * opcode; | |
50 | bfd_byte buffer[4]; | |
51 | unsigned short iword; | |
52 | fpr = info->fprintf_func; | |
53 | ||
54 | if ((status = info->read_memory_func (addr, buffer, 2, info))) | |
55 | goto fail; | |
56 | iword = bfd_getb16 (buffer); | |
57 | ||
58 | /* Form 1 instructions have the high bit set to 0. */ | |
59 | if ((iword & (1<<15)) == 0) | |
60 | { | |
61 | /* Extract the Form 1 opcode. */ | |
62 | opcode = &moxie_form1_opc_info[iword >> 8]; | |
63 | switch (opcode->itype) | |
64 | { | |
65 | case MOXIE_F1_NARG: | |
66 | fpr (stream, "%s", opcode->name); | |
67 | break; | |
68 | case MOXIE_F1_A: | |
69 | fpr (stream, "%s\t%s", opcode->name, | |
70 | reg_names[OP_A(iword)]); | |
71 | break; | |
72 | case MOXIE_F1_AB: | |
73 | fpr (stream, "%s\t%s, %s", opcode->name, | |
74 | reg_names[OP_A(iword)], | |
75 | reg_names[OP_B(iword)]); | |
76 | break; | |
77 | case MOXIE_F1_A4: | |
78 | { | |
79 | unsigned imm; | |
80 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
81 | goto fail; | |
82 | imm = bfd_getb32 (buffer); | |
83 | fpr (stream, "%s\t%s, 0x%x", opcode->name, | |
84 | reg_names[OP_A(iword)], imm); | |
85 | length = 6; | |
86 | } | |
87 | break; | |
88 | case MOXIE_F1_4: | |
89 | { | |
90 | unsigned imm; | |
91 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
92 | goto fail; | |
93 | imm = bfd_getb32 (buffer); | |
94 | fpr (stream, "%s\t0x%x", opcode->name, imm); | |
95 | length = 6; | |
96 | } | |
97 | break; | |
0e7c7f11 AG |
98 | case MOXIE_F1_M: |
99 | { | |
100 | unsigned imm; | |
101 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
102 | goto fail; | |
103 | imm = bfd_getb32 (buffer); | |
104 | fpr (stream, "%s\t", opcode->name); | |
105 | info->print_address_func ((bfd_vma) imm, info); | |
106 | length = 6; | |
107 | } | |
108 | break; | |
20135e4c NC |
109 | case MOXIE_F1_AiB: |
110 | fpr (stream, "%s\t(%s), %s", opcode->name, | |
111 | reg_names[OP_A(iword)], reg_names[OP_B(iword)]); | |
112 | break; | |
113 | case MOXIE_F1_ABi: | |
114 | fpr (stream, "%s\t%s, (%s)", opcode->name, | |
115 | reg_names[OP_A(iword)], reg_names[OP_B(iword)]); | |
116 | break; | |
117 | case MOXIE_F1_4A: | |
118 | { | |
119 | unsigned imm; | |
120 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
121 | goto fail; | |
122 | imm = bfd_getb32 (buffer); | |
123 | fpr (stream, "%s\t0x%x, %s", | |
124 | opcode->name, imm, reg_names[OP_A(iword)]); | |
125 | length = 6; | |
126 | } | |
127 | break; | |
128 | case MOXIE_F1_AiB4: | |
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\t0x%x(%s), %s", opcode->name, | |
135 | imm, | |
136 | reg_names[OP_A(iword)], | |
137 | reg_names[OP_B(iword)]); | |
138 | length = 6; | |
139 | } | |
140 | break; | |
141 | case MOXIE_F1_ABi4: | |
142 | { | |
143 | unsigned imm; | |
144 | if ((status = info->read_memory_func (addr+2, buffer, 4, info))) | |
145 | goto fail; | |
146 | imm = bfd_getb32 (buffer); | |
147 | fpr (stream, "%s\t%s, 0x%x(%s)", | |
148 | opcode->name, | |
149 | reg_names[OP_A(iword)], | |
150 | imm, | |
151 | reg_names[OP_B(iword)]); | |
152 | length = 6; | |
153 | } | |
154 | break; | |
155 | default: | |
156 | abort (); | |
157 | } | |
158 | } | |
159 | else if ((iword & (1<<14)) == 0) | |
160 | { | |
161 | /* Extract the Form 2 opcode. */ | |
162 | opcode = &moxie_form2_opc_info[(iword >> 12) & 3]; | |
163 | switch (opcode->itype) | |
164 | { | |
165 | case MOXIE_F2_A8V: | |
166 | fpr (stream, "%s\t%s, 0x%x", | |
167 | opcode->name, | |
168 | reg_names[(iword >> 8) & 0xf], | |
169 | iword & ((1 << 8) - 1)); | |
170 | break; | |
171 | case MOXIE_F2_NARG: | |
172 | fpr (stream, "%s", opcode->name); | |
173 | break; | |
174 | default: | |
175 | abort(); | |
176 | } | |
177 | } | |
178 | else | |
179 | { | |
180 | /* Extract the Form 3 opcode. */ | |
f865a31d | 181 | opcode = &moxie_form3_opc_info[(iword >> 10) & 15]; |
20135e4c NC |
182 | switch (opcode->itype) |
183 | { | |
f865a31d AG |
184 | case MOXIE_F3_PCREL: |
185 | fpr (stream, "%s\t", opcode->name); | |
186 | info->print_address_func ((bfd_vma) (addr + INST2OFFSET(iword)), | |
187 | info); | |
20135e4c NC |
188 | break; |
189 | default: | |
190 | abort(); | |
191 | } | |
192 | } | |
193 | ||
194 | return length; | |
195 | ||
196 | fail: | |
197 | info->memory_error_func (status, addr, info); | |
198 | return -1; | |
199 | } |