--- trunk/src/cpus/cpu_ppc_instr.c 2007/10/08 16:19:37 22 +++ trunk/src/cpus/cpu_ppc_instr.c 2007/10/08 16:20:40 30 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu_ppc_instr.c,v 1.59 2006/02/09 22:40:27 debug Exp $ + * $Id: cpu_ppc_instr.c,v 1.71 2006/07/26 23:21:48 debug Exp $ * * POWER/PowerPC instructions. * @@ -987,7 +987,7 @@ X(fctiwz) { struct ieee_float_value frb; - int32_t res = 0; + uint32_t res = 0; CHECK_FOR_FPU_EXCEPTION; @@ -1411,6 +1411,35 @@ /* + * rldicl: + * + * arg[0] = copy of the instruction word + */ +X(rldicl) +{ + int rs = (ic->arg[0] >> 21) & 31; + int ra = (ic->arg[0] >> 16) & 31; + int sh = ((ic->arg[0] >> 11) & 31) | ((ic->arg[0] & 2) << 4); + int mb = ((ic->arg[0] >> 6) & 31) | (ic->arg[0] & 0x20); + int rc = ic->arg[0] & 1; + uint64_t tmp = cpu->cd.ppc.gpr[rs], tmp2; + /* TODO: Fix this, its performance is awful: */ + while (sh-- != 0) { + int b = (tmp >> 63) & 1; + tmp = (tmp << 1) | b; + } + tmp2 = 0; + while (mb <= 63) { + tmp |= ((uint64_t)1 << (63-mb)); + mb ++; + } + cpu->cd.ppc.gpr[ra] = tmp & tmp2; + if (rc) + update_cr0(cpu, cpu->cd.ppc.gpr[ra]); +} + + +/* * rldicr: * * arg[0] = copy of the instruction word @@ -1437,6 +1466,37 @@ /* + * rldimi: + * + * arg[0] = copy of the instruction word + */ +X(rldimi) +{ + uint32_t iw = ic->arg[0]; + int rs = (iw >> 21) & 31, ra = (iw >> 16) & 31; + int sh = ((iw >> 11) & 31) | ((iw & 2) << 4); + int mb = ((iw >> 6) & 31) | (iw & 0x20); + int rc = ic->arg[0] & 1; + int m; + uint64_t tmp, s = cpu->cd.ppc.gpr[rs]; + /* TODO: Fix this, its performance is awful: */ + while (sh-- != 0) { + int b = (s >> 63) & 1; + s = (s << 1) | b; + } + m = mb; tmp = 0; + do { + tmp |= ((uint64_t)1 << (63-m)); + m ++; + } while (m != 63 - sh); + cpu->cd.ppc.gpr[ra] &= ~tmp; + cpu->cd.ppc.gpr[ra] |= (tmp & s); + if (rc) + update_cr0(cpu, cpu->cd.ppc.gpr[ra]); +} + + +/* * rlwnm: * * arg[0] = ptr to ra @@ -1673,7 +1733,7 @@ /* - * rfi: Return from Interrupt + * rfi[d]: Return from Interrupt */ X(rfi) { @@ -1687,6 +1747,20 @@ cpu->pc = cpu->cd.ppc.spr[SPR_SRR0]; quick_pc_to_pointers(cpu); } +X(rfid) +{ + uint64_t tmp, mask = 0x800000000000ff73ULL; + + reg_access_msr(cpu, &tmp, 0, 0); + tmp &= ~mask; + tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & mask); + reg_access_msr(cpu, &tmp, 1, 0); + + cpu->pc = cpu->cd.ppc.spr[SPR_SRR0]; + if (!(tmp & PPC_MSR_SF)) + cpu->pc = (uint32_t)cpu->pc; + quick_pc_to_pointers(cpu); +} /* @@ -1715,10 +1789,13 @@ * mtmsr: Move To MSR * * arg[0] = pointer to source register + * arg[1] = page offset of the next instruction + * arg[2] = 0 for 32-bit (mtmsr), 1 for 64-bit (mtmsrd) */ X(mtmsr) { MODE_uint_t old_pc; + uint64_t x = reg(ic->arg[0]); /* TODO: check permission! */ @@ -1726,7 +1803,13 @@ cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1]; old_pc = cpu->pc; - reg_access_msr(cpu, (uint64_t*)ic->arg[0], 1, 1); + if (!ic->arg[2]) { + uint64_t y; + reg_access_msr(cpu, &y, 0, 0); + x = (y & 0xffffffff00000000ULL) | (x & 0xffffffffULL); + } + + reg_access_msr(cpu, &x, 1, 1); /* * Super-ugly hack: If the pc wasn't changed (i.e. if there was no @@ -1948,7 +2031,7 @@ DOT2(extsh) X(extsw) { #ifdef MODE32 - fatal("TODO: extsw: invalid instruction\n"); exit(1); + fatal("TODO: extsw: invalid instruction\n"); #else reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]); #endif @@ -1957,6 +2040,10 @@ X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) << (reg(ic->arg[1]) & 31); } DOT2(slw) +X(sld) {int sa = reg(ic->arg[1]) & 127; + if (sa >= 64) reg(ic->arg[2]) = 0; + else reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) << (sa & 63); } +DOT2(sld) X(sraw) { uint32_t tmp = reg(ic->arg[0]); @@ -1995,6 +2082,8 @@ DOT2(orc) X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); } DOT2(xor) +X(eqv) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) ^ reg(ic->arg[1])); } +DOT2(eqv) /* @@ -2388,7 +2477,7 @@ */ X(tlbia) { - printf("[ tlbia ]\n"); + fatal("[ tlbia ]\n"); cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL); } @@ -2398,6 +2487,7 @@ */ X(tlbie) { + /* fatal("[ tlbie ]\n"); */ cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]), INVALIDATE_VADDR); } @@ -2426,6 +2516,11 @@ X(user_syscall) { useremul_syscall(cpu, ic->arg[0]); + + if (!cpu->running) { + cpu->n_translated_instrs --; + cpu->cd.ppc.next_ic = ¬hing_call; + } } @@ -2436,7 +2531,8 @@ { of_emul(cpu); if (cpu->running == 0) { - cpu->running_translated = 0; + cpu->n_translated_instrs --; + cpu->cd.ppc.next_ic = ¬hing_call; } cpu->pc = cpu->cd.ppc.spr[SPR_LR]; if (cpu->machine->show_trace_tree) @@ -2503,7 +2599,7 @@ /* * ppc_instr_to_be_translated(): * - * Translate an instruction word into an ppc_instr_call. ic is filled in with + * Translate an instruction word into a ppc_instr_call. ic is filled in with * valid data for the translated instruction, or a "nothing" instruction if * there was a translation failure. The newly translated instruction is then * executed. @@ -2514,9 +2610,6 @@ uint32_t iword, mask; unsigned char *page; unsigned char ib[4]; -#ifdef DYNTRANS_BACKEND - int simple = 0; -#endif int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh, xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0, bfa, fp, byterev, nb, mb, me; @@ -2533,7 +2626,22 @@ addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1); /* Read the instruction word from memory: */ - page = cpu->cd.ppc.host_load[addr >> 12]; +#ifdef MODE32 + page = cpu->cd.ppc.host_load[((uint32_t)addr) >> 12]; +#else + { + const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; + const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; + const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1; + uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1; + uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; + uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N- + DYNTRANS_L3N)) & mask3; + struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.ppc.l1_64[x1]; + struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2]; + page = l3->host_load[x3]; + } +#endif if (page != NULL) { /* fatal("TRANSLATION HIT!\n"); */ @@ -2689,6 +2797,7 @@ case PPC_HI6_LHAU: case PPC_HI6_LWZ: case PPC_HI6_LWZU: + case PPC_HI6_LD: case PPC_HI6_LFD: case PPC_HI6_LFS: case PPC_HI6_STB: @@ -2697,6 +2806,7 @@ case PPC_HI6_STHU: case PPC_HI6_STW: case PPC_HI6_STWU: + case PPC_HI6_STD: case PPC_HI6_STFD: case PPC_HI6_STFS: rs = (iword >> 21) & 31; @@ -2713,6 +2823,7 @@ case PPC_HI6_LHZU: load=1; size=1; update=1; break; case PPC_HI6_LWZ: load=1; size=2; break; case PPC_HI6_LWZU: load=1; size=2; update=1; break; + case PPC_HI6_LD: load=1; size=3; break; case PPC_HI6_LFD: load=1; size=3; fp=1;ic->f=instr(lfd);break; case PPC_HI6_LFS: load=1; size=2; fp=1;ic->f=instr(lfs);break; case PPC_HI6_STB: break; @@ -2721,6 +2832,7 @@ case PPC_HI6_STHU: size=1; update=1; break; case PPC_HI6_STW: size=2; break; case PPC_HI6_STWU: size=2; update=1; break; + case PPC_HI6_STD: size=3; break; case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break; case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break; } @@ -2890,6 +3002,10 @@ ic->f = instr(rfi); break; + case PPC_19_RFID: + ic->f = instr(rfid); + break; + case PPC_19_MCRF: bf = (iword >> 23) & 7; bfa = (iword >> 18) & 7; @@ -2979,11 +3095,17 @@ xo = (iword >> 2) & 7; switch (xo) { + case PPC_30_RLDICL: case PPC_30_RLDICR: - ic->f = instr(rldicr); + case PPC_30_RLDIMI: + switch (xo) { + case PPC_30_RLDICL: ic->f = instr(rldicl); break; + case PPC_30_RLDICR: ic->f = instr(rldicr); break; + case PPC_30_RLDIMI: ic->f = instr(rldimi); break; + } ic->arg[0] = iword; if (cpu->cd.ppc.bits == 32) { - fatal("TODO: rldicr in 32-bit mode?\n"); + fatal("TODO: rld* in 32-bit mode?\n"); goto bad; } break; @@ -3077,6 +3199,7 @@ break; case PPC_31_MTMSR: + case PPC_31_MTMSRD: rs = (iword >> 21) & 31; l_bit = (iword >> 16) & 1; if (l_bit) { @@ -3085,6 +3208,7 @@ } ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]); ic->arg[1] = (addr & 0xfff) + 4; + ic->arg[2] = xo == PPC_31_MTMSRD; ic->f = instr(mtmsr); break; @@ -3150,6 +3274,7 @@ break; case PPC_31_SYNC: + case PPC_31_DSSALL: case PPC_31_EIEIO: case PPC_31_DCBST: case PPC_31_DCBTST: @@ -3358,6 +3483,7 @@ case PPC_31_EXTSH: case PPC_31_EXTSW: case PPC_31_SLW: + case PPC_31_SLD: case PPC_31_SRAW: case PPC_31_SRW: case PPC_31_AND: @@ -3367,6 +3493,7 @@ case PPC_31_OR: case PPC_31_ORC: case PPC_31_XOR: + case PPC_31_EQV: rs = (iword >> 21) & 31; ra = (iword >> 16) & 31; rb = (iword >> 11) & 31; @@ -3381,6 +3508,8 @@ rc_f = instr(extsw_dot); break; case PPC_31_SLW: ic->f = instr(slw); rc_f = instr(slw_dot); break; + case PPC_31_SLD: ic->f = instr(sld); + rc_f = instr(sld_dot); break; case PPC_31_SRAW: ic->f = instr(sraw); rc_f = instr(sraw_dot); break; case PPC_31_SRW: ic->f = instr(srw); @@ -3400,6 +3529,8 @@ rc_f = instr(orc_dot); break; case PPC_31_XOR: ic->f = instr(xor); rc_f = instr(xor_dot); break; + case PPC_31_EQV: ic->f = instr(eqv); + rc_f = instr(eqv_dot); break; } ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]); ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]); @@ -3492,21 +3623,33 @@ } break; - case 359: - fatal("[ TODO: 359 ]\n"); - ic->f = instr(nop); - break; case PPC_31_LVX: - fatal("[ TODO: lvx ]\n"); - ic->f = instr(nop); - break; + case PPC_31_LVXL: case PPC_31_STVX: - fatal("[ TODO: stvx ]\n"); - ic->f = instr(nop); - break; case PPC_31_STVXL: - fatal("[ TODO: stvxl ]\n"); - ic->f = instr(nop); + fatal("[ TODO: altivec load/store ]\n"); + load = 0; + switch (xo) { + case PPC_31_LVX: + case PPC_31_LVXL: + load = 1; break; + } + rs = (iword >> 21) & 31; + ra = (iword >> 16) & 31; + rb = (iword >> 11) & 31; + ic->arg[0] = (size_t)(&cpu->cd.ppc.vr_hi[rs]); + if (ra == 0) + ic->arg[1] = (size_t)(&cpu->cd.ppc.zero); + else + ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]); + ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]); + ic->f = +#ifdef MODE32 + ppc32_loadstore_indexed +#else + ppc_loadstore_indexed +#endif + [3 + 4 * load]; break; default:goto bad;