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