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