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