1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13
14 #include "cpu.h"
15 #include "jit_op.h"
16 #include "ppc32_jit.h"
17 #include "ppc32_x86_trans.h"
18 #include "memory.h"
19
20 /* %esp adjustment (for MacOS X) */
21 #define STACK_ADJUST 12
22
23 /* ======================================================================= */
24
25 /* Macros for CPU structure access */
26 #define REG_OFFSET(reg) (OFFSET(cpu_ppc_t,gpr[(reg)]))
27 #define MEMOP_OFFSET(op) (OFFSET(cpu_ppc_t,mem_op_fn[(op)]))
28
29 #define DECLARE_INSN(name) \
30 static int ppc32_emit_##name(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, \
31 ppc_insn_t insn)
32
33 /* EFLAGS to Condition Register (CR) field - signed */
34 static m_uint32_t eflags_to_cr_signed[64] = {
35 0x04, 0x02, 0x08, 0x02, 0x04, 0x02, 0x08, 0x02,
36 0x04, 0x02, 0x08, 0x02, 0x04, 0x02, 0x08, 0x02,
37 0x04, 0x02, 0x08, 0x02, 0x04, 0x02, 0x08, 0x02,
38 0x04, 0x02, 0x08, 0x02, 0x04, 0x02, 0x08, 0x02,
39 0x08, 0x02, 0x04, 0x02, 0x08, 0x02, 0x04, 0x02,
40 0x08, 0x02, 0x04, 0x02, 0x08, 0x02, 0x04, 0x02,
41 0x08, 0x02, 0x04, 0x02, 0x08, 0x02, 0x04, 0x02,
42 0x08, 0x02, 0x04, 0x02, 0x08, 0x02, 0x04, 0x02,
43 };
44
45 /* EFLAGS to Condition Register (CR) field - unsigned */
46 static m_uint32_t eflags_to_cr_unsigned[256] = {
47 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
48 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
49 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
50 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
51 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
52 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
53 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
54 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
55 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
56 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
57 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
58 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
59 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
60 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
61 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
62 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
63 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
64 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
65 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
66 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
67 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
68 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
69 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
70 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,
71 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
72 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
73 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
74 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
75 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
76 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
77 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
78 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,
79 };
80
81 /* Emit unhandled instruction code */
82 static int ppc32_emit_unknown(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,
83 ppc_insn_t opcode);
84
85 /* Load a 32 bit immediate value */
ppc32_load_imm(u_char ** ptr,u_int reg,m_uint32_t val)86 static forced_inline void ppc32_load_imm(u_char **ptr,u_int reg,m_uint32_t val)
87 {
88 if (val)
89 x86_mov_reg_imm(*ptr,reg,val);
90 else
91 x86_alu_reg_reg(*ptr,X86_XOR,reg,reg);
92 }
93
94 /* Set the Instruction Address (IA) register */
ppc32_set_ia(u_char ** ptr,m_uint32_t new_ia)95 void ppc32_set_ia(u_char **ptr,m_uint32_t new_ia)
96 {
97 x86_mov_membase_imm(*ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),new_ia,4);
98 }
99
100 /* Set the Link Register (LR) */
ppc32_set_lr(jit_op_t * iop,m_uint32_t new_lr)101 static void ppc32_set_lr(jit_op_t *iop,m_uint32_t new_lr)
102 {
103 x86_mov_membase_imm(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),new_lr,4);
104 }
105
106 /*
107 * Try to branch directly to the specified JIT block without returning to
108 * main loop.
109 */
ppc32_try_direct_far_jump(cpu_ppc_t * cpu,jit_op_t * iop,m_uint32_t new_ia)110 static void ppc32_try_direct_far_jump(cpu_ppc_t *cpu,jit_op_t *iop,
111 m_uint32_t new_ia)
112 {
113 m_uint32_t new_page,ia_hash,ia_offset;
114 u_char *test1,*test2,*test3,*test4;
115
116 /* Indicate that we throw %esi, %edx */
117 ppc32_op_emit_alter_host_reg(cpu,X86_ESI);
118 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
119
120 new_page = new_ia & PPC32_MIN_PAGE_MASK;
121 ia_offset = (new_ia & PPC32_MIN_PAGE_IMASK) >> 2;
122 ia_hash = ppc32_jit_get_virt_hash(new_ia);
123
124 /* Get JIT block info in %edx */
125 x86_mov_reg_membase(iop->ob_ptr,X86_EBX,
126 X86_EDI,OFFSET(cpu_ppc_t,tcb_virt_hash),4);
127 x86_mov_reg_membase(iop->ob_ptr,X86_EDX,X86_EBX,ia_hash*sizeof(void *),4);
128
129 /* no JIT block found ? */
130 x86_test_reg_reg(iop->ob_ptr,X86_EDX,X86_EDX);
131 test1 = iop->ob_ptr;
132 x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1);
133
134 /* Check block IA */
135 x86_mov_reg_imm(iop->ob_ptr,X86_ESI,new_page);
136 x86_alu_reg_membase(iop->ob_ptr,X86_CMP,X86_ESI,X86_EDX,
137 OFFSET(ppc32_jit_tcb_t,start_ia));
138 test2 = iop->ob_ptr;
139 x86_branch8(iop->ob_ptr, X86_CC_NE, 0, 1);
140
141 /* Jump to the code */
142 x86_mov_reg_membase(iop->ob_ptr,X86_ESI,
143 X86_EDX,OFFSET(ppc32_jit_tcb_t,jit_insn_ptr),4);
144
145 x86_test_reg_reg(iop->ob_ptr,X86_ESI,X86_ESI);
146 test3 = iop->ob_ptr;
147 x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1);
148
149 x86_mov_reg_membase(iop->ob_ptr,X86_EBX,
150 X86_ESI,ia_offset * sizeof(void *),4);
151
152 x86_test_reg_reg(iop->ob_ptr,X86_EBX,X86_EBX);
153 test4 = iop->ob_ptr;
154 x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1);
155 x86_jump_reg(iop->ob_ptr,X86_EBX);
156
157 /* Returns to caller... */
158 x86_patch(test1,iop->ob_ptr);
159 x86_patch(test2,iop->ob_ptr);
160 x86_patch(test3,iop->ob_ptr);
161 x86_patch(test4,iop->ob_ptr);
162
163 ppc32_set_ia(&iop->ob_ptr,new_ia);
164 ppc32_jit_tcb_push_epilog(&iop->ob_ptr);
165 }
166
167 /* Set Jump */
ppc32_set_jump(cpu_ppc_t * cpu,ppc32_jit_tcb_t * b,jit_op_t * iop,m_uint32_t new_ia,int local_jump)168 static void ppc32_set_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,jit_op_t *iop,
169 m_uint32_t new_ia,int local_jump)
170 {
171 int return_to_caller = FALSE;
172 u_char *jump_ptr;
173
174 #if 0
175 if (cpu->sym_trace && !local_jump)
176 return_to_caller = TRUE;
177 #endif
178
179 if (!return_to_caller && ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr)) {
180 ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia);
181 x86_jump32(iop->ob_ptr,0);
182 } else {
183 if (cpu->exec_blk_direct_jump) {
184 /* Block lookup optimization */
185 ppc32_try_direct_far_jump(cpu,iop,new_ia);
186 } else {
187 ppc32_set_ia(&iop->ob_ptr,new_ia);
188 ppc32_jit_tcb_push_epilog(&iop->ob_ptr);
189 }
190 }
191 }
192
193 /* Jump to the next page */
ppc32_set_page_jump(cpu_ppc_t * cpu,ppc32_jit_tcb_t * b)194 void ppc32_set_page_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
195 {
196 jit_op_t *iop,*op_list = NULL;
197
198 cpu->gen->jit_op_current = &op_list;
199
200 iop = ppc32_op_emit_insn_output(cpu,4,"set_page_jump");
201 ppc32_set_jump(cpu,b,iop,b->start_ia + PPC32_MIN_PAGE_SIZE,FALSE);
202 ppc32_op_insn_output(b,iop);
203
204 jit_op_free_list(cpu->gen,op_list);
205 cpu->gen->jit_op_current = NULL;
206 }
207
208 /* Load a GPR into the specified host register */
ppc32_load_gpr(u_char ** ptr,u_int host_reg,u_int ppc_reg)209 static forced_inline void ppc32_load_gpr(u_char **ptr,u_int host_reg,
210 u_int ppc_reg)
211 {
212 x86_mov_reg_membase(*ptr,host_reg,X86_EDI,REG_OFFSET(ppc_reg),4);
213 }
214
215 /* Store contents for a host register into a GPR register */
ppc32_store_gpr(u_char ** ptr,u_int ppc_reg,u_int host_reg)216 static forced_inline void ppc32_store_gpr(u_char **ptr,u_int ppc_reg,
217 u_int host_reg)
218 {
219 x86_mov_membase_reg(*ptr,X86_EDI,REG_OFFSET(ppc_reg),host_reg,4);
220 }
221
222 /* Apply an ALU operation on a GPR register and a host register */
ppc32_alu_gpr(u_char ** ptr,u_int op,u_int host_reg,u_int ppc_reg)223 static forced_inline void ppc32_alu_gpr(u_char **ptr,u_int op,
224 u_int host_reg,u_int ppc_reg)
225 {
226 x86_alu_reg_membase(*ptr,op,host_reg,X86_EDI,REG_OFFSET(ppc_reg));
227 }
228
229 /*
230 * Update CR from %eflags
231 * %eax, %edx, %esi are modified.
232 */
ppc32_update_cr(ppc32_jit_tcb_t * b,int field,int is_signed)233 static void ppc32_update_cr(ppc32_jit_tcb_t *b,int field,int is_signed)
234 {
235 /* Get status bits from EFLAGS */
236 if (!is_signed) {
237 x86_mov_reg_imm(b->jit_ptr,X86_EAX,0);
238 x86_lahf(b->jit_ptr);
239 x86_xchg_ah_al(b->jit_ptr);
240
241 x86_mov_reg_imm(b->jit_ptr,X86_EDX,eflags_to_cr_unsigned);
242 } else {
243 x86_pushfd(b->jit_ptr);
244 x86_pop_reg(b->jit_ptr,X86_EAX);
245 x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_EAX,6);
246 x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x3F);
247
248 x86_mov_reg_imm(b->jit_ptr,X86_EDX,eflags_to_cr_signed);
249 }
250
251 x86_mov_reg_memindex(b->jit_ptr,X86_EAX,X86_EDX,0,X86_EAX,2,4);
252
253 /* Check XER Summary of Overflow and report it */
254 //x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,xer),4);
255 //x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,PPC32_XER_SO);
256 //x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_ESI,PPC32_XER_SO_BIT);
257 //x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ESI);
258
259 /* Store modified CR field */
260 x86_mov_membase_reg(b->jit_ptr,X86_EDI,PPC32_CR_FIELD_OFFSET(field),
261 X86_EAX,4);
262 }
263
264 /*
265 * Update CR0 from %eflags
266 * %eax, %edx, %esi are modified.
267 */
ppc32_update_cr0(ppc32_jit_tcb_t * b)268 static void ppc32_update_cr0(ppc32_jit_tcb_t *b)
269 {
270 ppc32_update_cr(b,0,TRUE);
271 }
272
273 /* Indicate registers modified by ppc32_update_cr() functions */
ppc32_update_cr_set_altered_hreg(cpu_ppc_t * cpu)274 void ppc32_update_cr_set_altered_hreg(cpu_ppc_t *cpu)
275 {
276 /* Throw %eax and %edx, which are modifed by ppc32_update_cr() */
277 ppc32_op_emit_alter_host_reg(cpu,X86_EAX);
278 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
279 }
280
281 /* Basic C call */
282 static forced_inline
ppc32_emit_basic_c_call(u_char ** ptr,void * f)283 void ppc32_emit_basic_c_call(u_char **ptr,void *f)
284 {
285 x86_mov_reg_imm(*ptr,X86_EBX,f);
286 x86_call_reg(*ptr,X86_EBX);
287 }
288
289 /* Emit a simple call to a C function without any parameter */
ppc32_emit_c_call(ppc32_jit_tcb_t * b,jit_op_t * iop,void * f)290 static void ppc32_emit_c_call(ppc32_jit_tcb_t *b,jit_op_t *iop,void *f)
291 {
292 ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2));
293 ppc32_emit_basic_c_call(&iop->ob_ptr,f);
294 }
295
296 /* ======================================================================== */
297
298 /* Initialize register mapping */
ppc32_jit_init_hreg_mapping(cpu_ppc_t * cpu)299 void ppc32_jit_init_hreg_mapping(cpu_ppc_t *cpu)
300 {
301 int avail_hregs[] = { X86_ESI, X86_EAX, X86_ECX, X86_EDX, -1 };
302 struct hreg_map *map;
303 int i,hreg;
304
305 cpu->hreg_map_list = cpu->hreg_lru = NULL;
306
307 /* Add the available registers to the map list */
308 for(i=0;avail_hregs[i]!=-1;i++) {
309 hreg = avail_hregs[i];
310 map = &cpu->hreg_map[hreg];
311
312 /* Initialize mapping. At the beginning, no PPC reg is mapped */
313 map->flags = 0;
314 map->hreg = hreg;
315 map->vreg = -1;
316 ppc32_jit_insert_hreg_mru(cpu,map);
317 }
318
319 /* Clear PPC registers mapping */
320 for(i=0;i<PPC32_GPR_NR;i++)
321 cpu->ppc_reg_map[i] = -1;
322 }
323
324 /* Allocate a specific temp register */
ppc32_jit_get_tmp_hreg(cpu_ppc_t * cpu)325 static int ppc32_jit_get_tmp_hreg(cpu_ppc_t *cpu)
326 {
327 return(X86_EBX);
328 }
329
330 /* ======================================================================== */
331 /* JIT operations (specific to target CPU). */
332 /* ======================================================================== */
333
334 /* INSN_OUTPUT */
ppc32_op_insn_output(ppc32_jit_tcb_t * b,jit_op_t * op)335 void ppc32_op_insn_output(ppc32_jit_tcb_t *b,jit_op_t *op)
336 {
337 op->ob_final = b->jit_ptr;
338 memcpy(b->jit_ptr,op->ob_data,op->ob_ptr - op->ob_data);
339 b->jit_ptr += op->ob_ptr - op->ob_data;
340
341 if ((op->ob_ptr - op->ob_data) >= jit_op_blk_sizes[op->ob_size_index]) {
342 printf("ppc32_op_insn_output: FAILURE: count=%d, size=%d\n",
343 op->ob_ptr - op->ob_data, jit_op_blk_sizes[op->ob_size_index]);
344 }
345 }
346
347 /* LOAD_GPR: p[0] = %host_reg, p[1] = %ppc_reg */
ppc32_op_load_gpr(ppc32_jit_tcb_t * b,jit_op_t * op)348 void ppc32_op_load_gpr(ppc32_jit_tcb_t *b,jit_op_t *op)
349 {
350 if (op->param[0] != JIT_OP_INV_REG)
351 ppc32_load_gpr(&b->jit_ptr,op->param[0],op->param[1]);
352 }
353
354 /* STORE_GPR: p[0] = %host_reg, p[1] = %ppc_reg */
ppc32_op_store_gpr(ppc32_jit_tcb_t * b,jit_op_t * op)355 void ppc32_op_store_gpr(ppc32_jit_tcb_t *b,jit_op_t *op)
356 {
357 if (op->param[0] != JIT_OP_INV_REG)
358 ppc32_store_gpr(&b->jit_ptr,op->param[1],op->param[0]);
359 }
360
361 /* UPDATE_FLAGS: p[0] = cr_field, p[1] = is_signed */
ppc32_op_update_flags(ppc32_jit_tcb_t * b,jit_op_t * op)362 void ppc32_op_update_flags(ppc32_jit_tcb_t *b,jit_op_t *op)
363 {
364 if (op->param[0] != JIT_OP_INV_REG)
365 ppc32_update_cr(b,op->param[0],op->param[1]);
366 }
367
368 /* MOVE_HOST_REG: p[0] = %host_dst_reg, p[1] = %host_src_reg */
ppc32_op_move_host_reg(ppc32_jit_tcb_t * b,jit_op_t * op)369 void ppc32_op_move_host_reg(ppc32_jit_tcb_t *b,jit_op_t *op)
370 {
371 if ((op->param[0] != JIT_OP_INV_REG) && (op->param[1] != JIT_OP_INV_REG))
372 x86_mov_reg_reg(b->jit_ptr,op->param[0],op->param[1],4);
373 }
374
375 /* SET_HOST_REG_IMM32: p[0] = %host_reg, p[1] = imm32 */
ppc32_op_set_host_reg_imm32(ppc32_jit_tcb_t * b,jit_op_t * op)376 void ppc32_op_set_host_reg_imm32(ppc32_jit_tcb_t *b,jit_op_t *op)
377 {
378 if (op->param[0] != JIT_OP_INV_REG)
379 ppc32_load_imm(&b->jit_ptr,op->param[0],op->param[1]);
380 }
381
382 /* ======================================================================== */
383
384 /* Memory operation */
ppc32_emit_memop(cpu_ppc_t * cpu,ppc32_jit_tcb_t * b,int op,int base,int offset,int target,int update)385 static void ppc32_emit_memop(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,
386 int op,int base,int offset,int target,int update)
387 {
388 m_uint32_t val = sign_extend(offset,16);
389 jit_op_t *iop;
390
391 /*
392 * Since an exception can be triggered, clear JIT state. This allows
393 * to use branch target tag (we can directly branch on this instruction).
394 */
395 ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET);
396 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
397
398 iop = ppc32_op_emit_insn_output(cpu,5,"memop");
399
400 /* Save PC for exception handling */
401 ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2));
402
403 /* EDX = sign-extended offset */
404 ppc32_load_imm(&iop->ob_ptr,X86_EDX,val);
405
406 /* EDX = GPR[base] + sign-extended offset */
407 if (update || (base != 0))
408 ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,X86_EDX,base);
409
410 if (update)
411 x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EDX,4);
412
413 /* ECX = target register */
414 x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target);
415
416 /* EAX = CPU instance pointer */
417 x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4);
418
419 /* Call memory function */
420 x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST);
421 x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op));
422 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST);
423
424 if (update)
425 ppc32_store_gpr(&iop->ob_ptr,base,X86_ESI);
426 }
427
428 /* Memory operation (indexed) */
ppc32_emit_memop_idx(cpu_ppc_t * cpu,ppc32_jit_tcb_t * b,int op,int ra,int rb,int target,int update)429 static void ppc32_emit_memop_idx(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,
430 int op,int ra,int rb,int target,int update)
431 {
432 jit_op_t *iop;
433
434 /*
435 * Since an exception can be triggered, clear JIT state. This allows
436 * to use branch target tag (we can directly branch on this instruction).
437 */
438 ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET);
439 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
440
441 iop = ppc32_op_emit_insn_output(cpu,5,"memop_idx");
442
443 /* Save PC for exception handling */
444 ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2));
445
446 /* EDX = $rb */
447 ppc32_load_gpr(&iop->ob_ptr,X86_EDX,rb);
448
449 /* EDX = $rb + $ra */
450 if (update || (ra != 0))
451 ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,X86_EDX,ra);
452
453 if (update)
454 x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EDX,4);
455
456 /* ECX = target register */
457 x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target);
458
459 /* EAX = CPU instance pointer */
460 x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4);
461
462 /* Call memory function */
463 x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST);
464 x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op));
465 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST);
466
467 if (update)
468 ppc32_store_gpr(&iop->ob_ptr,ra,X86_ESI);
469 }
470
471 typedef void (*memop_fast_access)(jit_op_t *iop,int target);
472
473 /* Fast LBZ */
ppc32_memop_fast_lbz(jit_op_t * iop,int target)474 static void ppc32_memop_fast_lbz(jit_op_t *iop,int target)
475 {
476 x86_clear_reg(iop->ob_ptr,X86_ECX);
477 x86_mov_reg_memindex(iop->ob_ptr,X86_ECX,X86_EAX,0,X86_EBX,0,1);
478 ppc32_store_gpr(&iop->ob_ptr,target,X86_ECX);
479 }
480
481 /* Fast STB */
ppc32_memop_fast_stb(jit_op_t * iop,int target)482 static void ppc32_memop_fast_stb(jit_op_t *iop,int target)
483 {
484 ppc32_load_gpr(&iop->ob_ptr,X86_EDX,target);
485 x86_mov_memindex_reg(iop->ob_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,1);
486 }
487
488 /* Fast LWZ */
ppc32_memop_fast_lwz(jit_op_t * iop,int target)489 static void ppc32_memop_fast_lwz(jit_op_t *iop,int target)
490 {
491 x86_mov_reg_memindex(iop->ob_ptr,X86_EAX,X86_EAX,0,X86_EBX,0,4);
492 x86_bswap(iop->ob_ptr,X86_EAX);
493 ppc32_store_gpr(&iop->ob_ptr,target,X86_EAX);
494 }
495
496 /* Fast STW */
ppc32_memop_fast_stw(jit_op_t * iop,int target)497 static void ppc32_memop_fast_stw(jit_op_t *iop,int target)
498 {
499 ppc32_load_gpr(&iop->ob_ptr,X86_EDX,target);
500 x86_bswap(iop->ob_ptr,X86_EDX);
501 x86_mov_memindex_reg(iop->ob_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,4);
502 }
503
504 /* Fast memory operation */
ppc32_emit_memop_fast(cpu_ppc_t * cpu,ppc32_jit_tcb_t * b,int write_op,int opcode,int base,int offset,int target,memop_fast_access op_handler)505 static void ppc32_emit_memop_fast(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,
506 int write_op,int opcode,
507 int base,int offset,int target,
508 memop_fast_access op_handler)
509 {
510 m_uint32_t val = sign_extend(offset,16);
511 u_char *test1,*test2,*p_exit;
512 jit_op_t *iop;
513
514 /*
515 * Since an exception can be triggered, clear JIT state. This allows
516 * to use branch target tag (we can directly branch on this instruction).
517 */
518 ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET);
519 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
520
521 iop = ppc32_op_emit_insn_output(cpu,5,"memop_fast");
522
523 test2 = NULL;
524
525 if (val != 0) {
526 /* EBX = sign-extended offset */
527 ppc32_load_imm(&iop->ob_ptr,X86_EBX,val);
528
529 /* EBX = GPR[base] + sign-extended offset */
530 if (base != 0)
531 ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,X86_EBX,base);
532 } else {
533 if (base != 0)
534 ppc32_load_gpr(&iop->ob_ptr,X86_EBX,base);
535 else
536 ppc32_load_imm(&iop->ob_ptr,X86_EBX,0);
537 }
538
539 /* EAX = mts32_entry index */
540 x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EBX,4);
541 x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EBX,4);
542
543 x86_shift_reg_imm(iop->ob_ptr,X86_SHR,X86_EAX,MTS32_HASH_SHIFT1);
544 x86_shift_reg_imm(iop->ob_ptr,X86_SHR,X86_ESI,MTS32_HASH_SHIFT2);
545 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,X86_EAX,X86_ESI);
546
547 x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_EAX,MTS32_HASH_MASK);
548
549 /* EDX = mts32_entry */
550 x86_mov_reg_membase(iop->ob_ptr,X86_EDX,
551 X86_EDI,OFFSET(cpu_ppc_t,mts_cache[PPC32_MTS_DCACHE]),
552 4);
553 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,X86_EAX,4);
554 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,X86_EDX,X86_EAX);
555
556 /* Compare virtual page address (ESI = vpage) */
557 x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EBX,4);
558 x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_MASK);
559
560 x86_alu_reg_membase(iop->ob_ptr,X86_CMP,X86_ESI,X86_EDX,
561 OFFSET(mts32_entry_t,gvpa));
562 test1 = iop->ob_ptr;
563 x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1);
564
565 /* Test if we are writing to a COW page */
566 if (write_op) {
567 x86_test_membase_imm(iop->ob_ptr,X86_EDX,OFFSET(mts32_entry_t,flags),
568 MTS_FLAG_COW|MTS_FLAG_EXEC);
569 test2 = iop->ob_ptr;
570 x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1);
571 }
572
573 /* EBX = offset in page, EAX = Host Page Address */
574 x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_EBX,PPC32_MIN_PAGE_IMASK);
575 x86_mov_reg_membase(iop->ob_ptr,X86_EAX,
576 X86_EDX,OFFSET(mts32_entry_t,hpa),4);
577
578 /* Memory access */
579 op_handler(iop,target);
580
581 p_exit = iop->ob_ptr;
582 x86_jump8(iop->ob_ptr,0);
583
584 /* === Slow lookup === */
585 x86_patch(test1,iop->ob_ptr);
586 if (test2)
587 x86_patch(test2,iop->ob_ptr);
588
589 /* Update IA (EBX = vaddr) */
590 ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2));
591
592 /* EDX = virtual address */
593 x86_mov_reg_reg(iop->ob_ptr,X86_EDX,X86_EBX,4);
594
595 /* ECX = target register */
596 x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target);
597
598 /* EAX = CPU instance pointer */
599 x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4);
600
601 /* Call memory function */
602 x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST);
603 x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(opcode));
604 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST);
605
606 x86_patch(p_exit,iop->ob_ptr);
607 }
608
609 /* Emit unhandled instruction code */
ppc32_emit_unknown(cpu_ppc_t * cpu,ppc32_jit_tcb_t * b,ppc_insn_t opcode)610 static int ppc32_emit_unknown(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,
611 ppc_insn_t opcode)
612 {
613 u_char *test1;
614 jit_op_t *iop;
615
616 iop = ppc32_op_emit_insn_output(cpu,3,"unknown");
617
618 /* Update IA */
619 ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2));
620
621 /* Fallback to non-JIT mode */
622 x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST);
623 x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4);
624 x86_mov_reg_imm(iop->ob_ptr,X86_EDX,opcode);
625
626 ppc32_emit_basic_c_call(&iop->ob_ptr,ppc32_exec_single_insn_ext);
627 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST);
628
629 x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX);
630 test1 = iop->ob_ptr;
631 x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1);
632 ppc32_jit_tcb_push_epilog(&iop->ob_ptr);
633
634 x86_patch(test1,iop->ob_ptr);
635
636 /* Signal this as an EOB to reset JIT state */
637 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
638 return(0);
639 }
640
641 /* Virtual Breakpoint */
ppc32_emit_breakpoint(cpu_ppc_t * cpu,ppc32_jit_tcb_t * b)642 void ppc32_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
643 {
644 jit_op_t *iop;
645
646 iop = ppc32_op_emit_insn_output(cpu,2,"breakpoint");
647
648 x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST);
649 x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4);
650 ppc32_emit_c_call(b,iop,ppc32_run_breakpoint);
651 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST);
652
653 /* Signal this as an EOB to to reset JIT state */
654 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
655 }
656
657 /* Dump regs */
ppc32_emit_dump_regs(cpu_ppc_t * cpu,ppc32_jit_tcb_t * b)658 _Unused static void ppc32_emit_dump_regs(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b)
659 {
660 jit_op_t *iop;
661
662 iop = ppc32_op_emit_insn_output(cpu,2,"dump_regs");
663
664 x86_mov_reg_membase(iop->ob_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,gen),4);
665
666 x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST-4);
667 x86_push_reg(iop->ob_ptr,X86_EAX);
668 ppc32_emit_c_call(b,iop,ppc32_dump_regs);
669 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST);
670
671 /* Signal this as an EOB to to reset JIT state */
672 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
673 }
674
675 /* Increment the number of executed instructions (performance debugging) */
ppc32_inc_perf_counter(cpu_ppc_t * cpu)676 void ppc32_inc_perf_counter(cpu_ppc_t *cpu)
677 {
678 jit_op_t *iop;
679
680 iop = ppc32_op_emit_insn_output(cpu,1,"perf_cnt");
681 x86_inc_membase(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,perf_counter));
682 }
683
684 /* ======================================================================== */
685
686 /* BLR - Branch to Link Register */
DECLARE_INSN(BLR)687 DECLARE_INSN(BLR)
688 {
689 jit_op_t *iop;
690 int hreg;
691
692 ppc32_jit_start_hreg_seq(cpu,"blr");
693 hreg = ppc32_jit_alloc_hreg(cpu,-1);
694 ppc32_op_emit_alter_host_reg(cpu,hreg);
695
696 iop = ppc32_op_emit_insn_output(cpu,2,"blr");
697
698 x86_mov_reg_membase(iop->ob_ptr,hreg,X86_EDI,OFFSET(cpu_ppc_t,lr),4);
699 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),hreg,4);
700
701 /* set the return address */
702 if (insn & 1)
703 ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2));
704
705 ppc32_jit_tcb_push_epilog(&iop->ob_ptr);
706 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
707 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2));
708
709 ppc32_jit_close_hreg_seq(cpu);
710 return(0);
711 }
712
713 /* BCTR - Branch to Count Register */
DECLARE_INSN(BCTR)714 DECLARE_INSN(BCTR)
715 {
716 jit_op_t *iop;
717 int hreg;
718
719 ppc32_jit_start_hreg_seq(cpu,"bctr");
720 hreg = ppc32_jit_alloc_hreg(cpu,-1);
721 ppc32_op_emit_alter_host_reg(cpu,hreg);
722
723 iop = ppc32_op_emit_insn_output(cpu,2,"bctr");
724
725 x86_mov_reg_membase(iop->ob_ptr,hreg,X86_EDI,OFFSET(cpu_ppc_t,ctr),4);
726 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),hreg,4);
727
728 /* set the return address */
729 if (insn & 1)
730 ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2));
731
732 ppc32_jit_tcb_push_epilog(&iop->ob_ptr);
733 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
734 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2));
735
736 ppc32_jit_close_hreg_seq(cpu);
737 return(0);
738 }
739
740 /* MFLR - Move From Link Register */
DECLARE_INSN(MFLR)741 DECLARE_INSN(MFLR)
742 {
743 int rd = bits(insn,21,25);
744 int hreg_rd;
745 jit_op_t *iop;
746
747 ppc32_jit_start_hreg_seq(cpu,"mflr");
748 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
749 iop = ppc32_op_emit_insn_output(cpu,1,"mflr");
750
751 x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,lr),4);
752 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
753
754 ppc32_jit_close_hreg_seq(cpu);
755 return(0);
756 }
757
758 /* MTLR - Move To Link Register */
DECLARE_INSN(MTLR)759 DECLARE_INSN(MTLR)
760 {
761 int rs = bits(insn,21,25);
762 int hreg_rs;
763 jit_op_t *iop;
764
765 ppc32_jit_start_hreg_seq(cpu,"mtlr");
766 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
767 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
768
769 iop = ppc32_op_emit_insn_output(cpu,1,"mtlr");
770 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),hreg_rs,4);
771
772 ppc32_jit_close_hreg_seq(cpu);
773 return(0);
774 }
775
776 /* MFCTR - Move From Counter Register */
DECLARE_INSN(MFCTR)777 DECLARE_INSN(MFCTR)
778 {
779 int rd = bits(insn,21,25);
780 int hreg_rd;
781 jit_op_t *iop;
782
783 ppc32_jit_start_hreg_seq(cpu,"mfctr");
784 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
785
786 iop = ppc32_op_emit_insn_output(cpu,1,"mfctr");
787
788 x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,ctr),4);
789 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
790
791 ppc32_jit_close_hreg_seq(cpu);
792 return(0);
793 }
794
795 /* MTCTR - Move To Counter Register */
DECLARE_INSN(MTCTR)796 DECLARE_INSN(MTCTR)
797 {
798 int rs = bits(insn,21,25);
799 int hreg_rs;
800 jit_op_t *iop;
801
802 ppc32_jit_start_hreg_seq(cpu,"mtctr");
803 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
804 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
805
806 iop = ppc32_op_emit_insn_output(cpu,1,"mtctr");
807 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr),hreg_rs,4);
808
809 ppc32_jit_close_hreg_seq(cpu);
810 return(0);
811 }
812
813 /* MFTBU - Move from Time Base (Up) */
DECLARE_INSN(MFTBU)814 DECLARE_INSN(MFTBU)
815 {
816 int rd = bits(insn,21,25);
817 int hreg_rd;
818 jit_op_t *iop;
819
820 ppc32_jit_start_hreg_seq(cpu,"mftbu");
821 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
822
823 iop = ppc32_op_emit_insn_output(cpu,1,"mftbu");
824
825 x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,4);
826 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
827
828 ppc32_jit_close_hreg_seq(cpu);
829 return(0);
830 }
831
832 #define PPC32_TB_INCREMENT 50
833
834 /* MFTBL - Move from Time Base (Lo) */
DECLARE_INSN(MFTBL)835 DECLARE_INSN(MFTBL)
836 {
837 int rd = bits(insn,21,25);
838 int hreg_rd,hreg_t0;
839 jit_op_t *iop;
840
841 ppc32_jit_start_hreg_seq(cpu,"mftbl");
842 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
843 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
844
845 iop = ppc32_op_emit_insn_output(cpu,3,"mftbl");
846
847 x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,tb),4);
848
849 /* Increment the time base register */
850 x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,tb),4);
851 x86_mov_reg_membase(iop->ob_ptr,hreg_t0,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,4);
852 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,PPC32_TB_INCREMENT);
853 x86_alu_reg_imm(iop->ob_ptr,X86_ADC,hreg_t0,0);
854 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,tb),hreg_rd,4);
855 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,hreg_t0,4);
856
857 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
858
859 ppc32_jit_close_hreg_seq(cpu);
860 return(0);
861 }
862
863 /* ADD */
DECLARE_INSN(ADD)864 DECLARE_INSN(ADD)
865 {
866 int rd = bits(insn,21,25);
867 int ra = bits(insn,16,20);
868 int rb = bits(insn,11,15);
869 int hreg_rd,hreg_ra,hreg_rb;
870 jit_op_t *iop;
871
872 /* $rd = $ra + $rb */
873 ppc32_jit_start_hreg_seq(cpu,"add");
874 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
875 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
876 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
877
878 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
879 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
880
881 iop = ppc32_op_emit_insn_output(cpu,2,"add");
882
883 if (rd == ra)
884 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb);
885 else if (rd == rb)
886 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_ra);
887 else {
888 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4);
889 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb);
890 }
891
892 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
893
894 if (insn & 1)
895 ppc32_op_emit_update_flags(cpu,0,TRUE);
896
897 ppc32_jit_close_hreg_seq(cpu);
898 return(0);
899 }
900
901 /* ADDC */
DECLARE_INSN(ADDC)902 DECLARE_INSN(ADDC)
903 {
904 int rd = bits(insn,21,25);
905 int ra = bits(insn,16,20);
906 int rb = bits(insn,11,15);
907 int hreg_rd,hreg_ra,hreg_rb,hreg_t0;
908 jit_op_t *iop;
909
910 /* $rd = $ra + $rb */
911 ppc32_jit_start_hreg_seq(cpu,"addc");
912 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
913 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
914 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
915
916 /* store the carry flag */
917 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
918
919 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
920 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
921
922 iop = ppc32_op_emit_insn_output(cpu,2,"addc");
923
924 if (rd == ra)
925 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb);
926 else if (rd == rb)
927 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_ra);
928 else {
929 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4);
930 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb);
931 }
932
933 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
934
935 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t0,FALSE);
936 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x1);
937 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),
938 hreg_t0,4);
939
940 if (insn & 1) {
941 x86_test_reg_reg(iop->ob_ptr,hreg_rd,hreg_rd);
942 ppc32_op_emit_update_flags(cpu,0,TRUE);
943 }
944
945 ppc32_jit_close_hreg_seq(cpu);
946 return(0);
947 }
948
949 /* ADDE - Add Extended */
DECLARE_INSN(ADDE)950 DECLARE_INSN(ADDE)
951 {
952 int rd = bits(insn,21,25);
953 int ra = bits(insn,16,20);
954 int rb = bits(insn,11,15);
955 int hreg_ra,hreg_rb,hreg_rd,hreg_t0,hreg_t1;
956 jit_op_t *iop;
957
958 ppc32_jit_start_hreg_seq(cpu,"adde");
959 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
960 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
961 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
962
963 hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1);
964 hreg_t1 = ppc32_jit_get_tmp_hreg(cpu);
965
966 ppc32_op_emit_alter_host_reg(cpu,hreg_t0);
967 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
968 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
969
970 iop = ppc32_op_emit_insn_output(cpu,3,"adde");
971
972 /* $t0 = $ra + carry */
973 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1);
974 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4);
975
976 x86_alu_reg_membase(iop->ob_ptr,X86_ADD,hreg_t0,
977 X86_EDI,OFFSET(cpu_ppc_t,xer_ca));
978 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE);
979 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t1,4);
980
981 /* $t0 += $rb */
982 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb);
983 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE);
984 x86_alu_membase_reg(iop->ob_ptr,X86_OR,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),
985 hreg_t1);
986
987 /* update cr0 */
988 if (insn & 1)
989 x86_test_reg_reg(iop->ob_ptr,hreg_t0,hreg_t0);
990
991 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4);
992 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
993
994 if (insn & 1)
995 ppc32_op_emit_update_flags(cpu,0,TRUE);
996
997 ppc32_jit_close_hreg_seq(cpu);
998 return(0);
999 }
1000
1001 /* ADDI - ADD Immediate */
DECLARE_INSN(ADDI)1002 DECLARE_INSN(ADDI)
1003 {
1004 int rd = bits(insn,21,25);
1005 int ra = bits(insn,16,20);
1006 int imm = bits(insn,0,15);
1007 m_uint32_t tmp = sign_extend_32(imm,16);
1008 int hreg_rd,hreg_ra;
1009 jit_op_t *iop;
1010
1011 /* $rd = $ra + imm */
1012 ppc32_jit_start_hreg_seq(cpu,"addi");
1013 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
1014
1015 if (ra != 0) {
1016 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1017 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1018
1019 iop = ppc32_op_emit_insn_output(cpu,2,"addi");
1020
1021 if (rd != ra)
1022 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4);
1023
1024 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,tmp);
1025 } else {
1026 iop = ppc32_op_emit_insn_output(cpu,1,"addi");
1027 ppc32_load_imm(&iop->ob_ptr,hreg_rd,tmp);
1028 }
1029
1030 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
1031
1032 ppc32_jit_close_hreg_seq(cpu);
1033 return(0);
1034 }
1035
1036 /* ADDIC - ADD Immediate with Carry */
DECLARE_INSN(ADDIC)1037 DECLARE_INSN(ADDIC)
1038 {
1039 int rd = bits(insn,21,25);
1040 int ra = bits(insn,16,20);
1041 int imm = bits(insn,0,15);
1042 m_uint32_t tmp = sign_extend_32(imm,16);
1043 int hreg_rd,hreg_ra;
1044 jit_op_t *iop;
1045
1046 /* $rd = $ra + imm */
1047 ppc32_jit_start_hreg_seq(cpu,"addic");
1048 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
1049 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1050
1051 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1052
1053 iop = ppc32_op_emit_insn_output(cpu,1,"addic");
1054
1055 if (rd != ra)
1056 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4);
1057
1058 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,tmp);
1059 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
1060
1061 x86_set_membase(iop->ob_ptr,X86_CC_C,
1062 X86_EDI,OFFSET(cpu_ppc_t,xer_ca),FALSE);
1063
1064 ppc32_jit_close_hreg_seq(cpu);
1065 return(0);
1066 }
1067
1068 /* ADDIC. */
DECLARE_INSN(ADDIC_dot)1069 DECLARE_INSN(ADDIC_dot)
1070 {
1071 int rd = bits(insn,21,25);
1072 int ra = bits(insn,16,20);
1073 int imm = bits(insn,0,15);
1074 m_uint32_t tmp = sign_extend_32(imm,16);
1075 int hreg_rd,hreg_ra;
1076 jit_op_t *iop;
1077
1078 /* $rd = $ra + imm */
1079 ppc32_jit_start_hreg_seq(cpu,"addic.");
1080 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
1081 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1082
1083 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1084
1085 iop = ppc32_op_emit_insn_output(cpu,1,"addic.");
1086
1087 if (rd != ra)
1088 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4);
1089
1090 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,tmp);
1091 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
1092
1093 x86_set_membase(iop->ob_ptr,X86_CC_C,
1094 X86_EDI,OFFSET(cpu_ppc_t,xer_ca),FALSE);
1095
1096 ppc32_op_emit_update_flags(cpu,0,TRUE);
1097
1098 ppc32_jit_close_hreg_seq(cpu);
1099 return(0);
1100 }
1101
1102 /* ADDIS - ADD Immediate Shifted */
DECLARE_INSN(ADDIS)1103 DECLARE_INSN(ADDIS)
1104 {
1105 int rd = bits(insn,21,25);
1106 int ra = bits(insn,16,20);
1107 m_uint32_t imm = bits(insn,0,15);
1108 m_uint32_t tmp = imm << 16;
1109 int hreg_rd,hreg_ra;
1110 jit_op_t *iop;
1111
1112 /* $rd = $ra + (imm << 16) */
1113 ppc32_jit_start_hreg_seq(cpu,"addis");
1114 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
1115
1116 if (ra != 0) {
1117 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1118 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1119
1120 iop = ppc32_op_emit_insn_output(cpu,1,"addis");
1121
1122 if (rd != ra)
1123 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4);
1124
1125 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,tmp);
1126 } else {
1127 //iop = ppc32_op_emit_insn_output(cpu,1,"addis");
1128 //x86_mov_reg_imm(iop->ob_ptr,hreg_rd,tmp);
1129 ppc32_op_emit_set_host_reg_imm32(cpu,hreg_rd,tmp);
1130 }
1131
1132 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
1133
1134 ppc32_jit_close_hreg_seq(cpu);
1135 return(0);
1136 }
1137
1138 /* ADDZE */
DECLARE_INSN(ADDZE)1139 DECLARE_INSN(ADDZE)
1140 {
1141 int rd = bits(insn,21,25);
1142 int ra = bits(insn,16,20);
1143 int hreg_rd,hreg_ra,hreg_t0;
1144 jit_op_t *iop;
1145
1146 /* $rd = $ra + xer_ca + set_carry */
1147 ppc32_jit_start_hreg_seq(cpu,"addze");
1148 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
1149 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1150 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
1151
1152 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1153
1154 iop = ppc32_op_emit_insn_output(cpu,2,"addze");
1155
1156 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,hreg_t0);
1157
1158 if (rd != ra)
1159 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4);
1160
1161 x86_alu_reg_membase(iop->ob_ptr,X86_ADD,hreg_rd,
1162 X86_EDI,OFFSET(cpu_ppc_t,xer_ca));
1163
1164 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t0,FALSE);
1165 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t0,4);
1166
1167 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
1168
1169 if (insn & 1)
1170 ppc32_op_emit_update_flags(cpu,0,TRUE);
1171
1172 ppc32_jit_close_hreg_seq(cpu);
1173 return(0);
1174 }
1175
1176 /* AND */
DECLARE_INSN(AND)1177 DECLARE_INSN(AND)
1178 {
1179 int rs = bits(insn,21,25);
1180 int ra = bits(insn,16,20);
1181 int rb = bits(insn,11,15);
1182 int hreg_rs,hreg_ra,hreg_rb;
1183 jit_op_t *iop;
1184
1185 /* $ra = $rs & $rb */
1186 ppc32_jit_start_hreg_seq(cpu,"and");
1187 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
1188 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1189 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
1190
1191 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
1192 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
1193
1194 iop = ppc32_op_emit_insn_output(cpu,1,"and");
1195
1196 if (ra == rs)
1197 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb);
1198 else if (ra == rb)
1199 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rs);
1200 else {
1201 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
1202 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb);
1203 }
1204
1205 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
1206
1207 if (insn & 1)
1208 ppc32_op_emit_update_flags(cpu,0,TRUE);
1209
1210 ppc32_jit_close_hreg_seq(cpu);
1211 return(0);
1212 }
1213
1214 /* ANDC */
DECLARE_INSN(ANDC)1215 DECLARE_INSN(ANDC)
1216 {
1217 int rs = bits(insn,21,25);
1218 int ra = bits(insn,16,20);
1219 int rb = bits(insn,11,15);
1220 int hreg_rs,hreg_ra,hreg_rb,hreg_t0;
1221 jit_op_t *iop;
1222
1223 /* $ra = $rs & ~$rb */
1224 ppc32_jit_start_hreg_seq(cpu,"andc");
1225 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
1226 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1227 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
1228
1229 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
1230 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
1231
1232 iop = ppc32_op_emit_insn_output(cpu,1,"andc");
1233
1234 /* $t0 = ~$rb */
1235 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
1236 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4);
1237 x86_not_reg(iop->ob_ptr,hreg_t0);
1238
1239 /* $ra = $rs & $t0 */
1240 if (ra == rs)
1241 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_t0);
1242 else {
1243 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_rs);
1244 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4);
1245 }
1246
1247 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
1248
1249 if (insn & 1)
1250 ppc32_op_emit_update_flags(cpu,0,TRUE);
1251
1252 ppc32_jit_close_hreg_seq(cpu);
1253 return(0);
1254 }
1255
1256 /* AND Immediate */
DECLARE_INSN(ANDI)1257 DECLARE_INSN(ANDI)
1258 {
1259 int rs = bits(insn,21,25);
1260 int ra = bits(insn,16,20);
1261 m_uint16_t imm = bits(insn,0,15);
1262 m_uint32_t tmp = imm;
1263 int hreg_rs,hreg_ra;
1264 jit_op_t *iop;
1265
1266 /* $ra = $rs & imm */
1267 ppc32_jit_start_hreg_seq(cpu,"andi");
1268 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
1269 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1270
1271 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
1272
1273 iop = ppc32_op_emit_insn_output(cpu,2,"andi");
1274
1275 if (ra != rs)
1276 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
1277
1278 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,tmp);
1279 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
1280
1281 ppc32_op_emit_update_flags(cpu,0,TRUE);
1282
1283 ppc32_jit_close_hreg_seq(cpu);
1284 return(0);
1285 }
1286
1287 /* AND Immediate Shifted */
DECLARE_INSN(ANDIS)1288 DECLARE_INSN(ANDIS)
1289 {
1290 int rs = bits(insn,21,25);
1291 int ra = bits(insn,16,20);
1292 m_uint32_t imm = bits(insn,0,15);
1293 m_uint32_t tmp = imm << 16;
1294 int hreg_rs,hreg_ra;
1295 jit_op_t *iop;
1296
1297 /* $ra = $rs & imm */
1298 ppc32_jit_start_hreg_seq(cpu,"andis");
1299 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
1300 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1301
1302 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
1303
1304 iop = ppc32_op_emit_insn_output(cpu,2,"andis");
1305
1306 if (ra != rs)
1307 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
1308
1309 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,tmp);
1310 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
1311
1312 ppc32_op_emit_update_flags(cpu,0,TRUE);
1313
1314 ppc32_jit_close_hreg_seq(cpu);
1315 return(0);
1316 }
1317
1318 /* B - Branch */
DECLARE_INSN(B)1319 DECLARE_INSN(B)
1320 {
1321 m_uint32_t offset = bits(insn,2,25);
1322 m_uint32_t new_ia;
1323 jit_op_t *iop;
1324
1325 iop = ppc32_op_emit_insn_output(cpu,4,"b");
1326
1327 /* compute the new ia */
1328 new_ia = b->start_ia + (b->ppc_trans_pos << 2);
1329 new_ia += sign_extend(offset << 2,26);
1330 ppc32_set_jump(cpu,b,iop,new_ia,TRUE);
1331
1332 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
1333 ppc32_op_emit_branch_target(cpu,b,new_ia);
1334 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2));
1335 return(0);
1336 }
1337
1338 /* BA - Branch Absolute */
DECLARE_INSN(BA)1339 DECLARE_INSN(BA)
1340 {
1341 m_uint32_t offset = bits(insn,2,25);
1342 m_uint32_t new_ia;
1343 jit_op_t *iop;
1344
1345 iop = ppc32_op_emit_insn_output(cpu,4,"ba");
1346
1347 /* compute the new ia */
1348 new_ia = sign_extend(offset << 2,26);
1349 ppc32_set_jump(cpu,b,iop,new_ia,TRUE);
1350
1351 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
1352 ppc32_op_emit_branch_target(cpu,b,new_ia);
1353 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2));
1354 return(0);
1355 }
1356
1357 /* BL - Branch and Link */
DECLARE_INSN(BL)1358 DECLARE_INSN(BL)
1359 {
1360 m_uint32_t offset = bits(insn,2,25);
1361 m_uint32_t new_ia;
1362 jit_op_t *iop;
1363
1364 iop = ppc32_op_emit_insn_output(cpu,4,"bl");
1365
1366 /* compute the new ia */
1367 new_ia = b->start_ia + (b->ppc_trans_pos << 2);
1368 new_ia += sign_extend(offset << 2,26);
1369
1370 /* set the return address */
1371 ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2));
1372 ppc32_set_jump(cpu,b,iop,new_ia,TRUE);
1373
1374 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
1375 ppc32_op_emit_branch_target(cpu,b,new_ia);
1376 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2));
1377 return(0);
1378 }
1379
1380 /* BLA - Branch and Link Absolute */
DECLARE_INSN(BLA)1381 DECLARE_INSN(BLA)
1382 {
1383 m_uint32_t offset = bits(insn,2,25);
1384 m_uint32_t new_ia;
1385 jit_op_t *iop;
1386
1387 iop = ppc32_op_emit_insn_output(cpu,4,"bla");
1388
1389 /* compute the new ia */
1390 new_ia = sign_extend(offset << 2,26);
1391
1392 /* set the return address */
1393 ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2));
1394 ppc32_set_jump(cpu,b,iop,new_ia,TRUE);
1395
1396 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
1397 ppc32_op_emit_branch_target(cpu,b,new_ia);
1398 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2));
1399 return(0);
1400 }
1401
1402 /* BC - Branch Conditional (Condition Check only) */
DECLARE_INSN(BCC)1403 DECLARE_INSN(BCC)
1404 {
1405 int bo = bits(insn,21,25);
1406 int bi = bits(insn,16,20);
1407 int bd = bits(insn,2,15);
1408 jit_op_t *iop;
1409 u_int cr_field,cr_bit;
1410 m_uint32_t new_ia;
1411 u_char *jump_ptr;
1412 int local_jump;
1413 int cond;
1414
1415 ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_JUMP);
1416
1417 iop = ppc32_op_emit_insn_output(cpu,5,"bcc");
1418
1419 /* Get the wanted value for the condition bit */
1420 cond = (bo >> 3) & 0x1;
1421
1422 /* Set the return address */
1423 if (insn & 1) {
1424 ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2));
1425 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1)<<2));
1426 }
1427
1428 /* Compute the new ia */
1429 new_ia = sign_extend_32(bd << 2,16);
1430 if (!(insn & 0x02))
1431 new_ia += b->start_ia + (b->ppc_trans_pos << 2);
1432
1433 /* Test the condition bit */
1434 cr_field = ppc32_get_cr_field(bi);
1435 cr_bit = ppc32_get_cr_bit(bi);
1436
1437 ppc32_op_emit_require_flags(cpu,cr_field);
1438
1439 x86_test_membase_imm(iop->ob_ptr,
1440 X86_EDI,PPC32_CR_FIELD_OFFSET(cr_field),
1441 (1 << cr_bit));
1442
1443 local_jump = ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr);
1444
1445 /*
1446 * Optimize the jump, depending if the destination is in the same
1447 * page or not.
1448 */
1449 if (local_jump) {
1450 ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia);
1451 x86_branch32(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,0,FALSE);
1452 } else {
1453 jump_ptr = iop->ob_ptr;
1454 x86_branch32(iop->ob_ptr,(cond) ? X86_CC_Z : X86_CC_NZ,0,FALSE);
1455 ppc32_set_jump(cpu,b,iop,new_ia,TRUE);
1456 x86_patch(jump_ptr,iop->ob_ptr);
1457 }
1458
1459 ppc32_op_emit_branch_target(cpu,b,new_ia);
1460 return(0);
1461 }
1462
1463 /* BC - Branch Conditional */
DECLARE_INSN(BC)1464 DECLARE_INSN(BC)
1465 {
1466 int bo = bits(insn,21,25);
1467 int bi = bits(insn,16,20);
1468 int bd = bits(insn,2,15);
1469 int hreg_t0,hreg_t1;
1470 jit_op_t *iop;
1471 u_int cr_field,cr_bit;
1472 m_uint32_t new_ia;
1473 u_char *jump_ptr;
1474 int local_jump;
1475 int cond,ctr;
1476
1477 ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_JUMP);
1478
1479 iop = ppc32_op_emit_insn_output(cpu,5,"bc");
1480
1481 ppc32_jit_start_hreg_seq(cpu,"bc");
1482 hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1);
1483 hreg_t1 = ppc32_jit_get_tmp_hreg(cpu);
1484
1485 ppc32_op_emit_alter_host_reg(cpu,hreg_t0);
1486
1487 /* Get the wanted value for the condition bit and CTR value */
1488 cond = (bo >> 3) & 0x1;
1489 ctr = (bo >> 1) & 0x1;
1490
1491 /* Set the return address */
1492 if (insn & 1) {
1493 ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2));
1494 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1)<<2));
1495 }
1496
1497 /* Compute the new ia */
1498 new_ia = sign_extend_32(bd << 2,16);
1499 if (!(insn & 0x02))
1500 new_ia += b->start_ia + (b->ppc_trans_pos << 2);
1501
1502 x86_mov_reg_imm(iop->ob_ptr,hreg_t0,1);
1503
1504 /* Decrement the count register */
1505 if (!(bo & 0x04)) {
1506 x86_dec_membase(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr));
1507 x86_set_reg(iop->ob_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,hreg_t1,FALSE);
1508 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1);
1509 }
1510
1511 /* Test the condition bit */
1512 if (!((bo >> 4) & 0x01)) {
1513 cr_field = ppc32_get_cr_field(bi);
1514 cr_bit = ppc32_get_cr_bit(bi);
1515
1516 ppc32_op_emit_require_flags(cpu,cr_field);
1517
1518 x86_test_membase_imm(iop->ob_ptr,
1519 X86_EDI,PPC32_CR_FIELD_OFFSET(cr_field),
1520 (1 << cr_bit));
1521
1522 x86_set_reg(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,hreg_t1,FALSE);
1523 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1);
1524 }
1525
1526 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
1527
1528 local_jump = ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr);
1529
1530 /*
1531 * Optimize the jump, depending if the destination is in the same
1532 * page or not.
1533 */
1534 if (local_jump) {
1535 ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia);
1536 x86_branch32(iop->ob_ptr,X86_CC_NZ,0,FALSE);
1537 } else {
1538 jump_ptr = iop->ob_ptr;
1539 x86_branch32(iop->ob_ptr,X86_CC_Z,0,FALSE);
1540 ppc32_set_jump(cpu,b,iop,new_ia,TRUE);
1541 x86_patch(jump_ptr,iop->ob_ptr);
1542 }
1543
1544 ppc32_op_emit_branch_target(cpu,b,new_ia);
1545
1546 ppc32_jit_close_hreg_seq(cpu);
1547 return(0);
1548 }
1549
1550 /* BCLR - Branch Conditional to Link register */
DECLARE_INSN(BCLR)1551 DECLARE_INSN(BCLR)
1552 {
1553 int bo = bits(insn,21,25);
1554 int bi = bits(insn,16,20);
1555 int bd = bits(insn,2,15);
1556 int hreg_t0,hreg_t1;
1557 jit_op_t *iop;
1558 u_int cr_field,cr_bit;
1559 m_uint32_t new_ia;
1560 u_char *jump_ptr;
1561 int cond,ctr;
1562
1563 ppc32_jit_start_hreg_seq(cpu,"bclr");
1564 hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1);
1565 hreg_t1 = ppc32_jit_get_tmp_hreg(cpu);
1566
1567 ppc32_op_emit_alter_host_reg(cpu,hreg_t0);
1568
1569 iop = ppc32_op_emit_insn_output(cpu,5,"bclr");
1570
1571 /* Get the wanted value for the condition bit and CTR value */
1572 cond = (bo >> 3) & 0x1;
1573 ctr = (bo >> 1) & 0x1;
1574
1575 /* Compute the new ia */
1576 new_ia = sign_extend_32(bd << 2,16);
1577 if (!(insn & 0x02))
1578 new_ia += b->start_ia + (b->ppc_trans_pos << 2);
1579
1580 x86_mov_reg_imm(iop->ob_ptr,hreg_t0,1);
1581
1582 /* Decrement the count register */
1583 if (!(bo & 0x04)) {
1584 x86_dec_membase(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr));
1585 x86_set_reg(iop->ob_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,hreg_t1,FALSE);
1586 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1);
1587 }
1588
1589 /* Test the condition bit */
1590 if (!((bo >> 4) & 0x01)) {
1591 cr_field = ppc32_get_cr_field(bi);
1592 cr_bit = ppc32_get_cr_bit(bi);
1593
1594 ppc32_op_emit_require_flags(cpu,cr_field);
1595
1596 x86_test_membase_imm(iop->ob_ptr,
1597 X86_EDI,PPC32_CR_FIELD_OFFSET(cr_field),
1598 (1 << cr_bit));
1599
1600 x86_set_reg(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,hreg_t1,FALSE);
1601 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1);
1602 }
1603
1604 /* Set the return address */
1605 x86_mov_reg_membase(iop->ob_ptr,hreg_t1,X86_EDI,OFFSET(cpu_ppc_t,lr),4);
1606
1607 if (insn & 1) {
1608 ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2));
1609 ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1)<<2));
1610 }
1611
1612 /* Branching */
1613 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
1614
1615 jump_ptr = iop->ob_ptr;
1616 x86_branch32(iop->ob_ptr,X86_CC_Z,0,FALSE);
1617
1618 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t1,0xFFFFFFFC);
1619 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),hreg_t1,4);
1620 ppc32_jit_tcb_push_epilog(&iop->ob_ptr);
1621
1622 x86_patch(jump_ptr,iop->ob_ptr);
1623
1624 ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);
1625
1626 ppc32_jit_close_hreg_seq(cpu);
1627 return(0);
1628 }
1629
1630 /* CMP - Compare */
DECLARE_INSN(CMP)1631 DECLARE_INSN(CMP)
1632 {
1633 int rd = bits(insn,23,25);
1634 int ra = bits(insn,16,20);
1635 int rb = bits(insn,11,15);
1636 int hreg_ra,hreg_rb;
1637 jit_op_t *iop;
1638
1639 ppc32_jit_start_hreg_seq(cpu,"cmp");
1640 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1641 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
1642
1643 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1644 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
1645
1646 iop = ppc32_op_emit_insn_output(cpu,1,"cmp");
1647
1648 x86_alu_reg_reg(iop->ob_ptr,X86_CMP,hreg_ra,hreg_rb);
1649 ppc32_op_emit_update_flags(cpu,rd,TRUE);
1650
1651 ppc32_jit_close_hreg_seq(cpu);
1652 return(0);
1653 }
1654
1655 /* CMPI - Compare Immediate */
DECLARE_INSN(CMPI)1656 DECLARE_INSN(CMPI)
1657 {
1658 int rd = bits(insn,23,25);
1659 int ra = bits(insn,16,20);
1660 m_uint16_t imm = bits(insn,0,15);
1661 m_uint32_t tmp = sign_extend_32(imm,16);
1662 int hreg_ra;
1663 jit_op_t *iop;
1664
1665 ppc32_jit_start_hreg_seq(cpu,"cmpi");
1666 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1667 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1668
1669 iop = ppc32_op_emit_insn_output(cpu,1,"cmpi");
1670
1671 x86_alu_reg_imm(iop->ob_ptr,X86_CMP,hreg_ra,tmp);
1672 ppc32_op_emit_update_flags(cpu,rd,TRUE);
1673
1674 ppc32_jit_close_hreg_seq(cpu);
1675 return(0);
1676 }
1677
1678 /* CMPL - Compare Logical */
DECLARE_INSN(CMPL)1679 DECLARE_INSN(CMPL)
1680 {
1681 int rd = bits(insn,23,25);
1682 int ra = bits(insn,16,20);
1683 int rb = bits(insn,11,15);
1684 int hreg_ra,hreg_rb;
1685 jit_op_t *iop;
1686
1687 ppc32_jit_start_hreg_seq(cpu,"cmpl");
1688 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1689 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
1690
1691 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1692 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
1693
1694 iop = ppc32_op_emit_insn_output(cpu,1,"cmpl");
1695
1696 x86_alu_reg_reg(iop->ob_ptr,X86_CMP,hreg_ra,hreg_rb);
1697 ppc32_op_emit_update_flags(cpu,rd,FALSE);
1698
1699 ppc32_jit_close_hreg_seq(cpu);
1700 return(0);
1701 }
1702
1703 /* CMPLI - Compare Immediate */
DECLARE_INSN(CMPLI)1704 DECLARE_INSN(CMPLI)
1705 {
1706 int rd = bits(insn,23,25);
1707 int ra = bits(insn,16,20);
1708 m_uint32_t imm = bits(insn,0,15);
1709 int hreg_ra;
1710 jit_op_t *iop;
1711
1712 ppc32_jit_start_hreg_seq(cpu,"cmpli");
1713 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
1714 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
1715
1716 iop = ppc32_op_emit_insn_output(cpu,1,"cmpli");
1717
1718 x86_alu_reg_imm(iop->ob_ptr,X86_CMP,hreg_ra,imm);
1719 ppc32_op_emit_update_flags(cpu,rd,FALSE);
1720
1721 ppc32_jit_close_hreg_seq(cpu);
1722 return(0);
1723 }
1724
1725 /* CRAND - Condition Register AND */
DECLARE_INSN(CRAND)1726 DECLARE_INSN(CRAND)
1727 {
1728 int bd = bits(insn,21,25);
1729 int bb = bits(insn,16,20);
1730 int ba = bits(insn,11,15);
1731 int hreg_t0;
1732 jit_op_t *iop;
1733
1734 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
1735
1736 ppc32_jit_start_hreg_seq(cpu,"crand");
1737 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
1738 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
1739
1740 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba));
1741 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb));
1742 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd));
1743
1744 iop = ppc32_op_emit_insn_output(cpu,3,"crand");
1745
1746 /* test $ba bit */
1747 x86_test_membase_imm(iop->ob_ptr,
1748 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)),
1749 (1 << ppc32_get_cr_bit(ba)));
1750 x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE);
1751
1752 /* test $bb bit */
1753 x86_test_membase_imm(iop->ob_ptr,
1754 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)),
1755 (1 << ppc32_get_cr_bit(bb)));
1756 x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE);
1757
1758 /* result of AND between $ba and $bb */
1759 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,X86_EDX);
1760 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
1761
1762 /* set/clear $bd bit depending on the result */
1763 x86_alu_membase_imm(iop->ob_ptr,X86_AND,
1764 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1765 ~(1 << ppc32_get_cr_bit(bd)));
1766
1767 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd));
1768 x86_alu_membase_reg(iop->ob_ptr,X86_OR,
1769 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1770 hreg_t0);
1771
1772 ppc32_jit_close_hreg_seq(cpu);
1773 return(0);
1774 }
1775
1776 /* CRANDC - Condition Register AND with Complement */
DECLARE_INSN(CRANDC)1777 DECLARE_INSN(CRANDC)
1778 {
1779 int bd = bits(insn,21,25);
1780 int bb = bits(insn,16,20);
1781 int ba = bits(insn,11,15);
1782 int hreg_t0;
1783 jit_op_t *iop;
1784
1785 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
1786
1787 ppc32_jit_start_hreg_seq(cpu,"crandc");
1788 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
1789 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
1790
1791 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba));
1792 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb));
1793 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd));
1794
1795 iop = ppc32_op_emit_insn_output(cpu,3,"crandc");
1796
1797 /* test $ba bit */
1798 x86_test_membase_imm(iop->ob_ptr,
1799 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)),
1800 (1 << ppc32_get_cr_bit(ba)));
1801 x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE);
1802
1803 /* test $bb bit */
1804 x86_test_membase_imm(iop->ob_ptr,
1805 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)),
1806 (1 << ppc32_get_cr_bit(bb)));
1807 x86_set_reg(iop->ob_ptr,X86_CC_Z,hreg_t0,FALSE);
1808
1809 /* result of AND between $ba and $bb */
1810 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,X86_EDX);
1811 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
1812
1813 /* set/clear $bd bit depending on the result */
1814 x86_alu_membase_imm(iop->ob_ptr,X86_AND,
1815 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1816 ~(1 << ppc32_get_cr_bit(bd)));
1817
1818 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd));
1819 x86_alu_membase_reg(iop->ob_ptr,X86_OR,
1820 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1821 hreg_t0);
1822
1823 ppc32_jit_close_hreg_seq(cpu);
1824 return(0);
1825 }
1826
1827 /* CREQV - Condition Register EQV */
DECLARE_INSN(CREQV)1828 DECLARE_INSN(CREQV)
1829 {
1830 int bd = bits(insn,21,25);
1831 int bb = bits(insn,16,20);
1832 int ba = bits(insn,11,15);
1833 int hreg_t0;
1834 jit_op_t *iop;
1835
1836 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
1837
1838 ppc32_jit_start_hreg_seq(cpu,"creqv");
1839 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
1840 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
1841
1842 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba));
1843 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb));
1844 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd));
1845
1846 iop = ppc32_op_emit_insn_output(cpu,3,"creqv");
1847
1848 /* test $ba bit */
1849 x86_test_membase_imm(iop->ob_ptr,
1850 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)),
1851 (1 << ppc32_get_cr_bit(ba)));
1852 x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE);
1853
1854 /* test $bb bit */
1855 x86_test_membase_imm(iop->ob_ptr,
1856 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)),
1857 (1 << ppc32_get_cr_bit(bb)));
1858 x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE);
1859
1860 /* result of XOR between $ba and $bb */
1861 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,X86_EDX);
1862 x86_not_reg(iop->ob_ptr,hreg_t0);
1863 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
1864
1865 /* set/clear $bd bit depending on the result */
1866 x86_alu_membase_imm(iop->ob_ptr,X86_AND,
1867 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1868 ~(1 << ppc32_get_cr_bit(bd)));
1869
1870 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd));
1871 x86_alu_membase_reg(iop->ob_ptr,X86_OR,
1872 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1873 hreg_t0);
1874
1875 ppc32_jit_close_hreg_seq(cpu);
1876 return(0);
1877 }
1878
1879 /* CRNAND - Condition Register NAND */
DECLARE_INSN(CRNAND)1880 DECLARE_INSN(CRNAND)
1881 {
1882 int bd = bits(insn,21,25);
1883 int bb = bits(insn,16,20);
1884 int ba = bits(insn,11,15);
1885 int hreg_t0;
1886 jit_op_t *iop;
1887
1888 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
1889
1890 ppc32_jit_start_hreg_seq(cpu,"crnand");
1891 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
1892 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
1893
1894 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba));
1895 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb));
1896 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd));
1897
1898 iop = ppc32_op_emit_insn_output(cpu,3,"crnand");
1899
1900 /* test $ba bit */
1901 x86_test_membase_imm(iop->ob_ptr,
1902 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)),
1903 (1 << ppc32_get_cr_bit(ba)));
1904 x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE);
1905
1906 /* test $bb bit */
1907 x86_test_membase_imm(iop->ob_ptr,
1908 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)),
1909 (1 << ppc32_get_cr_bit(bb)));
1910 x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE);
1911
1912 /* result of NAND between $ba and $bb */
1913 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,X86_EDX);
1914 x86_not_reg(iop->ob_ptr,hreg_t0);
1915 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
1916
1917 /* set/clear $bd bit depending on the result */
1918 x86_alu_membase_imm(iop->ob_ptr,X86_AND,
1919 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1920 ~(1 << ppc32_get_cr_bit(bd)));
1921
1922 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd));
1923 x86_alu_membase_reg(iop->ob_ptr,X86_OR,
1924 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1925 hreg_t0);
1926
1927 ppc32_jit_close_hreg_seq(cpu);
1928 return(0);
1929 }
1930
1931 /* CRNOR - Condition Register NOR */
DECLARE_INSN(CRNOR)1932 DECLARE_INSN(CRNOR)
1933 {
1934 int bd = bits(insn,21,25);
1935 int bb = bits(insn,16,20);
1936 int ba = bits(insn,11,15);
1937 int hreg_t0;
1938 jit_op_t *iop;
1939
1940 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
1941
1942 ppc32_jit_start_hreg_seq(cpu,"crnor");
1943 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
1944 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
1945
1946 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba));
1947 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb));
1948 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd));
1949
1950 iop = ppc32_op_emit_insn_output(cpu,3,"crnor");
1951
1952 /* test $ba bit */
1953 x86_test_membase_imm(iop->ob_ptr,
1954 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)),
1955 (1 << ppc32_get_cr_bit(ba)));
1956 x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE);
1957
1958 /* test $bb bit */
1959 x86_test_membase_imm(iop->ob_ptr,
1960 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)),
1961 (1 << ppc32_get_cr_bit(bb)));
1962 x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE);
1963
1964 /* result of NOR between $ba and $bb */
1965 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,X86_EDX);
1966 x86_not_reg(iop->ob_ptr,hreg_t0);
1967 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
1968
1969 /* set/clear $bd bit depending on the result */
1970 x86_alu_membase_imm(iop->ob_ptr,X86_AND,
1971 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1972 ~(1 << ppc32_get_cr_bit(bd)));
1973
1974 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd));
1975 x86_alu_membase_reg(iop->ob_ptr,X86_OR,
1976 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
1977 hreg_t0);
1978
1979 ppc32_jit_close_hreg_seq(cpu);
1980 return(0);
1981 }
1982
1983 /* CROR - Condition Register OR */
DECLARE_INSN(CROR)1984 DECLARE_INSN(CROR)
1985 {
1986 int bd = bits(insn,21,25);
1987 int bb = bits(insn,16,20);
1988 int ba = bits(insn,11,15);
1989 int hreg_t0;
1990 jit_op_t *iop;
1991
1992 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
1993
1994 ppc32_jit_start_hreg_seq(cpu,"cror");
1995 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
1996 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
1997
1998 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba));
1999 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb));
2000 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd));
2001
2002 iop = ppc32_op_emit_insn_output(cpu,3,"cror");
2003
2004 /* test $ba bit */
2005 x86_test_membase_imm(iop->ob_ptr,
2006 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)),
2007 (1 << ppc32_get_cr_bit(ba)));
2008 x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE);
2009
2010 /* test $bb bit */
2011 x86_test_membase_imm(iop->ob_ptr,
2012 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)),
2013 (1 << ppc32_get_cr_bit(bb)));
2014 x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE);
2015
2016 /* result of OR between $ba and $bb */
2017 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,X86_EDX);
2018 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
2019
2020 /* set/clear $bd bit depending on the result */
2021 x86_alu_membase_imm(iop->ob_ptr,X86_AND,
2022 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
2023 ~(1 << ppc32_get_cr_bit(bd)));
2024
2025 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd));
2026 x86_alu_membase_reg(iop->ob_ptr,X86_OR,
2027 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
2028 hreg_t0);
2029
2030 ppc32_jit_close_hreg_seq(cpu);
2031 return(0);
2032 }
2033
2034 /* CRORC - Condition Register OR with Complement */
DECLARE_INSN(CRORC)2035 DECLARE_INSN(CRORC)
2036 {
2037 int bd = bits(insn,21,25);
2038 int bb = bits(insn,16,20);
2039 int ba = bits(insn,11,15);
2040 int hreg_t0;
2041 jit_op_t *iop;
2042
2043 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
2044
2045 ppc32_jit_start_hreg_seq(cpu,"crorc");
2046 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
2047 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
2048
2049 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba));
2050 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb));
2051 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd));
2052
2053 iop = ppc32_op_emit_insn_output(cpu,3,"crorc");
2054
2055 /* test $ba bit */
2056 x86_test_membase_imm(iop->ob_ptr,
2057 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)),
2058 (1 << ppc32_get_cr_bit(ba)));
2059 x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE);
2060
2061 /* test $bb bit */
2062 x86_test_membase_imm(iop->ob_ptr,
2063 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)),
2064 (1 << ppc32_get_cr_bit(bb)));
2065 x86_set_reg(iop->ob_ptr,X86_CC_Z,hreg_t0,FALSE);
2066
2067 /* result of ORC between $ba and $bb */
2068 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,X86_EDX);
2069 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
2070
2071 /* set/clear $bd bit depending on the result */
2072 x86_alu_membase_imm(iop->ob_ptr,X86_AND,
2073 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
2074 ~(1 << ppc32_get_cr_bit(bd)));
2075
2076 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd));
2077 x86_alu_membase_reg(iop->ob_ptr,X86_OR,
2078 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
2079 hreg_t0);
2080
2081 ppc32_jit_close_hreg_seq(cpu);
2082 return(0);
2083 }
2084
2085 /* CRXOR - Condition Register XOR */
DECLARE_INSN(CRXOR)2086 DECLARE_INSN(CRXOR)
2087 {
2088 int bd = bits(insn,21,25);
2089 int bb = bits(insn,16,20);
2090 int ba = bits(insn,11,15);
2091 int hreg_t0;
2092 jit_op_t *iop;
2093
2094 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
2095
2096 ppc32_jit_start_hreg_seq(cpu,"crxor");
2097 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
2098 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
2099
2100 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba));
2101 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb));
2102 ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd));
2103
2104 iop = ppc32_op_emit_insn_output(cpu,3,"crxor");
2105
2106 /* test $ba bit */
2107 x86_test_membase_imm(iop->ob_ptr,
2108 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)),
2109 (1 << ppc32_get_cr_bit(ba)));
2110 x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE);
2111
2112 /* test $bb bit */
2113 x86_test_membase_imm(iop->ob_ptr,
2114 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)),
2115 (1 << ppc32_get_cr_bit(bb)));
2116 x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE);
2117
2118 /* result of XOR between $ba and $bb */
2119 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,X86_EDX);
2120 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01);
2121
2122 /* set/clear $bd bit depending on the result */
2123 x86_alu_membase_imm(iop->ob_ptr,X86_AND,
2124 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
2125 ~(1 << ppc32_get_cr_bit(bd)));
2126
2127 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd));
2128 x86_alu_membase_reg(iop->ob_ptr,X86_OR,
2129 X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)),
2130 hreg_t0);
2131
2132 ppc32_jit_close_hreg_seq(cpu);
2133 return(0);
2134 }
2135
2136 /* DIVWU - Divide Word Unsigned */
DECLARE_INSN(DIVWU)2137 DECLARE_INSN(DIVWU)
2138 {
2139 int rd = bits(insn,21,25);
2140 int ra = bits(insn,16,20);
2141 int rb = bits(insn,11,15);
2142 int hreg_rb;
2143 jit_op_t *iop;
2144
2145 ppc32_jit_start_hreg_seq(cpu,"divwu");
2146 ppc32_jit_alloc_hreg_forced(cpu,X86_EAX);
2147 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
2148 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2149
2150 /* $rd = $ra / $rb */
2151 ppc32_op_emit_load_gpr(cpu,X86_EAX,ra);
2152 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2153
2154 iop = ppc32_op_emit_insn_output(cpu,2,"divwu");
2155 ppc32_load_imm(&iop->ob_ptr,X86_EDX,0);
2156
2157 x86_div_reg(iop->ob_ptr,hreg_rb,0);
2158
2159 if (insn & 1)
2160 x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX);
2161
2162 ppc32_op_emit_store_gpr(cpu,rd,X86_EAX);
2163
2164 if (insn & 1)
2165 ppc32_op_emit_update_flags(cpu,0,TRUE);
2166
2167 /* edx:eax are directly modified: throw them */
2168 ppc32_op_emit_alter_host_reg(cpu,X86_EAX);
2169 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
2170
2171 ppc32_jit_close_hreg_seq(cpu);
2172 return(0);
2173 }
2174
2175 /* EQV */
DECLARE_INSN(EQV)2176 DECLARE_INSN(EQV)
2177 {
2178 int rs = bits(insn,21,25);
2179 int ra = bits(insn,16,20);
2180 int rb = bits(insn,11,15);
2181 int hreg_rs,hreg_ra,hreg_rb;
2182 jit_op_t *iop;
2183
2184 /* $ra = ~($rs ^ $rb) */
2185 ppc32_jit_start_hreg_seq(cpu,"eqv");
2186 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2187 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2188 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2189
2190 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2191 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2192
2193 iop = ppc32_op_emit_insn_output(cpu,1,"eqv");
2194
2195 if (ra == rs)
2196 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb);
2197 else if (ra == rb)
2198 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rs);
2199 else {
2200 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
2201 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb);
2202 }
2203
2204 x86_not_reg(iop->ob_ptr,hreg_ra);
2205
2206 if (insn & 1)
2207 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
2208
2209 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2210
2211 if (insn & 1)
2212 ppc32_op_emit_update_flags(cpu,0,TRUE);
2213
2214 ppc32_jit_close_hreg_seq(cpu);
2215 return(0);
2216 }
2217
2218 /* EXTSB - Extend Sign Byte */
DECLARE_INSN(EXTSB)2219 DECLARE_INSN(EXTSB)
2220 {
2221 int rs = bits(insn,21,25);
2222 int ra = bits(insn,16,20);
2223 int hreg_rs,hreg_ra;
2224 jit_op_t *iop;
2225
2226 /* $ra = extsb($rs) */
2227 ppc32_jit_start_hreg_seq(cpu,"extsb");
2228 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2229 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2230
2231 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2232
2233 iop = ppc32_op_emit_insn_output(cpu,2,"extsb");
2234
2235 if (rs != ra)
2236 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
2237
2238 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_ra,24);
2239 x86_shift_reg_imm(iop->ob_ptr,X86_SAR,hreg_ra,24);
2240
2241 if (insn & 1)
2242 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
2243
2244 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2245
2246 if (insn & 1)
2247 ppc32_op_emit_update_flags(cpu,0,TRUE);
2248
2249 ppc32_jit_close_hreg_seq(cpu);
2250 return(0);
2251 }
2252
2253 /* EXTSH - Extend Sign Word */
DECLARE_INSN(EXTSH)2254 DECLARE_INSN(EXTSH)
2255 {
2256 int rs = bits(insn,21,25);
2257 int ra = bits(insn,16,20);
2258 int hreg_rs,hreg_ra;
2259 jit_op_t *iop;
2260
2261 /* $ra = extsh($rs) */
2262 ppc32_jit_start_hreg_seq(cpu,"extsh");
2263 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2264 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2265
2266 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2267
2268 iop = ppc32_op_emit_insn_output(cpu,2,"extsh");
2269
2270 if (rs != ra)
2271 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
2272
2273 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_ra,16);
2274 x86_shift_reg_imm(iop->ob_ptr,X86_SAR,hreg_ra,16);
2275
2276 if (insn & 1)
2277 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
2278
2279 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2280
2281 if (insn & 1)
2282 ppc32_op_emit_update_flags(cpu,0,TRUE);
2283
2284 ppc32_jit_close_hreg_seq(cpu);
2285 return(0);
2286 }
2287
2288 /* LBZ - Load Byte and Zero */
DECLARE_INSN(LBZ)2289 DECLARE_INSN(LBZ)
2290 {
2291 int rs = bits(insn,21,25);
2292 int ra = bits(insn,16,20);
2293 m_uint16_t offset = bits(insn,0,15);
2294
2295 //ppc32_emit_memop(cpu,b,PPC_MEMOP_LBZ,ra,offset,rs,0);
2296 ppc32_emit_memop_fast(cpu,b,0,PPC_MEMOP_LBZ,ra,offset,rs,
2297 ppc32_memop_fast_lbz);
2298 return(0);
2299 }
2300
2301 /* LBZU - Load Byte and Zero with Update */
DECLARE_INSN(LBZU)2302 DECLARE_INSN(LBZU)
2303 {
2304 int rs = bits(insn,21,25);
2305 int ra = bits(insn,16,20);
2306 m_uint16_t offset = bits(insn,0,15);
2307
2308 ppc32_emit_memop(cpu,b,PPC_MEMOP_LBZ,ra,offset,rs,1);
2309 return(0);
2310 }
2311
2312 /* LBZUX - Load Byte and Zero with Update Indexed */
DECLARE_INSN(LBZUX)2313 DECLARE_INSN(LBZUX)
2314 {
2315 int rs = bits(insn,21,25);
2316 int ra = bits(insn,16,20);
2317 int rb = bits(insn,11,15);
2318
2319 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LBZ,ra,rb,rs,1);
2320 return(0);
2321 }
2322
2323 /* LBZX - Load Byte and Zero Indexed */
DECLARE_INSN(LBZX)2324 DECLARE_INSN(LBZX)
2325 {
2326 int rs = bits(insn,21,25);
2327 int ra = bits(insn,16,20);
2328 int rb = bits(insn,11,15);
2329
2330 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LBZ,ra,rb,rs,0);
2331 return(0);
2332 }
2333
2334 /* LHA - Load Half-Word Algebraic */
DECLARE_INSN(LHA)2335 DECLARE_INSN(LHA)
2336 {
2337 int rs = bits(insn,21,25);
2338 int ra = bits(insn,16,20);
2339 m_uint16_t offset = bits(insn,0,15);
2340
2341 ppc32_emit_memop(cpu,b,PPC_MEMOP_LHA,ra,offset,rs,0);
2342 return(0);
2343 }
2344
2345 /* LHAU - Load Half-Word Algebraic with Update */
DECLARE_INSN(LHAU)2346 DECLARE_INSN(LHAU)
2347 {
2348 int rs = bits(insn,21,25);
2349 int ra = bits(insn,16,20);
2350 m_uint16_t offset = bits(insn,0,15);
2351
2352 ppc32_emit_memop(cpu,b,PPC_MEMOP_LHA,ra,offset,rs,1);
2353 return(0);
2354 }
2355
2356 /* LHAUX - Load Half-Word Algebraic with Update Indexed */
DECLARE_INSN(LHAUX)2357 DECLARE_INSN(LHAUX)
2358 {
2359 int rs = bits(insn,21,25);
2360 int ra = bits(insn,16,20);
2361 int rb = bits(insn,11,15);
2362
2363 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LHA,ra,rb,rs,1);
2364 return(0);
2365 }
2366
2367 /* LHAX - Load Half-Word Algebraic Indexed */
DECLARE_INSN(LHAX)2368 DECLARE_INSN(LHAX)
2369 {
2370 int rs = bits(insn,21,25);
2371 int ra = bits(insn,16,20);
2372 int rb = bits(insn,11,15);
2373
2374 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LHA,ra,rb,rs,0);
2375 return(0);
2376 }
2377
2378 /* LHZ - Load Half-Word and Zero */
DECLARE_INSN(LHZ)2379 DECLARE_INSN(LHZ)
2380 {
2381 int rs = bits(insn,21,25);
2382 int ra = bits(insn,16,20);
2383 m_uint16_t offset = bits(insn,0,15);
2384
2385 ppc32_emit_memop(cpu,b,PPC_MEMOP_LHZ,ra,offset,rs,0);
2386 return(0);
2387 }
2388
2389 /* LHZU - Load Half-Word and Zero with Update */
DECLARE_INSN(LHZU)2390 DECLARE_INSN(LHZU)
2391 {
2392 int rs = bits(insn,21,25);
2393 int ra = bits(insn,16,20);
2394 m_uint16_t offset = bits(insn,0,15);
2395
2396 ppc32_emit_memop(cpu,b,PPC_MEMOP_LHZ,ra,offset,rs,1);
2397 return(0);
2398 }
2399
2400 /* LHZUX - Load Half-Word and Zero with Update Indexed */
DECLARE_INSN(LHZUX)2401 DECLARE_INSN(LHZUX)
2402 {
2403 int rs = bits(insn,21,25);
2404 int ra = bits(insn,16,20);
2405 int rb = bits(insn,11,15);
2406
2407 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LHZ,ra,rb,rs,1);
2408 return(0);
2409 }
2410
2411 /* LHZX - Load Half-Word and Zero Indexed */
DECLARE_INSN(LHZX)2412 DECLARE_INSN(LHZX)
2413 {
2414 int rs = bits(insn,21,25);
2415 int ra = bits(insn,16,20);
2416 int rb = bits(insn,11,15);
2417
2418 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LHZ,ra,rb,rs,0);
2419 return(0);
2420 }
2421
2422 /* LWZ - Load Word and Zero */
DECLARE_INSN(LWZ)2423 DECLARE_INSN(LWZ)
2424 {
2425 int rs = bits(insn,21,25);
2426 int ra = bits(insn,16,20);
2427 m_uint16_t offset = bits(insn,0,15);
2428
2429 //ppc32_emit_memop(b,PPC_MEMOP_LWZ,ra,offset,rs,0);
2430 ppc32_emit_memop_fast(cpu,b,0,PPC_MEMOP_LWZ,ra,offset,rs,
2431 ppc32_memop_fast_lwz);
2432 return(0);
2433 }
2434
2435 /* LWZU - Load Word and Zero with Update */
DECLARE_INSN(LWZU)2436 DECLARE_INSN(LWZU)
2437 {
2438 int rs = bits(insn,21,25);
2439 int ra = bits(insn,16,20);
2440 m_uint16_t offset = bits(insn,0,15);
2441
2442 ppc32_emit_memop(cpu,b,PPC_MEMOP_LWZ,ra,offset,rs,1);
2443 return(0);
2444 }
2445
2446 /* LWZUX - Load Word and Zero with Update Indexed */
DECLARE_INSN(LWZUX)2447 DECLARE_INSN(LWZUX)
2448 {
2449 int rs = bits(insn,21,25);
2450 int ra = bits(insn,16,20);
2451 int rb = bits(insn,11,15);
2452
2453 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LWZ,ra,rb,rs,1);
2454 return(0);
2455 }
2456
2457 /* LWZX - Load Word and Zero Indexed */
DECLARE_INSN(LWZX)2458 DECLARE_INSN(LWZX)
2459 {
2460 int rs = bits(insn,21,25);
2461 int ra = bits(insn,16,20);
2462 int rb = bits(insn,11,15);
2463
2464 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LWZ,ra,rb,rs,0);
2465 return(0);
2466 }
2467
2468 /* MCRF - Move Condition Register Field */
DECLARE_INSN(MCRF)2469 DECLARE_INSN(MCRF)
2470 {
2471 int rd = bits(insn,23,25);
2472 int rs = bits(insn,18,20);
2473 int hreg_t0;
2474 jit_op_t *iop;
2475
2476 ppc32_jit_start_hreg_seq(cpu,"mcrf");
2477 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
2478 ppc32_op_emit_require_flags(cpu,rs);
2479
2480 iop = ppc32_op_emit_insn_output(cpu,1,"mcrf");
2481
2482 /* Load "rs" field in %edx */
2483 x86_mov_reg_membase(iop->ob_ptr,hreg_t0,
2484 X86_EDI,PPC32_CR_FIELD_OFFSET(rs),4);
2485
2486 /* Store it in "rd" field */
2487 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,PPC32_CR_FIELD_OFFSET(rd),
2488 hreg_t0,4);
2489
2490 ppc32_jit_close_hreg_seq(cpu);
2491 return(0);
2492 }
2493
2494 /* MFCR - Move from Condition Register */
DECLARE_INSN(MFCR)2495 DECLARE_INSN(MFCR)
2496 {
2497 int rd = bits(insn,21,25);
2498 int hreg_rd,hreg_t0;
2499 jit_op_t *iop;
2500 int i;
2501
2502 ppc32_jit_start_hreg_seq(cpu,"mfcr");
2503 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
2504 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
2505 ppc32_op_emit_require_flags(cpu,JIT_OP_PPC_ALL_FLAGS);
2506
2507 iop = ppc32_op_emit_insn_output(cpu,3,"mfcr");
2508
2509 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_rd,hreg_rd);
2510
2511 for(i=0;i<8;i++) {
2512 /* load field in %edx */
2513 x86_mov_reg_membase(iop->ob_ptr,hreg_t0,
2514 X86_EDI,PPC32_CR_FIELD_OFFSET(i),4);
2515 x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_rd,4);
2516 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_rd,hreg_t0);
2517 }
2518
2519 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
2520
2521 ppc32_jit_close_hreg_seq(cpu);
2522 return(0);
2523 }
2524
2525 /* MFMSR - Move from Machine State Register */
DECLARE_INSN(MFMSR)2526 DECLARE_INSN(MFMSR)
2527 {
2528 int rd = bits(insn,21,25);
2529 int hreg_rd;
2530 jit_op_t *iop;
2531
2532 ppc32_jit_start_hreg_seq(cpu,"mfmsr");
2533 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
2534
2535 iop = ppc32_op_emit_insn_output(cpu,1,"mfmsr");
2536 x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,msr),4);
2537 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
2538
2539 ppc32_jit_close_hreg_seq(cpu);
2540 return(0);
2541 }
2542
2543 /* MFSR - Move From Segment Register */
DECLARE_INSN(MFSR)2544 DECLARE_INSN(MFSR)
2545 {
2546 int rd = bits(insn,21,25);
2547 int sr = bits(insn,16,19);
2548 int hreg_rd;
2549 jit_op_t *iop;
2550
2551 ppc32_jit_start_hreg_seq(cpu,"mfsr");
2552 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
2553
2554 iop = ppc32_op_emit_insn_output(cpu,1,"mfsr");
2555
2556 x86_mov_reg_membase(iop->ob_ptr,hreg_rd,
2557 X86_EDI,(OFFSET(cpu_ppc_t,sr) + (sr << 2)),4);
2558 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
2559
2560 ppc32_jit_close_hreg_seq(cpu);
2561 return(0);
2562 }
2563
2564 /* MTCRF - Move to Condition Register Fields */
DECLARE_INSN(MTCRF)2565 DECLARE_INSN(MTCRF)
2566 {
2567 int rs = bits(insn,21,25);
2568 int crm = bits(insn,12,19);
2569 int hreg_rs,hreg_t0;
2570 jit_op_t *iop;
2571 int i;
2572
2573 ppc32_jit_start_hreg_seq(cpu,"mtcrf");
2574 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2575 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
2576
2577 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2578
2579 iop = ppc32_op_emit_insn_output(cpu,3,"mtcrf");
2580
2581 for(i=0;i<8;i++)
2582 if (crm & (1 << (7 - i))) {
2583 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4);
2584
2585 if (i != 7)
2586 x86_shift_reg_imm(iop->ob_ptr,X86_SHR,hreg_t0,28 - (i << 2));
2587
2588 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x0F);
2589 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,PPC32_CR_FIELD_OFFSET(i),
2590 hreg_t0,4);
2591 }
2592
2593 ppc32_op_emit_basic_opcode(cpu,JIT_OP_TRASH_FLAGS);
2594
2595 ppc32_jit_close_hreg_seq(cpu);
2596 return(0);
2597 }
2598
2599 /* MULHW - Multiply High Word */
DECLARE_INSN(MULHW)2600 DECLARE_INSN(MULHW)
2601 {
2602 int rd = bits(insn,21,25);
2603 int ra = bits(insn,16,20);
2604 int rb = bits(insn,11,15);
2605 int hreg_rb;
2606 jit_op_t *iop;
2607
2608 ppc32_jit_start_hreg_seq(cpu,"mulhw");
2609 ppc32_jit_alloc_hreg_forced(cpu,X86_EAX);
2610 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
2611 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2612
2613 ppc32_op_emit_load_gpr(cpu,X86_EAX,ra);
2614 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2615
2616 /* rd = hi(ra * rb) */
2617 iop = ppc32_op_emit_insn_output(cpu,2,"mulhw");
2618 x86_mul_reg(iop->ob_ptr,hreg_rb,1);
2619
2620 if (insn & 1)
2621 x86_test_reg_reg(iop->ob_ptr,X86_EDX,X86_EDX);
2622
2623 ppc32_op_emit_store_gpr(cpu,rd,X86_EDX);
2624
2625 if (insn & 1)
2626 ppc32_op_emit_update_flags(cpu,0,TRUE);
2627
2628 /* edx:eax are directly modified: throw them */
2629 ppc32_op_emit_alter_host_reg(cpu,X86_EAX);
2630 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
2631
2632 ppc32_jit_close_hreg_seq(cpu);
2633 return(0);
2634 }
2635
2636 /* MULHWU - Multiply High Word Unsigned */
DECLARE_INSN(MULHWU)2637 DECLARE_INSN(MULHWU)
2638 {
2639 int rd = bits(insn,21,25);
2640 int ra = bits(insn,16,20);
2641 int rb = bits(insn,11,15);
2642 int hreg_rb;
2643 jit_op_t *iop;
2644
2645 ppc32_jit_start_hreg_seq(cpu,"mulhwu");
2646 ppc32_jit_alloc_hreg_forced(cpu,X86_EAX);
2647 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
2648 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2649
2650 ppc32_op_emit_load_gpr(cpu,X86_EAX,ra);
2651 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2652
2653 /* rd = hi(ra * rb) */
2654 iop = ppc32_op_emit_insn_output(cpu,2,"mulhwu");
2655 x86_mul_reg(iop->ob_ptr,hreg_rb,0);
2656
2657 if (insn & 1)
2658 x86_test_reg_reg(iop->ob_ptr,X86_EDX,X86_EDX);
2659
2660 ppc32_op_emit_store_gpr(cpu,rd,X86_EDX);
2661
2662 if (insn & 1)
2663 ppc32_op_emit_update_flags(cpu,0,TRUE);
2664
2665 /* edx:eax are directly modified: throw them */
2666 ppc32_op_emit_alter_host_reg(cpu,X86_EAX);
2667 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
2668
2669 ppc32_jit_close_hreg_seq(cpu);
2670 return(0);
2671 }
2672
2673 /* MULLI - Multiply Low Immediate */
DECLARE_INSN(MULLI)2674 DECLARE_INSN(MULLI)
2675 {
2676 int rd = bits(insn,21,25);
2677 int ra = bits(insn,16,20);
2678 m_uint32_t imm = bits(insn,0,15);
2679 int hreg_t0;
2680 jit_op_t *iop;
2681
2682 ppc32_jit_start_hreg_seq(cpu,"mulli");
2683 ppc32_jit_alloc_hreg_forced(cpu,X86_EAX);
2684 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
2685 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
2686
2687 ppc32_op_emit_load_gpr(cpu,X86_EAX,ra);
2688
2689 /* rd = lo(ra * imm) */
2690 iop = ppc32_op_emit_insn_output(cpu,2,"mulli");
2691
2692 ppc32_load_imm(&iop->ob_ptr,hreg_t0,sign_extend_32(imm,16));
2693 x86_mul_reg(iop->ob_ptr,hreg_t0,1);
2694 ppc32_op_emit_store_gpr(cpu,rd,X86_EAX);
2695
2696 /* edx:eax are directly modified: throw them */
2697 ppc32_op_emit_alter_host_reg(cpu,X86_EAX);
2698 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
2699
2700 ppc32_jit_close_hreg_seq(cpu);
2701 return(0);
2702 }
2703
2704 /* MULLW - Multiply Low Word */
DECLARE_INSN(MULLW)2705 DECLARE_INSN(MULLW)
2706 {
2707 int rd = bits(insn,21,25);
2708 int ra = bits(insn,16,20);
2709 int rb = bits(insn,11,15);
2710 int hreg_rb;
2711 jit_op_t *iop;
2712
2713 ppc32_jit_start_hreg_seq(cpu,"mullw");
2714 ppc32_jit_alloc_hreg_forced(cpu,X86_EAX);
2715 ppc32_jit_alloc_hreg_forced(cpu,X86_EDX);
2716 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2717
2718 ppc32_op_emit_load_gpr(cpu,X86_EAX,ra);
2719 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2720
2721 /* rd = lo(ra * rb) */
2722 iop = ppc32_op_emit_insn_output(cpu,2,"mullw");
2723 x86_mul_reg(iop->ob_ptr,hreg_rb,1);
2724
2725 if (insn & 1)
2726 x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX);
2727
2728 ppc32_op_emit_store_gpr(cpu,rd,X86_EAX);
2729
2730 if (insn & 1)
2731 ppc32_op_emit_update_flags(cpu,0,TRUE);
2732
2733 /* edx:eax are directly modified: throw them */
2734 ppc32_op_emit_alter_host_reg(cpu,X86_EAX);
2735 ppc32_op_emit_alter_host_reg(cpu,X86_EDX);
2736
2737 ppc32_jit_close_hreg_seq(cpu);
2738 return(0);
2739 }
2740
2741 /* NAND */
DECLARE_INSN(NAND)2742 DECLARE_INSN(NAND)
2743 {
2744 int rs = bits(insn,21,25);
2745 int ra = bits(insn,16,20);
2746 int rb = bits(insn,11,15);
2747 int hreg_rs,hreg_ra,hreg_rb;
2748 jit_op_t *iop;
2749
2750 /* $ra = ~($rs & $rb) */
2751 ppc32_jit_start_hreg_seq(cpu,"nand");
2752 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2753 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2754 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2755
2756 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2757 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2758
2759 iop = ppc32_op_emit_insn_output(cpu,2,"nand");
2760
2761 if (ra == rs)
2762 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb);
2763 else if (ra == rb)
2764 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rs);
2765 else {
2766 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
2767 x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb);
2768 }
2769
2770 x86_not_reg(iop->ob_ptr,hreg_ra);
2771
2772 if (insn & 1)
2773 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
2774
2775 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2776
2777 if (insn & 1)
2778 ppc32_op_emit_update_flags(cpu,0,TRUE);
2779
2780 ppc32_jit_close_hreg_seq(cpu);
2781 return(0);
2782 }
2783
2784 /* NEG */
DECLARE_INSN(NEG)2785 DECLARE_INSN(NEG)
2786 {
2787 int rd = bits(insn,21,25);
2788 int ra = bits(insn,16,20);
2789 int hreg_rd,hreg_ra;
2790 jit_op_t *iop;
2791
2792 /* $rd = neg($ra) */
2793 ppc32_jit_start_hreg_seq(cpu,"neg");
2794 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2795 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
2796
2797 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
2798
2799 iop = ppc32_op_emit_insn_output(cpu,1,"neg");
2800
2801 if (rd != ra)
2802 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4);
2803
2804 x86_neg_reg(iop->ob_ptr,hreg_rd);
2805
2806 if (insn & 1)
2807 x86_test_reg_reg(iop->ob_ptr,hreg_rd,hreg_rd);
2808
2809 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
2810
2811 if (insn & 1)
2812 ppc32_op_emit_update_flags(cpu,0,TRUE);
2813
2814 ppc32_jit_close_hreg_seq(cpu);
2815 return(0);
2816 }
2817
2818 /* NOR */
DECLARE_INSN(NOR)2819 DECLARE_INSN(NOR)
2820 {
2821 int rs = bits(insn,21,25);
2822 int ra = bits(insn,16,20);
2823 int rb = bits(insn,11,15);
2824 int hreg_rs,hreg_ra,hreg_rb;
2825 jit_op_t *iop;
2826
2827 /* $ra = ~($rs | $rb) */
2828 ppc32_jit_start_hreg_seq(cpu,"nor");
2829 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2830 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2831 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2832
2833 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2834 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2835
2836 iop = ppc32_op_emit_insn_output(cpu,2,"nor");
2837
2838 if (ra == rs)
2839 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb);
2840 else if (ra == rb)
2841 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rs);
2842 else {
2843 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
2844 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb);
2845 }
2846
2847 x86_not_reg(iop->ob_ptr,hreg_ra);
2848
2849 if (insn & 1)
2850 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
2851
2852 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2853
2854 if (insn & 1)
2855 ppc32_op_emit_update_flags(cpu,0,TRUE);
2856
2857 ppc32_jit_close_hreg_seq(cpu);
2858 return(0);
2859 }
2860
2861 /* OR */
DECLARE_INSN(OR)2862 DECLARE_INSN(OR)
2863 {
2864 int rs = bits(insn,21,25);
2865 int ra = bits(insn,16,20);
2866 int rb = bits(insn,11,15);
2867 int hreg_rs,hreg_ra,hreg_rb;
2868 jit_op_t *iop;
2869
2870 /* $ra = $rs | $rb */
2871 ppc32_jit_start_hreg_seq(cpu,"or");
2872 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2873 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2874 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2875
2876 /* special optimization for move/nop operation */
2877 if (rs == rb) {
2878 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2879 iop = ppc32_op_emit_insn_output(cpu,2,"or");
2880
2881 if (ra != rs)
2882 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
2883
2884 if (insn & 1)
2885 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
2886
2887 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2888
2889 if (insn & 1)
2890 ppc32_op_emit_update_flags(cpu,0,TRUE);
2891
2892 ppc32_jit_close_hreg_seq(cpu);
2893 return(0);
2894 }
2895
2896 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2897 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2898
2899 iop = ppc32_op_emit_insn_output(cpu,2,"or");
2900
2901 if (ra == rs) {
2902 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb);
2903 } else if (ra == rb)
2904 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rs);
2905 else {
2906 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
2907 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb);
2908 }
2909
2910 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2911
2912 if (insn & 1)
2913 ppc32_op_emit_update_flags(cpu,0,TRUE);
2914
2915 ppc32_jit_close_hreg_seq(cpu);
2916 return(0);
2917 }
2918
2919 /* OR with Complement */
DECLARE_INSN(ORC)2920 DECLARE_INSN(ORC)
2921 {
2922 int rs = bits(insn,21,25);
2923 int ra = bits(insn,16,20);
2924 int rb = bits(insn,11,15);
2925 int hreg_rs,hreg_ra,hreg_rb,hreg_t0;
2926 jit_op_t *iop;
2927
2928 /* $ra = $rs & ~$rb */
2929 ppc32_jit_start_hreg_seq(cpu,"orc");
2930 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2931 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2932 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
2933
2934 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2935 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
2936
2937 iop = ppc32_op_emit_insn_output(cpu,1,"orc");
2938
2939 /* $t0 = ~$rb */
2940 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
2941 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4);
2942 x86_not_reg(iop->ob_ptr,hreg_t0);
2943
2944 /* $ra = $rs | $t0 */
2945 if (ra == rs)
2946 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_t0);
2947 else {
2948 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,hreg_rs);
2949 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4);
2950 }
2951
2952 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2953
2954 if (insn & 1)
2955 ppc32_op_emit_update_flags(cpu,0,TRUE);
2956
2957 ppc32_jit_close_hreg_seq(cpu);
2958 return(0);
2959 }
2960
2961 /* OR Immediate */
DECLARE_INSN(ORI)2962 DECLARE_INSN(ORI)
2963 {
2964 int rs = bits(insn,21,25);
2965 int ra = bits(insn,16,20);
2966 m_uint16_t imm = bits(insn,0,15);
2967 m_uint32_t tmp = imm;
2968 int hreg_rs,hreg_ra;
2969 jit_op_t *iop;
2970
2971 /* $ra = $rs | imm */
2972 ppc32_jit_start_hreg_seq(cpu,"ori");
2973 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
2974 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
2975
2976 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
2977
2978 iop = ppc32_op_emit_insn_output(cpu,1,"ori");
2979
2980 if (ra != rs)
2981 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
2982
2983 x86_alu_reg_imm(iop->ob_ptr,X86_OR,hreg_ra,tmp);
2984 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
2985
2986 ppc32_jit_close_hreg_seq(cpu);
2987 return(0);
2988 }
2989
2990 /* OR Immediate Shifted */
DECLARE_INSN(ORIS)2991 DECLARE_INSN(ORIS)
2992 {
2993 int rs = bits(insn,21,25);
2994 int ra = bits(insn,16,20);
2995 m_uint16_t imm = bits(insn,0,15);
2996 m_uint32_t tmp = imm << 16;
2997 int hreg_rs,hreg_ra;
2998 jit_op_t *iop;
2999
3000 /* $ra = $rs | imm */
3001 ppc32_jit_start_hreg_seq(cpu,"oris");
3002 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3003 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3004
3005 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3006
3007 iop = ppc32_op_emit_insn_output(cpu,1,"oris");
3008
3009 if (ra != rs)
3010 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
3011
3012 x86_alu_reg_imm(iop->ob_ptr,X86_OR,hreg_ra,tmp);
3013 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3014
3015 ppc32_jit_close_hreg_seq(cpu);
3016 return(0);
3017 }
3018
3019 /* RLWIMI - Rotate Left Word Immediate then Mask Insert */
DECLARE_INSN(RLWIMI)3020 DECLARE_INSN(RLWIMI)
3021 {
3022 int rs = bits(insn,21,25);
3023 int ra = bits(insn,16,20);
3024 int sh = bits(insn,11,15);
3025 int mb = bits(insn,6,10);
3026 int me = bits(insn,1,5);
3027 register m_uint32_t mask;
3028 int hreg_rs,hreg_ra,hreg_t0;
3029 jit_op_t *iop;
3030
3031 ppc32_jit_start_hreg_seq(cpu,"rlwimi");
3032 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
3033 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3034 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3035
3036 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3037 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
3038
3039 mask = ppc32_rotate_mask(mb,me);
3040
3041 iop = ppc32_op_emit_insn_output(cpu,2,"rlwimi");
3042
3043 /* Apply inverse mask to $ra */
3044 if (mask != 0)
3045 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,~mask);
3046
3047 /* Rotate $rs of "sh" bits and apply the mask */
3048 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4);
3049
3050 if (sh != 0)
3051 x86_shift_reg_imm(iop->ob_ptr,X86_ROL,hreg_t0,sh);
3052
3053 if (mask != 0xFFFFFFFF)
3054 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask);
3055
3056 /* Store the result */
3057 x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_t0);
3058 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3059
3060 if (insn & 1)
3061 ppc32_op_emit_update_flags(cpu,0,TRUE);
3062
3063 ppc32_jit_close_hreg_seq(cpu);
3064 return(0);
3065 }
3066
3067 /* RLWINM - Rotate Left Word Immediate AND with Mask */
DECLARE_INSN(RLWINM)3068 DECLARE_INSN(RLWINM)
3069 {
3070 int rs = bits(insn,21,25);
3071 int ra = bits(insn,16,20);
3072 int sh = bits(insn,11,15);
3073 int mb = bits(insn,6,10);
3074 int me = bits(insn,1,5);
3075 register m_uint32_t mask;
3076 int hreg_rs,hreg_ra;
3077 jit_op_t *iop;
3078
3079 ppc32_jit_start_hreg_seq(cpu,"rlwinm");
3080 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3081 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3082
3083 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3084
3085 iop = ppc32_op_emit_insn_output(cpu,2,"rlwinm");
3086
3087 /* Rotate $rs of "sh" bits and apply the mask */
3088 mask = ppc32_rotate_mask(mb,me);
3089
3090 if (rs != ra)
3091 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
3092
3093 if (sh != 0)
3094 x86_shift_reg_imm(iop->ob_ptr,X86_ROL,hreg_ra,sh);
3095
3096 if (mask != 0xFFFFFFFF)
3097 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,mask);
3098
3099 if (insn & 1)
3100 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
3101
3102 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3103
3104 if (insn & 1)
3105 ppc32_op_emit_update_flags(cpu,0,TRUE);
3106
3107 ppc32_jit_close_hreg_seq(cpu);
3108 return(0);
3109 }
3110
3111 /* RLWNM - Rotate Left Word then Mask Insert */
DECLARE_INSN(RLWNM)3112 DECLARE_INSN(RLWNM)
3113 {
3114 int rs = bits(insn,21,25);
3115 int ra = bits(insn,16,20);
3116 int rb = bits(insn,11,15);
3117 int mb = bits(insn,6,10);
3118 int me = bits(insn,1,5);
3119 register m_uint32_t mask;
3120 int hreg_rs,hreg_ra,hreg_t0;
3121 jit_op_t *iop;
3122
3123 /* ecx is directly modified: throw it */
3124 ppc32_op_emit_alter_host_reg(cpu,X86_ECX);
3125
3126 ppc32_jit_start_hreg_seq(cpu,"rlwnm");
3127 ppc32_jit_alloc_hreg_forced(cpu,X86_ECX);
3128
3129 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
3130 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3131 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3132
3133 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
3134 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3135 ppc32_op_emit_load_gpr(cpu,X86_ECX,rb);
3136
3137 iop = ppc32_op_emit_insn_output(cpu,2,"rlwnm");
3138
3139 /* Load the shift register ("sh") */
3140 mask = ppc32_rotate_mask(mb,me);
3141
3142 /* Rotate $rs and apply the mask */
3143 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4);
3144
3145 x86_shift_reg(iop->ob_ptr,X86_ROL,hreg_t0);
3146
3147 if (mask != 0xFFFFFFFF)
3148 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask);
3149
3150 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4);
3151
3152 if (insn & 1)
3153 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
3154
3155 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3156
3157 if (insn & 1)
3158 ppc32_op_emit_update_flags(cpu,0,TRUE);
3159
3160 ppc32_jit_close_hreg_seq(cpu);
3161 return(0);
3162 }
3163
3164 /* Shift Left Word */
DECLARE_INSN(SLW)3165 DECLARE_INSN(SLW)
3166 {
3167 int rs = bits(insn,21,25);
3168 int ra = bits(insn,16,20);
3169 int rb = bits(insn,11,15);
3170 u_char *test1;
3171 int hreg_rs,hreg_ra,hreg_t0;
3172 jit_op_t *iop;
3173
3174 /* ecx is directly modified: throw it */
3175 ppc32_op_emit_alter_host_reg(cpu,X86_ECX);
3176
3177 ppc32_jit_start_hreg_seq(cpu,"slw");
3178 ppc32_jit_alloc_hreg_forced(cpu,X86_ECX);
3179 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
3180 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3181 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3182
3183 /* $ra = $rs << $rb. If count >= 32, then null result */
3184 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3185 ppc32_op_emit_load_gpr(cpu,X86_ECX,rb);
3186
3187 iop = ppc32_op_emit_insn_output(cpu,3,"slw");
3188
3189 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,hreg_t0);
3190 x86_test_reg_imm(iop->ob_ptr,X86_ECX,0x20);
3191 test1 = iop->ob_ptr;
3192 x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1);
3193
3194 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4);
3195 x86_shift_reg(iop->ob_ptr,X86_SHL,hreg_t0);
3196
3197 /* store the result */
3198 x86_patch(test1,iop->ob_ptr);
3199 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4);
3200
3201 if (insn & 1)
3202 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
3203
3204 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3205
3206 if (insn & 1)
3207 ppc32_op_emit_update_flags(cpu,0,TRUE);
3208
3209 ppc32_jit_close_hreg_seq(cpu);
3210 return(0);
3211 }
3212
3213 /* SRAWI - Shift Right Algebraic Word Immediate */
DECLARE_INSN(SRAWI)3214 DECLARE_INSN(SRAWI)
3215 {
3216 int rs = bits(insn,21,25);
3217 int ra = bits(insn,16,20);
3218 int sh = bits(insn,11,15);
3219 register m_uint32_t mask;
3220 int hreg_rs,hreg_ra,hreg_t0;
3221 jit_op_t *iop;
3222
3223 ppc32_jit_start_hreg_seq(cpu,"srawi");
3224 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
3225 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3226 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3227
3228 /* $ra = (int32)$rs >> sh */
3229 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3230
3231 iop = ppc32_op_emit_insn_output(cpu,3,"srawi");
3232 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4);
3233
3234 if (ra != rs)
3235 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
3236 x86_shift_reg_imm(iop->ob_ptr,X86_SAR,hreg_ra,sh);
3237
3238 /* set XER_CA depending on the result */
3239 mask = ~(0xFFFFFFFFU << sh) | 0x80000000;
3240
3241 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask);
3242 x86_alu_reg_imm(iop->ob_ptr,X86_CMP,hreg_t0,0x80000000);
3243 x86_set_reg(iop->ob_ptr,X86_CC_A,hreg_t0,FALSE);
3244 x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x1);
3245 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t0,4);
3246
3247 if (insn & 1)
3248 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
3249
3250 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3251
3252 if (insn & 1)
3253 ppc32_op_emit_update_flags(cpu,0,TRUE);
3254
3255 ppc32_jit_close_hreg_seq(cpu);
3256 return(0);
3257 }
3258
3259 /* Shift Right Word */
DECLARE_INSN(SRW)3260 DECLARE_INSN(SRW)
3261 {
3262 int rs = bits(insn,21,25);
3263 int ra = bits(insn,16,20);
3264 int rb = bits(insn,11,15);
3265 u_char *test1;
3266 int hreg_rs,hreg_ra,hreg_t0;
3267 jit_op_t *iop;
3268
3269 /* ecx is directly modified: throw it */
3270 ppc32_op_emit_alter_host_reg(cpu,X86_ECX);
3271
3272 ppc32_jit_start_hreg_seq(cpu,"srw");
3273 ppc32_jit_alloc_hreg_forced(cpu,X86_ECX);
3274 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
3275 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3276 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3277
3278 /* $ra = $rs >> $rb. If count >= 32, then null result */
3279 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3280 ppc32_op_emit_load_gpr(cpu,X86_ECX,rb);
3281
3282 iop = ppc32_op_emit_insn_output(cpu,3,"srw");
3283
3284 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,hreg_t0);
3285 x86_test_reg_imm(iop->ob_ptr,X86_ECX,0x20);
3286 test1 = iop->ob_ptr;
3287 x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1);
3288
3289 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4);
3290 x86_shift_reg(iop->ob_ptr,X86_SHR,hreg_t0);
3291
3292 /* store the result */
3293 x86_patch(test1,iop->ob_ptr);
3294 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4);
3295
3296 if (insn & 1)
3297 x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra);
3298
3299 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3300
3301 if (insn & 1)
3302 ppc32_op_emit_update_flags(cpu,0,TRUE);
3303
3304 ppc32_jit_close_hreg_seq(cpu);
3305 return(0);
3306 }
3307
3308 /* STB - Store Byte */
DECLARE_INSN(STB)3309 DECLARE_INSN(STB)
3310 {
3311 int rs = bits(insn,21,25);
3312 int ra = bits(insn,16,20);
3313 m_uint16_t offset = bits(insn,0,15);
3314
3315 //ppc32_emit_memop(b,PPC_MEMOP_STB,ra,offset,rs,0);
3316 ppc32_emit_memop_fast(cpu,b,1,PPC_MEMOP_STB,ra,offset,rs,
3317 ppc32_memop_fast_stb);
3318 return(0);
3319 }
3320
3321 /* STBU - Store Byte with Update */
DECLARE_INSN(STBU)3322 DECLARE_INSN(STBU)
3323 {
3324 int rs = bits(insn,21,25);
3325 int ra = bits(insn,16,20);
3326 m_uint16_t offset = bits(insn,0,15);
3327
3328 ppc32_emit_memop(cpu,b,PPC_MEMOP_STB,ra,offset,rs,1);
3329 return(0);
3330 }
3331
3332 /* STBUX - Store Byte with Update Indexed */
DECLARE_INSN(STBUX)3333 DECLARE_INSN(STBUX)
3334 {
3335 int rs = bits(insn,21,25);
3336 int ra = bits(insn,16,20);
3337 int rb = bits(insn,11,15);
3338
3339 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STB,ra,rb,rs,1);
3340 return(0);
3341 }
3342
3343 /* STBUX - Store Byte Indexed */
DECLARE_INSN(STBX)3344 DECLARE_INSN(STBX)
3345 {
3346 int rs = bits(insn,21,25);
3347 int ra = bits(insn,16,20);
3348 int rb = bits(insn,11,15);
3349
3350 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STB,ra,rb,rs,0);
3351 return(0);
3352 }
3353
3354 /* STH - Store Half-Word */
DECLARE_INSN(STH)3355 DECLARE_INSN(STH)
3356 {
3357 int rs = bits(insn,21,25);
3358 int ra = bits(insn,16,20);
3359 m_uint16_t offset = bits(insn,0,15);
3360
3361 ppc32_emit_memop(cpu,b,PPC_MEMOP_STH,ra,offset,rs,0);
3362 return(0);
3363 }
3364
3365 /* STHU - Store Half-Word with Update */
DECLARE_INSN(STHU)3366 DECLARE_INSN(STHU)
3367 {
3368 int rs = bits(insn,21,25);
3369 int ra = bits(insn,16,20);
3370 m_uint16_t offset = bits(insn,0,15);
3371
3372 ppc32_emit_memop(cpu,b,PPC_MEMOP_STH,ra,offset,rs,1);
3373 return(0);
3374 }
3375
3376 /* STHUX - Store Half-Word with Update Indexed */
DECLARE_INSN(STHUX)3377 DECLARE_INSN(STHUX)
3378 {
3379 int rs = bits(insn,21,25);
3380 int ra = bits(insn,16,20);
3381 int rb = bits(insn,11,15);
3382
3383 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STH,ra,rb,rs,1);
3384 return(0);
3385 }
3386
3387 /* STHUX - Store Half-Word Indexed */
DECLARE_INSN(STHX)3388 DECLARE_INSN(STHX)
3389 {
3390 int rs = bits(insn,21,25);
3391 int ra = bits(insn,16,20);
3392 int rb = bits(insn,11,15);
3393
3394 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STH,ra,rb,rs,0);
3395 return(0);
3396 }
3397
3398 /* STW - Store Word */
DECLARE_INSN(STW)3399 DECLARE_INSN(STW)
3400 {
3401 int rs = bits(insn,21,25);
3402 int ra = bits(insn,16,20);
3403 m_uint16_t offset = bits(insn,0,15);
3404
3405 //ppc32_emit_memop(b,PPC_MEMOP_STW,ra,offset,rs,0);
3406 ppc32_emit_memop_fast(cpu,b,1,PPC_MEMOP_STW,ra,offset,rs,
3407 ppc32_memop_fast_stw);
3408 return(0);
3409 }
3410
3411 /* STWU - Store Word with Update */
DECLARE_INSN(STWU)3412 DECLARE_INSN(STWU)
3413 {
3414 int rs = bits(insn,21,25);
3415 int ra = bits(insn,16,20);
3416 m_uint16_t offset = bits(insn,0,15);
3417
3418 ppc32_emit_memop(cpu,b,PPC_MEMOP_STW,ra,offset,rs,1);
3419 return(0);
3420 }
3421
3422 /* STWUX - Store Word with Update Indexed */
DECLARE_INSN(STWUX)3423 DECLARE_INSN(STWUX)
3424 {
3425 int rs = bits(insn,21,25);
3426 int ra = bits(insn,16,20);
3427 int rb = bits(insn,11,15);
3428
3429 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STW,ra,rb,rs,1);
3430 return(0);
3431 }
3432
3433 /* STWUX - Store Word Indexed */
DECLARE_INSN(STWX)3434 DECLARE_INSN(STWX)
3435 {
3436 int rs = bits(insn,21,25);
3437 int ra = bits(insn,16,20);
3438 int rb = bits(insn,11,15);
3439
3440 ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STW,ra,rb,rs,0);
3441 return(0);
3442 }
3443
3444 /* SUBF - Subtract From */
DECLARE_INSN(SUBF)3445 DECLARE_INSN(SUBF)
3446 {
3447 int rd = bits(insn,21,25);
3448 int ra = bits(insn,16,20);
3449 int rb = bits(insn,11,15);
3450 int hreg_rd,hreg_ra,hreg_rb,hreg_t0;
3451 jit_op_t *iop;
3452
3453 /* $rd = $rb - $ra */
3454 ppc32_jit_start_hreg_seq(cpu,"subf");
3455 hreg_t0 = ppc32_jit_get_tmp_hreg(cpu);
3456
3457 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
3458 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3459 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
3460
3461 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
3462 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
3463
3464 iop = ppc32_op_emit_insn_output(cpu,2,"subf");
3465
3466 if (rd == rb)
3467 x86_alu_reg_reg(iop->ob_ptr,X86_SUB,hreg_rd,hreg_ra);
3468 else if (rd == ra) {
3469 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4);
3470 x86_alu_reg_reg(iop->ob_ptr,X86_SUB,hreg_t0,hreg_ra);
3471 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4);
3472 } else {
3473 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_rb,4);
3474 x86_alu_reg_reg(iop->ob_ptr,X86_SUB,hreg_rd,hreg_ra);
3475 }
3476
3477 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
3478
3479 if (insn & 1)
3480 ppc32_op_emit_update_flags(cpu,0,TRUE);
3481
3482 ppc32_jit_close_hreg_seq(cpu);
3483 return(0);
3484 }
3485
3486 /* SUBFC - Subtract From Carrying */
DECLARE_INSN(SUBFC)3487 DECLARE_INSN(SUBFC)
3488 {
3489 int rd = bits(insn,21,25);
3490 int ra = bits(insn,16,20);
3491 int rb = bits(insn,11,15);
3492 int hreg_ra,hreg_rb,hreg_rd,hreg_t0,hreg_t1;
3493 jit_op_t *iop;
3494
3495 /* $rd = ~$ra + 1 + $rb */
3496 ppc32_jit_start_hreg_seq(cpu,"subfc");
3497 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3498 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
3499 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
3500
3501 hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1);
3502 hreg_t1 = ppc32_jit_get_tmp_hreg(cpu);
3503
3504 ppc32_op_emit_alter_host_reg(cpu,hreg_t0);
3505 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
3506 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
3507
3508 iop = ppc32_op_emit_insn_output(cpu,3,"subfc");
3509
3510 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1);
3511
3512 /* $t0 = ~$ra + 1 */
3513 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4);
3514 x86_not_reg(iop->ob_ptr,hreg_t0);
3515 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_t0,1);
3516 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE);
3517 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t1,4);
3518
3519 /* $t0 += $rb */
3520 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb);
3521 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE);
3522 x86_alu_membase_reg(iop->ob_ptr,X86_OR,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),
3523 hreg_t1);
3524
3525 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4);
3526
3527 if (insn & 1)
3528 x86_test_reg_reg(iop->ob_ptr,hreg_rd,hreg_rd);
3529
3530 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
3531
3532 /* update cr0 */
3533 if (insn & 1)
3534 ppc32_update_cr0(b);
3535
3536 ppc32_jit_close_hreg_seq(cpu);
3537 return(0);
3538 }
3539
3540 /* SUBFE - Subtract From Extended */
DECLARE_INSN(SUBFE)3541 DECLARE_INSN(SUBFE)
3542 {
3543 int rd = bits(insn,21,25);
3544 int ra = bits(insn,16,20);
3545 int rb = bits(insn,11,15);
3546 int hreg_ra,hreg_rb,hreg_rd,hreg_t0,hreg_t1;
3547 jit_op_t *iop;
3548
3549 /* $rd = ~$ra + $carry (xer_ca) + $rb */
3550 ppc32_jit_start_hreg_seq(cpu,"subfe");
3551 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3552 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
3553 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
3554
3555 hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1);
3556 hreg_t1 = ppc32_jit_get_tmp_hreg(cpu);
3557
3558 ppc32_op_emit_alter_host_reg(cpu,hreg_t0);
3559 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
3560 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
3561
3562 iop = ppc32_op_emit_insn_output(cpu,3,"subfe");
3563
3564 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1);
3565
3566 /* $t0 = ~$ra + $carry */
3567 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4);
3568 x86_not_reg(iop->ob_ptr,hreg_t0);
3569 x86_alu_reg_membase(iop->ob_ptr,X86_ADD,hreg_t0,
3570 X86_EDI,OFFSET(cpu_ppc_t,xer_ca));
3571
3572 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE);
3573 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t1,4);
3574
3575 /* $t0 += $rb */
3576 x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb);
3577 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE);
3578 x86_alu_membase_reg(iop->ob_ptr,X86_OR,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),
3579 hreg_t1);
3580
3581 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4);
3582
3583 if (insn & 1)
3584 x86_test_reg_reg(iop->ob_ptr,hreg_rd,hreg_rd);
3585
3586 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
3587
3588 /* update cr0 */
3589 if (insn & 1)
3590 ppc32_update_cr0(b);
3591
3592 ppc32_jit_close_hreg_seq(cpu);
3593 return(0);
3594 }
3595
3596 /* SUBFIC - Subtract From Immediate Carrying */
DECLARE_INSN(SUBFIC)3597 DECLARE_INSN(SUBFIC)
3598 {
3599 int rd = bits(insn,21,25);
3600 int ra = bits(insn,16,20);
3601 m_uint16_t imm = bits(insn,0,15);
3602 m_uint32_t tmp = sign_extend_32(imm,16);
3603 int hreg_ra,hreg_rd,hreg_t0,hreg_t1;
3604 jit_op_t *iop;
3605
3606 /* $rd = ~$ra + 1 + sign_extend(imm,16) */
3607 ppc32_jit_start_hreg_seq(cpu,"subfic");
3608 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3609 hreg_rd = ppc32_jit_alloc_hreg(cpu,rd);
3610
3611 hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1);
3612 hreg_t1 = ppc32_jit_get_tmp_hreg(cpu);
3613
3614 ppc32_op_emit_alter_host_reg(cpu,hreg_t0);
3615 ppc32_op_emit_load_gpr(cpu,hreg_ra,ra);
3616
3617 iop = ppc32_op_emit_insn_output(cpu,3,"subfic");
3618
3619 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1);
3620
3621 /* $t0 = ~$ra + 1 */
3622 x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4);
3623 x86_not_reg(iop->ob_ptr,hreg_t0);
3624 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_t0,1);
3625
3626 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE);
3627 x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t1,4);
3628
3629 /* $t0 += sign_extend(imm,16) */
3630 x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_t0,tmp);
3631 x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE);
3632 x86_alu_membase_reg(iop->ob_ptr,X86_OR,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),
3633 hreg_t1);
3634
3635 x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4);
3636 ppc32_op_emit_store_gpr(cpu,rd,hreg_rd);
3637
3638 ppc32_jit_close_hreg_seq(cpu);
3639 return(0);
3640 }
3641
3642 /* SYNC - Synchronize */
DECLARE_INSN(SYNC)3643 DECLARE_INSN(SYNC)
3644 {
3645 return(0);
3646 }
3647
3648 /* XOR */
DECLARE_INSN(XOR)3649 DECLARE_INSN(XOR)
3650 {
3651 int rs = bits(insn,21,25);
3652 int ra = bits(insn,16,20);
3653 int rb = bits(insn,11,15);
3654 int hreg_rs,hreg_ra,hreg_rb;
3655 jit_op_t *iop;
3656
3657 /* $ra = $rs ^ $rb */
3658 ppc32_jit_start_hreg_seq(cpu,"xor");
3659 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3660 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3661 hreg_rb = ppc32_jit_alloc_hreg(cpu,rb);
3662
3663 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3664 ppc32_op_emit_load_gpr(cpu,hreg_rb,rb);
3665
3666 iop = ppc32_op_emit_insn_output(cpu,1,"xor");
3667
3668 if (ra == rs)
3669 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb);
3670 else if (ra == rb)
3671 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rs);
3672 else {
3673 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
3674 x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb);
3675 }
3676
3677 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3678
3679 if (insn & 1)
3680 ppc32_op_emit_update_flags(cpu,0,TRUE);
3681
3682 ppc32_jit_close_hreg_seq(cpu);
3683 return(0);
3684 }
3685
3686 /* XORI - XOR Immediate */
DECLARE_INSN(XORI)3687 DECLARE_INSN(XORI)
3688 {
3689 int rs = bits(insn,21,25);
3690 int ra = bits(insn,16,20);
3691 m_uint32_t imm = bits(insn,0,15);
3692 int hreg_rs,hreg_ra;
3693 jit_op_t *iop;
3694
3695 /* $ra = $rs ^ imm */
3696 ppc32_jit_start_hreg_seq(cpu,"xori");
3697 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3698 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3699
3700 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3701
3702 iop = ppc32_op_emit_insn_output(cpu,1,"xori");
3703
3704 if (ra != rs)
3705 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
3706
3707 x86_alu_reg_imm(iop->ob_ptr,X86_XOR,hreg_ra,imm);
3708 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3709
3710 ppc32_jit_close_hreg_seq(cpu);
3711 return(0);
3712 }
3713
3714 /* XORIS - XOR Immediate Shifted */
DECLARE_INSN(XORIS)3715 DECLARE_INSN(XORIS)
3716 {
3717 int rs = bits(insn,21,25);
3718 int ra = bits(insn,16,20);
3719 m_uint16_t imm = bits(insn,0,15);
3720 m_uint32_t tmp = imm << 16;
3721 int hreg_rs,hreg_ra;
3722 jit_op_t *iop;
3723
3724 /* $ra = $rs ^ (imm << 16) */
3725 ppc32_jit_start_hreg_seq(cpu,"xoris");
3726 hreg_rs = ppc32_jit_alloc_hreg(cpu,rs);
3727 hreg_ra = ppc32_jit_alloc_hreg(cpu,ra);
3728
3729 ppc32_op_emit_load_gpr(cpu,hreg_rs,rs);
3730
3731 iop = ppc32_op_emit_insn_output(cpu,1,"xoris");
3732
3733 if (ra != rs)
3734 x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4);
3735
3736 x86_alu_reg_imm(iop->ob_ptr,X86_XOR,hreg_ra,tmp);
3737 ppc32_op_emit_store_gpr(cpu,ra,hreg_ra);
3738
3739 ppc32_jit_close_hreg_seq(cpu);
3740 return(0);
3741 }
3742
3743 /* PPC instruction array */
3744 struct ppc32_insn_tag ppc32_insn_tags[] = {
3745 { ppc32_emit_BLR , 0xfffffffe , 0x4e800020 },
3746 { ppc32_emit_BCTR , 0xfffffffe , 0x4e800420 },
3747 { ppc32_emit_MFLR , 0xfc1fffff , 0x7c0802a6 },
3748 { ppc32_emit_MTLR , 0xfc1fffff , 0x7c0803a6 },
3749 { ppc32_emit_MFCTR , 0xfc1fffff , 0x7c0902a6 },
3750 { ppc32_emit_MTCTR , 0xfc1fffff , 0x7c0903a6 },
3751 { ppc32_emit_MFTBL , 0xfc1ff7ff , 0x7c0c42e6 },
3752 { ppc32_emit_MFTBU , 0xfc1ff7ff , 0x7c0d42e6 },
3753 { ppc32_emit_ADD , 0xfc0007fe , 0x7c000214 },
3754 { ppc32_emit_ADDC , 0xfc0007fe , 0x7c000014 },
3755 { ppc32_emit_ADDE , 0xfc0007fe , 0x7c000114 },
3756 { ppc32_emit_ADDI , 0xfc000000 , 0x38000000 },
3757 { ppc32_emit_ADDIC , 0xfc000000 , 0x30000000 },
3758 { ppc32_emit_ADDIC_dot , 0xfc000000 , 0x34000000 },
3759 { ppc32_emit_ADDIS , 0xfc000000 , 0x3c000000 },
3760 { ppc32_emit_ADDZE , 0xfc00fffe , 0x7c000194 },
3761 { ppc32_emit_AND , 0xfc0007fe , 0x7c000038 },
3762 { ppc32_emit_ANDC , 0xfc0007fe , 0x7c000078 },
3763 { ppc32_emit_ANDI , 0xfc000000 , 0x70000000 },
3764 { ppc32_emit_ANDIS , 0xfc000000 , 0x74000000 },
3765 { ppc32_emit_B , 0xfc000003 , 0x48000000 },
3766 { ppc32_emit_BA , 0xfc000003 , 0x48000002 },
3767 { ppc32_emit_BL , 0xfc000003 , 0x48000001 },
3768 { ppc32_emit_BLA , 0xfc000003 , 0x48000003 },
3769 { ppc32_emit_BCC , 0xfe800000 , 0x40800000 },
3770 { ppc32_emit_BC , 0xfc000000 , 0x40000000 },
3771 { ppc32_emit_BCLR , 0xfc00fffe , 0x4c000020 },
3772 { ppc32_emit_CMP , 0xfc6007ff , 0x7c000000 },
3773 { ppc32_emit_CMPI , 0xfc600000 , 0x2c000000 },
3774 { ppc32_emit_CMPL , 0xfc6007ff , 0x7c000040 },
3775 { ppc32_emit_CMPLI , 0xfc600000 , 0x28000000 },
3776 { ppc32_emit_CRAND , 0xfc0007ff , 0x4c000202 },
3777 { ppc32_emit_CRANDC , 0xfc0007ff , 0x4c000102 },
3778 { ppc32_emit_CREQV , 0xfc0007ff , 0x4c000242 },
3779 { ppc32_emit_CRNAND , 0xfc0007ff , 0x4c0001c2 },
3780 { ppc32_emit_CRNOR , 0xfc0007ff , 0x4c000042 },
3781 { ppc32_emit_CROR , 0xfc0007ff , 0x4c000382 },
3782 { ppc32_emit_CRORC , 0xfc0007ff , 0x4c000342 },
3783 { ppc32_emit_CRXOR , 0xfc0007ff , 0x4c000182 },
3784 { ppc32_emit_DIVWU , 0xfc0007fe , 0x7c000396 },
3785 { ppc32_emit_EQV , 0xfc0007fe , 0x7c000238 },
3786 { ppc32_emit_EXTSB , 0xfc00fffe , 0x7c000774 },
3787 { ppc32_emit_EXTSH , 0xfc00fffe , 0x7c000734 },
3788 { ppc32_emit_LBZ , 0xfc000000 , 0x88000000 },
3789 { ppc32_emit_LBZU , 0xfc000000 , 0x8c000000 },
3790 { ppc32_emit_LBZUX , 0xfc0007ff , 0x7c0000ee },
3791 { ppc32_emit_LBZX , 0xfc0007ff , 0x7c0000ae },
3792 { ppc32_emit_LHA , 0xfc000000 , 0xa8000000 },
3793 { ppc32_emit_LHAU , 0xfc000000 , 0xac000000 },
3794 { ppc32_emit_LHAUX , 0xfc0007ff , 0x7c0002ee },
3795 { ppc32_emit_LHAX , 0xfc0007ff , 0x7c0002ae },
3796 { ppc32_emit_LHZ , 0xfc000000 , 0xa0000000 },
3797 { ppc32_emit_LHZU , 0xfc000000 , 0xa4000000 },
3798 { ppc32_emit_LHZUX , 0xfc0007ff , 0x7c00026e },
3799 { ppc32_emit_LHZX , 0xfc0007ff , 0x7c00022e },
3800 { ppc32_emit_LWZ , 0xfc000000 , 0x80000000 },
3801 { ppc32_emit_LWZU , 0xfc000000 , 0x84000000 },
3802 { ppc32_emit_LWZUX , 0xfc0007ff , 0x7c00006e },
3803 { ppc32_emit_LWZX , 0xfc0007ff , 0x7c00002e },
3804 { ppc32_emit_MCRF , 0xfc63ffff , 0x4c000000 },
3805 { ppc32_emit_MFCR , 0xfc1fffff , 0x7c000026 },
3806 { ppc32_emit_MFMSR , 0xfc1fffff , 0x7c0000a6 },
3807 { ppc32_emit_MFSR , 0xfc10ffff , 0x7c0004a6 },
3808 { ppc32_emit_MTCRF , 0xfc100fff , 0x7c000120 },
3809 { ppc32_emit_MULHW , 0xfc0007fe , 0x7c000096 },
3810 { ppc32_emit_MULHWU , 0xfc0007fe , 0x7c000016 },
3811 { ppc32_emit_MULLI , 0xfc000000 , 0x1c000000 },
3812 { ppc32_emit_MULLW , 0xfc0007fe , 0x7c0001d6 },
3813 { ppc32_emit_NAND , 0xfc0007fe , 0x7c0003b8 },
3814 { ppc32_emit_NEG , 0xfc00fffe , 0x7c0000d0 },
3815 { ppc32_emit_NOR , 0xfc0007fe , 0x7c0000f8 },
3816 { ppc32_emit_OR , 0xfc0007fe , 0x7c000378 },
3817 { ppc32_emit_ORC , 0xfc0007fe , 0x7c000338 },
3818 { ppc32_emit_ORI , 0xfc000000 , 0x60000000 },
3819 { ppc32_emit_ORIS , 0xfc000000 , 0x64000000 },
3820 { ppc32_emit_RLWIMI , 0xfc000000 , 0x50000000 },
3821 { ppc32_emit_RLWINM , 0xfc000000 , 0x54000000 },
3822 { ppc32_emit_RLWNM , 0xfc000000 , 0x5c000000 },
3823 { ppc32_emit_SLW , 0xfc0007fe , 0x7c000030 },
3824 { ppc32_emit_SRAWI , 0xfc0007fe , 0x7c000670 },
3825 { ppc32_emit_SRW , 0xfc0007fe , 0x7c000430 },
3826 { ppc32_emit_STB , 0xfc000000 , 0x98000000 },
3827 { ppc32_emit_STBU , 0xfc000000 , 0x9c000000 },
3828 { ppc32_emit_STBUX , 0xfc0007ff , 0x7c0001ee },
3829 { ppc32_emit_STBX , 0xfc0007ff , 0x7c0001ae },
3830 { ppc32_emit_STH , 0xfc000000 , 0xb0000000 },
3831 { ppc32_emit_STHU , 0xfc000000 , 0xb4000000 },
3832 { ppc32_emit_STHUX , 0xfc0007ff , 0x7c00036e },
3833 { ppc32_emit_STHX , 0xfc0007ff , 0x7c00032e },
3834 { ppc32_emit_STW , 0xfc000000 , 0x90000000 },
3835 { ppc32_emit_STWU , 0xfc000000 , 0x94000000 },
3836 { ppc32_emit_STWUX , 0xfc0007ff , 0x7c00016e },
3837 { ppc32_emit_STWX , 0xfc0007ff , 0x7c00012e },
3838 { ppc32_emit_SUBF , 0xfc0007fe , 0x7c000050 },
3839 { ppc32_emit_SUBFC , 0xfc0007fe , 0x7c000010 },
3840 { ppc32_emit_SUBFE , 0xfc0007fe , 0x7c000110 },
3841 { ppc32_emit_SUBFIC , 0xfc000000 , 0x20000000 },
3842 { ppc32_emit_SYNC , 0xffffffff , 0x7c0004ac },
3843 { ppc32_emit_XOR , 0xfc0007fe , 0x7c000278 },
3844 { ppc32_emit_XORI , 0xfc000000 , 0x68000000 },
3845 { ppc32_emit_XORIS , 0xfc000000 , 0x6c000000 },
3846 { ppc32_emit_unknown , 0x00000000 , 0x00000000 },
3847 { NULL , 0x00000000 , 0x00000000 },
3848 };
3849