1 |
/* |
2 |
* PearPC |
3 |
* ppc_dec.cc |
4 |
* |
5 |
* Copyright (C) 2003, 2004 Sebastian Biallas (sb@biallas.net) |
6 |
* Portions Copyright (C) 2004 Daniel Foesch (dfoesch@cs.nmsu.edu) |
7 |
* Portions Copyright (C) 2004 Apple Computer, Inc. |
8 |
* |
9 |
* This program is free software; you can redistribute it and/or modify |
10 |
* it under the terms of the GNU General Public License version 2 as |
11 |
* published by the Free Software Foundation. |
12 |
* |
13 |
* This program is distributed in the hope that it will be useful, |
14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
* GNU General Public License for more details. |
17 |
* |
18 |
* You should have received a copy of the GNU General Public License |
19 |
* along with this program; if not, write to the Free Software |
20 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 |
*/ |
22 |
|
23 |
#include "cstring" |
24 |
|
25 |
#include "system/types.h" |
26 |
#include "cpu/debug.h" |
27 |
#include "cpu/cpu.h" |
28 |
#include "ppc_alu.h" |
29 |
#include "ppc_cpu.h" |
30 |
#include "ppc_dec.h" |
31 |
#include "ppc_exc.h" |
32 |
#include "ppc_fpu.h" |
33 |
#include "ppc_vec.h" |
34 |
#include "ppc_mmu.h" |
35 |
#include "ppc_opc.h" |
36 |
|
37 |
#include "io/prom/promosi.h" |
38 |
|
39 |
static void ppc_opc_invalid() |
40 |
{ |
41 |
if (gCPU.pc == gPromOSIEntry && gCPU.current_opc == PROM_MAGIC_OPCODE) { |
42 |
call_prom_osi(); |
43 |
return; |
44 |
} |
45 |
if (gCPU.current_opc == 0x00333301) { |
46 |
// memset(r3, r4, r5) |
47 |
uint32 dest = gCPU.gpr[3]; |
48 |
uint32 c = gCPU.gpr[4]; |
49 |
uint32 size = gCPU.gpr[5]; |
50 |
if (dest & 0xfff) { |
51 |
byte *dst; |
52 |
ppc_direct_effective_memory_handle(dest, dst); |
53 |
uint32 a = 4096 - (dest & 0xfff); |
54 |
memset(dst, c, a); |
55 |
size -= a; |
56 |
dest += a; |
57 |
} |
58 |
while (size >= 4096) { |
59 |
byte *dst; |
60 |
ppc_direct_effective_memory_handle(dest, dst); |
61 |
memset(dst, c, 4096); |
62 |
dest += 4096; |
63 |
size -= 4096; |
64 |
} |
65 |
if (size) { |
66 |
byte *dst; |
67 |
ppc_direct_effective_memory_handle(dest, dst); |
68 |
memset(dst, c, size); |
69 |
} |
70 |
gCPU.pc = gCPU.npc; |
71 |
return; |
72 |
} |
73 |
if (gCPU.current_opc == 0x00333302) { |
74 |
// memcpy |
75 |
uint32 dest = gCPU.gpr[3]; |
76 |
uint32 src = gCPU.gpr[4]; |
77 |
uint32 size = gCPU.gpr[5]; |
78 |
byte *d, *s; |
79 |
ppc_direct_effective_memory_handle(dest, d); |
80 |
ppc_direct_effective_memory_handle(src, s); |
81 |
while (size--) { |
82 |
if (!(dest & 0xfff)) ppc_direct_effective_memory_handle(dest, d); |
83 |
if (!(src & 0xfff)) ppc_direct_effective_memory_handle(src, s); |
84 |
*d = *s; |
85 |
src++; dest++; d++; s++; |
86 |
} |
87 |
gCPU.pc = gCPU.npc; |
88 |
return; |
89 |
} |
90 |
fprintf(stderr, "[PPC/DEC] Bad opcode: %08x (%u:%u)\n", |
91 |
gCPU.current_opc, PPC_OPC_MAIN(gCPU.current_opc), |
92 |
PPC_OPC_EXT(gCPU.current_opc)); |
93 |
|
94 |
SINGLESTEP("unknown instruction\n"); |
95 |
} |
96 |
|
97 |
// main opcode 19 |
98 |
static void ppc_opc_group_1() |
99 |
{ |
100 |
uint32 ext = PPC_OPC_EXT(gCPU.current_opc); |
101 |
if (ext & 1) { |
102 |
// crxxx |
103 |
if (ext <= 225) { |
104 |
switch (ext) { |
105 |
case 33: ppc_opc_crnor(); return; |
106 |
case 129: ppc_opc_crandc(); return; |
107 |
case 193: ppc_opc_crxor(); return; |
108 |
case 225: ppc_opc_crnand(); return; |
109 |
} |
110 |
} else { |
111 |
switch (ext) { |
112 |
case 257: ppc_opc_crand(); return; |
113 |
case 289: ppc_opc_creqv(); return; |
114 |
case 417: ppc_opc_crorc(); return; |
115 |
case 449: ppc_opc_cror(); return; |
116 |
} |
117 |
} |
118 |
} else if (ext & (1<<9)) { |
119 |
// bcctrx |
120 |
if (ext == 528) { |
121 |
ppc_opc_bcctrx(); |
122 |
return; |
123 |
} |
124 |
} else { |
125 |
switch (ext) { |
126 |
case 16: ppc_opc_bclrx(); return; |
127 |
case 0: ppc_opc_mcrf(); return; |
128 |
case 50: ppc_opc_rfi(); return; |
129 |
case 150: ppc_opc_isync(); return; |
130 |
} |
131 |
} |
132 |
ppc_opc_invalid(); |
133 |
} |
134 |
|
135 |
ppc_opc_function ppc_opc_table_group2[1015]; |
136 |
|
137 |
// main opcode 31 |
138 |
static void ppc_opc_init_group2() |
139 |
{ |
140 |
for (uint i=0; i<(sizeof ppc_opc_table_group2 / sizeof ppc_opc_table_group2[0]); i++) { |
141 |
ppc_opc_table_group2[i] = ppc_opc_invalid; |
142 |
} |
143 |
ppc_opc_table_group2[0] = ppc_opc_cmp; |
144 |
ppc_opc_table_group2[4] = ppc_opc_tw; |
145 |
ppc_opc_table_group2[8] = ppc_opc_subfcx;//+ |
146 |
ppc_opc_table_group2[10] = ppc_opc_addcx;//+ |
147 |
ppc_opc_table_group2[11] = ppc_opc_mulhwux; |
148 |
ppc_opc_table_group2[19] = ppc_opc_mfcr; |
149 |
ppc_opc_table_group2[20] = ppc_opc_lwarx; |
150 |
ppc_opc_table_group2[23] = ppc_opc_lwzx; |
151 |
ppc_opc_table_group2[24] = ppc_opc_slwx; |
152 |
ppc_opc_table_group2[26] = ppc_opc_cntlzwx; |
153 |
ppc_opc_table_group2[28] = ppc_opc_andx; |
154 |
ppc_opc_table_group2[32] = ppc_opc_cmpl; |
155 |
ppc_opc_table_group2[40] = ppc_opc_subfx; |
156 |
ppc_opc_table_group2[54] = ppc_opc_dcbst; |
157 |
ppc_opc_table_group2[55] = ppc_opc_lwzux; |
158 |
ppc_opc_table_group2[60] = ppc_opc_andcx; |
159 |
ppc_opc_table_group2[75] = ppc_opc_mulhwx; |
160 |
ppc_opc_table_group2[83] = ppc_opc_mfmsr; |
161 |
ppc_opc_table_group2[86] = ppc_opc_dcbf; |
162 |
ppc_opc_table_group2[87] = ppc_opc_lbzx; |
163 |
ppc_opc_table_group2[104] = ppc_opc_negx; |
164 |
ppc_opc_table_group2[119] = ppc_opc_lbzux; |
165 |
ppc_opc_table_group2[124] = ppc_opc_norx; |
166 |
ppc_opc_table_group2[136] = ppc_opc_subfex;//+ |
167 |
ppc_opc_table_group2[138] = ppc_opc_addex;//+ |
168 |
ppc_opc_table_group2[144] = ppc_opc_mtcrf; |
169 |
ppc_opc_table_group2[146] = ppc_opc_mtmsr; |
170 |
ppc_opc_table_group2[150] = ppc_opc_stwcx_; |
171 |
ppc_opc_table_group2[151] = ppc_opc_stwx; |
172 |
ppc_opc_table_group2[183] = ppc_opc_stwux; |
173 |
ppc_opc_table_group2[200] = ppc_opc_subfzex;//+ |
174 |
ppc_opc_table_group2[202] = ppc_opc_addzex;//+ |
175 |
ppc_opc_table_group2[210] = ppc_opc_mtsr; |
176 |
ppc_opc_table_group2[215] = ppc_opc_stbx; |
177 |
ppc_opc_table_group2[232] = ppc_opc_subfmex;//+ |
178 |
ppc_opc_table_group2[234] = ppc_opc_addmex; |
179 |
ppc_opc_table_group2[235] = ppc_opc_mullwx;//+ |
180 |
ppc_opc_table_group2[242] = ppc_opc_mtsrin; |
181 |
ppc_opc_table_group2[246] = ppc_opc_dcbtst; |
182 |
ppc_opc_table_group2[247] = ppc_opc_stbux; |
183 |
ppc_opc_table_group2[266] = ppc_opc_addx;//+ |
184 |
ppc_opc_table_group2[278] = ppc_opc_dcbt; |
185 |
ppc_opc_table_group2[279] = ppc_opc_lhzx; |
186 |
ppc_opc_table_group2[284] = ppc_opc_eqvx; |
187 |
ppc_opc_table_group2[306] = ppc_opc_tlbie; |
188 |
ppc_opc_table_group2[310] = ppc_opc_eciwx; |
189 |
ppc_opc_table_group2[311] = ppc_opc_lhzux; |
190 |
ppc_opc_table_group2[316] = ppc_opc_xorx; |
191 |
ppc_opc_table_group2[339] = ppc_opc_mfspr; |
192 |
ppc_opc_table_group2[343] = ppc_opc_lhax; |
193 |
ppc_opc_table_group2[370] = ppc_opc_tlbia; |
194 |
ppc_opc_table_group2[371] = ppc_opc_mftb; |
195 |
ppc_opc_table_group2[375] = ppc_opc_lhaux; |
196 |
ppc_opc_table_group2[407] = ppc_opc_sthx; |
197 |
ppc_opc_table_group2[412] = ppc_opc_orcx; |
198 |
ppc_opc_table_group2[438] = ppc_opc_ecowx; |
199 |
ppc_opc_table_group2[439] = ppc_opc_sthux; |
200 |
ppc_opc_table_group2[444] = ppc_opc_orx; |
201 |
ppc_opc_table_group2[459] = ppc_opc_divwux;//+ |
202 |
ppc_opc_table_group2[467] = ppc_opc_mtspr; |
203 |
ppc_opc_table_group2[470] = ppc_opc_dcbi; |
204 |
ppc_opc_table_group2[476] = ppc_opc_nandx; |
205 |
ppc_opc_table_group2[491] = ppc_opc_divwx;//+ |
206 |
ppc_opc_table_group2[512] = ppc_opc_mcrxr; |
207 |
ppc_opc_table_group2[533] = ppc_opc_lswx; |
208 |
ppc_opc_table_group2[534] = ppc_opc_lwbrx; |
209 |
ppc_opc_table_group2[535] = ppc_opc_lfsx; |
210 |
ppc_opc_table_group2[536] = ppc_opc_srwx; |
211 |
ppc_opc_table_group2[566] = ppc_opc_tlbsync; |
212 |
ppc_opc_table_group2[567] = ppc_opc_lfsux; |
213 |
ppc_opc_table_group2[595] = ppc_opc_mfsr; |
214 |
ppc_opc_table_group2[597] = ppc_opc_lswi; |
215 |
ppc_opc_table_group2[598] = ppc_opc_sync; |
216 |
ppc_opc_table_group2[599] = ppc_opc_lfdx; |
217 |
ppc_opc_table_group2[631] = ppc_opc_lfdux; |
218 |
ppc_opc_table_group2[659] = ppc_opc_mfsrin; |
219 |
ppc_opc_table_group2[661] = ppc_opc_stswx; |
220 |
ppc_opc_table_group2[662] = ppc_opc_stwbrx; |
221 |
ppc_opc_table_group2[663] = ppc_opc_stfsx; |
222 |
ppc_opc_table_group2[695] = ppc_opc_stfsux; |
223 |
ppc_opc_table_group2[725] = ppc_opc_stswi; |
224 |
ppc_opc_table_group2[727] = ppc_opc_stfdx; |
225 |
ppc_opc_table_group2[758] = ppc_opc_dcba; |
226 |
ppc_opc_table_group2[759] = ppc_opc_stfdux; |
227 |
ppc_opc_table_group2[790] = ppc_opc_lhbrx; |
228 |
ppc_opc_table_group2[792] = ppc_opc_srawx; |
229 |
ppc_opc_table_group2[824] = ppc_opc_srawix; |
230 |
ppc_opc_table_group2[854] = ppc_opc_eieio; |
231 |
ppc_opc_table_group2[918] = ppc_opc_sthbrx; |
232 |
ppc_opc_table_group2[922] = ppc_opc_extshx; |
233 |
ppc_opc_table_group2[954] = ppc_opc_extsbx; |
234 |
ppc_opc_table_group2[982] = ppc_opc_icbi; |
235 |
ppc_opc_table_group2[983] = ppc_opc_stfiwx; |
236 |
ppc_opc_table_group2[1014] = ppc_opc_dcbz; |
237 |
|
238 |
if ((ppc_cpu_get_pvr(0) & 0xffff0000) == 0x000c0000) { |
239 |
/* Added for Altivec support */ |
240 |
ppc_opc_table_group2[6] = ppc_opc_lvsl; |
241 |
ppc_opc_table_group2[7] = ppc_opc_lvebx; |
242 |
ppc_opc_table_group2[38] = ppc_opc_lvsr; |
243 |
ppc_opc_table_group2[39] = ppc_opc_lvehx; |
244 |
ppc_opc_table_group2[71] = ppc_opc_lvewx; |
245 |
ppc_opc_table_group2[103] = ppc_opc_lvx; |
246 |
ppc_opc_table_group2[135] = ppc_opc_stvebx; |
247 |
ppc_opc_table_group2[167] = ppc_opc_stvehx; |
248 |
ppc_opc_table_group2[199] = ppc_opc_stvewx; |
249 |
ppc_opc_table_group2[231] = ppc_opc_stvx; |
250 |
ppc_opc_table_group2[342] = ppc_opc_dst; |
251 |
ppc_opc_table_group2[359] = ppc_opc_lvxl; |
252 |
ppc_opc_table_group2[374] = ppc_opc_dstst; |
253 |
ppc_opc_table_group2[487] = ppc_opc_stvxl; |
254 |
ppc_opc_table_group2[822] = ppc_opc_dss; |
255 |
} |
256 |
} |
257 |
|
258 |
// main opcode 31 |
259 |
inline static void ppc_opc_group_2() |
260 |
{ |
261 |
uint32 ext = PPC_OPC_EXT(gCPU.current_opc); |
262 |
if (ext >= (sizeof ppc_opc_table_group2 / sizeof ppc_opc_table_group2[0])) { |
263 |
ppc_opc_invalid(); |
264 |
} |
265 |
ppc_opc_table_group2[ext](); |
266 |
} |
267 |
|
268 |
// main opcode 59 |
269 |
static void ppc_opc_group_f1() |
270 |
{ |
271 |
if ((gCPU.msr & MSR_FP) == 0) { |
272 |
ppc_exception(PPC_EXC_NO_FPU); |
273 |
return; |
274 |
} |
275 |
uint32 ext = PPC_OPC_EXT(gCPU.current_opc); |
276 |
switch (ext & 0x1f) { |
277 |
case 18: ppc_opc_fdivsx(); return; |
278 |
case 20: ppc_opc_fsubsx(); return; |
279 |
case 21: ppc_opc_faddsx(); return; |
280 |
case 22: ppc_opc_fsqrtsx(); return; |
281 |
case 24: ppc_opc_fresx(); return; |
282 |
case 25: ppc_opc_fmulsx(); return; |
283 |
case 28: ppc_opc_fmsubsx(); return; |
284 |
case 29: ppc_opc_fmaddsx(); return; |
285 |
case 30: ppc_opc_fnmsubsx(); return; |
286 |
case 31: ppc_opc_fnmaddsx(); return; |
287 |
} |
288 |
ppc_opc_invalid(); |
289 |
} |
290 |
|
291 |
// main opcode 63 |
292 |
static void ppc_opc_group_f2() |
293 |
{ |
294 |
if ((gCPU.msr & MSR_FP) == 0) { |
295 |
ppc_exception(PPC_EXC_NO_FPU); |
296 |
return; |
297 |
} |
298 |
uint32 ext = PPC_OPC_EXT(gCPU.current_opc); |
299 |
if (ext & 16) { |
300 |
switch (ext & 0x1f) { |
301 |
case 18: ppc_opc_fdivx(); return; |
302 |
case 20: ppc_opc_fsubx(); return; |
303 |
case 21: ppc_opc_faddx(); return; |
304 |
case 22: ppc_opc_fsqrtx(); return; |
305 |
case 23: ppc_opc_fselx(); return; |
306 |
case 25: ppc_opc_fmulx(); return; |
307 |
case 26: ppc_opc_frsqrtex(); return; |
308 |
case 28: ppc_opc_fmsubx(); return; |
309 |
case 29: ppc_opc_fmaddx(); return; |
310 |
case 30: ppc_opc_fnmsubx(); return; |
311 |
case 31: ppc_opc_fnmaddx(); return; |
312 |
} |
313 |
} else { |
314 |
switch (ext) { |
315 |
case 0: ppc_opc_fcmpu(); return; |
316 |
case 12: ppc_opc_frspx(); return; |
317 |
case 14: ppc_opc_fctiwx(); return; |
318 |
case 15: ppc_opc_fctiwzx(); return; |
319 |
//-- |
320 |
case 32: ppc_opc_fcmpo(); return; |
321 |
case 38: ppc_opc_mtfsb1x(); return; |
322 |
case 40: ppc_opc_fnegx(); return; |
323 |
case 64: ppc_opc_mcrfs(); return; |
324 |
case 70: ppc_opc_mtfsb0x(); return; |
325 |
case 72: ppc_opc_fmrx(); return; |
326 |
case 134: ppc_opc_mtfsfix(); return; |
327 |
case 136: ppc_opc_fnabsx(); return; |
328 |
case 264: ppc_opc_fabsx(); return; |
329 |
case 583: ppc_opc_mffsx(); return; |
330 |
case 711: ppc_opc_mtfsfx(); return; |
331 |
} |
332 |
} |
333 |
ppc_opc_invalid(); |
334 |
} |
335 |
|
336 |
ppc_opc_function ppc_opc_table_groupv[965]; |
337 |
|
338 |
static void ppc_opc_init_groupv() |
339 |
{ |
340 |
for (uint i=0; i<(sizeof ppc_opc_table_groupv / sizeof ppc_opc_table_groupv[0]);i++) { |
341 |
ppc_opc_table_groupv[i] = ppc_opc_invalid; |
342 |
} |
343 |
ppc_opc_table_groupv[0] = ppc_opc_vaddubm; |
344 |
ppc_opc_table_groupv[1] = ppc_opc_vmaxub; |
345 |
ppc_opc_table_groupv[2] = ppc_opc_vrlb; |
346 |
ppc_opc_table_groupv[4] = ppc_opc_vmuloub; |
347 |
ppc_opc_table_groupv[5] = ppc_opc_vaddfp; |
348 |
ppc_opc_table_groupv[6] = ppc_opc_vmrghb; |
349 |
ppc_opc_table_groupv[7] = ppc_opc_vpkuhum; |
350 |
ppc_opc_table_groupv[32] = ppc_opc_vadduhm; |
351 |
ppc_opc_table_groupv[33] = ppc_opc_vmaxuh; |
352 |
ppc_opc_table_groupv[34] = ppc_opc_vrlh; |
353 |
ppc_opc_table_groupv[36] = ppc_opc_vmulouh; |
354 |
ppc_opc_table_groupv[37] = ppc_opc_vsubfp; |
355 |
ppc_opc_table_groupv[38] = ppc_opc_vmrghh; |
356 |
ppc_opc_table_groupv[39] = ppc_opc_vpkuwum; |
357 |
ppc_opc_table_groupv[64] = ppc_opc_vadduwm; |
358 |
ppc_opc_table_groupv[65] = ppc_opc_vmaxuw; |
359 |
ppc_opc_table_groupv[66] = ppc_opc_vrlw; |
360 |
ppc_opc_table_groupv[70] = ppc_opc_vmrghw; |
361 |
ppc_opc_table_groupv[71] = ppc_opc_vpkuhus; |
362 |
ppc_opc_table_groupv[103] = ppc_opc_vpkuwus; |
363 |
ppc_opc_table_groupv[129] = ppc_opc_vmaxsb; |
364 |
ppc_opc_table_groupv[130] = ppc_opc_vslb; |
365 |
ppc_opc_table_groupv[132] = ppc_opc_vmulosb; |
366 |
ppc_opc_table_groupv[133] = ppc_opc_vrefp; |
367 |
ppc_opc_table_groupv[134] = ppc_opc_vmrglb; |
368 |
ppc_opc_table_groupv[135] = ppc_opc_vpkshus; |
369 |
ppc_opc_table_groupv[161] = ppc_opc_vmaxsh; |
370 |
ppc_opc_table_groupv[162] = ppc_opc_vslh; |
371 |
ppc_opc_table_groupv[164] = ppc_opc_vmulosh; |
372 |
ppc_opc_table_groupv[165] = ppc_opc_vrsqrtefp; |
373 |
ppc_opc_table_groupv[166] = ppc_opc_vmrglh; |
374 |
ppc_opc_table_groupv[167] = ppc_opc_vpkswus; |
375 |
ppc_opc_table_groupv[192] = ppc_opc_vaddcuw; |
376 |
ppc_opc_table_groupv[193] = ppc_opc_vmaxsw; |
377 |
ppc_opc_table_groupv[194] = ppc_opc_vslw; |
378 |
ppc_opc_table_groupv[197] = ppc_opc_vexptefp; |
379 |
ppc_opc_table_groupv[198] = ppc_opc_vmrglw; |
380 |
ppc_opc_table_groupv[199] = ppc_opc_vpkshss; |
381 |
ppc_opc_table_groupv[226] = ppc_opc_vsl; |
382 |
ppc_opc_table_groupv[229] = ppc_opc_vlogefp; |
383 |
ppc_opc_table_groupv[231] = ppc_opc_vpkswss; |
384 |
ppc_opc_table_groupv[256] = ppc_opc_vaddubs; |
385 |
ppc_opc_table_groupv[257] = ppc_opc_vminub; |
386 |
ppc_opc_table_groupv[258] = ppc_opc_vsrb; |
387 |
ppc_opc_table_groupv[260] = ppc_opc_vmuleub; |
388 |
ppc_opc_table_groupv[261] = ppc_opc_vrfin; |
389 |
ppc_opc_table_groupv[262] = ppc_opc_vspltb; |
390 |
ppc_opc_table_groupv[263] = ppc_opc_vupkhsb; |
391 |
ppc_opc_table_groupv[288] = ppc_opc_vadduhs; |
392 |
ppc_opc_table_groupv[289] = ppc_opc_vminuh; |
393 |
ppc_opc_table_groupv[290] = ppc_opc_vsrh; |
394 |
ppc_opc_table_groupv[292] = ppc_opc_vmuleuh; |
395 |
ppc_opc_table_groupv[293] = ppc_opc_vrfiz; |
396 |
ppc_opc_table_groupv[294] = ppc_opc_vsplth; |
397 |
ppc_opc_table_groupv[295] = ppc_opc_vupkhsh; |
398 |
ppc_opc_table_groupv[320] = ppc_opc_vadduws; |
399 |
ppc_opc_table_groupv[321] = ppc_opc_vminuw; |
400 |
ppc_opc_table_groupv[322] = ppc_opc_vsrw; |
401 |
ppc_opc_table_groupv[325] = ppc_opc_vrfip; |
402 |
ppc_opc_table_groupv[326] = ppc_opc_vspltw; |
403 |
ppc_opc_table_groupv[327] = ppc_opc_vupklsb; |
404 |
ppc_opc_table_groupv[354] = ppc_opc_vsr; |
405 |
ppc_opc_table_groupv[357] = ppc_opc_vrfim; |
406 |
ppc_opc_table_groupv[359] = ppc_opc_vupklsh; |
407 |
ppc_opc_table_groupv[384] = ppc_opc_vaddsbs; |
408 |
ppc_opc_table_groupv[385] = ppc_opc_vminsb; |
409 |
ppc_opc_table_groupv[386] = ppc_opc_vsrab; |
410 |
ppc_opc_table_groupv[388] = ppc_opc_vmulesb; |
411 |
ppc_opc_table_groupv[389] = ppc_opc_vcfux; |
412 |
ppc_opc_table_groupv[390] = ppc_opc_vspltisb; |
413 |
ppc_opc_table_groupv[391] = ppc_opc_vpkpx; |
414 |
ppc_opc_table_groupv[416] = ppc_opc_vaddshs; |
415 |
ppc_opc_table_groupv[417] = ppc_opc_vminsh; |
416 |
ppc_opc_table_groupv[418] = ppc_opc_vsrah; |
417 |
ppc_opc_table_groupv[420] = ppc_opc_vmulesh; |
418 |
ppc_opc_table_groupv[421] = ppc_opc_vcfsx; |
419 |
ppc_opc_table_groupv[422] = ppc_opc_vspltish; |
420 |
ppc_opc_table_groupv[423] = ppc_opc_vupkhpx; |
421 |
ppc_opc_table_groupv[448] = ppc_opc_vaddsws; |
422 |
ppc_opc_table_groupv[449] = ppc_opc_vminsw; |
423 |
ppc_opc_table_groupv[450] = ppc_opc_vsraw; |
424 |
ppc_opc_table_groupv[453] = ppc_opc_vctuxs; |
425 |
ppc_opc_table_groupv[454] = ppc_opc_vspltisw; |
426 |
ppc_opc_table_groupv[485] = ppc_opc_vctsxs; |
427 |
ppc_opc_table_groupv[487] = ppc_opc_vupklpx; |
428 |
ppc_opc_table_groupv[512] = ppc_opc_vsububm; |
429 |
ppc_opc_table_groupv[513] = ppc_opc_vavgub; |
430 |
ppc_opc_table_groupv[514] = ppc_opc_vand; |
431 |
ppc_opc_table_groupv[517] = ppc_opc_vmaxfp; |
432 |
ppc_opc_table_groupv[518] = ppc_opc_vslo; |
433 |
ppc_opc_table_groupv[544] = ppc_opc_vsubuhm; |
434 |
ppc_opc_table_groupv[545] = ppc_opc_vavguh; |
435 |
ppc_opc_table_groupv[546] = ppc_opc_vandc; |
436 |
ppc_opc_table_groupv[549] = ppc_opc_vminfp; |
437 |
ppc_opc_table_groupv[550] = ppc_opc_vsro; |
438 |
ppc_opc_table_groupv[576] = ppc_opc_vsubuwm; |
439 |
ppc_opc_table_groupv[577] = ppc_opc_vavguw; |
440 |
ppc_opc_table_groupv[578] = ppc_opc_vor; |
441 |
ppc_opc_table_groupv[610] = ppc_opc_vxor; |
442 |
ppc_opc_table_groupv[641] = ppc_opc_vavgsb; |
443 |
ppc_opc_table_groupv[642] = ppc_opc_vnor; |
444 |
ppc_opc_table_groupv[673] = ppc_opc_vavgsh; |
445 |
ppc_opc_table_groupv[704] = ppc_opc_vsubcuw; |
446 |
ppc_opc_table_groupv[705] = ppc_opc_vavgsw; |
447 |
ppc_opc_table_groupv[768] = ppc_opc_vsububs; |
448 |
ppc_opc_table_groupv[770] = ppc_opc_mfvscr; |
449 |
ppc_opc_table_groupv[772] = ppc_opc_vsum4ubs; |
450 |
ppc_opc_table_groupv[800] = ppc_opc_vsubuhs; |
451 |
ppc_opc_table_groupv[802] = ppc_opc_mtvscr; |
452 |
ppc_opc_table_groupv[804] = ppc_opc_vsum4shs; |
453 |
ppc_opc_table_groupv[832] = ppc_opc_vsubuws; |
454 |
ppc_opc_table_groupv[836] = ppc_opc_vsum2sws; |
455 |
ppc_opc_table_groupv[896] = ppc_opc_vsubsbs; |
456 |
ppc_opc_table_groupv[900] = ppc_opc_vsum4sbs; |
457 |
ppc_opc_table_groupv[928] = ppc_opc_vsubshs; |
458 |
ppc_opc_table_groupv[960] = ppc_opc_vsubsws; |
459 |
ppc_opc_table_groupv[964] = ppc_opc_vsumsws; |
460 |
} |
461 |
|
462 |
// main opcode 04 |
463 |
static void ppc_opc_group_v() |
464 |
{ |
465 |
uint32 ext = PPC_OPC_EXT(gCPU.current_opc); |
466 |
#ifndef __VEC_EXC_OFF__ |
467 |
if ((gCPU.msr & MSR_VEC) == 0) { |
468 |
ppc_exception(PPC_EXC_NO_VEC); |
469 |
return; |
470 |
} |
471 |
#endif |
472 |
switch(ext & 0x1f) { |
473 |
case 16: |
474 |
if (gCPU.current_opc & PPC_OPC_Rc) |
475 |
return ppc_opc_vmhraddshs(); |
476 |
else |
477 |
return ppc_opc_vmhaddshs(); |
478 |
case 17: return ppc_opc_vmladduhm(); |
479 |
case 18: |
480 |
if (gCPU.current_opc & PPC_OPC_Rc) |
481 |
return ppc_opc_vmsummbm(); |
482 |
else |
483 |
return ppc_opc_vmsumubm(); |
484 |
case 19: |
485 |
if (gCPU.current_opc & PPC_OPC_Rc) |
486 |
return ppc_opc_vmsumuhs(); |
487 |
else |
488 |
return ppc_opc_vmsumuhm(); |
489 |
case 20: |
490 |
if (gCPU.current_opc & PPC_OPC_Rc) |
491 |
return ppc_opc_vmsumshs(); |
492 |
else |
493 |
return ppc_opc_vmsumshm(); |
494 |
case 21: |
495 |
if (gCPU.current_opc & PPC_OPC_Rc) |
496 |
return ppc_opc_vperm(); |
497 |
else |
498 |
return ppc_opc_vsel(); |
499 |
case 22: return ppc_opc_vsldoi(); |
500 |
case 23: |
501 |
if (gCPU.current_opc & PPC_OPC_Rc) |
502 |
return ppc_opc_vnmsubfp(); |
503 |
else |
504 |
return ppc_opc_vmaddfp(); |
505 |
} |
506 |
switch(ext & 0x1ff) |
507 |
{ |
508 |
case 3: return ppc_opc_vcmpequbx(); |
509 |
case 35: return ppc_opc_vcmpequhx(); |
510 |
case 67: return ppc_opc_vcmpequwx(); |
511 |
case 99: return ppc_opc_vcmpeqfpx(); |
512 |
case 227: return ppc_opc_vcmpgefpx(); |
513 |
case 259: return ppc_opc_vcmpgtubx(); |
514 |
case 291: return ppc_opc_vcmpgtuhx(); |
515 |
case 323: return ppc_opc_vcmpgtuwx(); |
516 |
case 355: return ppc_opc_vcmpgtfpx(); |
517 |
case 387: return ppc_opc_vcmpgtsbx(); |
518 |
case 419: return ppc_opc_vcmpgtshx(); |
519 |
case 451: return ppc_opc_vcmpgtswx(); |
520 |
case 483: return ppc_opc_vcmpbfpx(); |
521 |
} |
522 |
|
523 |
if (ext >= (sizeof ppc_opc_table_groupv / sizeof ppc_opc_table_groupv[0])) { |
524 |
return ppc_opc_invalid(); |
525 |
} |
526 |
return ppc_opc_table_groupv[ext](); |
527 |
} |
528 |
|
529 |
static ppc_opc_function ppc_opc_table_main[64] = { |
530 |
&ppc_opc_invalid, // 0 |
531 |
&ppc_opc_invalid, // 1 |
532 |
&ppc_opc_invalid, // 2 (tdi on 64 bit platforms) |
533 |
&ppc_opc_twi, // 3 |
534 |
&ppc_opc_invalid, // 4 (altivec group 1) |
535 |
&ppc_opc_invalid, // 5 |
536 |
&ppc_opc_invalid, // 6 |
537 |
&ppc_opc_mulli, // 7 |
538 |
&ppc_opc_subfic, // 8 |
539 |
&ppc_opc_invalid, // 9 |
540 |
&ppc_opc_cmpli, // 10 |
541 |
&ppc_opc_cmpi, // 11 |
542 |
&ppc_opc_addic, // 12 |
543 |
&ppc_opc_addic_, // 13 |
544 |
&ppc_opc_addi, // 14 |
545 |
&ppc_opc_addis, // 15 |
546 |
&ppc_opc_bcx, // 16 |
547 |
&ppc_opc_sc, // 17 |
548 |
&ppc_opc_bx, // 18 |
549 |
&ppc_opc_group_1, // 19 |
550 |
&ppc_opc_rlwimix, // 20 |
551 |
&ppc_opc_rlwinmx, // 21 |
552 |
&ppc_opc_invalid, // 22 |
553 |
&ppc_opc_rlwnmx, // 23 |
554 |
&ppc_opc_ori, // 24 |
555 |
&ppc_opc_oris, // 25 |
556 |
&ppc_opc_xori, // 26 |
557 |
&ppc_opc_xoris, // 27 |
558 |
&ppc_opc_andi_, // 28 |
559 |
&ppc_opc_andis_, // 29 |
560 |
&ppc_opc_invalid, // 30 (group_rld on 64 bit platforms) |
561 |
&ppc_opc_group_2, // 31 |
562 |
&ppc_opc_lwz, // 32 |
563 |
&ppc_opc_lwzu, // 33 |
564 |
&ppc_opc_lbz, // 34 |
565 |
&ppc_opc_lbzu, // 35 |
566 |
&ppc_opc_stw, // 36 |
567 |
&ppc_opc_stwu, // 37 |
568 |
&ppc_opc_stb, // 38 |
569 |
&ppc_opc_stbu, // 39 |
570 |
&ppc_opc_lhz, // 40 |
571 |
&ppc_opc_lhzu, // 41 |
572 |
&ppc_opc_lha, // 42 |
573 |
&ppc_opc_lhau, // 43 |
574 |
&ppc_opc_sth, // 44 |
575 |
&ppc_opc_sthu, // 45 |
576 |
&ppc_opc_lmw, // 46 |
577 |
&ppc_opc_stmw, // 47 |
578 |
&ppc_opc_lfs, // 48 |
579 |
&ppc_opc_lfsu, // 49 |
580 |
&ppc_opc_lfd, // 50 |
581 |
&ppc_opc_lfdu, // 51 |
582 |
&ppc_opc_stfs, // 52 |
583 |
&ppc_opc_stfsu, // 53 |
584 |
&ppc_opc_stfd, // 54 |
585 |
&ppc_opc_stfdu, // 55 |
586 |
&ppc_opc_invalid, // 56 |
587 |
&ppc_opc_invalid, // 57 |
588 |
&ppc_opc_invalid, // 58 (ld on 64 bit platforms) |
589 |
&ppc_opc_group_f1, // 59 |
590 |
&ppc_opc_invalid, // 60 |
591 |
&ppc_opc_invalid, // 61 |
592 |
&ppc_opc_invalid, // 62 |
593 |
&ppc_opc_group_f2, // 63 |
594 |
}; |
595 |
|
596 |
void FASTCALL ppc_exec_opc() |
597 |
{ |
598 |
uint32 mainopc = PPC_OPC_MAIN(gCPU.current_opc); |
599 |
ppc_opc_table_main[mainopc](); |
600 |
} |
601 |
|
602 |
void ppc_dec_init() |
603 |
{ |
604 |
ppc_opc_init_group2(); |
605 |
if ((ppc_cpu_get_pvr(0) & 0xffff0000) == 0x000c0000) { |
606 |
ppc_opc_table_main[4] = ppc_opc_group_v; |
607 |
ppc_opc_init_groupv(); |
608 |
} |
609 |
} |