📄 ppc_opc.c
字号:
/* * PearPC * ppc_opc.cc * * Copyright (C) 2003 Sebastian Biallas (sb@biallas.net) * Copyright (C) 2004 Dainel Foesch (dfoesch@cs.nmsu.edu) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//*#include "debug/tracers.h"#include "cpu/debug.h"#include "io/pic/pic.h"#include "info.h"*/#include <stdio.h>#include "ppc_cpu.h"#include "ppc_exc.h"#include "ppc_e500_exc.h"#include "ppc_mmu.h"#include "ppc_opc.h"#include "ppc_dec.h"#include "tracers.h"#include "debug.h"void ppc_set_msr(uint32 newmsr){/* if ((newmsr & MSR_EE) && !(gCPU.msr & MSR_EE)) { if (pic_check_interrupt()) { gCPU.exception_pending = true; gCPU.ext_exception = true; } }*/ ppc_mmu_tlb_invalidate();#ifndef PPC_CPU_ENABLE_SINGLESTEP if (newmsr & MSR_SE) { PPC_CPU_WARN("MSR[SE] (singlestep enable) set, but compiled w/o SE support.\n"); }#else gCPU.singlestep_ignore = true;#endif if (newmsr & PPC_CPU_UNSUPPORTED_MSR_BITS) { PPC_CPU_ERR("unsupported bits in MSR set: %08x @%08x\n", newmsr & PPC_CPU_UNSUPPORTED_MSR_BITS, gCPU.pc); } if (newmsr & MSR_POW) { // doze(); newmsr &= ~MSR_POW; } gCPU.msr = newmsr; }/* * bx Branch * .435 */void ppc_opc_bx(){ uint32 li; PPC_OPC_TEMPL_I(gCPU.current_opc, li); if (!(gCPU.current_opc & PPC_OPC_AA)) { li += gCPU.pc; } if (gCPU.current_opc & PPC_OPC_LK) { gCPU.lr = gCPU.pc + 4; } gCPU.npc = li;}/* * bcx Branch Conditional * .436 */void ppc_opc_bcx(){ uint32 BO, BI, BD; PPC_OPC_TEMPL_B(gCPU.current_opc, BO, BI, BD); if (!(BO & 4)) { gCPU.ctr--; } bool bo2 = ((BO & 2)?1:0); bool bo8 = ((BO & 8)?1:0); // branch condition true bool cr = ((gCPU.cr & (1<<(31-BI)))?1:0) ; if (((BO & 4) || ((gCPU.ctr!=0) ^ bo2)) && ((BO & 16) || (!(cr ^ bo8)))) { if (!(gCPU.current_opc & PPC_OPC_AA)) { BD += gCPU.pc; } if (gCPU.current_opc & PPC_OPC_LK) { gCPU.lr = gCPU.pc + 4; } gCPU.npc = BD; } //fprintf(stderr,"in %s,BO=0x%x,BI=0x%x,BD=0x%x,cr=0x%x,cr^bo8=0x%x,ctr=0x%x,pc=0x%x\n",__FUNCTION__,BO,BI,BD,gCPU.cr,(cr ^ bo8),gCPU.ctr, gCPU.pc);}/* * bcctrx Branch Conditional to Count Register * .438 */void ppc_opc_bcctrx(){ uint32 BO, BI, BD; PPC_OPC_TEMPL_XL(gCPU.current_opc, BO, BI, BD); PPC_OPC_ASSERT(BD==0); PPC_OPC_ASSERT(!(BO & 2)); bool bo8 = ((BO & 8)?1:0); bool cr = ((gCPU.cr & (1<<(31-BI)))?1:0); if ((BO & 16) || (!(cr ^ bo8))) { if (gCPU.current_opc & PPC_OPC_LK) { gCPU.lr = gCPU.pc + 4; } gCPU.npc = gCPU.ctr & 0xfffffffc; } //fprintf(stderr,"in %s,BO=0x%x,BI=0x%x,BD=0x%x,cr=0x%x,cr^bo8=0x%x,ctr=0x%x,pc=0x%x,npc=0x%x\n",__FUNCTION__,BO,BI,BD,gCPU.cr,(cr ^ bo8),gCPU.ctr, gCPU.pc,gCPU.npc);}/* * bclrx Branch Conditional to Link Register * .440 */void ppc_opc_bclrx(){ uint32 BO, BI, BD; PPC_OPC_TEMPL_XL(gCPU.current_opc, BO, BI, BD); PPC_OPC_ASSERT(BD==0); if (!(BO & 4)) { gCPU.ctr--; } bool bo2 = ((BO & 2)?1:0); bool bo8 = ((BO & 8)?1:0); bool cr = ((gCPU.cr & (1<<(31-BI)))?1:0); if (((BO & 4) || ((gCPU.ctr!=0) ^ bo2)) && ((BO & 16) || (!(cr ^ bo8)))) { BD = gCPU.lr & 0xfffffffc; if (gCPU.current_opc & PPC_OPC_LK) { gCPU.lr = gCPU.pc + 4; } gCPU.npc = BD; }}/* * dcbf Data Cache Block Flush * .458 */void ppc_opc_dcbf(){ // NO-OP}/* * dcbi Data Cache Block Invalidate * .460 */void ppc_opc_dcbi(){ if (gCPU.msr & MSR_PR) { ppc_exception(PPC_EXC_PROGRAM, PPC_EXC_PROGRAM_PRIV, 0); return; } // FIXME: check addr}/* * dcbst Data Cache Block Store * .461 */void ppc_opc_dcbst(){ // NO-OP}/* * dcbt Data Cache Block Touch * .462 */void ppc_opc_dcbt(){ // NO-OP}/* * dcbtst Data Cache Block Touch for Store * .463 */void ppc_opc_dcbtst(){ // NO-OP}/* * eciwx External Control In Word Indexed * .474 */void ppc_opc_eciwx(){ PPC_OPC_ERR("eciwx unimplemented.\n");}/* * ecowx External Control Out Word Indexed * .476 */void ppc_opc_ecowx(){ PPC_OPC_ERR("ecowx unimplemented.\n");}/* * eieio Enforce In-Order Execution of I/O * .478 */void ppc_opc_eieio(){ // NO-OP}/* * icbi Instruction Cache Block Invalidate * .519 */void ppc_opc_icbi(){ // NO-OP}/* * isync Instruction Synchronize * .520 */void ppc_opc_isync(){ // NO-OP}static uint32 ppc_cmp_and_mask[8] = { 0xfffffff0, 0xffffff0f, 0xfffff0ff, 0xffff0fff, 0xfff0ffff, 0xff0fffff, 0xf0ffffff, 0x0fffffff,};/* * mcrf Move Condition Register Field * .561 */void ppc_opc_mcrf(){ uint32 crD, crS, bla; PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crS, bla); // FIXME: bla == 0 crD>>=2; crS>>=2; crD = 7-crD; crS = 7-crS; uint32 c = (gCPU.cr>>(crS*4)) & 0xf; gCPU.cr &= ppc_cmp_and_mask[crD]; gCPU.cr |= c<<(crD*4);}/* * mcrfs Move to Condition Register from FPSCR * .562 */void ppc_opc_mcrfs(){ PPC_OPC_ERR("mcrfs unimplemented.\n");}/* * mcrxr Move to Condition Register from XER * .563 */void ppc_opc_mcrxr(){ PPC_OPC_ERR("mcrxr unimplemented.\n");}/* * mfcr Move from Condition Register * .564 */void ppc_opc_mfcr(){ int rD, rA, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, rD, rA, rB); PPC_OPC_ASSERT(rA==0 && rB==0); gCPU.gpr[rD] = gCPU.cr;}/* * mffs Move from FPSCR * .565 */void ppc_opc_mffsx(){ int frD, rA, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, frD, rA, rB); PPC_OPC_ASSERT(rA==0 && rB==0); gCPU.fpr[frD] = gCPU.fpscr; if (gCPU.current_opc & PPC_OPC_Rc) { // update cr1 flags PPC_OPC_ERR("mffs. unimplemented.\n"); }}/* * mfmsr Move from Machine State Register * .566 */void ppc_opc_mfmsr(){ if (gCPU.msr & MSR_PR) { ppc_exception(PPC_EXC_PROGRAM, PPC_EXC_PROGRAM_PRIV, 0); return; } int rD, rA, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, rD, rA, rB); PPC_OPC_ASSERT((rA == 0) && (rB == 0)); gCPU.gpr[rD] = gCPU.msr;}/* * mfspr Move from Special-Purpose Register * .567 */void ppc_opc_mfspr(){ int rD, spr1, spr2; PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, spr1, spr2); if (gCPU.msr & MSR_PR) { //ppc_exception(PPC_EXC_PROGRAM, PPC_EXC_PROGRAM_PRIV, 0); //printf("Warning, execute mfspe in user mode\n"); //return; } switch (spr2) { case 0: switch (spr1) { case 1: gCPU.gpr[rD] = gCPU.xer; return; case 8: gCPU.gpr[rD] = gCPU.lr; return; case 9: gCPU.gpr[rD] = gCPU.ctr; return; case 18: gCPU.gpr[rD] = gCPU.dsisr; return; case 19: gCPU.gpr[rD] = gCPU.dar; return; case 22: { gCPU.dec = gCPU.pdec / TB_TO_PTB_FACTOR; gCPU.gpr[rD] = gCPU.dec; return; } case 25: gCPU.gpr[rD] = gCPU.sdr1; return; case 26: gCPU.gpr[rD] = gCPU.srr[0]; return; case 27: gCPU.gpr[rD] = gCPU.srr[1]; return; } break; case 1: switch(spr1) { case 16: gCPU.gpr[rD] = e500_mmu.pid[1];return; case 29: gCPU.gpr[rD] = gCPU.dear;return; case 30: gCPU.gpr[rD] = gCPU.esr; return; } break; case 8: switch (spr1) { case 12: { /* gCPU.tb = gCPU.ptb / TB_TO_PTB_FACTOR; gCPU.gpr[rD] = gCPU.tb; */ gCPU.gpr[rD] = gCPU.tbl; return; } case 13: { /* gCPU.tb = gCPU.ptb / TB_TO_PTB_FACTOR; gCPU.gpr[rD] = gCPU.tb >> 32; */ gCPU.gpr[rD] = gCPU.tbu; return; } case 0: gCPU.gpr[rD] = gCPU.vrsave; return; case 16: gCPU.gpr[rD] = gCPU.sprg[0]; return; case 1: case 17: gCPU.gpr[rD] = gCPU.sprg[1]; return; case 2: case 18: gCPU.gpr[rD] = gCPU.sprg[2]; return; case 3: case 19: gCPU.gpr[rD] = gCPU.sprg[3]; return; case 4: case 20: gCPU.gpr[rD] = gCPU.sprg[4]; return; case 5: case 21: gCPU.gpr[rD] = gCPU.sprg[5]; return; case 6: case 22: gCPU.gpr[rD] = gCPU.sprg[6]; return; case 23: case 7: gCPU.gpr[rD] = gCPU.sprg[7]; return; case 26: gCPU.gpr[rD] = gCPU.ear; return; case 31: gCPU.gpr[rD] = gCPU.pvr; return; default: fprintf(stderr, "unknown mfspr: %i:%i\n", spr1, spr2); fprintf(stderr, "pc=0x%x\n", gCPU.pc); skyeye_exit(-1); } break; case 9: switch(spr1) { case 16:gCPU.gpr[rD] = gCPU.dbsr; return; case 20:gCPU.gpr[rD] = gCPU.dbcr[0]; return; case 21:gCPU.gpr[rD] = gCPU.dbcr[1]; return; case 22:gCPU.gpr[rD] = gCPU.dbcr[2]; return; case 28:gCPU.gpr[rD] = gCPU.dac[0]; return; case 29:gCPU.gpr[rD] = gCPU.dac[1]; return; } break; case 16: switch (spr1) { case 0: gCPU.gpr[rD] = gCPU.spefscr; return; case 16: gCPU.gpr[rD] = gCPU.ibatu[0]; return; case 17: gCPU.gpr[rD] = gCPU.ibatl[0]; return; case 18: gCPU.gpr[rD] = gCPU.ibatu[1]; return; case 19: gCPU.gpr[rD] = gCPU.ibatl[1]; return; case 20: gCPU.gpr[rD] = gCPU.ibatu[2]; return; case 21: gCPU.gpr[rD] = gCPU.ibatl[2]; return; case 22: gCPU.gpr[rD] = gCPU.ibatu[3]; return; case 23: gCPU.gpr[rD] = gCPU.ibatl[3]; return; case 24: gCPU.gpr[rD] = gCPU.dbatu[0]; return; case 25: gCPU.gpr[rD] = gCPU.dbatl[0]; return; case 26: gCPU.gpr[rD] = gCPU.dbatu[1]; return; case 27: gCPU.gpr[rD] = gCPU.dbatl[1]; return; case 28: gCPU.gpr[rD] = gCPU.dbatu[2]; return; case 29: gCPU.gpr[rD] = gCPU.dbatl[2]; return; case 30: gCPU.gpr[rD] = gCPU.dbatu[3]; return; case 31: gCPU.gpr[rD] = gCPU.dbatl[3]; return; } break; case 19: switch(spr1) { case 16: gCPU.gpr[rD] = e500_mmu.mas[0]; return; case 17: gCPU.gpr[rD] = e500_mmu.mas[1]; return; case 18: gCPU.gpr[rD] = e500_mmu.mas[2]; return; case 19: gCPU.gpr[rD] = e500_mmu.mas[3]; return; case 20: gCPU.gpr[rD] = e500_mmu.mas[4]; return; case 22: gCPU.gpr[rD] = e500_mmu.mas[6]; return; case 25: gCPU.gpr[rD] = e500_mmu.pid[1]; return; case 26: gCPU.gpr[rD] = e500_mmu.pid[2]; return; } break; case 21: switch(spr1) { case 17:gCPU.gpr[rD] = e500_mmu.tlbcfg[1]; return; } break; case 29: switch (spr1) { case 16: gCPU.gpr[rD] = 0; return; case 17: gCPU.gpr[rD] = 0; return; case 18: gCPU.gpr[rD] = 0; return; case 24: gCPU.gpr[rD] = 0; return; case 25: gCPU.gpr[rD] = 0; return; case 26: gCPU.gpr[rD] = 0; return; case 28: gCPU.gpr[rD] = 0; return; case 29: gCPU.gpr[rD] = 0; return; case 30: gCPU.gpr[rD] = 0; return; } break; case 31: switch (spr1) { case 16:// PPC_OPC_WARN("read from spr %d:%d (HID0) not supported!\n", spr1, spr2); gCPU.gpr[rD] = gCPU.hid[0]; return; case 17: PPC_OPC_WARN("read from spr %d:%d (HID1) not supported!\n", spr1, spr2); gCPU.gpr[rD] = gCPU.hid[1]; return; case 18: gCPU.gpr[rD] = 0; return; case 19: gCPU.gpr[rD] = gCPU.l1csr[1]; return; case 20: gCPU.gpr[rD] = gCPU.iac[0]; return; case 21: gCPU.gpr[rD] = 0; return; case 22: gCPU.gpr[rD] = 0; return; case 23: gCPU.gpr[rD] = 0; return; case 25: PPC_OPC_WARN("read from spr %d:%d (L2CR) not supported! (from %08x)\n", spr1, spr2, gCPU.pc); gCPU.gpr[rD] = 0; return; case 27: PPC_OPC_WARN("read from spr %d:%d (ICTC) not supported!\n", spr1, spr2); gCPU.gpr[rD] = 0; return; case 28:// PPC_OPC_WARN("read from spr %d:%d (THRM1) not supported!\n", spr1, spr2); gCPU.gpr[rD] = 0; return; case 29:// PPC_OPC_WARN("read from spr %d:%d (THRM2) not supported!\n", spr1, spr2); gCPU.gpr[rD] = 0; return; case 30:// PPC_OPC_WARN("read from spr %d:%d (THRM3) not supported!\n", spr1, spr2); gCPU.gpr[rD] = 0; return; case 31:// PPC_OPC_WARN("read from spr %d:%d (???) not supported!\n", spr1, spr2); gCPU.gpr[rD] = 0; return; } break; } fprintf(stderr, "unknown mfspr: %i:%i\n", spr1, spr2); fprintf(stderr, "pc=0x%x\n", gCPU.pc); skyeye_exit(-1); //SINGLESTEP("invalid mfspr\n");}/* * mfsr Move from Segment Register * .570 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -