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