|
|
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" ! 16: #include "ppc32_jit.h" ! 17: #include "ppc32_x86_trans.h" ! 18: #include "memory.h" ! 19: ! 20: /* Macros for CPU structure access */ ! 21: #define REG_OFFSET(reg) (OFFSET(cpu_ppc_t,gpr[(reg)])) ! 22: #define MEMOP_OFFSET(op) (OFFSET(cpu_ppc_t,mem_op_fn[(op)])) ! 23: ! 24: #define DECLARE_INSN(name) \ ! 25: static int ppc32_emit_##name(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, \ ! 26: ppc_insn_t insn) ! 27: ! 28: /* Dump regs */ ! 29: static void ppc32_emit_dump_regs(ppc32_jit_tcb_t *b); ! 30: ! 31: /* Load a 32 bit immediate value */ ! 32: static inline void ppc32_load_imm(ppc32_jit_tcb_t *b,u_int reg,m_uint32_t val) ! 33: { ! 34: if (val) ! 35: x86_mov_reg_imm(b->jit_ptr,reg,val); ! 36: else ! 37: x86_alu_reg_reg(b->jit_ptr,X86_XOR,reg,reg); ! 38: } ! 39: ! 40: /* Set the Instruction Address (IA) register */ ! 41: void ppc32_set_ia(ppc32_jit_tcb_t *b,m_uint32_t new_ia) ! 42: { ! 43: x86_mov_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),new_ia,4); ! 44: } ! 45: ! 46: /* Set the Link Register (LR) */ ! 47: void ppc32_set_lr(ppc32_jit_tcb_t *b,m_uint32_t new_lr) ! 48: { ! 49: x86_mov_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),new_lr,4); ! 50: } ! 51: ! 52: /* Set Jump */ ! 53: static void ppc32_set_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, ! 54: m_uint32_t new_ia,int local_jump) ! 55: { ! 56: int return_to_caller = FALSE; ! 57: u_char *jump_ptr; ! 58: ! 59: #if 0 ! 60: if (cpu->sym_trace && !local_jump) ! 61: return_to_caller = TRUE; ! 62: #endif ! 63: ! 64: if (!return_to_caller && ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr)) { ! 65: if (jump_ptr) { ! 66: x86_jump_code(b->jit_ptr,jump_ptr); ! 67: } else { ! 68: ppc32_jit_tcb_record_patch(b,b->jit_ptr,new_ia); ! 69: x86_jump32(b->jit_ptr,0); ! 70: } ! 71: } else { ! 72: /* save PC */ ! 73: ppc32_set_ia(b,new_ia); ! 74: ! 75: /* address is in another block, for now, returns to caller */ ! 76: ppc32_jit_tcb_push_epilog(b); ! 77: } ! 78: } ! 79: ! 80: /* Load the Condition Register (CR) into the specified host register */ ! 81: static forced_inline void ppc32_load_cr(ppc32_jit_tcb_t *b,u_int host_reg) ! 82: { ! 83: x86_mov_reg_membase(b->jit_ptr,host_reg,X86_EDI,OFFSET(cpu_ppc_t,cr),4); ! 84: } ! 85: ! 86: /* Store the Condition Register (CR) from the specified host register */ ! 87: static forced_inline void ppc32_store_cr(ppc32_jit_tcb_t *b,u_int host_reg) ! 88: { ! 89: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,cr),host_reg,4); ! 90: } ! 91: ! 92: /* Load a GPR into the specified host register */ ! 93: static forced_inline void ppc32_load_gpr(ppc32_jit_tcb_t *b,u_int host_reg, ! 94: u_int ppc_reg) ! 95: { ! 96: x86_mov_reg_membase(b->jit_ptr,host_reg,X86_EDI,REG_OFFSET(ppc_reg),4); ! 97: } ! 98: ! 99: /* Store contents for a host register into a GPR register */ ! 100: static forced_inline void ppc32_store_gpr(ppc32_jit_tcb_t *b,u_int ppc_reg, ! 101: u_int host_reg) ! 102: { ! 103: x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(ppc_reg),host_reg,4); ! 104: } ! 105: ! 106: /* Apply an ALU operation on a GPR register and a host register */ ! 107: static forced_inline void ppc32_alu_gpr(ppc32_jit_tcb_t *b,u_int op, ! 108: u_int host_reg,u_int ppc_reg) ! 109: { ! 110: x86_alu_reg_membase(b->jit_ptr,op,host_reg,X86_EDI,REG_OFFSET(ppc_reg)); ! 111: } ! 112: ! 113: /* ! 114: * Update CR from %eflags ! 115: * %eax, %ecx, %edx, %esi are modified. ! 116: */ ! 117: #define PPC32_CR_LT_BIT 3 ! 118: #define PPC32_CR_GT_BIT 2 ! 119: #define PPC32_CR_EQ_BIT 1 ! 120: #define PPC32_CR_SO_BIT 0 ! 121: ! 122: static void ppc32_update_cr(ppc32_jit_tcb_t *b,int field,int is_signed) ! 123: { ! 124: m_uint32_t cr_mask; ! 125: u_int cfb; ! 126: ! 127: cr_mask = 0xF0000000 >> (field << 2); ! 128: cfb = 28 - (field << 2); ! 129: ! 130: x86_set_reg(b->jit_ptr,X86_CC_LT,X86_EAX,is_signed); ! 131: x86_set_reg(b->jit_ptr,X86_CC_GT,X86_ECX,is_signed); ! 132: x86_set_reg(b->jit_ptr,X86_CC_Z,X86_EDX,is_signed); ! 133: ! 134: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EAX,(cfb + PPC32_CR_LT_BIT)); ! 135: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_ECX,(cfb + PPC32_CR_GT_BIT)); ! 136: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EDX,(cfb + PPC32_CR_EQ_BIT)); ! 137: ! 138: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); ! 139: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_EDX); ! 140: ! 141: /* Load Condition Register */ ! 142: x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,cr),4); ! 143: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EDX,~cr_mask); ! 144: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,cr_mask); ! 145: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EDX,X86_EAX); ! 146: ! 147: /* Check XER Summary of Overflow and report it */ ! 148: x86_mov_reg_membase(b->jit_ptr,X86_ECX,X86_EDI,OFFSET(cpu_ppc_t,xer),4); ! 149: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ECX,PPC32_XER_SO); ! 150: x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_ECX,(field << 2) + 3); ! 151: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EDX,X86_ECX); ! 152: ! 153: /* Store modified CR */ ! 154: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,cr),X86_EDX,4); ! 155: } ! 156: ! 157: /* ! 158: * Update CR0 from %eflags ! 159: * %eax, %ecx, %edx, %esi are modified. ! 160: */ ! 161: static void ppc32_update_cr0(ppc32_jit_tcb_t *b) ! 162: { ! 163: ppc32_update_cr(b,0,TRUE); ! 164: } ! 165: ! 166: /* Basic C call */ ! 167: static forced_inline void ppc32_emit_basic_c_call(ppc32_jit_tcb_t *b,void *f) ! 168: { ! 169: x86_mov_reg_imm(b->jit_ptr,X86_EBX,f); ! 170: x86_call_reg(b->jit_ptr,X86_EBX); ! 171: } ! 172: ! 173: /* Emit a simple call to a C function without any parameter */ ! 174: static void ppc32_emit_c_call(ppc32_jit_tcb_t *b,void *f) ! 175: { ! 176: ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); ! 177: ppc32_emit_basic_c_call(b,f); ! 178: } ! 179: ! 180: /* Memory operation */ ! 181: static void ppc32_emit_memop(ppc32_jit_tcb_t *b,int op,int base,int offset, ! 182: int target,int update) ! 183: { ! 184: m_uint32_t val = sign_extend(offset,16); ! 185: u_char *test1; ! 186: ! 187: /* Save PC for exception handling */ ! 188: ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); ! 189: ! 190: /* EDX = sign-extended offset */ ! 191: ppc32_load_imm(b,X86_EDX,val); ! 192: ! 193: /* EDX = GPR[base] + sign-extended offset */ ! 194: if (update || (base != 0)) ! 195: ppc32_alu_gpr(b,X86_ADD,X86_EDX,base); ! 196: ! 197: if (update) ! 198: x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EDX,4); ! 199: ! 200: /* ECX = target register */ ! 201: x86_mov_reg_imm(b->jit_ptr,X86_ECX,target); ! 202: ! 203: /* EAX = CPU instance pointer */ ! 204: x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); ! 205: ! 206: /* Call memory function */ ! 207: x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(op)); ! 208: ! 209: /* Exception ? */ ! 210: x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); ! 211: test1 = b->jit_ptr; ! 212: x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); ! 213: ppc32_jit_tcb_push_epilog(b); ! 214: x86_patch(test1,b->jit_ptr); ! 215: ! 216: if (update) ! 217: ppc32_store_gpr(b,base,X86_ESI); ! 218: } ! 219: ! 220: /* Memory operation (indexed) */ ! 221: static void ppc32_emit_memop_idx(ppc32_jit_tcb_t *b,int op,int ra,int rb, ! 222: int target,int update) ! 223: { ! 224: u_char *test1; ! 225: ! 226: /* Save PC for exception handling */ ! 227: ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); ! 228: ! 229: /* EDX = $rb */ ! 230: ppc32_load_gpr(b,X86_EDX,rb); ! 231: ! 232: /* EDX = $rb + $ra */ ! 233: if (update || (ra != 0)) ! 234: ppc32_alu_gpr(b,X86_ADD,X86_EDX,ra); ! 235: ! 236: if (update) ! 237: x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EDX,4); ! 238: ! 239: /* ECX = target register */ ! 240: x86_mov_reg_imm(b->jit_ptr,X86_ECX,target); ! 241: ! 242: /* EAX = CPU instance pointer */ ! 243: x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); ! 244: ! 245: /* Call memory function */ ! 246: x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(op)); ! 247: ! 248: /* Exception ? */ ! 249: x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); ! 250: test1 = b->jit_ptr; ! 251: x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); ! 252: ppc32_jit_tcb_push_epilog(b); ! 253: x86_patch(test1,b->jit_ptr); ! 254: ! 255: if (update) ! 256: ppc32_store_gpr(b,ra,X86_ESI); ! 257: } ! 258: ! 259: typedef void (*memop_fast_access)(ppc32_jit_tcb_t *b,int target); ! 260: ! 261: /* Fast LBZ */ ! 262: static void ppc32_memop_fast_lbz(ppc32_jit_tcb_t *b,int target) ! 263: { ! 264: x86_clear_reg(b->jit_ptr,X86_ECX); ! 265: x86_mov_reg_memindex(b->jit_ptr,X86_ECX,X86_EAX,0,X86_EBX,0,1); ! 266: ppc32_store_gpr(b,target,X86_ECX); ! 267: } ! 268: ! 269: /* Fast STB */ ! 270: static void ppc32_memop_fast_stb(ppc32_jit_tcb_t *b,int target) ! 271: { ! 272: ppc32_load_gpr(b,X86_EDX,target); ! 273: x86_mov_memindex_reg(b->jit_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,1); ! 274: } ! 275: ! 276: /* Fast LWZ */ ! 277: static void ppc32_memop_fast_lwz(ppc32_jit_tcb_t *b,int target) ! 278: { ! 279: x86_mov_reg_memindex(b->jit_ptr,X86_EAX,X86_EAX,0,X86_EBX,0,4); ! 280: x86_bswap(b->jit_ptr,X86_EAX); ! 281: ppc32_store_gpr(b,target,X86_EAX); ! 282: } ! 283: ! 284: /* Fast STW */ ! 285: static void ppc32_memop_fast_stw(ppc32_jit_tcb_t *b,int target) ! 286: { ! 287: ppc32_load_gpr(b,X86_EDX,target); ! 288: x86_bswap(b->jit_ptr,X86_EDX); ! 289: x86_mov_memindex_reg(b->jit_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,4); ! 290: } ! 291: ! 292: /* Fast memory operation */ ! 293: static void ppc32_emit_memop_fast(ppc32_jit_tcb_t *b,int write_op,int opcode, ! 294: int base,int offset,int target, ! 295: memop_fast_access op_handler) ! 296: { ! 297: m_uint32_t val = sign_extend(offset,16); ! 298: u_char *test1,*test2,*p_exception,*p_exit; ! 299: ! 300: test2 = NULL; ! 301: ! 302: /* EBX = sign-extended offset */ ! 303: ppc32_load_imm(b,X86_EBX,val); ! 304: ! 305: /* EBX = GPR[base] + sign-extended offset */ ! 306: if (base != 0) ! 307: ppc32_alu_gpr(b,X86_ADD,X86_EBX,base); ! 308: ! 309: /* EAX = mts32_entry index */ ! 310: x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EBX,4); ! 311: x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_EAX,MTS32_HASH_SHIFT); ! 312: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,MTS32_HASH_MASK); ! 313: ! 314: /* EDX = mts32_entry */ ! 315: x86_mov_reg_membase(b->jit_ptr,X86_EDX, ! 316: X86_EDI,OFFSET(cpu_ppc_t,mts_cache[PPC32_MTS_DCACHE]), ! 317: 4); ! 318: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EAX,4); ! 319: x86_alu_reg_reg(b->jit_ptr,X86_ADD,X86_EDX,X86_EAX); ! 320: ! 321: /* Compare virtual page address (ESI = vpage) */ ! 322: x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EBX,4); ! 323: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_MASK); ! 324: ! 325: x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ESI,X86_EDX, ! 326: OFFSET(mts32_entry_t,gvpa)); ! 327: test1 = b->jit_ptr; ! 328: x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); ! 329: ! 330: /* Test if we are writing to a COW page */ ! 331: if (write_op) { ! 332: x86_test_membase_imm(b->jit_ptr,X86_EDX,OFFSET(mts32_entry_t,flags), ! 333: MTS_FLAG_COW); ! 334: test2 = b->jit_ptr; ! 335: x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); ! 336: } ! 337: ! 338: /* EBX = offset in page, EAX = Host Page Address */ ! 339: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,PPC32_MIN_PAGE_IMASK); ! 340: x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDX,OFFSET(mts32_entry_t,hpa),4); ! 341: ! 342: /* Memory access */ ! 343: op_handler(b,target); ! 344: ! 345: p_exit = b->jit_ptr; ! 346: x86_jump8(b->jit_ptr,0); ! 347: ! 348: /* === Slow lookup === */ ! 349: x86_patch(test1,b->jit_ptr); ! 350: if (test2) ! 351: x86_patch(test2,b->jit_ptr); ! 352: ! 353: /* Update IA (EBX = vaddr) */ ! 354: ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); ! 355: ! 356: /* EDX = virtual address */ ! 357: x86_mov_reg_reg(b->jit_ptr,X86_EDX,X86_EBX,4); ! 358: ! 359: /* ECX = target register */ ! 360: x86_mov_reg_imm(b->jit_ptr,X86_ECX,target); ! 361: ! 362: /* EAX = CPU instance pointer */ ! 363: x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); ! 364: ! 365: /* Call memory function */ ! 366: x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode)); ! 367: ! 368: /* Check for exception */ ! 369: x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); ! 370: p_exception = b->jit_ptr; ! 371: x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); ! 372: ppc32_jit_tcb_push_epilog(b); ! 373: ! 374: x86_patch(p_exit,b->jit_ptr); ! 375: x86_patch(p_exception,b->jit_ptr); ! 376: } ! 377: ! 378: /* Virtual Breakpoint */ ! 379: void ppc32_emit_breakpoint(ppc32_jit_tcb_t *b) ! 380: { ! 381: x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); ! 382: ppc32_emit_c_call(b,ppc32_run_breakpoint); ! 383: } ! 384: ! 385: /* Unknown opcode handler */ ! 386: static asmlinkage void ppc32_unknown_opcode(cpu_ppc_t *cpu,m_uint32_t opcode) ! 387: { ! 388: printf("PPC32: unhandled opcode 0x%8.8x at 0x%8.8x (lr=0x%8.8x)\n", ! 389: opcode,cpu->ia,cpu->lr); ! 390: ! 391: ppc32_dump_regs(cpu->gen); ! 392: exit(1); ! 393: } ! 394: ! 395: /* Emit unhandled instruction code */ ! 396: static int ppc32_emit_unknown(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, ! 397: ppc_insn_t opcode) ! 398: { ! 399: u_char *test1; ! 400: ! 401: #if 0 ! 402: x86_mov_reg_imm(b->jit_ptr,X86_EAX,opcode); ! 403: x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,4); ! 404: x86_push_reg(b->jit_ptr,X86_EAX); ! 405: x86_push_reg(b->jit_ptr,X86_EDI); ! 406: ppc32_emit_c_call(b,ppc32_unknown_opcode); ! 407: x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); ! 408: #endif ! 409: ! 410: /* Update IA */ ! 411: ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); ! 412: ! 413: /* Fallback to non-JIT mode */ ! 414: x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); ! 415: x86_mov_reg_imm(b->jit_ptr,X86_EDX,opcode); ! 416: ! 417: ppc32_emit_c_call(b,ppc32_exec_single_insn_ext); ! 418: x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); ! 419: test1 = b->jit_ptr; ! 420: x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); ! 421: ppc32_jit_tcb_push_epilog(b); ! 422: ! 423: x86_patch(test1,b->jit_ptr); ! 424: return(0); ! 425: } ! 426: ! 427: /* Dump regs */ ! 428: static void ppc32_emit_dump_regs(ppc32_jit_tcb_t *b) ! 429: { ! 430: x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,gen),4); ! 431: x86_push_reg(b->jit_ptr,X86_EAX); ! 432: ppc32_emit_c_call(b,ppc32_dump_regs); ! 433: x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,4); ! 434: } ! 435: ! 436: /* Increment the number of executed instructions (performance debugging) */ ! 437: void ppc32_inc_perf_counter(ppc32_jit_tcb_t *b) ! 438: { ! 439: x86_alu_membase_imm(b->jit_ptr,X86_ADD, ! 440: X86_EDI,OFFSET(cpu_ppc_t,perf_counter),1); ! 441: x86_alu_membase_imm(b->jit_ptr,X86_ADC, ! 442: X86_EDI,OFFSET(cpu_ppc_t,perf_counter)+4,0); ! 443: } ! 444: ! 445: /* ======================================================================== */ ! 446: ! 447: /* BLR - Branch to Link Register */ ! 448: DECLARE_INSN(BLR) ! 449: { ! 450: x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,lr),4); ! 451: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),X86_EDX,4); ! 452: ! 453: /* set the return address */ ! 454: if (insn & 1) ! 455: ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); ! 456: ! 457: ppc32_jit_tcb_push_epilog(b); ! 458: return(0); ! 459: } ! 460: ! 461: /* BCTR - Branch to Count Register */ ! 462: DECLARE_INSN(BCTR) ! 463: { ! 464: x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,ctr),4); ! 465: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),X86_EDX,4); ! 466: ! 467: /* set the return address */ ! 468: if (insn & 1) ! 469: ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); ! 470: ! 471: ppc32_jit_tcb_push_epilog(b); ! 472: return(0); ! 473: } ! 474: ! 475: /* MFLR - Move From Link Register */ ! 476: DECLARE_INSN(MFLR) ! 477: { ! 478: int rd = bits(insn,21,25); ! 479: ! 480: x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,lr),4); ! 481: ppc32_store_gpr(b,rd,X86_EDX); ! 482: return(0); ! 483: } ! 484: ! 485: /* MTLR - Move To Link Register */ ! 486: DECLARE_INSN(MTLR) ! 487: { ! 488: int rs = bits(insn,21,25); ! 489: ! 490: ppc32_load_gpr(b,X86_EDX,rs); ! 491: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),X86_EDX,4); ! 492: return(0); ! 493: } ! 494: ! 495: /* MFCTR - Move From Counter Register */ ! 496: DECLARE_INSN(MFCTR) ! 497: { ! 498: int rd = bits(insn,21,25); ! 499: ! 500: x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,ctr),4); ! 501: ppc32_store_gpr(b,rd,X86_EDX); ! 502: return(0); ! 503: } ! 504: ! 505: /* MTCTR - Move To Counter Register */ ! 506: DECLARE_INSN(MTCTR) ! 507: { ! 508: int rs = bits(insn,21,25); ! 509: ! 510: ppc32_load_gpr(b,X86_EDX,rs); ! 511: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr),X86_EDX,4); ! 512: return(0); ! 513: } ! 514: ! 515: /* MFTBU - Move from Time Base (Up) */ ! 516: DECLARE_INSN(MFTBU) ! 517: { ! 518: int rd = bits(insn,21,25); ! 519: ! 520: x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,4); ! 521: ppc32_store_gpr(b,rd,X86_EDX); ! 522: return(0); ! 523: } ! 524: ! 525: #define PPC32_TB_INCREMENT 50 ! 526: ! 527: /* MFTBL - Move from Time Base (Lo) */ ! 528: DECLARE_INSN(MFTBL) ! 529: { ! 530: int rd = bits(insn,21,25); ! 531: ! 532: /* Increment the time base register */ ! 533: x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,tb),4); ! 534: x86_mov_reg_membase(b->jit_ptr,X86_EBX,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,4); ! 535: x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_EDX,PPC32_TB_INCREMENT); ! 536: x86_alu_reg_imm(b->jit_ptr,X86_ADC,X86_EBX,0); ! 537: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,tb),X86_EDX,4); ! 538: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,X86_EBX,4); ! 539: ! 540: ppc32_store_gpr(b,rd,X86_EDX); ! 541: return(0); ! 542: } ! 543: ! 544: /* ADD */ ! 545: DECLARE_INSN(ADD) ! 546: { ! 547: int rd = bits(insn,21,25); ! 548: int ra = bits(insn,16,20); ! 549: int rb = bits(insn,11,15); ! 550: ! 551: /* $rd = $ra + $rb */ ! 552: ppc32_load_gpr(b,X86_EBX,ra); ! 553: ppc32_alu_gpr(b,X86_ADD,X86_EBX,rb); ! 554: ppc32_store_gpr(b,rd,X86_EBX); ! 555: ! 556: if (insn & 1) ! 557: ppc32_update_cr0(b); ! 558: ! 559: return(0); ! 560: } ! 561: ! 562: /* ADDC */ ! 563: DECLARE_INSN(ADDC) ! 564: { ! 565: int rd = bits(insn,21,25); ! 566: int ra = bits(insn,16,20); ! 567: int rb = bits(insn,11,15); ! 568: ! 569: /* $rd = $ra + $rb */ ! 570: ppc32_load_gpr(b,X86_EBX,ra); ! 571: ppc32_alu_gpr(b,X86_ADD,X86_EBX,rb); ! 572: ppc32_store_gpr(b,rd,X86_EBX); ! 573: ! 574: /* store the carry flag */ ! 575: x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); ! 576: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); ! 577: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); ! 578: ! 579: if (insn & 1) { ! 580: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 581: ppc32_update_cr0(b); ! 582: } ! 583: ! 584: return(0); ! 585: } ! 586: ! 587: /* ADDE - Add Extended */ ! 588: DECLARE_INSN(ADDE) ! 589: { ! 590: int rd = bits(insn,21,25); ! 591: int ra = bits(insn,16,20); ! 592: int rb = bits(insn,11,15); ! 593: ! 594: /* $ra + carry */ ! 595: ppc32_load_gpr(b,X86_ESI,ra); ! 596: x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_ESI, ! 597: X86_EDI,OFFSET(cpu_ppc_t,xer_ca)); ! 598: x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); ! 599: ! 600: /* add $rb */ ! 601: ppc32_alu_gpr(b,X86_ADD,X86_ESI,rb); ! 602: x86_set_reg(b->jit_ptr,X86_CC_C,X86_ECX,FALSE); ! 603: ! 604: ppc32_store_gpr(b,rd,X86_ESI); ! 605: ! 606: /* store the carry flag */ ! 607: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); ! 608: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); ! 609: ! 610: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); ! 611: ! 612: /* update cr0 */ ! 613: if (insn & 1) { ! 614: x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI); ! 615: ppc32_update_cr0(b); ! 616: } ! 617: ! 618: return(0); ! 619: } ! 620: ! 621: /* ADDI - ADD Immediate */ ! 622: DECLARE_INSN(ADDI) ! 623: { ! 624: int rd = bits(insn,21,25); ! 625: int ra = bits(insn,16,20); ! 626: int imm = bits(insn,0,15); ! 627: m_uint32_t tmp = sign_extend_32(imm,16); ! 628: ! 629: ppc32_load_imm(b,X86_EBX,tmp); ! 630: ! 631: if (ra != 0) ! 632: x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EBX,X86_EDI,REG_OFFSET(ra)); ! 633: ! 634: ppc32_store_gpr(b,rd,X86_EBX); ! 635: return(0); ! 636: } ! 637: ! 638: /* ADDIC - ADD Immediate with Carry */ ! 639: DECLARE_INSN(ADDIC) ! 640: { ! 641: int rd = bits(insn,21,25); ! 642: int ra = bits(insn,16,20); ! 643: int imm = bits(insn,0,15); ! 644: m_uint32_t tmp = sign_extend_32(imm,16); ! 645: ! 646: ppc32_load_imm(b,X86_EAX,tmp); ! 647: ppc32_alu_gpr(b,X86_ADD,X86_EAX,ra); ! 648: ppc32_store_gpr(b,rd,X86_EAX); ! 649: x86_set_membase(b->jit_ptr,X86_CC_C,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),FALSE); ! 650: return(0); ! 651: } ! 652: ! 653: /* ADDIC. */ ! 654: DECLARE_INSN(ADDIC_dot) ! 655: { ! 656: int rd = bits(insn,21,25); ! 657: int ra = bits(insn,16,20); ! 658: int imm = bits(insn,0,15); ! 659: m_uint32_t tmp = sign_extend_32(imm,16); ! 660: ! 661: ppc32_load_imm(b,X86_EAX,tmp); ! 662: ppc32_alu_gpr(b,X86_ADD,X86_EAX,ra); ! 663: ppc32_store_gpr(b,rd,X86_EAX); ! 664: x86_set_membase(b->jit_ptr,X86_CC_C,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),FALSE); ! 665: ! 666: x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); ! 667: ppc32_update_cr0(b); ! 668: return(0); ! 669: } ! 670: ! 671: /* ADDIS - ADD Immediate Shifted */ ! 672: DECLARE_INSN(ADDIS) ! 673: { ! 674: int rd = bits(insn,21,25); ! 675: int ra = bits(insn,16,20); ! 676: m_uint32_t imm = bits(insn,0,15); ! 677: ! 678: ppc32_load_imm(b,X86_EBX,imm << 16); ! 679: ! 680: if (ra != 0) ! 681: x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EBX,X86_EDI,REG_OFFSET(ra)); ! 682: ! 683: ppc32_store_gpr(b,rd,X86_EBX); ! 684: return(0); ! 685: } ! 686: ! 687: /* AND */ ! 688: DECLARE_INSN(AND) ! 689: { ! 690: int rs = bits(insn,21,25); ! 691: int ra = bits(insn,16,20); ! 692: int rb = bits(insn,11,15); ! 693: ! 694: ppc32_load_gpr(b,X86_EBX,rs); ! 695: ppc32_alu_gpr(b,X86_AND,X86_EBX,rb); ! 696: ppc32_store_gpr(b,ra,X86_EBX); ! 697: ! 698: if (insn & 1) ! 699: ppc32_update_cr0(b); ! 700: ! 701: return(0); ! 702: } ! 703: ! 704: /* ANDC */ ! 705: DECLARE_INSN(ANDC) ! 706: { ! 707: int rs = bits(insn,21,25); ! 708: int ra = bits(insn,16,20); ! 709: int rb = bits(insn,11,15); ! 710: ! 711: /* $ra = $rs & ~$rb */ ! 712: ppc32_load_gpr(b,X86_EBX,rb); ! 713: x86_not_reg(b->jit_ptr,X86_EBX); ! 714: ppc32_alu_gpr(b,X86_AND,X86_EBX,rs); ! 715: ppc32_store_gpr(b,ra,X86_EBX); ! 716: ! 717: if (insn & 1) ! 718: ppc32_update_cr0(b); ! 719: ! 720: return(0); ! 721: } ! 722: ! 723: /* AND Immediate */ ! 724: DECLARE_INSN(ANDI) ! 725: { ! 726: int rs = bits(insn,21,25); ! 727: int ra = bits(insn,16,20); ! 728: m_uint16_t imm = bits(insn,0,15); ! 729: ! 730: /* $ra = $rs & imm */ ! 731: ppc32_load_imm(b,X86_EBX,imm); ! 732: ppc32_alu_gpr(b,X86_AND,X86_EBX,rs); ! 733: ppc32_store_gpr(b,ra,X86_EBX); ! 734: ! 735: ppc32_update_cr0(b); ! 736: return(0); ! 737: } ! 738: ! 739: /* AND Immediate Shifted */ ! 740: DECLARE_INSN(ANDIS) ! 741: { ! 742: int rs = bits(insn,21,25); ! 743: int ra = bits(insn,16,20); ! 744: m_uint32_t imm = bits(insn,0,15); ! 745: ! 746: /* $ra = $rs & imm */ ! 747: ppc32_load_imm(b,X86_EBX,imm << 16); ! 748: ppc32_alu_gpr(b,X86_AND,X86_EBX,rs); ! 749: ppc32_store_gpr(b,ra,X86_EBX); ! 750: ! 751: ppc32_update_cr0(b); ! 752: return(0); ! 753: } ! 754: ! 755: /* B - Branch */ ! 756: DECLARE_INSN(B) ! 757: { ! 758: m_uint32_t offset = bits(insn,2,25); ! 759: m_uint64_t new_ia; ! 760: ! 761: /* compute the new ia */ ! 762: new_ia = b->start_ia + ((b->ppc_trans_pos-1) << 2); ! 763: new_ia += sign_extend(offset << 2,26); ! 764: ppc32_set_jump(cpu,b,new_ia,1); ! 765: return(0); ! 766: } ! 767: ! 768: /* BA - Branch Absolute */ ! 769: DECLARE_INSN(BA) ! 770: { ! 771: m_uint32_t offset = bits(insn,2,25); ! 772: m_uint64_t new_ia; ! 773: ! 774: /* compute the new ia */ ! 775: new_ia = sign_extend(offset << 2,26); ! 776: ppc32_set_jump(cpu,b,new_ia,1); ! 777: return(0); ! 778: } ! 779: ! 780: /* BL - Branch and Link */ ! 781: DECLARE_INSN(BL) ! 782: { ! 783: m_uint32_t offset = bits(insn,2,25); ! 784: m_uint64_t new_ia; ! 785: ! 786: /* compute the new ia */ ! 787: new_ia = b->start_ia + ((b->ppc_trans_pos-1) << 2); ! 788: new_ia += sign_extend(offset << 2,26); ! 789: ! 790: /* set the return address */ ! 791: ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); ! 792: ! 793: ppc32_set_jump(cpu,b,new_ia,1); ! 794: return(0); ! 795: } ! 796: ! 797: /* BLA - Branch and Link Absolute */ ! 798: DECLARE_INSN(BLA) ! 799: { ! 800: m_uint32_t offset = bits(insn,2,25); ! 801: m_uint64_t new_ia; ! 802: ! 803: /* compute the new ia */ ! 804: new_ia = sign_extend(offset << 2,26); ! 805: ! 806: /* set the return address */ ! 807: ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); ! 808: ! 809: ppc32_set_jump(cpu,b,new_ia,1); ! 810: return(0); ! 811: } ! 812: ! 813: /* BC - Branch Conditional (Condition Check only) */ ! 814: DECLARE_INSN(BCC) ! 815: { ! 816: int bo = bits(insn,21,25); ! 817: int bi = bits(insn,16,20); ! 818: int bd = bits(insn,2,15); ! 819: m_uint32_t new_ia; ! 820: u_char *jump_ptr; ! 821: int local_jump; ! 822: int cond; ! 823: ! 824: /* Get the wanted value for the condition bit */ ! 825: cond = (bo >> 3) & 0x1; ! 826: ! 827: /* Set the return address */ ! 828: if (insn & 1) ! 829: ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); ! 830: ! 831: /* Compute the new ia */ ! 832: new_ia = sign_extend_32(bd << 2,16); ! 833: if (!(insn & 0x02)) ! 834: new_ia += b->start_ia + ((b->ppc_trans_pos-1) << 2); ! 835: ! 836: /* Test the condition bit */ ! 837: x86_test_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,cr), ! 838: (1 << (31 - bi))); ! 839: ! 840: local_jump = ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr); ! 841: ! 842: /* ! 843: * Optimize the jump, depending if the destination is in the same ! 844: * page or not. ! 845: */ ! 846: if (local_jump) { ! 847: if (jump_ptr) { ! 848: x86_branch(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,jump_ptr,FALSE); ! 849: } else { ! 850: ppc32_jit_tcb_record_patch(b,b->jit_ptr,new_ia); ! 851: x86_branch32(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,0,FALSE); ! 852: } ! 853: } else { ! 854: jump_ptr = b->jit_ptr; ! 855: x86_branch32(b->jit_ptr,(cond) ? X86_CC_Z : X86_CC_NZ,0,FALSE); ! 856: ppc32_set_jump(cpu,b,new_ia,TRUE); ! 857: x86_patch(jump_ptr,b->jit_ptr); ! 858: } ! 859: ! 860: return(0); ! 861: } ! 862: ! 863: /* BC - Branch Conditional */ ! 864: DECLARE_INSN(BC) ! 865: { ! 866: int bo = bits(insn,21,25); ! 867: int bi = bits(insn,16,20); ! 868: int bd = bits(insn,2,15); ! 869: m_uint32_t new_ia; ! 870: u_char *jump_ptr; ! 871: int local_jump; ! 872: int cond,ctr; ! 873: ! 874: /* Get the wanted value for the condition bit and CTR value */ ! 875: cond = (bo >> 3) & 0x1; ! 876: ctr = (bo >> 1) & 0x1; ! 877: ! 878: /* Set the return address */ ! 879: if (insn & 1) ! 880: ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); ! 881: ! 882: /* Compute the new ia */ ! 883: new_ia = sign_extend_32(bd << 2,16); ! 884: if (!(insn & 0x02)) ! 885: new_ia += b->start_ia + ((b->ppc_trans_pos-1) << 2); ! 886: ! 887: x86_mov_reg_imm(b->jit_ptr,X86_EAX,1); ! 888: ! 889: /* Decrement the count register */ ! 890: if (!(bo & 0x04)) { ! 891: x86_dec_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr)); ! 892: x86_set_reg(b->jit_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,X86_EBX,FALSE); ! 893: x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_EBX); ! 894: } ! 895: ! 896: /* Test the condition bit */ ! 897: if (!((bo >> 4) & 0x01)) { ! 898: x86_test_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,cr), ! 899: (1 << (31 - bi))); ! 900: x86_set_reg(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,X86_ECX,FALSE); ! 901: x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_ECX); ! 902: } ! 903: ! 904: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x01); ! 905: ! 906: local_jump = ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr); ! 907: ! 908: /* ! 909: * Optimize the jump, depending if the destination is in the same ! 910: * page or not. ! 911: */ ! 912: if (local_jump) { ! 913: if (jump_ptr) { ! 914: x86_branch(b->jit_ptr,X86_CC_NZ,jump_ptr,FALSE); ! 915: } else { ! 916: ppc32_jit_tcb_record_patch(b,b->jit_ptr,new_ia); ! 917: x86_branch32(b->jit_ptr,X86_CC_NZ,0,FALSE); ! 918: } ! 919: } else { ! 920: jump_ptr = b->jit_ptr; ! 921: x86_branch32(b->jit_ptr,X86_CC_Z,0,FALSE); ! 922: ppc32_set_jump(cpu,b,new_ia,TRUE); ! 923: x86_patch(jump_ptr,b->jit_ptr); ! 924: } ! 925: ! 926: return(0); ! 927: } ! 928: ! 929: /* BCLR - Branch Conditional to Link register */ ! 930: DECLARE_INSN(BCLR) ! 931: { ! 932: int bo = bits(insn,21,25); ! 933: int bi = bits(insn,16,20); ! 934: int bd = bits(insn,2,15); ! 935: m_uint32_t new_ia; ! 936: u_char *jump_ptr; ! 937: int cond,ctr; ! 938: ! 939: /* Get the wanted value for the condition bit and CTR value */ ! 940: cond = (bo >> 3) & 0x1; ! 941: ctr = (bo >> 1) & 0x1; ! 942: ! 943: /* Compute the new ia */ ! 944: new_ia = sign_extend_32(bd << 2,16); ! 945: if (!(insn & 0x02)) ! 946: new_ia += b->start_ia + ((b->ppc_trans_pos-1) << 2); ! 947: ! 948: ppc32_load_imm(b,X86_EAX,1); ! 949: ! 950: /* Decrement the count register */ ! 951: if (!(bo & 0x04)) { ! 952: x86_dec_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr)); ! 953: x86_set_reg(b->jit_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,X86_EBX,FALSE); ! 954: x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_EBX); ! 955: } ! 956: ! 957: /* Test the condition bit */ ! 958: if (!((bo >> 4) & 0x01)) { ! 959: x86_test_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,cr), ! 960: (1 << (31 - bi))); ! 961: x86_set_reg(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,X86_ECX,FALSE); ! 962: x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_ECX); ! 963: } ! 964: ! 965: /* Set the return address */ ! 966: x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,lr),4); ! 967: ! 968: if (insn & 1) ! 969: ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); ! 970: ! 971: /* Branching */ ! 972: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x01); ! 973: ! 974: jump_ptr = b->jit_ptr; ! 975: x86_branch32(b->jit_ptr,X86_CC_Z,0,FALSE); ! 976: ! 977: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EDX,0xFFFFFFFC); ! 978: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),X86_EDX,4); ! 979: ppc32_jit_tcb_push_epilog(b); ! 980: ! 981: x86_patch(jump_ptr,b->jit_ptr); ! 982: return(0); ! 983: } ! 984: ! 985: /* CMP - Compare */ ! 986: DECLARE_INSN(CMP) ! 987: { ! 988: int rd = bits(insn,23,25); ! 989: int ra = bits(insn,16,20); ! 990: int rb = bits(insn,11,15); ! 991: ! 992: ppc32_load_gpr(b,X86_EBX,ra); ! 993: ppc32_alu_gpr(b,X86_CMP,X86_EBX,rb); ! 994: ppc32_update_cr(b,rd,TRUE); ! 995: return(0); ! 996: } ! 997: ! 998: /* CMPI - Compare Immediate */ ! 999: DECLARE_INSN(CMPI) ! 1000: { ! 1001: int rd = bits(insn,23,25); ! 1002: int ra = bits(insn,16,20); ! 1003: m_uint16_t imm = bits(insn,0,15); ! 1004: m_uint32_t tmp = sign_extend_32(imm,16); ! 1005: ! 1006: ppc32_load_imm(b,X86_EBX,tmp); ! 1007: ppc32_load_gpr(b,X86_ESI,ra); ! 1008: x86_alu_reg_reg(b->jit_ptr,X86_CMP,X86_ESI,X86_EBX); ! 1009: ! 1010: ppc32_update_cr(b,rd,TRUE); ! 1011: return(0); ! 1012: } ! 1013: ! 1014: /* CMPL - Compare Logical */ ! 1015: DECLARE_INSN(CMPL) ! 1016: { ! 1017: int rd = bits(insn,23,25); ! 1018: int ra = bits(insn,16,20); ! 1019: int rb = bits(insn,11,15); ! 1020: ! 1021: ppc32_load_gpr(b,X86_EAX,ra); ! 1022: ppc32_alu_gpr(b,X86_CMP,X86_EAX,rb); ! 1023: ppc32_update_cr(b,rd,FALSE); ! 1024: return(0); ! 1025: } ! 1026: ! 1027: /* CMPLI - Compare Immediate */ ! 1028: DECLARE_INSN(CMPLI) ! 1029: { ! 1030: int rd = bits(insn,23,25); ! 1031: int ra = bits(insn,16,20); ! 1032: m_uint16_t imm = bits(insn,0,15); ! 1033: ! 1034: ppc32_load_imm(b,X86_EBX,imm); ! 1035: ppc32_load_gpr(b,X86_ESI,ra); ! 1036: x86_alu_reg_reg(b->jit_ptr,X86_CMP,X86_ESI,X86_EBX); ! 1037: ! 1038: ppc32_update_cr(b,rd,FALSE); ! 1039: return(0); ! 1040: } ! 1041: ! 1042: /* CRAND - Condition Register AND */ ! 1043: DECLARE_INSN(CRAND) ! 1044: { ! 1045: int bd = bits(insn,21,25); ! 1046: int bb = bits(insn,16,20); ! 1047: int ba = bits(insn,11,15); ! 1048: ! 1049: ppc32_load_cr(b,X86_ESI); ! 1050: ! 1051: /* test $ba bit */ ! 1052: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - ba))); ! 1053: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); ! 1054: ! 1055: /* test $bb bit */ ! 1056: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - bb))); ! 1057: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); ! 1058: ! 1059: /* result of AND between $ba and $bb */ ! 1060: x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EBX,X86_EAX); ! 1061: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); ! 1062: ! 1063: /* set/clear $bd bit depending on the result */ ! 1064: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,~(1 << (31 - bd))); ! 1065: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(31 - bd)); ! 1066: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_ESI,X86_EBX); ! 1067: ! 1068: ppc32_store_cr(b,X86_ESI); ! 1069: return(0); ! 1070: } ! 1071: ! 1072: /* CRANDC - Condition Register AND with Complement */ ! 1073: DECLARE_INSN(CRANDC) ! 1074: { ! 1075: int bd = bits(insn,21,25); ! 1076: int bb = bits(insn,16,20); ! 1077: int ba = bits(insn,11,15); ! 1078: ! 1079: ppc32_load_cr(b,X86_ESI); ! 1080: ! 1081: /* test $ba bit */ ! 1082: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - ba))); ! 1083: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); ! 1084: ! 1085: /* test $bb bit */ ! 1086: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - bb))); ! 1087: x86_set_reg(b->jit_ptr,X86_CC_Z,X86_EBX,FALSE); ! 1088: ! 1089: /* result of AND between $ba and $bb */ ! 1090: x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EBX,X86_EAX); ! 1091: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); ! 1092: ! 1093: /* set/clear $bd bit depending on the result */ ! 1094: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,~(1 << (31 - bd))); ! 1095: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(31 - bd)); ! 1096: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_ESI,X86_EBX); ! 1097: ! 1098: ppc32_store_cr(b,X86_ESI); ! 1099: return(0); ! 1100: } ! 1101: ! 1102: /* CREQV - Condition Register EQV */ ! 1103: DECLARE_INSN(CREQV) ! 1104: { ! 1105: int bd = bits(insn,21,25); ! 1106: int bb = bits(insn,16,20); ! 1107: int ba = bits(insn,11,15); ! 1108: ! 1109: ppc32_load_cr(b,X86_ESI); ! 1110: ! 1111: /* test $ba bit */ ! 1112: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - ba))); ! 1113: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); ! 1114: ! 1115: /* test $bb bit */ ! 1116: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - bb))); ! 1117: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); ! 1118: ! 1119: /* result of XOR between $ba and $bb */ ! 1120: x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EAX); ! 1121: x86_not_reg(b->jit_ptr,X86_EBX); ! 1122: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); ! 1123: ! 1124: /* set/clear $bd bit depending on the result */ ! 1125: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,~(1 << (31 - bd))); ! 1126: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(31 - bd)); ! 1127: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_ESI,X86_EBX); ! 1128: ! 1129: ppc32_store_cr(b,X86_ESI); ! 1130: return(0); ! 1131: } ! 1132: ! 1133: /* CRNAND - Condition Register NAND */ ! 1134: DECLARE_INSN(CRNAND) ! 1135: { ! 1136: int bd = bits(insn,21,25); ! 1137: int bb = bits(insn,16,20); ! 1138: int ba = bits(insn,11,15); ! 1139: ! 1140: ppc32_load_cr(b,X86_ESI); ! 1141: ! 1142: /* test $ba bit */ ! 1143: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - ba))); ! 1144: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); ! 1145: ! 1146: /* test $bb bit */ ! 1147: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - bb))); ! 1148: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); ! 1149: ! 1150: /* result of NAND between $ba and $bb */ ! 1151: x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EBX,X86_EAX); ! 1152: x86_not_reg(b->jit_ptr,X86_EBX); ! 1153: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); ! 1154: ! 1155: /* set/clear $bd bit depending on the result */ ! 1156: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,~(1 << (31 - bd))); ! 1157: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(31 - bd)); ! 1158: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_ESI,X86_EBX); ! 1159: ! 1160: ppc32_store_cr(b,X86_ESI); ! 1161: return(0); ! 1162: } ! 1163: ! 1164: /* CRNOR - Condition Register NOR */ ! 1165: DECLARE_INSN(CRNOR) ! 1166: { ! 1167: int bd = bits(insn,21,25); ! 1168: int bb = bits(insn,16,20); ! 1169: int ba = bits(insn,11,15); ! 1170: ! 1171: ppc32_load_cr(b,X86_ESI); ! 1172: ! 1173: /* test $ba bit */ ! 1174: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - ba))); ! 1175: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); ! 1176: ! 1177: /* test $bb bit */ ! 1178: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - bb))); ! 1179: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); ! 1180: ! 1181: /* result of NOR between $ba and $bb */ ! 1182: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EBX,X86_EAX); ! 1183: x86_not_reg(b->jit_ptr,X86_EBX); ! 1184: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); ! 1185: ! 1186: /* set/clear $bd bit depending on the result */ ! 1187: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,~(1 << (31 - bd))); ! 1188: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(31 - bd)); ! 1189: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_ESI,X86_EBX); ! 1190: ! 1191: ppc32_store_cr(b,X86_ESI); ! 1192: return(0); ! 1193: } ! 1194: ! 1195: /* CROR - Condition Register OR */ ! 1196: DECLARE_INSN(CROR) ! 1197: { ! 1198: int bd = bits(insn,21,25); ! 1199: int bb = bits(insn,16,20); ! 1200: int ba = bits(insn,11,15); ! 1201: ! 1202: ppc32_load_cr(b,X86_ESI); ! 1203: ! 1204: /* test $ba bit */ ! 1205: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - ba))); ! 1206: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); ! 1207: ! 1208: /* test $bb bit */ ! 1209: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - bb))); ! 1210: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); ! 1211: ! 1212: /* result of OR between $ba and $bb */ ! 1213: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EBX,X86_EAX); ! 1214: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); ! 1215: ! 1216: /* set/clear $bd bit depending on the result */ ! 1217: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,~(1 << (31 - bd))); ! 1218: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(31 - bd)); ! 1219: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_ESI,X86_EBX); ! 1220: ! 1221: ppc32_store_cr(b,X86_ESI); ! 1222: return(0); ! 1223: } ! 1224: ! 1225: /* CRORC - Condition Register OR with Complement */ ! 1226: DECLARE_INSN(CRORC) ! 1227: { ! 1228: int bd = bits(insn,21,25); ! 1229: int bb = bits(insn,16,20); ! 1230: int ba = bits(insn,11,15); ! 1231: ! 1232: ppc32_load_cr(b,X86_ESI); ! 1233: ! 1234: /* test $ba bit */ ! 1235: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - ba))); ! 1236: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); ! 1237: ! 1238: /* test $bb bit */ ! 1239: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - bb))); ! 1240: x86_set_reg(b->jit_ptr,X86_CC_Z,X86_EBX,FALSE); ! 1241: ! 1242: /* result of ORC between $ba and $bb */ ! 1243: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EBX,X86_EAX); ! 1244: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); ! 1245: ! 1246: /* set/clear $bd bit depending on the result */ ! 1247: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,~(1 << (31 - bd))); ! 1248: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(31 - bd)); ! 1249: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_ESI,X86_EBX); ! 1250: ! 1251: ppc32_store_cr(b,X86_ESI); ! 1252: return(0); ! 1253: } ! 1254: ! 1255: /* CRXOR - Condition Register XOR */ ! 1256: DECLARE_INSN(CRXOR) ! 1257: { ! 1258: int bd = bits(insn,21,25); ! 1259: int bb = bits(insn,16,20); ! 1260: int ba = bits(insn,11,15); ! 1261: ! 1262: ppc32_load_cr(b,X86_ESI); ! 1263: ! 1264: /* test $ba bit */ ! 1265: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - ba))); ! 1266: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); ! 1267: ! 1268: /* test $bb bit */ ! 1269: x86_test_reg_imm(b->jit_ptr,X86_ESI,(1 << (31 - bb))); ! 1270: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); ! 1271: ! 1272: /* result of XOR between $ba and $bb */ ! 1273: x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EAX); ! 1274: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); ! 1275: ! 1276: /* set/clear $bd bit depending on the result */ ! 1277: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,~(1 << (31 - bd))); ! 1278: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(31 - bd)); ! 1279: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_ESI,X86_EBX); ! 1280: ! 1281: ppc32_store_cr(b,X86_ESI); ! 1282: return(0); ! 1283: } ! 1284: ! 1285: /* DIVWU - Divide Word Unsigned */ ! 1286: DECLARE_INSN(DIVWU) ! 1287: { ! 1288: int rd = bits(insn,21,25); ! 1289: int ra = bits(insn,16,20); ! 1290: int rb = bits(insn,11,15); ! 1291: ! 1292: ppc32_load_gpr(b,X86_EAX,ra); ! 1293: ppc32_load_gpr(b,X86_EBX,rb); ! 1294: ppc32_load_imm(b,X86_EDX,0); ! 1295: ! 1296: x86_div_reg(b->jit_ptr,X86_EBX,0); ! 1297: ppc32_store_gpr(b,rd,X86_EAX); ! 1298: ! 1299: if (insn & 1) { ! 1300: x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); ! 1301: ppc32_update_cr0(b); ! 1302: } ! 1303: ! 1304: return(0); ! 1305: } ! 1306: ! 1307: /* EQV */ ! 1308: DECLARE_INSN(EQV) ! 1309: { ! 1310: int rs = bits(insn,21,25); ! 1311: int ra = bits(insn,16,20); ! 1312: int rb = bits(insn,11,15); ! 1313: ! 1314: /* $ra = ~($rs ^ $rb) */ ! 1315: ppc32_load_gpr(b,X86_EBX,rs); ! 1316: ppc32_alu_gpr(b,X86_XOR,X86_EBX,rb); ! 1317: x86_not_reg(b->jit_ptr,X86_EBX); ! 1318: ppc32_store_gpr(b,ra,X86_EBX); ! 1319: ! 1320: if (insn & 1) { ! 1321: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1322: ppc32_update_cr0(b); ! 1323: } ! 1324: ! 1325: return(0); ! 1326: } ! 1327: ! 1328: /* EXTSB - Extend Sign Byte */ ! 1329: DECLARE_INSN(EXTSB) ! 1330: { ! 1331: int rs = bits(insn,21,25); ! 1332: int ra = bits(insn,16,20); ! 1333: ! 1334: ppc32_load_gpr(b,X86_EBX,rs); ! 1335: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,24); ! 1336: x86_shift_reg_imm(b->jit_ptr,X86_SAR,X86_EBX,24); ! 1337: ppc32_store_gpr(b,ra,X86_EBX); ! 1338: ! 1339: if (insn & 1) { ! 1340: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1341: ppc32_update_cr0(b); ! 1342: } ! 1343: ! 1344: return(0); ! 1345: } ! 1346: ! 1347: /* EXTSH - Extend Sign Word */ ! 1348: DECLARE_INSN(EXTSH) ! 1349: { ! 1350: int rs = bits(insn,21,25); ! 1351: int ra = bits(insn,16,20); ! 1352: ! 1353: ppc32_load_gpr(b,X86_EBX,rs); ! 1354: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,16); ! 1355: x86_shift_reg_imm(b->jit_ptr,X86_SAR,X86_EBX,16); ! 1356: ppc32_store_gpr(b,ra,X86_EBX); ! 1357: ! 1358: if (insn & 1) { ! 1359: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1360: ppc32_update_cr0(b); ! 1361: } ! 1362: ! 1363: return(0); ! 1364: } ! 1365: ! 1366: /* LBZ - Load Byte and Zero */ ! 1367: DECLARE_INSN(LBZ) ! 1368: { ! 1369: int rs = bits(insn,21,25); ! 1370: int ra = bits(insn,16,20); ! 1371: m_uint16_t offset = bits(insn,0,15); ! 1372: ! 1373: //ppc32_emit_memop(b,PPC_MEMOP_LBZ,ra,offset,rs,0); ! 1374: ppc32_emit_memop_fast(b,0,PPC_MEMOP_LBZ,ra,offset,rs,ppc32_memop_fast_lbz); ! 1375: return(0); ! 1376: } ! 1377: ! 1378: /* LBZU - Load Byte and Zero with Update */ ! 1379: DECLARE_INSN(LBZU) ! 1380: { ! 1381: int rs = bits(insn,21,25); ! 1382: int ra = bits(insn,16,20); ! 1383: m_uint16_t offset = bits(insn,0,15); ! 1384: ! 1385: ppc32_emit_memop(b,PPC_MEMOP_LBZ,ra,offset,rs,1); ! 1386: return(0); ! 1387: } ! 1388: ! 1389: /* LBZUX - Load Byte and Zero with Update Indexed */ ! 1390: DECLARE_INSN(LBZUX) ! 1391: { ! 1392: int rs = bits(insn,21,25); ! 1393: int ra = bits(insn,16,20); ! 1394: int rb = bits(insn,11,15); ! 1395: ! 1396: ppc32_emit_memop_idx(b,PPC_MEMOP_LBZ,ra,rb,rs,1); ! 1397: return(0); ! 1398: } ! 1399: ! 1400: /* LBZX - Load Byte and Zero Indexed */ ! 1401: DECLARE_INSN(LBZX) ! 1402: { ! 1403: int rs = bits(insn,21,25); ! 1404: int ra = bits(insn,16,20); ! 1405: int rb = bits(insn,11,15); ! 1406: ! 1407: ppc32_emit_memop_idx(b,PPC_MEMOP_LBZ,ra,rb,rs,0); ! 1408: return(0); ! 1409: } ! 1410: ! 1411: /* LHA - Load Half-Word Algebraic */ ! 1412: DECLARE_INSN(LHA) ! 1413: { ! 1414: int rs = bits(insn,21,25); ! 1415: int ra = bits(insn,16,20); ! 1416: m_uint16_t offset = bits(insn,0,15); ! 1417: ! 1418: ppc32_emit_memop(b,PPC_MEMOP_LHA,ra,offset,rs,0); ! 1419: return(0); ! 1420: } ! 1421: ! 1422: /* LHAU - Load Half-Word Algebraic with Update */ ! 1423: DECLARE_INSN(LHAU) ! 1424: { ! 1425: int rs = bits(insn,21,25); ! 1426: int ra = bits(insn,16,20); ! 1427: m_uint16_t offset = bits(insn,0,15); ! 1428: ! 1429: ppc32_emit_memop(b,PPC_MEMOP_LHA,ra,offset,rs,1); ! 1430: return(0); ! 1431: } ! 1432: ! 1433: /* LHAUX - Load Half-Word Algebraic with Update Indexed */ ! 1434: DECLARE_INSN(LHAUX) ! 1435: { ! 1436: int rs = bits(insn,21,25); ! 1437: int ra = bits(insn,16,20); ! 1438: int rb = bits(insn,11,15); ! 1439: ! 1440: ppc32_emit_memop_idx(b,PPC_MEMOP_LHA,ra,rb,rs,1); ! 1441: return(0); ! 1442: } ! 1443: ! 1444: /* LHAX - Load Half-Word Algebraic Indexed */ ! 1445: DECLARE_INSN(LHAX) ! 1446: { ! 1447: int rs = bits(insn,21,25); ! 1448: int ra = bits(insn,16,20); ! 1449: int rb = bits(insn,11,15); ! 1450: ! 1451: ppc32_emit_memop_idx(b,PPC_MEMOP_LHA,ra,rb,rs,0); ! 1452: return(0); ! 1453: } ! 1454: ! 1455: /* LHZ - Load Half-Word and Zero */ ! 1456: DECLARE_INSN(LHZ) ! 1457: { ! 1458: int rs = bits(insn,21,25); ! 1459: int ra = bits(insn,16,20); ! 1460: m_uint16_t offset = bits(insn,0,15); ! 1461: ! 1462: ppc32_emit_memop(b,PPC_MEMOP_LHZ,ra,offset,rs,0); ! 1463: return(0); ! 1464: } ! 1465: ! 1466: /* LHZU - Load Half-Word and Zero with Update */ ! 1467: DECLARE_INSN(LHZU) ! 1468: { ! 1469: int rs = bits(insn,21,25); ! 1470: int ra = bits(insn,16,20); ! 1471: m_uint16_t offset = bits(insn,0,15); ! 1472: ! 1473: ppc32_emit_memop(b,PPC_MEMOP_LHZ,ra,offset,rs,1); ! 1474: return(0); ! 1475: } ! 1476: ! 1477: /* LHZUX - Load Half-Word and Zero with Update Indexed */ ! 1478: DECLARE_INSN(LHZUX) ! 1479: { ! 1480: int rs = bits(insn,21,25); ! 1481: int ra = bits(insn,16,20); ! 1482: int rb = bits(insn,11,15); ! 1483: ! 1484: ppc32_emit_memop_idx(b,PPC_MEMOP_LHZ,ra,rb,rs,1); ! 1485: return(0); ! 1486: } ! 1487: ! 1488: /* LHZX - Load Half-Word and Zero Indexed */ ! 1489: DECLARE_INSN(LHZX) ! 1490: { ! 1491: int rs = bits(insn,21,25); ! 1492: int ra = bits(insn,16,20); ! 1493: int rb = bits(insn,11,15); ! 1494: ! 1495: ppc32_emit_memop_idx(b,PPC_MEMOP_LHZ,ra,rb,rs,0); ! 1496: return(0); ! 1497: } ! 1498: ! 1499: /* LWZ - Load Word and Zero */ ! 1500: DECLARE_INSN(LWZ) ! 1501: { ! 1502: int rs = bits(insn,21,25); ! 1503: int ra = bits(insn,16,20); ! 1504: m_uint16_t offset = bits(insn,0,15); ! 1505: ! 1506: //ppc32_emit_memop(b,PPC_MEMOP_LWZ,ra,offset,rs,0); ! 1507: ppc32_emit_memop_fast(b,0,PPC_MEMOP_LWZ,ra,offset,rs,ppc32_memop_fast_lwz); ! 1508: return(0); ! 1509: } ! 1510: ! 1511: /* LWZU - Load Word and Zero with Update */ ! 1512: DECLARE_INSN(LWZU) ! 1513: { ! 1514: int rs = bits(insn,21,25); ! 1515: int ra = bits(insn,16,20); ! 1516: m_uint16_t offset = bits(insn,0,15); ! 1517: ! 1518: ppc32_emit_memop(b,PPC_MEMOP_LWZ,ra,offset,rs,1); ! 1519: return(0); ! 1520: } ! 1521: ! 1522: /* LWZUX - Load Word and Zero with Update Indexed */ ! 1523: DECLARE_INSN(LWZUX) ! 1524: { ! 1525: int rs = bits(insn,21,25); ! 1526: int ra = bits(insn,16,20); ! 1527: int rb = bits(insn,11,15); ! 1528: ! 1529: ppc32_emit_memop_idx(b,PPC_MEMOP_LWZ,ra,rb,rs,1); ! 1530: return(0); ! 1531: } ! 1532: ! 1533: /* LWZX - Load Word and Zero Indexed */ ! 1534: DECLARE_INSN(LWZX) ! 1535: { ! 1536: int rs = bits(insn,21,25); ! 1537: int ra = bits(insn,16,20); ! 1538: int rb = bits(insn,11,15); ! 1539: ! 1540: ppc32_emit_memop_idx(b,PPC_MEMOP_LWZ,ra,rb,rs,0); ! 1541: return(0); ! 1542: } ! 1543: ! 1544: /* MCRF - Move Condition Register Field */ ! 1545: DECLARE_INSN(MCRF) ! 1546: { ! 1547: int rd = bits(insn,23,25); ! 1548: int rs = bits(insn,18,20); ! 1549: m_uint32_t dmask; ! 1550: ! 1551: /* %eax = %ebx = CR */ ! 1552: ppc32_load_cr(b,X86_EAX); ! 1553: x86_mov_reg_reg(b->jit_ptr,X86_EBX,X86_EAX,4); ! 1554: ! 1555: x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_EBX,(28 - (rs << 2))); ! 1556: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x0F); ! 1557: x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,(28 - (rd << 2))); ! 1558: ! 1559: /* clear the destination bits */ ! 1560: dmask = (0xF0000000 >> (rd << 2)); ! 1561: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,~dmask); ! 1562: ! 1563: /* set the new field value */ ! 1564: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_EBX); ! 1565: ppc32_store_cr(b,X86_EAX); ! 1566: return(0); ! 1567: } ! 1568: ! 1569: /* MFCR - Move from Condition Register */ ! 1570: DECLARE_INSN(MFCR) ! 1571: { ! 1572: int rd = bits(insn,21,25); ! 1573: ! 1574: ppc32_load_cr(b,X86_EAX); ! 1575: ppc32_store_gpr(b,rd,X86_EAX); ! 1576: return(0); ! 1577: } ! 1578: ! 1579: /* MFMSR - Move from Machine State Register */ ! 1580: DECLARE_INSN(MFMSR) ! 1581: { ! 1582: int rd = bits(insn,21,25); ! 1583: ! 1584: x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,msr),4); ! 1585: ppc32_store_gpr(b,rd,X86_EAX); ! 1586: return(0); ! 1587: } ! 1588: ! 1589: /* MFSR - Move From Segment Register */ ! 1590: DECLARE_INSN(MFSR) ! 1591: { ! 1592: int rd = bits(insn,21,25); ! 1593: int sr = bits(insn,16,19); ! 1594: ! 1595: x86_mov_reg_membase(b->jit_ptr,X86_EAX, ! 1596: X86_EDI,(OFFSET(cpu_ppc_t,sr) + (sr << 2)),4); ! 1597: ppc32_store_gpr(b,rd,X86_EAX); ! 1598: return(0); ! 1599: } ! 1600: ! 1601: /* MTCRF - Move to Condition Register Fields */ ! 1602: DECLARE_INSN(MTCRF) ! 1603: { ! 1604: int rs = bits(insn,21,25); ! 1605: int crm = bits(insn,12,19); ! 1606: m_uint32_t mask = 0; ! 1607: int i; ! 1608: ! 1609: for(i=0;i<8;i++) ! 1610: if (crm & (1 << i)) ! 1611: mask |= 0xF << (i << 2); ! 1612: ! 1613: ppc32_load_cr(b,X86_EAX); ! 1614: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,~mask); ! 1615: ! 1616: ppc32_load_gpr(b,X86_EDX,rs); ! 1617: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EDX,mask); ! 1618: ! 1619: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EDX,X86_EAX); ! 1620: ppc32_store_cr(b,X86_EDX); ! 1621: return(0); ! 1622: } ! 1623: ! 1624: /* MULHW - Multiply High Word */ ! 1625: DECLARE_INSN(MULHW) ! 1626: { ! 1627: int rd = bits(insn,21,25); ! 1628: int ra = bits(insn,16,20); ! 1629: int rb = bits(insn,11,15); ! 1630: ! 1631: ppc32_load_gpr(b,X86_EAX,ra); ! 1632: ppc32_load_gpr(b,X86_EBX,rb); ! 1633: x86_mul_reg(b->jit_ptr,X86_EBX,1); ! 1634: ppc32_store_gpr(b,rd,X86_EDX); ! 1635: ! 1636: if (insn & 1) { ! 1637: x86_test_reg_reg(b->jit_ptr,X86_EDX,X86_EDX); ! 1638: ppc32_update_cr0(b); ! 1639: } ! 1640: ! 1641: return(0); ! 1642: } ! 1643: ! 1644: /* MULHWU - Multiply High Word Unsigned */ ! 1645: DECLARE_INSN(MULHWU) ! 1646: { ! 1647: int rd = bits(insn,21,25); ! 1648: int ra = bits(insn,16,20); ! 1649: int rb = bits(insn,11,15); ! 1650: ! 1651: ppc32_load_gpr(b,X86_EAX,ra); ! 1652: ppc32_load_gpr(b,X86_EBX,rb); ! 1653: x86_mul_reg(b->jit_ptr,X86_EBX,0); ! 1654: ppc32_store_gpr(b,rd,X86_EDX); ! 1655: ! 1656: if (insn & 1) { ! 1657: x86_test_reg_reg(b->jit_ptr,X86_EDX,X86_EDX); ! 1658: ppc32_update_cr0(b); ! 1659: } ! 1660: ! 1661: return(0); ! 1662: } ! 1663: ! 1664: /* MULLI - Multiply Low Immediate */ ! 1665: DECLARE_INSN(MULLI) ! 1666: { ! 1667: int rd = bits(insn,21,25); ! 1668: int ra = bits(insn,16,20); ! 1669: m_uint32_t imm = bits(insn,0,15); ! 1670: ! 1671: ppc32_load_gpr(b,X86_EAX,ra); ! 1672: ppc32_load_imm(b,X86_EBX,sign_extend_32(imm,16)); ! 1673: ! 1674: x86_mul_reg(b->jit_ptr,X86_EBX,1); ! 1675: ppc32_store_gpr(b,rd,X86_EAX); ! 1676: return(0); ! 1677: } ! 1678: ! 1679: /* MULLW - Multiply Low Word */ ! 1680: DECLARE_INSN(MULLW) ! 1681: { ! 1682: int rd = bits(insn,21,25); ! 1683: int ra = bits(insn,16,20); ! 1684: int rb = bits(insn,11,15); ! 1685: ! 1686: ppc32_load_gpr(b,X86_EAX,ra); ! 1687: ppc32_load_gpr(b,X86_EBX,rb); ! 1688: x86_mul_reg(b->jit_ptr,X86_EBX,1); ! 1689: ppc32_store_gpr(b,rd,X86_EAX); ! 1690: ! 1691: if (insn & 1) { ! 1692: x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); ! 1693: ppc32_update_cr0(b); ! 1694: } ! 1695: ! 1696: return(0); ! 1697: } ! 1698: ! 1699: /* NAND */ ! 1700: DECLARE_INSN(NAND) ! 1701: { ! 1702: int rs = bits(insn,21,25); ! 1703: int ra = bits(insn,16,20); ! 1704: int rb = bits(insn,11,15); ! 1705: ! 1706: /* $ra = ~($rs & $rb) */ ! 1707: ppc32_load_gpr(b,X86_EBX,rs); ! 1708: ppc32_alu_gpr(b,X86_AND,X86_EBX,rb); ! 1709: x86_not_reg(b->jit_ptr,X86_EBX); ! 1710: ppc32_store_gpr(b,ra,X86_EBX); ! 1711: ! 1712: if (insn & 1) { ! 1713: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1714: ppc32_update_cr0(b); ! 1715: } ! 1716: ! 1717: return(0); ! 1718: } ! 1719: ! 1720: /* NEG */ ! 1721: DECLARE_INSN(NEG) ! 1722: { ! 1723: int rd = bits(insn,21,25); ! 1724: int ra = bits(insn,16,20); ! 1725: ! 1726: ppc32_load_gpr(b,X86_EBX,ra); ! 1727: x86_neg_reg(b->jit_ptr,X86_EBX); ! 1728: ppc32_store_gpr(b,rd,X86_EBX); ! 1729: ! 1730: if (insn & 1) { ! 1731: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1732: ppc32_update_cr0(b); ! 1733: } ! 1734: ! 1735: return(0); ! 1736: } ! 1737: ! 1738: /* NOR */ ! 1739: DECLARE_INSN(NOR) ! 1740: { ! 1741: int rs = bits(insn,21,25); ! 1742: int ra = bits(insn,16,20); ! 1743: int rb = bits(insn,11,15); ! 1744: ! 1745: /* $ra = ~($rs | $rb) */ ! 1746: ppc32_load_gpr(b,X86_EBX,rs); ! 1747: ppc32_alu_gpr(b,X86_OR,X86_EBX,rb); ! 1748: x86_not_reg(b->jit_ptr,X86_EBX); ! 1749: ppc32_store_gpr(b,ra,X86_EBX); ! 1750: ! 1751: if (insn & 1) { ! 1752: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1753: ppc32_update_cr0(b); ! 1754: } ! 1755: ! 1756: return(0); ! 1757: } ! 1758: ! 1759: /* OR */ ! 1760: DECLARE_INSN(OR) ! 1761: { ! 1762: int rs = bits(insn,21,25); ! 1763: int ra = bits(insn,16,20); ! 1764: int rb = bits(insn,11,15); ! 1765: ! 1766: ppc32_load_gpr(b,X86_ECX,rs); ! 1767: ! 1768: if (rs != rb) ! 1769: ppc32_alu_gpr(b,X86_OR,X86_ECX,rb); ! 1770: ! 1771: ppc32_store_gpr(b,ra,X86_ECX); ! 1772: ! 1773: if (insn & 1) { ! 1774: if (rs == rb) ! 1775: x86_test_reg_reg(b->jit_ptr,X86_ECX,X86_ECX); ! 1776: ppc32_update_cr0(b); ! 1777: } ! 1778: ! 1779: return(0); ! 1780: } ! 1781: ! 1782: /* OR with Complement */ ! 1783: DECLARE_INSN(ORC) ! 1784: { ! 1785: int rs = bits(insn,21,25); ! 1786: int ra = bits(insn,16,20); ! 1787: int rb = bits(insn,11,15); ! 1788: ! 1789: /* $ra = $rs | ~$rb */ ! 1790: ppc32_load_gpr(b,X86_EBX,rb); ! 1791: x86_not_reg(b->jit_ptr,X86_EBX); ! 1792: ppc32_alu_gpr(b,X86_OR,X86_EBX,rs); ! 1793: ppc32_store_gpr(b,ra,X86_EBX); ! 1794: ! 1795: if (insn & 1) ! 1796: ppc32_update_cr0(b); ! 1797: ! 1798: return(0); ! 1799: } ! 1800: ! 1801: /* OR Immediate */ ! 1802: DECLARE_INSN(ORI) ! 1803: { ! 1804: int rs = bits(insn,21,25); ! 1805: int ra = bits(insn,16,20); ! 1806: m_uint16_t imm = bits(insn,0,15); ! 1807: ! 1808: /* $ra = $rs | imm */ ! 1809: ppc32_load_imm(b,X86_EBX,imm); ! 1810: ppc32_alu_gpr(b,X86_OR,X86_EBX,rs); ! 1811: ppc32_store_gpr(b,ra,X86_EBX); ! 1812: return(0); ! 1813: } ! 1814: ! 1815: /* OR Immediate Shifted */ ! 1816: DECLARE_INSN(ORIS) ! 1817: { ! 1818: int rs = bits(insn,21,25); ! 1819: int ra = bits(insn,16,20); ! 1820: m_uint32_t imm = bits(insn,0,15); ! 1821: ! 1822: /* $ra = $rs | (imm << 16) */ ! 1823: ppc32_load_imm(b,X86_EBX,imm << 16); ! 1824: ppc32_alu_gpr(b,X86_OR,X86_EBX,rs); ! 1825: ppc32_store_gpr(b,ra,X86_EBX); ! 1826: return(0); ! 1827: } ! 1828: ! 1829: /* RLWIMI - Rotate Left Word Immediate then Mask Insert */ ! 1830: DECLARE_INSN(RLWIMI) ! 1831: { ! 1832: int rs = bits(insn,21,25); ! 1833: int ra = bits(insn,16,20); ! 1834: int sh = bits(insn,11,15); ! 1835: int mb = bits(insn,6,10); ! 1836: int me = bits(insn,1,5); ! 1837: register m_uint32_t mask; ! 1838: ! 1839: mask = ppc32_rotate_mask(mb,me); ! 1840: ! 1841: /* Apply inverse mask to %eax "ra" */ ! 1842: ppc32_load_gpr(b,X86_EAX,ra); ! 1843: if (mask != 0) ! 1844: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,~mask); ! 1845: ! 1846: /* Rotate %ebx ("rs") of "sh" bits and apply the mask */ ! 1847: ppc32_load_gpr(b,X86_EBX,rs); ! 1848: ! 1849: if (sh != 0) ! 1850: x86_shift_reg_imm(b->jit_ptr,X86_ROL,X86_EBX,sh); ! 1851: ! 1852: if (mask != 0xFFFFFFFF) ! 1853: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,mask); ! 1854: ! 1855: /* Store the result */ ! 1856: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EBX,X86_EAX); ! 1857: ppc32_store_gpr(b,ra,X86_EBX); ! 1858: ! 1859: if (insn & 1) ! 1860: ppc32_update_cr0(b); ! 1861: ! 1862: return(0); ! 1863: } ! 1864: ! 1865: /* RLWINM - Rotate Left Word Immediate AND with Mask */ ! 1866: DECLARE_INSN(RLWINM) ! 1867: { ! 1868: int rs = bits(insn,21,25); ! 1869: int ra = bits(insn,16,20); ! 1870: int sh = bits(insn,11,15); ! 1871: int mb = bits(insn,6,10); ! 1872: int me = bits(insn,1,5); ! 1873: register m_uint32_t mask; ! 1874: ! 1875: mask = ppc32_rotate_mask(mb,me); ! 1876: ! 1877: /* Rotate %ebx ("rs") of "sh" bits and apply the mask */ ! 1878: ppc32_load_gpr(b,X86_EBX,rs); ! 1879: ! 1880: if (sh != 0) ! 1881: x86_shift_reg_imm(b->jit_ptr,X86_ROL,X86_EBX,sh); ! 1882: ! 1883: if (mask != 0xFFFFFFFF) ! 1884: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,mask); ! 1885: ! 1886: ppc32_store_gpr(b,ra,X86_EBX); ! 1887: ! 1888: if (insn & 1) { ! 1889: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1890: ppc32_update_cr0(b); ! 1891: } ! 1892: ! 1893: return(0); ! 1894: } ! 1895: ! 1896: /* RLWNM - Rotate Left Word then Mask Insert */ ! 1897: DECLARE_INSN(RLWNM) ! 1898: { ! 1899: int rs = bits(insn,21,25); ! 1900: int ra = bits(insn,16,20); ! 1901: int rb = bits(insn,11,15); ! 1902: int mb = bits(insn,6,10); ! 1903: int me = bits(insn,1,5); ! 1904: register m_uint32_t mask; ! 1905: ! 1906: mask = ppc32_rotate_mask(mb,me); ! 1907: ! 1908: /* Load the shift register ("sh") */ ! 1909: ppc32_load_gpr(b,X86_ECX,rb); ! 1910: ! 1911: /* Rotate %ebx ("rs") and apply the mask */ ! 1912: ppc32_load_gpr(b,X86_EBX,rs); ! 1913: x86_shift_reg(b->jit_ptr,X86_ROL,X86_EBX); ! 1914: ! 1915: if (mask != 0xFFFFFFFF) ! 1916: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,mask); ! 1917: ! 1918: ppc32_store_gpr(b,ra,X86_EBX); ! 1919: ! 1920: if (insn & 1) { ! 1921: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1922: ppc32_update_cr0(b); ! 1923: } ! 1924: ! 1925: return(0); ! 1926: } ! 1927: ! 1928: /* Shift Left Word */ ! 1929: DECLARE_INSN(SLW) ! 1930: { ! 1931: int rs = bits(insn,21,25); ! 1932: int ra = bits(insn,16,20); ! 1933: int rb = bits(insn,11,15); ! 1934: u_char *test1; ! 1935: ! 1936: /* If count >= 32, then null result */ ! 1937: ppc32_load_gpr(b,X86_ECX,rb); ! 1938: x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EBX); ! 1939: ! 1940: x86_test_reg_imm(b->jit_ptr,X86_ECX,0x20); ! 1941: test1 = b->jit_ptr; ! 1942: x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); ! 1943: ! 1944: ppc32_load_gpr(b,X86_EBX,rs); ! 1945: x86_shift_reg(b->jit_ptr,X86_SHL,X86_EBX); ! 1946: ! 1947: /* Store the result */ ! 1948: x86_patch(test1,b->jit_ptr); ! 1949: ppc32_store_gpr(b,ra,X86_EBX); ! 1950: ! 1951: if (insn & 1) { ! 1952: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1953: ppc32_update_cr0(b); ! 1954: } ! 1955: ! 1956: return(0); ! 1957: } ! 1958: ! 1959: /* SRAWI - Shift Right Algebraic Word Immediate */ ! 1960: DECLARE_INSN(SRAWI) ! 1961: { ! 1962: int rs = bits(insn,21,25); ! 1963: int ra = bits(insn,16,20); ! 1964: int sh = bits(insn,11,15); ! 1965: register m_uint32_t mask; ! 1966: ! 1967: mask = ~(0xFFFFFFFFU << sh); ! 1968: ! 1969: /* $ra = (int32)$rs >> sh */ ! 1970: ppc32_load_gpr(b,X86_EBX,rs); ! 1971: x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EBX,4); ! 1972: x86_shift_reg_imm(b->jit_ptr,X86_SAR,X86_EBX,sh); ! 1973: ppc32_store_gpr(b,ra,X86_EBX); ! 1974: ! 1975: /* test the sign-bit of gpr[rs] */ ! 1976: x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI); ! 1977: x86_set_reg(b->jit_ptr,X86_CC_LT,X86_EAX,TRUE); ! 1978: ! 1979: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,mask); ! 1980: x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_ECX,TRUE); ! 1981: ! 1982: x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_ECX,X86_EAX); ! 1983: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ECX,0x1); ! 1984: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_ECX,4); ! 1985: ! 1986: if (insn & 1) { ! 1987: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 1988: ppc32_update_cr0(b); ! 1989: } ! 1990: ! 1991: return(0); ! 1992: } ! 1993: ! 1994: /* Shift Right Word */ ! 1995: DECLARE_INSN(SRW) ! 1996: { ! 1997: int rs = bits(insn,21,25); ! 1998: int ra = bits(insn,16,20); ! 1999: int rb = bits(insn,11,15); ! 2000: u_char *test1; ! 2001: ! 2002: /* If count >= 32, then null result */ ! 2003: ppc32_load_gpr(b,X86_ECX,rb); ! 2004: x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EBX); ! 2005: ! 2006: x86_test_reg_imm(b->jit_ptr,X86_ECX,0x20); ! 2007: test1 = b->jit_ptr; ! 2008: x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); ! 2009: ! 2010: ppc32_load_gpr(b,X86_EBX,rs); ! 2011: x86_shift_reg(b->jit_ptr,X86_SHR,X86_EBX); ! 2012: ! 2013: /* Store the result */ ! 2014: x86_patch(test1,b->jit_ptr); ! 2015: ppc32_store_gpr(b,ra,X86_EBX); ! 2016: ! 2017: if (insn & 1) { ! 2018: x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); ! 2019: ppc32_update_cr0(b); ! 2020: } ! 2021: ! 2022: return(0); ! 2023: } ! 2024: ! 2025: /* STB - Store Byte */ ! 2026: DECLARE_INSN(STB) ! 2027: { ! 2028: int rs = bits(insn,21,25); ! 2029: int ra = bits(insn,16,20); ! 2030: m_uint16_t offset = bits(insn,0,15); ! 2031: ! 2032: //ppc32_emit_memop(b,PPC_MEMOP_STB,ra,offset,rs,0); ! 2033: ppc32_emit_memop_fast(b,1,PPC_MEMOP_STB,ra,offset,rs,ppc32_memop_fast_stb); ! 2034: return(0); ! 2035: } ! 2036: ! 2037: /* STBU - Store Byte with Update */ ! 2038: DECLARE_INSN(STBU) ! 2039: { ! 2040: int rs = bits(insn,21,25); ! 2041: int ra = bits(insn,16,20); ! 2042: m_uint16_t offset = bits(insn,0,15); ! 2043: ! 2044: ppc32_emit_memop(b,PPC_MEMOP_STB,ra,offset,rs,1); ! 2045: return(0); ! 2046: } ! 2047: ! 2048: /* STBUX - Store Byte with Update Indexed */ ! 2049: DECLARE_INSN(STBUX) ! 2050: { ! 2051: int rs = bits(insn,21,25); ! 2052: int ra = bits(insn,16,20); ! 2053: int rb = bits(insn,11,15); ! 2054: ! 2055: ppc32_emit_memop_idx(b,PPC_MEMOP_STB,ra,rb,rs,1); ! 2056: return(0); ! 2057: } ! 2058: ! 2059: /* STBUX - Store Byte Indexed */ ! 2060: DECLARE_INSN(STBX) ! 2061: { ! 2062: int rs = bits(insn,21,25); ! 2063: int ra = bits(insn,16,20); ! 2064: int rb = bits(insn,11,15); ! 2065: ! 2066: ppc32_emit_memop_idx(b,PPC_MEMOP_STB,ra,rb,rs,0); ! 2067: return(0); ! 2068: } ! 2069: ! 2070: /* STH - Store Half-Word */ ! 2071: DECLARE_INSN(STH) ! 2072: { ! 2073: int rs = bits(insn,21,25); ! 2074: int ra = bits(insn,16,20); ! 2075: m_uint16_t offset = bits(insn,0,15); ! 2076: ! 2077: ppc32_emit_memop(b,PPC_MEMOP_STH,ra,offset,rs,0); ! 2078: return(0); ! 2079: } ! 2080: ! 2081: /* STHU - Store Half-Word with Update */ ! 2082: DECLARE_INSN(STHU) ! 2083: { ! 2084: int rs = bits(insn,21,25); ! 2085: int ra = bits(insn,16,20); ! 2086: m_uint16_t offset = bits(insn,0,15); ! 2087: ! 2088: ppc32_emit_memop(b,PPC_MEMOP_STH,ra,offset,rs,1); ! 2089: return(0); ! 2090: } ! 2091: ! 2092: /* STHUX - Store Half-Word with Update Indexed */ ! 2093: DECLARE_INSN(STHUX) ! 2094: { ! 2095: int rs = bits(insn,21,25); ! 2096: int ra = bits(insn,16,20); ! 2097: int rb = bits(insn,11,15); ! 2098: ! 2099: ppc32_emit_memop_idx(b,PPC_MEMOP_STH,ra,rb,rs,1); ! 2100: return(0); ! 2101: } ! 2102: ! 2103: /* STHUX - Store Half-Word Indexed */ ! 2104: DECLARE_INSN(STHX) ! 2105: { ! 2106: int rs = bits(insn,21,25); ! 2107: int ra = bits(insn,16,20); ! 2108: int rb = bits(insn,11,15); ! 2109: ! 2110: ppc32_emit_memop_idx(b,PPC_MEMOP_STH,ra,rb,rs,0); ! 2111: return(0); ! 2112: } ! 2113: ! 2114: /* STW - Store Word */ ! 2115: DECLARE_INSN(STW) ! 2116: { ! 2117: int rs = bits(insn,21,25); ! 2118: int ra = bits(insn,16,20); ! 2119: m_uint16_t offset = bits(insn,0,15); ! 2120: ! 2121: //ppc32_emit_memop(b,PPC_MEMOP_STW,ra,offset,rs,0); ! 2122: ppc32_emit_memop_fast(b,1,PPC_MEMOP_STW,ra,offset,rs,ppc32_memop_fast_stw); ! 2123: return(0); ! 2124: } ! 2125: ! 2126: /* STWU - Store Word with Update */ ! 2127: DECLARE_INSN(STWU) ! 2128: { ! 2129: int rs = bits(insn,21,25); ! 2130: int ra = bits(insn,16,20); ! 2131: m_uint16_t offset = bits(insn,0,15); ! 2132: ! 2133: ppc32_emit_memop(b,PPC_MEMOP_STW,ra,offset,rs,1); ! 2134: return(0); ! 2135: } ! 2136: ! 2137: /* STWUX - Store Word with Update Indexed */ ! 2138: DECLARE_INSN(STWUX) ! 2139: { ! 2140: int rs = bits(insn,21,25); ! 2141: int ra = bits(insn,16,20); ! 2142: int rb = bits(insn,11,15); ! 2143: ! 2144: ppc32_emit_memop_idx(b,PPC_MEMOP_STW,ra,rb,rs,1); ! 2145: return(0); ! 2146: } ! 2147: ! 2148: /* STWUX - Store Word Indexed */ ! 2149: DECLARE_INSN(STWX) ! 2150: { ! 2151: int rs = bits(insn,21,25); ! 2152: int ra = bits(insn,16,20); ! 2153: int rb = bits(insn,11,15); ! 2154: ! 2155: ppc32_emit_memop_idx(b,PPC_MEMOP_STW,ra,rb,rs,0); ! 2156: return(0); ! 2157: } ! 2158: ! 2159: /* SUBF - Subtract From */ ! 2160: DECLARE_INSN(SUBF) ! 2161: { ! 2162: int rd = bits(insn,21,25); ! 2163: int ra = bits(insn,16,20); ! 2164: int rb = bits(insn,11,15); ! 2165: ! 2166: /* $rd = $rb - $rb */ ! 2167: ppc32_load_gpr(b,X86_EBX,rb); ! 2168: ppc32_alu_gpr(b,X86_SUB,X86_EBX,ra); ! 2169: ppc32_store_gpr(b,rd,X86_EBX); ! 2170: ! 2171: if (insn & 1) ! 2172: ppc32_update_cr0(b); ! 2173: ! 2174: return(0); ! 2175: } ! 2176: ! 2177: /* SUBFC - Subtract From Carrying */ ! 2178: DECLARE_INSN(SUBFC) ! 2179: { ! 2180: int rd = bits(insn,21,25); ! 2181: int ra = bits(insn,16,20); ! 2182: int rb = bits(insn,11,15); ! 2183: ! 2184: /* ~$ra + 1 */ ! 2185: ppc32_load_gpr(b,X86_ESI,ra); ! 2186: x86_not_reg(b->jit_ptr,X86_ESI); ! 2187: x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESI,1); ! 2188: x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); ! 2189: ! 2190: /* add $rb */ ! 2191: ppc32_alu_gpr(b,X86_ADD,X86_ESI,rb); ! 2192: x86_set_reg(b->jit_ptr,X86_CC_C,X86_ECX,FALSE); ! 2193: ! 2194: ppc32_store_gpr(b,rd,X86_ESI); ! 2195: ! 2196: /* store the carry flag */ ! 2197: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); ! 2198: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); ! 2199: ! 2200: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); ! 2201: ! 2202: /* update cr0 */ ! 2203: if (insn & 1) { ! 2204: x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI); ! 2205: ppc32_update_cr0(b); ! 2206: } ! 2207: ! 2208: return(0); ! 2209: } ! 2210: ! 2211: /* SUBFE - Subtract From Extended */ ! 2212: DECLARE_INSN(SUBFE) ! 2213: { ! 2214: int rd = bits(insn,21,25); ! 2215: int ra = bits(insn,16,20); ! 2216: int rb = bits(insn,11,15); ! 2217: ! 2218: /* ~$ra + carry */ ! 2219: ppc32_load_gpr(b,X86_ESI,ra); ! 2220: x86_not_reg(b->jit_ptr,X86_ESI); ! 2221: x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_ESI, ! 2222: X86_EDI,OFFSET(cpu_ppc_t,xer_ca)); ! 2223: x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); ! 2224: ! 2225: /* add $rb */ ! 2226: ppc32_alu_gpr(b,X86_ADD,X86_ESI,rb); ! 2227: x86_set_reg(b->jit_ptr,X86_CC_C,X86_ECX,FALSE); ! 2228: ! 2229: ppc32_store_gpr(b,rd,X86_ESI); ! 2230: ! 2231: /* store the carry flag */ ! 2232: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); ! 2233: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); ! 2234: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); ! 2235: ! 2236: /* update cr0 */ ! 2237: if (insn & 1) { ! 2238: x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI); ! 2239: ppc32_update_cr0(b); ! 2240: } ! 2241: ! 2242: return(0); ! 2243: } ! 2244: ! 2245: /* SUBFIC - Subtract From Immediate Carrying */ ! 2246: DECLARE_INSN(SUBFIC) ! 2247: { ! 2248: int rd = bits(insn,21,25); ! 2249: int ra = bits(insn,16,20); ! 2250: m_uint16_t imm = bits(insn,0,15); ! 2251: m_uint32_t tmp = sign_extend_32(imm,16); ! 2252: ! 2253: /* ~$ra + 1 */ ! 2254: ppc32_load_gpr(b,X86_ESI,ra); ! 2255: x86_not_reg(b->jit_ptr,X86_ESI); ! 2256: x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESI,1); ! 2257: x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); ! 2258: ! 2259: /* add sign-extended $immediate */ ! 2260: x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESI,tmp); ! 2261: x86_set_reg(b->jit_ptr,X86_CC_C,X86_ECX,FALSE); ! 2262: ! 2263: ppc32_store_gpr(b,rd,X86_ESI); ! 2264: ! 2265: /* store the carry flag */ ! 2266: x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); ! 2267: x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); ! 2268: ! 2269: x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); ! 2270: return(0); ! 2271: } ! 2272: ! 2273: /* SYNC - Synchronize */ ! 2274: DECLARE_INSN(SYNC) ! 2275: { ! 2276: return(0); ! 2277: } ! 2278: ! 2279: /* XOR */ ! 2280: DECLARE_INSN(XOR) ! 2281: { ! 2282: int rs = bits(insn,21,25); ! 2283: int ra = bits(insn,16,20); ! 2284: int rb = bits(insn,11,15); ! 2285: ! 2286: ppc32_load_gpr(b,X86_EBX,rs); ! 2287: ppc32_alu_gpr(b,X86_XOR,X86_EBX,rb); ! 2288: ppc32_store_gpr(b,ra,X86_EBX); ! 2289: ! 2290: if (insn & 1) ! 2291: ppc32_update_cr0(b); ! 2292: ! 2293: return(0); ! 2294: } ! 2295: ! 2296: /* XORI - XOR Immediate */ ! 2297: DECLARE_INSN(XORI) ! 2298: { ! 2299: int rs = bits(insn,21,25); ! 2300: int ra = bits(insn,16,20); ! 2301: m_uint32_t imm = bits(insn,0,15); ! 2302: ! 2303: ppc32_load_imm(b,X86_EBX,imm); ! 2304: ppc32_alu_gpr(b,X86_XOR,X86_EBX,rs); ! 2305: ppc32_store_gpr(b,ra,X86_EBX); ! 2306: return(0); ! 2307: } ! 2308: ! 2309: /* XORIS - XOR Immediate Shifted */ ! 2310: DECLARE_INSN(XORIS) ! 2311: { ! 2312: int rs = bits(insn,21,25); ! 2313: int ra = bits(insn,16,20); ! 2314: m_uint32_t imm = bits(insn,0,15); ! 2315: ! 2316: ppc32_load_imm(b,X86_EBX,imm << 16); ! 2317: ppc32_alu_gpr(b,X86_XOR,X86_EBX,rs); ! 2318: ppc32_store_gpr(b,ra,X86_EBX); ! 2319: return(0); ! 2320: } ! 2321: ! 2322: /* PPC instruction array */ ! 2323: struct ppc32_insn_tag ppc32_insn_tags[] = { ! 2324: { ppc32_emit_BLR , 0xfffffffe , 0x4e800020 }, ! 2325: { ppc32_emit_BCTR , 0xfffffffe , 0x4e800420 }, ! 2326: { ppc32_emit_MFLR , 0xfc1fffff , 0x7c0802a6 }, ! 2327: { ppc32_emit_MTLR , 0xfc1fffff , 0x7c0803a6 }, ! 2328: { ppc32_emit_MFCTR , 0xfc1fffff , 0x7c0902a6 }, ! 2329: { ppc32_emit_MTCTR , 0xfc1fffff , 0x7c0903a6 }, ! 2330: { ppc32_emit_MFTBL , 0xfc1ff7ff , 0x7c0c42e6 }, ! 2331: { ppc32_emit_MFTBU , 0xfc1ff7ff , 0x7c0d42e6 }, ! 2332: { ppc32_emit_ADD , 0xfc0007fe , 0x7c000214 }, ! 2333: { ppc32_emit_ADDC , 0xfc0007fe , 0x7c000014 }, ! 2334: { ppc32_emit_ADDE , 0xfc0007fe , 0x7c000114 }, ! 2335: { ppc32_emit_ADDI , 0xfc000000 , 0x38000000 }, ! 2336: { ppc32_emit_ADDIC , 0xfc000000 , 0x30000000 }, ! 2337: { ppc32_emit_ADDIC_dot , 0xfc000000 , 0x34000000 }, ! 2338: { ppc32_emit_ADDIS , 0xfc000000 , 0x3c000000 }, ! 2339: { ppc32_emit_AND , 0xfc0007fe , 0x7c000038 }, ! 2340: { ppc32_emit_ANDC , 0xfc0007fe , 0x7c000078 }, ! 2341: { ppc32_emit_ANDI , 0xfc000000 , 0x70000000 }, ! 2342: { ppc32_emit_ANDIS , 0xfc000000 , 0x74000000 }, ! 2343: { ppc32_emit_B , 0xfc000003 , 0x48000000 }, ! 2344: { ppc32_emit_BA , 0xfc000003 , 0x48000002 }, ! 2345: { ppc32_emit_BL , 0xfc000003 , 0x48000001 }, ! 2346: { ppc32_emit_BLA , 0xfc000003 , 0x48000003 }, ! 2347: { ppc32_emit_BCC , 0xfe800000 , 0x40800000 }, ! 2348: { ppc32_emit_BC , 0xfc000000 , 0x40000000 }, ! 2349: { ppc32_emit_BCLR , 0xfc00fffe , 0x4c000020 }, ! 2350: { ppc32_emit_CMP , 0xfc6007ff , 0x7c000000 }, ! 2351: { ppc32_emit_CMPI , 0xfc600000 , 0x2c000000 }, ! 2352: { ppc32_emit_CMPL , 0xfc6007ff , 0x7c000040 }, ! 2353: { ppc32_emit_CMPLI , 0xfc600000 , 0x28000000 }, ! 2354: { ppc32_emit_CRAND , 0xfc0007ff , 0x4c000202 }, ! 2355: { ppc32_emit_CRANDC , 0xfc0007ff , 0x4c000102 }, ! 2356: { ppc32_emit_CREQV , 0xfc0007ff , 0x4c000242 }, ! 2357: { ppc32_emit_CRNAND , 0xfc0007ff , 0x4c0001c2 }, ! 2358: { ppc32_emit_CRNOR , 0xfc0007ff , 0x4c000042 }, ! 2359: { ppc32_emit_CROR , 0xfc0007ff , 0x4c000382 }, ! 2360: { ppc32_emit_CRORC , 0xfc0007ff , 0x4c000342 }, ! 2361: { ppc32_emit_CRXOR , 0xfc0007ff , 0x4c000182 }, ! 2362: { ppc32_emit_DIVWU , 0xfc0007fe , 0x7c000396 }, ! 2363: { ppc32_emit_EQV , 0xfc0007fe , 0x7c000238 }, ! 2364: { ppc32_emit_EXTSB , 0xfc00fffe , 0x7c000774 }, ! 2365: { ppc32_emit_EXTSH , 0xfc00fffe , 0x7c000734 }, ! 2366: { ppc32_emit_LBZ , 0xfc000000 , 0x88000000 }, ! 2367: { ppc32_emit_LBZU , 0xfc000000 , 0x8c000000 }, ! 2368: { ppc32_emit_LBZUX , 0xfc0007ff , 0x7c0000ee }, ! 2369: { ppc32_emit_LBZX , 0xfc0007ff , 0x7c0000ae }, ! 2370: { ppc32_emit_LHA , 0xfc000000 , 0xa8000000 }, ! 2371: { ppc32_emit_LHAU , 0xfc000000 , 0xac000000 }, ! 2372: { ppc32_emit_LHAUX , 0xfc0007ff , 0x7c0002ee }, ! 2373: { ppc32_emit_LHAX , 0xfc0007ff , 0x7c0002ae }, ! 2374: { ppc32_emit_LHZ , 0xfc000000 , 0xa0000000 }, ! 2375: { ppc32_emit_LHZU , 0xfc000000 , 0xa4000000 }, ! 2376: { ppc32_emit_LHZUX , 0xfc0007ff , 0x7c00026e }, ! 2377: { ppc32_emit_LHZX , 0xfc0007ff , 0x7c00022e }, ! 2378: { ppc32_emit_LWZ , 0xfc000000 , 0x80000000 }, ! 2379: { ppc32_emit_LWZU , 0xfc000000 , 0x84000000 }, ! 2380: { ppc32_emit_LWZUX , 0xfc0007ff , 0x7c00006e }, ! 2381: { ppc32_emit_LWZX , 0xfc0007ff , 0x7c00002e }, ! 2382: { ppc32_emit_MCRF , 0xfc63ffff , 0x4c000000 }, ! 2383: { ppc32_emit_MFCR , 0xfc1fffff , 0x7c000026 }, ! 2384: { ppc32_emit_MFMSR , 0xfc1fffff , 0x7c0000a6 }, ! 2385: { ppc32_emit_MFSR , 0xfc10ffff , 0x7c0004a6 }, ! 2386: { ppc32_emit_MTCRF , 0xfc100fff , 0x7c000120 }, ! 2387: { ppc32_emit_MULHW , 0xfc0007fe , 0x7c000096 }, ! 2388: { ppc32_emit_MULHWU , 0xfc0007fe , 0x7c000016 }, ! 2389: { ppc32_emit_MULLI , 0xfc000000 , 0x1c000000 }, ! 2390: { ppc32_emit_MULLW , 0xfc0007fe , 0x7c0001d6 }, ! 2391: { ppc32_emit_NAND , 0xfc0007fe , 0x7c0003b8 }, ! 2392: { ppc32_emit_NEG , 0xfc00fffe , 0x7c0000d0 }, ! 2393: { ppc32_emit_NOR , 0xfc0007fe , 0x7c0000f8 }, ! 2394: { ppc32_emit_OR , 0xfc0007fe , 0x7c000378 }, ! 2395: { ppc32_emit_ORC , 0xfc0007fe , 0x7c000338 }, ! 2396: { ppc32_emit_ORI , 0xfc000000 , 0x60000000 }, ! 2397: { ppc32_emit_ORIS , 0xfc000000 , 0x64000000 }, ! 2398: { ppc32_emit_RLWIMI , 0xfc000000 , 0x50000000 }, ! 2399: { ppc32_emit_RLWINM , 0xfc000000 , 0x54000000 }, ! 2400: { ppc32_emit_RLWNM , 0xfc000000 , 0x5c000000 }, ! 2401: { ppc32_emit_SLW , 0xfc0007fe , 0x7c000030 }, ! 2402: { ppc32_emit_SRAWI , 0xfc0007fe , 0x7c000670 }, ! 2403: { ppc32_emit_SRW , 0xfc0007fe , 0x7c000430 }, ! 2404: { ppc32_emit_STB , 0xfc000000 , 0x98000000 }, ! 2405: { ppc32_emit_STBU , 0xfc000000 , 0x9c000000 }, ! 2406: { ppc32_emit_STBUX , 0xfc0007ff , 0x7c0001ee }, ! 2407: { ppc32_emit_STBX , 0xfc0007ff , 0x7c0001ae }, ! 2408: { ppc32_emit_STH , 0xfc000000 , 0xb0000000 }, ! 2409: { ppc32_emit_STHU , 0xfc000000 , 0xb4000000 }, ! 2410: { ppc32_emit_STHUX , 0xfc0007ff , 0x7c00036e }, ! 2411: { ppc32_emit_STHX , 0xfc0007ff , 0x7c00032e }, ! 2412: { ppc32_emit_STW , 0xfc000000 , 0x90000000 }, ! 2413: { ppc32_emit_STWU , 0xfc000000 , 0x94000000 }, ! 2414: { ppc32_emit_STWUX , 0xfc0007ff , 0x7c00016e }, ! 2415: { ppc32_emit_STWX , 0xfc0007ff , 0x7c00012e }, ! 2416: { ppc32_emit_SUBF , 0xfc0007fe , 0x7c000050 }, ! 2417: { ppc32_emit_SUBFC , 0xfc0007fe , 0x7c000010 }, ! 2418: { ppc32_emit_SUBFE , 0xfc0007fe , 0x7c000110 }, ! 2419: { ppc32_emit_SUBFIC , 0xfc000000 , 0x20000000 }, ! 2420: { ppc32_emit_SYNC , 0xffffffff , 0x7c0004ac }, ! 2421: { ppc32_emit_XOR , 0xfc0007fe , 0x7c000278 }, ! 2422: { ppc32_emit_XORI , 0xfc000000 , 0x68000000 }, ! 2423: { ppc32_emit_XORIS , 0xfc000000 , 0x6c000000 }, ! 2424: { ppc32_emit_unknown , 0x00000000 , 0x00000000 }, ! 2425: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.