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