📄 instructions_ppc.c
字号:
/* * ---------------------------------------------------- * * PowerPC Instruction Set * (C) 2005 Jochen Karrer * Author: Jochen Karrer * * With some code from PearPC * * ---------------------------------------------------- */#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <debug.h>#include <instructions_ppc.h>#include <byteorder.h>#include <cpu_ppc.h>#include <mmu_ppc.h>#ifdef DEBUG#define dprintf(x...) { if(unlikely(debugflags&DEBUG_INSTRUCTIONS)) { fprintf(stderr,x); fflush(stderr); } }#else#define dprintf(x...)#endifstatic inline intcount_leading_zeros(uint32_t value) { int i; for(i=0;i<32;i++) { if(value & 0x80000000) { return i; } value=value<<1; } return 32;}static inline voidupdate_cr0(uint32_t result) { CR=CR &~(CR_LT | CR_GT | CR_EQ | CR_SO); if(!result) { CR=CR|CR_EQ; } else if (ISNEG(result)) { CR=CR|CR_LT; } else { CR=CR|CR_GT; } if (XER & XER_SO) { CR |= CR_SO; }}/* * --------------------------------------- * Carry and overflow Flag Helper * functions for add and sub * --------------------------------------- */static inline uint32_tsub_carry(uint32_t op1,uint32_t op2,uint32_t result) { if( ((ISNEG(op1) && ISNOTNEG(op2)) || (ISNEG(op1) && ISNOTNEG(result)) || (ISNOTNEG(op2) && ISNOTNEG(result)))) { return 1; } else { return 0; }}static inline uint32_tadd_carry(uint32_t op1,uint32_t op2,uint32_t result) { if( ((ISNEG(op1) && ISNEG(op2)) || (ISNEG(op1) && ISNOTNEG(result)) || (ISNEG(op2) && ISNOTNEG(result)))) { return 1; } else { return 0; }}static inline uint32_tsub_overflow(uint32_t op1,uint32_t op2,uint32_t result) { if ((ISNEG (op1) && ISNOTNEG (op2) && ISNOTNEG (result)) || (ISNOTNEG (op1) && ISNEG (op2) && ISNEG (result))) { return 1; } else { return 0; }}static inline uint32_tadd_overflow(uint32_t op1,uint32_t op2,uint32_t result) { if ((ISNEG (op1) && ISNEG (op2) && ISNOTNEG (result)) || (ISNOTNEG (op1) && ISNOTNEG (op2) && ISNEG (result))) { return 1; } else { return 0; }}void i_tdi(uint32_t icode) { fprintf(stderr,"instr i_tdi(%08x) not implemented\n",icode);}/* * ------------------------------------------------------------ * twi UISA Form D * Trap word Immediate * ------------------------------------------------------------ */void i_twi(uint32_t icode) { int to = (icode>>21)&0x1f; int a = (icode>>16)&0x1f; int16_t imm = icode & 0xffff; int32_t eimm = imm; int32_t A = GPR(a); if(((int32_t)A < (int32_t)eimm) && (to & (1<<0))) { // Exception } if(((int32_t)A > (int32_t)eimm) && (to & (1<<1))) { // Exception } if((A==eimm) && (to & (1<<2))) { // Exception } if(((uint32_t)A < (uint32_t)eimm) && (to & (1<<3))) { // Exception } if(((uint32_t)A > (uint32_t)eimm) && (to & (1<<4))) { // Exception } fprintf(stderr,"instr i_twi(%08x) not implemented\n",icode);}/* * ------------------------------------- * mulli UISA Form D * Multiply Low Immediate * ------------------------------------- */void i_mulli(uint32_t icode) { int d = (icode>>21)&0x1f; int a = (icode>>16)&0x1f; int rc = icode & 1; uint32_t result; int16_t simm = (icode & 0xffff); result = GPR(d) = (int64_t)GPR(a) * (int64_t)simm; if(rc) { update_cr0(result); } dprintf("instr i_mulli(%08x)\n",icode);}/* * ------------------------------------------------ * subfic UISA Form D * ------------------------------------------------ */void i_subfic(uint32_t icode) { int d = (icode>>21)&0x1f; int a = (icode>>16)&0x1f; int16_t imm = icode & 0xffff; uint32_t result; uint32_t op2 = GPR(a); result = GPR(d) = imm - op2; if(sub_carry(imm,op2,result)) { XER = XER | XER_CA; } else { XER = XER & ~XER_CA; } dprintf("instr i_subfic(%08x)\n",icode);}/* * ------------------ * cmpli UISA Form D * v1 * ------------------ */void i_cmpli(uint32_t icode) { uint32_t crfd=7-((icode>>23)&7); uint32_t a=(icode>>16)&0x1f; uint16_t uimm = icode &0xffff; uint32_t Ra = GPR(a); int L=(icode>>21)&1; uint32_t c; if(L) { fprintf(stderr,"Invalid instruction format for cmpli\n"); return; } if(Ra < uimm) { c=8; } else if(Ra > uimm) { c=4; } else { c=2; } if (XER & XER_SO) { c |= 1; } CR &= 0xffffffff ^ (0xf<<(crfd<<2)); CR |= c<<(crfd<<2); dprintf("instr i_cmpli(%08x)\n",icode);}/* * ---------------------- * cmpi UISA Form D * v1 * ---------------------- */void i_cmpi(uint32_t icode) { uint32_t crfd=7-((icode>>23)&7); uint32_t a=(icode>>16)&0x1f; int16_t simm = icode &0xffff; int32_t Ra = GPR(a); int L=(icode>>21)&1; uint32_t c; if(L) { fprintf(stderr,"invalid instruction format\n"); } if(Ra<simm) { c=8; } else if(Ra>simm) { c=4; } else { c=2; } if (XER & XER_SO) { c |= 1; } CR &= 0xffffffff ^ (0xf<<(crfd<<2)); CR |= c<<(crfd<<2); dprintf("instr i_cmpi(%08x)\n",icode);}/* * ----------------------------- * addic UISA form D * v1 * ----------------------------- */void i_addic(uint32_t icode) { int d=(icode>>21)&0x1f; int a=(icode>>16)&0x1f; int16_t simm = (icode&0xffff); uint32_t op1; uint32_t result; op1=GPR(a); GPR(d) = result = op1 + simm; if(add_carry(op1,simm,result)) { XER=XER | XER_CA; } else { XER=XER & ~XER_CA; } dprintf("instr i_addic(%08x)\n",icode);}/* * -------------------------------- * addic. UISA Form D * v1 * -------------------------------- */void i_addic_(uint32_t icode) { int d=(icode>>21)&0x1f; int a=(icode>>16)&0x1f; int16_t simm = (icode&0xffff); uint32_t op1; uint32_t result; op1=GPR(a); GPR(d) = result = op1+simm; if(add_carry(op1,simm,result)) { XER=XER | XER_CA; } else { XER=XER & ~XER_CA; } update_cr0(result); dprintf("instr i_addic_(%08x)\n",icode);}/* * ------------------------- * addi UISA form D * v1 * ------------------------- */void i_addi(uint32_t icode) { int d=(icode>>21)&0x1f; int a=(icode>>16)&0x1f; int16_t simm = (icode&0xffff); if(a==0) { GPR(d) = simm; } else { GPR(d) = GPR(a)+simm; } dprintf("instr i_addi(%08x)\n",icode);}/* * -------------------------------- * addis UISA Form D * v1 * -------------------------------- */void i_addis(uint32_t icode) { int d=(icode>>21)&0x1f; int a=(icode>>16)&0x1f; int32_t simm = (icode&0xffff)<<16; if(a==0) { GPR(d) = simm; } else { GPR(d) = GPR(a)+simm; } dprintf("instr i_addis(%08x)\n",icode);}/* * ------------------------------------- * bcx UISA Form D * v1 * ------------------------------------- */void i_bcx(uint32_t icode) { uint32_t bo = (icode>>21)&0x1f; uint32_t bi = (icode>>16)&0x1f; int16_t bd = (icode)&0xfffc; int aa = (icode&2); int lk = (icode&1); int ctr_ok; uint32_t cond_ok; if(!(bo & (1<<(4-2) ))) { CTR = CTR - 1; } ctr_ok = ((bo>>2) & 1) | ((CTR!=0) != ((bo>>(4-3))&1)); cond_ok = (bo & (1<<(4-0))) | (((CR>>(31-bi))&1)==((bo>>(4-1))&1)); if(ctr_ok && cond_ok) { if(lk) { LR=CIA+4; } if(aa) { NIA=bd; } else { NIA=CIA+bd; } } dprintf("instr i_bcx(%08x)\n",icode);}/* * ---------------------------------------- * sc * Systemcall * not complete * ---------------------------------------- */void i_sc(uint32_t icode) { uint32_t mask = 0x87c0ff73; SRR0 = CIA + 4; SRR1 = SRR1 & ~0x783f0000; SRR1 = (SRR1 & ~mask ) | ( MSR & mask);// MSR = bla;// NIA = bla;// Exception(SYSCALL); fprintf(stderr,"instr i_sc(%08x) not implemented\n",icode);}/* * ---------------------------------- * bx UISA Form I * ---------------------------------- */void i_bx(uint32_t icode) { int32_t li; int aa = icode & (1<<1); int lk = icode & 1; if(icode&0x02000000) { li = (icode & 0x03fffffc) | 0xfc000000; } else { li = icode& 0x03fffffc; } if(lk) { LR=CIA+4; } if(aa) { NIA=li; } else { NIA=CIA+li; } dprintf("instr i_bx(%08x)\n",icode);}/* * --------------------------------------- * mcrf UISA Form XL * Move condition register field * v1 * --------------------------------------- */void i_mcrf(uint32_t icode) { uint32_t mask; int crfd = 7-((icode>>23)&7); // shit PPC bit counting int crfs = 7-((icode>>18)&7); uint32_t or; or=((CR>>(4*crfs))&0xf) << (4*crfd); mask = ~(0xf << (4*crfd)); CR = (CR & mask) | or; dprintf("instr i_mcrf(%08x)\n",icode);}/* * ------------------------------------------ * bclrx UISA Form XL * v1 * ------------------------------------------ */void i_bclrx(uint32_t icode) { uint32_t bo = (icode>>21)&0x1f; uint32_t bi = (icode>>16)&0x1f; int lk = icode&1; int ctr_ok; int cond_ok; if(!((bo>>(4-2))&1)) { CTR-=1; } ctr_ok = ((bo>>(4-2))&1) | ((CTR !=0) ^ ((bo>>(4-3))&1)); cond_ok = (bo& (1<<(4-0))) | (((CR>>(31-bi))&1)==((bo>>(4-1))&1)); fprintf(stderr,"from CIA %08x \n",CIA); if(ctr_ok & cond_ok) { uint32_t tmp_lr = LR; if(lk) { LR=CIA+4; } NIA=tmp_lr & 0xfffffffc; } fprintf(stderr,"instr i_bclrx(%08x) to NIA %08x\n",icode,NIA);}/* * ------------------------------------------- * crnor UISA Form XL * v1 * ------------------------------------------- */void i_crnor(uint32_t icode) { uint32_t crbD=31-((icode>>21)&0x1f); uint32_t crbA=31-((icode>>16)&0x1f); uint32_t crbB=31-((icode>>11)&0x1f); if((CR&(1<<crbA)) || (CR&(1<<crbB))) { CR=CR & ~(1<<crbD); } else { CR=CR | (1<<crbD); } dprintf("instr i_crnor(%08x)\n",icode);}/* * ----------------------------------- * rfi OEA Supervisor Form XL * return from interrupt * incomplete v1 * ----------------------------------- */void i_rfi(uint32_t icode) { uint32_t mask = 0x87c0ff73;#if 0 if(!supervisor) { fprintf(stderr,"Mist\n"); Exception(); }#endif PpcSetMsr((MSR & ~(mask|(1<<18))) | (SRR1 & mask)); NIA = SRR0 & 0xfffffffc; fprintf(stderr,"instr i_rfi(%08x) incomplete\n",icode);}/* * ------------------------------ * crandc UISA Form XL * v1 * ------------------------------ */void i_crandc(uint32_t icode) { uint32_t crbD=31-((icode>>21)&0x1f); uint32_t crbA=31-((icode>>16)&0x1f); uint32_t crbB=31-((icode>>11)&0x1f); if((CR&(1<<crbA)) && !(CR&(1<<crbB))) { CR=CR | (1<<crbD); } else { CR=CR & ~(1<<crbD); } dprintf("instr i_crandc(%08x)\n",icode);}/* * ------------------------------------------------------------------------------ * isync VEA Form XL * Instruction Synchronize * Currently does nothing because Instruction pipeline is not implemented * ------------------------------------------------------------------------------ */void i_isync(uint32_t icode) { dprintf("instr i_isync(%08x) ignored\n",icode);}/* * ---------------------------------------- * crxor UISA Form XL * v1 * ---------------------------------------- */void i_crxor(uint32_t icode) { uint32_t crbD=31-((icode>>21)&0x1f); uint32_t crbA=31-((icode>>16)&0x1f); uint32_t crbB=31-((icode>>11)&0x1f); if((((CR>>crbA)&1) != ((CR>>crbB)&1))) { CR=CR | (1<<crbD); } else { CR=CR & ~(1<<crbD); } dprintf("instr i_crxor(%08x)\n",icode);}/* * ------------------------------ * crnand UISA Form XL * v1 * ------------------------------ */void i_crnand(uint32_t icode) { uint32_t crbD=31-((icode>>21)&0x1f); uint32_t crbA=31-((icode>>16)&0x1f); uint32_t crbB=31-((icode>>11)&0x1f); if((CR&(1<<crbA)) && (CR&(1<<crbB))) { CR=CR & ~(1<<crbD); } else { CR=CR | (1<<crbD); } dprintf("instr i_crnand(%08x)\n",icode);}/* * --------------------------- * crand UISA Form XL * v1 * --------------------------- */void i_crand(uint32_t icode) { uint32_t crbD=31-((icode>>21)&0x1f); uint32_t crbA=31-((icode>>16)&0x1f); uint32_t crbB=31-((icode>>11)&0x1f); if((CR&(1<<crbA)) && (CR&(1<<crbB))) { CR=CR | (1<<crbD); } else { CR=CR & ~(1<<crbD); } dprintf("instr i_crand(%08x)\n",icode);}/* * --------------------------------------- * creqv UISA Form XL * v1 * --------------------------------------- */void i_creqv(uint32_t icode) { uint32_t crbD=31-((icode>>21)&0x1f); uint32_t crbA=31-((icode>>16)&0x1f); uint32_t crbB=31-((icode>>11)&0x1f); if(((CR>>crbA)&1) == ((CR>>crbB)&1)) { CR=CR | (1<<crbD); } else { CR=CR & ~(1<<crbD); } dprintf("instr i_creqv(%08x)\n",icode);}/* * -------------------- * crorc UISA Form XL * v1 * -------------------- */void i_crorc(uint32_t icode) { uint32_t crbD=31-((icode>>21)&0x1f); uint32_t crbA=31-((icode>>16)&0x1f); uint32_t crbB=31-((icode>>11)&0x1f); if((CR&(1<<crbA)) || !(CR&(1<<crbB))) { CR=CR | (1<<crbD); } else { CR=CR & ~(1<<crbD); } dprintf("instr i_crorc(%08x)\n",icode);}/* * -------------------------- * cror UISA Form XL * v1 * -------------------------- */void i_cror(uint32_t icode) { uint32_t crbD=31-((icode>>21)&0x1f); uint32_t crbA=31-((icode>>16)&0x1f); uint32_t crbB=31-((icode>>11)&0x1f); if((CR&(1<<crbA)) || (CR&(1<<crbB))) { CR=CR | (1<<crbD); } else { CR=CR & ~(1<<crbD); } dprintf("instr i_cror(%08x)\n",icode);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -