Skip to content

Commit bd86a88

Browse files
atgreenblueswirl
authored andcommitted
Add moxie disassembler
Signed-off-by: Anthony Green <[email protected]> Signed-off-by: Blue Swirl <[email protected]>
1 parent 525bd32 commit bd86a88

File tree

4 files changed

+369
-0
lines changed

4 files changed

+369
-0
lines changed

disas.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code,
256256
#elif defined(TARGET_MICROBLAZE)
257257
s.info.mach = bfd_arch_microblaze;
258258
print_insn = print_insn_microblaze;
259+
#elif defined(TARGET_MOXIE)
260+
s.info.mach = bfd_arch_moxie;
261+
print_insn = print_insn_moxie;
259262
#elif defined(TARGET_LM32)
260263
s.info.mach = bfd_mach_lm32;
261264
print_insn = print_insn_lm32;
@@ -462,6 +465,9 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
462465
#elif defined(TARGET_S390X)
463466
s.info.mach = bfd_mach_s390_64;
464467
print_insn = print_insn_s390;
468+
#elif defined(TARGET_MOXIE)
469+
s.info.mach = bfd_arch_moxie;
470+
print_insn = print_insn_moxie;
465471
#elif defined(TARGET_LM32)
466472
s.info.mach = bfd_mach_lm32;
467473
print_insn = print_insn_lm32;

disas/Makefile.objs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_IA64_DIS) += ia64.o
77
common-obj-$(CONFIG_M68K_DIS) += m68k.o
88
common-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o
99
common-obj-$(CONFIG_MIPS_DIS) += mips.o
10+
common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
1011
common-obj-$(CONFIG_PPC_DIS) += ppc.o
1112
common-obj-$(CONFIG_S390_DIS) += s390.o
1213
common-obj-$(CONFIG_SH4_DIS) += sh4.o

