comparison jagcpu.c @ 1093:4987fddd42a0

Initial stab at jaguar disassemler
author Michael Pavone <pavone@retrodev.com>
date Sun, 30 Oct 2016 19:42:48 -0700
parents
children 1dba006bad47
comparison
equal deleted inserted replaced
1092:f338c950fcef 1093:4987fddd42a0
1 #include <stdint.h>
2 #include <stdio.h>
3 #include "jagcpu.h"
4
5 char *gpu_mnemonics[] = {
6 "add",
7 "addc",
8 "addq",
9 "addqt",
10 "sub",
11 "subc",
12 "subq",
13 "subqt",
14 "neg",
15 "and",
16 "or",
17 "xor",
18 "not",
19 "btst",
20 "bset",
21 "bclr",
22 "mult",
23 "imult",
24 "imultn",
25 "resmac",
26 "imacn",
27 "div",
28 "abs",
29 "sh",
30 "shlq",
31 "shrq",
32 "sha",
33 "sharq",
34 "ror",
35 "rorq",
36 "cmp",
37 "cmpq",
38 "sat8",
39 "sat16",
40 "move",
41 "moveq",
42 "moveta",
43 "movefa",
44 "movei",
45 "loadb",
46 "loadw",
47 "load",
48 "loadp",
49 "load", //r14 relative
50 "load", //r15 relative
51 "storeb",
52 "storew",
53 "store",
54 "storep",
55 "store", //r14 relative
56 "store", //r15 relative
57 "move", //PC
58 "jump",
59 "jr",
60 "mmult",
61 "mtoi",
62 "normi",
63 "nop",
64 "load", //r14 indexed
65 "load", //r15 indexed
66 "store", //r14 indexed
67 "store", //r15 indexed
68 "sat24",
69 "pack",
70 "unpack"
71 };
72
73 char *dsp_mnemonics[DSP_ADDQMOD+1] = {
74 [DSP_SUBQMOD] = "subqmod",
75 [DSP_SAT16S] = "sat16s",
76 [DSP_SAT32S] = "sat32s",
77 [DSP_MIRROR] = "mirror",
78 [DSP_ADDQMOD] = "addqmod"
79 };
80
81 void init_dsp_mnemonic_table()
82 {
83 static uint8_t init_done;
84 if (init_done) {
85 return;
86 }
87 for (int i = 0; i < DSP_ADDQMOD; i++)
88 {
89 if (!dsp_mnemonics[i]) {
90 dsp_mnemonics[i] = gpu_mnemonics[i];
91 }
92 }
93 init_done = 1;
94 }
95
96 uint16_t jag_opcode(uint16_t inst, uint8_t is_gpu)
97 {
98 uint16_t opcode = inst >> 11;
99 if (is_gpu && opcode == GPU_PACK && (inst & 0x20)) {
100 return GPU_UNPACK;
101 }
102 return opcode;
103 }
104
105 uint16_t jag_reg2(uint16_t inst)
106 {
107 return inst & 0x1F;
108 }
109
110 uint16_t jag_reg1(uint16_t inst)
111 {
112 return inst >> 5 & 0x1F;
113 }
114
115 //moveq and bit instructions should just use jag_reg1 instead
116 uint32_t jag_quick(uint16_t inst)
117 {
118 uint32_t val = inst >> 5 & 0x1F;
119 return val ? val : 32;
120 }
121
122 uint8_t is_quick_1_32_opcode(uint16_t opcode, uint8_t is_gpu)
123 {
124 return opcode == JAG_ADDQ
125 || opcode == JAG_ADDQT
126 || opcode == JAG_SUBQ
127 || opcode == JAG_SUBQT
128 || opcode == JAG_SHLQ
129 || opcode == JAG_SHRQ
130 || opcode == JAG_SHARQ
131 || opcode == JAG_RORQ
132 || (!is_gpu && (
133 opcode == DSP_SUBQMOD
134 || opcode == DSP_ADDQMOD
135 ));
136 }
137
138 uint8_t is_quick_0_31_opcode(uint16_t opcode)
139 {
140 return opcode == JAG_MOVEQ
141 || opcode == JAG_BTST
142 || opcode == JAG_BSET
143 || opcode == JAG_BCLR;
144 }
145
146 char * jag_cc_names[] = {
147 "t",
148 "ne",
149 "eq",
150 "f",
151 "cc",
152 "hi",
153 "eq_cc",
154 "f",
155 "cs",
156 "ne_cs",
157 "eq_cs",
158 "f",
159 "f",
160 "f",
161 "f",
162 "f"
163 "t_alt",
164 "ne_alt",
165 "eq_alt",
166 "f",
167 "pl",
168 "ne_pl",
169 "eq_pl",
170 "f",
171 "mi",
172 "ne_mi",
173 "eq_mi"
174 };
175
176 char * jag_cc(uint16_t inst)
177 {
178 uint16_t ccnum = jag_reg2(inst);
179 if (ccnum >= sizeof(jag_cc_names)/sizeof(*jag_cc_names)) {
180 return jag_cc_names[3];
181 }
182 return jag_cc_names[ccnum];
183 }
184
185 uint32_t jag_jr_dest(uint16_t inst, uint32_t address)
186 {
187 uint32_t rel = jag_reg1(inst);
188 if (rel & 0x10) {
189 rel |= 0xFFFFFFE0;
190 }
191 return address + 2 + rel;
192 }
193
194 int jag_cpu_disasm(uint16_t **stream, uint32_t address, char *dst, uint8_t is_gpu, uint8_t labels)
195 {
196 uint16_t inst = **stream;
197 *stream++;
198 uint16_t opcode = jag_opcode(inst, is_gpu);
199 char **mnemonics;
200 if (is_gpu) {
201 mnemonics = gpu_mnemonics;
202 } else {
203 init_dsp_mnemonic_table();
204 mnemonics = dsp_mnemonics;
205 }
206 switch (opcode)
207 {
208 case JAG_MOVEI: {
209 uint32_t immed = **stream;
210 *stream++;
211 immed |= **stream << 16;
212 *stream++;
213 return sprintf("%s $%X, r%d", mnemonics[opcode], immed, jag_reg2(inst));
214 }
215 case JAG_JR:
216 return sprintf(
217 labels ? "%s %s, ADR_%X" : "%s %s, $W%X",
218 mnemonics[opcode], jag_cc(inst), jag_jr_dest(inst, address)
219 );
220 case JAG_JUMP:
221 return sprintf("%s %s, (r%d)", mnemonics[opcode], jag_cc(inst), jag_reg1(inst));
222 default:
223 if (is_quick_1_32_opcode(opcode, is_gpu)) {
224 return sprintf("%s %d, r%d", mnemonics[opcode], jag_quick(inst), jag_reg2(inst));
225 } else if (is_quick_0_31_opcode(opcode)) {
226 return sprintf("%s %d, r%d", mnemonics[opcode], jag_reg1(inst), jag_reg2(inst));
227 } else {
228 return sprintf("%s r%d, r%d", mnemonics[opcode], jag_reg1(inst), jag_reg2(inst));
229 }
230 }
231 }