/[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 10 - (show annotations)
Sat Oct 6 16:29:14 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7/ppc32_x86_trans.c
File MIME type: text/plain
File size: 110328 byte(s)
dynamips-0.2.7

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

  ViewVC Help
Powered by ViewVC 1.1.26