disas/moxie.c

Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
/* Disassemble moxie instructions.
2+
Copyright (c) 2009 Free Software Foundation, Inc.
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program; if not, see <http://www.gnu.org/licenses/>. */
16+
17+
#include <stdio.h>
18+
#define STATIC_TABLE
19+
#define DEFINE_TABLE
20+
21+
#include "disas/bfd.h"
22+
23+
static void *stream;
24+
25+
/* Form 1 instructions come in different flavors:
26+
27+
Some have no arguments (MOXIE_F1_NARG)
28+
Some only use the A operand (MOXIE_F1_A)
29+
Some use A and B registers (MOXIE_F1_AB)
30+
Some use A and consume a 4 byte immediate value (MOXIE_F1_A4)
31+
Some use just a 4 byte immediate value (MOXIE_F1_4)
32+
Some use just a 4 byte memory address (MOXIE_F1_M)
33+
Some use B and an indirect A (MOXIE_F1_AiB)
34+
Some use A and an indirect B (MOXIE_F1_ABi)
35+
Some consume a 4 byte immediate value and use X (MOXIE_F1_4A)
36+
Some use B and an indirect A plus 4 bytes (MOXIE_F1_AiB4)
37+
Some use A and an indirect B plus 4 bytes (MOXIE_F1_ABi4)
38+
39+
Form 2 instructions also come in different flavors:
40+
41+
Some have no arguments (MOXIE_F2_NARG)
42+
Some use the A register and an 8-bit value (MOXIE_F2_A8V)
43+
44+
Form 3 instructions also come in different flavors:
45+
46+
Some have no arguments (MOXIE_F3_NARG)
47+
Some have a 10-bit PC relative operand (MOXIE_F3_PCREL). */
48+
49+
#define MOXIE_F1_NARG 0x100
50+
#define MOXIE_F1_A 0x101
51+
#define MOXIE_F1_AB 0x102
52+
/* #define MOXIE_F1_ABC 0x103 */
53+
#define MOXIE_F1_A4 0x104
54+
#define MOXIE_F1_4 0x105
55+
#define MOXIE_F1_AiB 0x106
56+
#define MOXIE_F1_ABi 0x107
57+
#define MOXIE_F1_4A 0x108
58+
#define MOXIE_F1_AiB4 0x109
59+
#define MOXIE_F1_ABi4 0x10a
60+
#define MOXIE_F1_M 0x10b
61+
62+
#define MOXIE_F2_NARG 0x200
63+
#define MOXIE_F2_A8V 0x201
64+
65+
#define MOXIE_F3_NARG 0x300
66+
#define MOXIE_F3_PCREL 0x301
67+
68+
typedef struct moxie_opc_info_t {
69+
short opcode;
70+
unsigned itype;
71+
const char * name;
72+
} moxie_opc_info_t;
73+
74+
extern const moxie_opc_info_t moxie_form1_opc_info[64];
75+
extern const moxie_opc_info_t moxie_form2_opc_info[4];
76+
extern const moxie_opc_info_t moxie_form3_opc_info[16];
77+
78+
/* The moxie processor's 16-bit instructions come in two forms:
79+
80+
FORM 1 instructions start with a 0 bit...
81+
82+
0oooooooaaaabbbb
83+
0 F
84+
85+
ooooooo - form 1 opcode number
86+
aaaa - operand A
87+
bbbb - operand B
88+
89+
FORM 2 instructions start with bits "10"...
90+
91+
10ooaaaavvvvvvvv
92+
0 F
93+
94+
oo - form 2 opcode number
95+
aaaa - operand A
96+
vvvvvvvv - 8-bit immediate value
97+
98+
FORM 3 instructions start with a bits "11"...
99+
100+
11oooovvvvvvvvvv
101+
0 F
102+
103+
oooo - form 3 opcode number
104+
vvvvvvvvvv - 10-bit immediate value. */
105+
106+
const moxie_opc_info_t moxie_form1_opc_info[64] =
107+
{
108+
{ 0x00, MOXIE_F1_NARG, "nop" },
109+
{ 0x01, MOXIE_F1_A4, "ldi.l" },
110+
{ 0x02, MOXIE_F1_AB, "mov" },
111+
{ 0x03, MOXIE_F1_M, "jsra" },
112+
{ 0x04, MOXIE_F1_NARG, "ret" },
113+
{ 0x05, MOXIE_F1_AB, "add.l" },
114+
{ 0x06, MOXIE_F1_AB, "push" },
115+
{ 0x07, MOXIE_F1_AB, "pop" },
116+
{ 0x08, MOXIE_F1_A4, "lda.l" },
117+
{ 0x09, MOXIE_F1_4A, "sta.l" },
118+
{ 0x0a, MOXIE_F1_ABi, "ld.l" },
119+
{ 0x0b, MOXIE_F1_AiB, "st.l" },
120+
{ 0x0c, MOXIE_F1_ABi4, "ldo.l" },
121+
{ 0x0d, MOXIE_F1_AiB4, "sto.l" },
122+
{ 0x0e, MOXIE_F1_AB, "cmp" },
123+
{ 0x0f, MOXIE_F1_NARG, "bad" },
124+
{ 0x10, MOXIE_F1_NARG, "bad" },
125+
{ 0x11, MOXIE_F1_NARG, "bad" },
126+
{ 0x12, MOXIE_F1_NARG, "bad" },
127+
{ 0x13, MOXIE_F1_NARG, "bad" },
128+
{ 0x14, MOXIE_F1_NARG, "bad" },
129+
{ 0x15, MOXIE_F1_NARG, "bad" },
130+
{ 0x16, MOXIE_F1_NARG, "bad" },
131+
{ 0x17, MOXIE_F1_NARG, "bad" },
132+
{ 0x18, MOXIE_F1_NARG, "bad" },
133+
{ 0x19, MOXIE_F1_A, "jsr" },
134+
{ 0x1a, MOXIE_F1_M, "jmpa" },
135+
{ 0x1b, MOXIE_F1_A4, "ldi.b" },
136+
{ 0x1c, MOXIE_F1_ABi, "ld.b" },
137+
{ 0x1d, MOXIE_F1_A4, "lda.b" },
138+
{ 0x1e, MOXIE_F1_AiB, "st.b" },
139+
{ 0x1f, MOXIE_F1_4A, "sta.b" },
140+
{ 0x20, MOXIE_F1_A4, "ldi.s" },
141+
{ 0x21, MOXIE_F1_ABi, "ld.s" },
142+
{ 0x22, MOXIE_F1_A4, "lda.s" },
143+
{ 0x23, MOXIE_F1_AiB, "st.s" },
144+
{ 0x24, MOXIE_F1_4A, "sta.s" },
145+
{ 0x25, MOXIE_F1_A, "jmp" },
146+
{ 0x26, MOXIE_F1_AB, "and" },
147+
{ 0x27, MOXIE_F1_AB, "lshr" },
148+
{ 0x28, MOXIE_F1_AB, "ashl" },
149+
{ 0x29, MOXIE_F1_AB, "sub.l" },
150+
{ 0x2a, MOXIE_F1_AB, "neg" },
151+
{ 0x2b, MOXIE_F1_AB, "or" },
152+
{ 0x2c, MOXIE_F1_AB, "not" },
153+
{ 0x2d, MOXIE_F1_AB, "ashr" },
154+
{ 0x2e, MOXIE_F1_AB, "xor" },
155+
{ 0x2f, MOXIE_F1_AB, "mul.l" },
156+
{ 0x30, MOXIE_F1_4, "swi" },
157+
{ 0x31, MOXIE_F1_AB, "div.l" },
158+
{ 0x32, MOXIE_F1_AB, "udiv.l" },
159+
{ 0x33, MOXIE_F1_AB, "mod.l" },
160+
{ 0x34, MOXIE_F1_AB, "umod.l" },
161+
{ 0x35, MOXIE_F1_NARG, "brk" },
162+
{ 0x36, MOXIE_F1_ABi4, "ldo.b" },
163+
{ 0x37, MOXIE_F1_AiB4, "sto.b" },
164+
{ 0x38, MOXIE_F1_ABi4, "ldo.s" },
165+
{ 0x39, MOXIE_F1_AiB4, "sto.s" },
166+
{ 0x3a, MOXIE_F1_NARG, "bad" },
167+
{ 0x3b, MOXIE_F1_NARG, "bad" },
168+
{ 0x3c, MOXIE_F1_NARG, "bad" },
169+
{ 0x3d, MOXIE_F1_NARG, "bad" },
170+
{ 0x3e, MOXIE_F1_NARG, "bad" },
171+
{ 0x3f, MOXIE_F1_NARG, "bad" }
172+
};
173+
174+
const moxie_opc_info_t moxie_form2_opc_info[4] =
175+
{
176+
{ 0x00, MOXIE_F2_A8V, "inc" },
177+
{ 0x01, MOXIE_F2_A8V, "dec" },
178+
{ 0x02, MOXIE_F2_A8V, "gsr" },
179+
{ 0x03, MOXIE_F2_A8V, "ssr" }
180+
};
181+
182+
const moxie_opc_info_t moxie_form3_opc_info[16] =
183+
{
184+
{ 0x00, MOXIE_F3_PCREL,"beq" },
185+
{ 0x01, MOXIE_F3_PCREL,"bne" },
186+
{ 0x02, MOXIE_F3_PCREL,"blt" },
187+
{ 0x03, MOXIE_F3_PCREL,"bgt" },
188+
{ 0x04, MOXIE_F3_PCREL,"bltu" },
189+
{ 0x05, MOXIE_F3_PCREL,"bgtu" },
190+
{ 0x06, MOXIE_F3_PCREL,"bge" },
191+
{ 0x07, MOXIE_F3_PCREL,"ble" },
192+
{ 0x08, MOXIE_F3_PCREL,"bgeu" },
193+
{ 0x09, MOXIE_F3_PCREL,"bleu" },
194+
{ 0x0a, MOXIE_F3_NARG, "bad" },
195+
{ 0x0b, MOXIE_F3_NARG, "bad" },
196+
{ 0x0c, MOXIE_F3_NARG, "bad" },
197+
{ 0x0d, MOXIE_F3_NARG, "bad" },
198+
{ 0x0e, MOXIE_F3_NARG, "bad" },
199+
{ 0x0f, MOXIE_F3_NARG, "bad" }
200+
};
201+
202+
/* Macros to extract operands from the instruction word. */
203+
#define OP_A(i) ((i >> 4) & 0xf)
204+
#define OP_B(i) (i & 0xf)
205+
#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
206+
207+
static const char * reg_names[16] =
208+
{ "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
209+
"$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
210+
211+
int
212+
print_insn_moxie(bfd_vma addr, struct disassemble_info * info)
213+
{
214+
int length = 2;
215+
int status;
216+
stream = info->stream;
217+
const moxie_opc_info_t * opcode;
218+
bfd_byte buffer[4];
219+
unsigned short iword;
220+
fprintf_function fpr = info->fprintf_func;
221+
222+
if ((status = info->read_memory_func(addr, buffer, 2, info)))
223+
goto fail;
224+
iword = (bfd_getb16(buffer) >> 16);
225+
226+
/* Form 1 instructions have the high bit set to 0. */
227+
if ((iword & (1<<15)) == 0) {
228+
/* Extract the Form 1 opcode. */
229+
opcode = &moxie_form1_opc_info[iword >> 8];
230+
switch (opcode->itype) {
231+
case MOXIE_F1_NARG:
232+
fpr(stream, "%s", opcode->name);
233+
break;
234+
case MOXIE_F1_A:
235+
fpr(stream, "%s\t%s", opcode->name,
236+
reg_names[OP_A(iword)]);
237+
break;
238+
case MOXIE_F1_AB:
239+
fpr(stream, "%s\t%s, %s", opcode->name,
240+
reg_names[OP_A(iword)],
241+
reg_names[OP_B(iword)]);
242+
break;
243+
case MOXIE_F1_A4:
244+
{
245+
unsigned imm;
246+
if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
247+
goto fail;
248+
imm = bfd_getb32(buffer);
249+
fpr(stream, "%s\t%s, 0x%x", opcode->name,
250+
reg_names[OP_A(iword)], imm);
251+
length = 6;
252+
}
253+
break;
254+
case MOXIE_F1_4:
255+
{
256+
unsigned imm;
257+
if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
258+
goto fail;
259+
imm = bfd_getb32(buffer);
260+
fpr(stream, "%s\t0x%x", opcode->name, imm);
261+
length = 6;
262+
}
263+
break;
264+
case MOXIE_F1_M:
265+
{
266+
unsigned imm;
267+
if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
268+
goto fail;
269+
imm = bfd_getb32(buffer);
270+
fpr(stream, "%s\t", opcode->name);
271+
info->print_address_func((bfd_vma) imm, info);
272+
length = 6;
273+
}
274+
break;
275+
case MOXIE_F1_AiB:
276+
fpr (stream, "%s\t(%s), %s", opcode->name,
277+
reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
278+
break;
279+
case MOXIE_F1_ABi:
280+
fpr(stream, "%s\t%s, (%s)", opcode->name,
281+
reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
282+
break;
283+
case MOXIE_F1_4A:
284+
{
285+
unsigned imm;
286+
if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
287+
goto fail;
288+
imm = bfd_getb32(buffer);
289+
fpr(stream, "%s\t0x%x, %s",
290+
opcode->name, imm, reg_names[OP_A(iword)]);
291+
length = 6;
292+
}
293+
break;
294+
case MOXIE_F1_AiB4:
295+
{
296+
unsigned imm;
297+
if ((status = info->read_memory_func(addr+2, buffer, 4, info)))
298+
goto fail;
299+
imm = bfd_getb32(buffer);
300+
fpr(stream, "%s\t0x%x(%s), %s", opcode->name,
301+
imm,
302+
reg_names[OP_A(iword)],
303+
reg_names[OP_B(iword)]);
304+
length = 6;
305+
}
306+
break;
307+
case MOXIE_F1_ABi4:
308+
{
309+
unsigned imm;
310+
if ((status = info->read_memory_func(addr+2, buffer, 4, info)))
311+
goto fail;
312+
imm = bfd_getb32(buffer);
313+
fpr(stream, "%s\t%s, 0x%x(%s)",
314+
opcode->name,
315+
reg_names[OP_A(iword)],
316+
imm,
317+
reg_names[OP_B(iword)]);
318+
length = 6;
319+
}
320+
break;
321+
default:
322+
abort();
323+
}
324+
}
325+
else if ((iword & (1<<14)) == 0) {
326+
/* Extract the Form 2 opcode. */
327+
opcode = &moxie_form2_opc_info[(iword >> 12) & 3];
328+
switch (opcode->itype) {
329+
case MOXIE_F2_A8V:
330+
fpr(stream, "%s\t%s, 0x%x",
331+
opcode->name,
332+
reg_names[(iword >> 8) & 0xf],
333+
iword & ((1 << 8) - 1));
334+
break;
335+
case MOXIE_F2_NARG:
336+
fpr(stream, "%s", opcode->name);
337+
break;
338+
default:
339+
abort();
340+
}
341+
} else {
342+
/* Extract the Form 3 opcode. */
343+
opcode = &moxie_form3_opc_info[(iword >> 10) & 15];
344+
switch (opcode->itype) {
345+
case MOXIE_F3_PCREL:
346+
fpr(stream, "%s\t", opcode->name);
347+
info->print_address_func((bfd_vma) (addr + INST2OFFSET(iword) + 2),
348+
info);
349+
break;
350+
default:
351+
abort();
352+
}
353+
}
354+
355+
return length;
356+
357+
fail:
358+
info->memory_error_func(status, addr, info);
359+
return -1;
360+
}

0 commit comments

Comments
 (0)