/[dynamips]/trunk/ppc32_x86_trans.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/ppc32_x86_trans.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (11 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 111515 byte(s)
make working copy

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

  ViewVC Help
Powered by ViewVC 1.1.26