⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppc_alu.c

📁 SkyEye是一个可以运行嵌入式操作系统的硬件仿真工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	PearPC *	ppc_alu.cc * *	Copyright (C) 2003, 2004 Sebastian Biallas (sb@biallas.net) * *	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 "debug.h"#include "tracers.h"#include "ppc_alu.h"#include "ppc_dec.h"#include "ppc_exc.h"#include "ppc_cpu.h"#include "ppc_opc.h"#include "ppc_tools.h"#include "ppc_mmu.h"static inline uint32 ppc_mask(int MB, int ME){	uint32 mask;	if (MB <= ME) {		if (ME-MB == 31) {			mask = 0xffffffff;		} else {			mask = ((1<<(ME-MB+1))-1)<<(31-ME);		}	} else {		mask = ppc_word_rotl((1<<(32-MB+ME+1))-1, 31-ME);	}	return mask;}/* *	addx		Add *	.422 */void ppc_opc_addx(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	gCPU.gpr[rD] = gCPU.gpr[rA] + gCPU.gpr[rB];	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}}/* *	addox		Add with Overflow *	.422 */void ppc_opc_addox(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	gCPU.gpr[rD] = gCPU.gpr[rA] + gCPU.gpr[rB];	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}	// update XER flags	PPC_ALU_ERR("addox unimplemented\n");}/* *	addcx		Add Carrying *	.423 */void ppc_opc_addcx(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	uint32 a = gCPU.gpr[rA];	gCPU.gpr[rD] = a + gCPU.gpr[rB];	// update xer	if (gCPU.gpr[rD] < a) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}}/* *	addcox		Add Carrying with Overflow *	.423 */void ppc_opc_addcox(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	uint32 a = gCPU.gpr[rA];	gCPU.gpr[rD] = a + gCPU.gpr[rB];	// update xer	if (gCPU.gpr[rD] < a) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}	// update XER flags	PPC_ALU_ERR("addcox unimplemented\n");}/* *	addex		Add Extended *	.424 */void ppc_opc_addex(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	uint32 a = gCPU.gpr[rA];	uint32 b = gCPU.gpr[rB];	uint32 ca = ((gCPU.xer&XER_CA)?1:0);	gCPU.gpr[rD] = a + b + ca;	// update xer	if (ppc_carry_3(a, b, ca)) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}}/* *	addeox		Add Extended with Overflow *	.424 */void ppc_opc_addeox(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	uint32 a = gCPU.gpr[rA];	uint32 b = gCPU.gpr[rB];	uint32 ca = ((gCPU.xer&XER_CA)?1:0);	gCPU.gpr[rD] = a + b + ca;	// update xer	if (ppc_carry_3(a, b, ca)) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}	// update XER flags	PPC_ALU_ERR("addeox unimplemented\n");}/* *	addi		Add Immediate *	.425 */void ppc_opc_addi(){	int rD, rA;	uint32 imm;	PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, rD, rA, imm);	gCPU.gpr[rD] = (rA ? gCPU.gpr[rA] : 0) + imm;	//fprintf(stderr, "in %s,rD=0x%x,rA=0x%x,imm=0x%x,gCPU.gpr[rD]=0x%x\n",__FUNCTION__, rD,rA,imm,gCPU.gpr[rD]);}/* *	addic		Add Immediate Carrying *	.426 */void ppc_opc_addic(){	int rD, rA;	uint32 imm;	PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, rD, rA, imm);	uint32 a = gCPU.gpr[rA];	gCPU.gpr[rD] = a + imm;		// update XER	if (gCPU.gpr[rD] < a) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}}/* *	addic.		Add Immediate Carrying and Record *	.427 */void ppc_opc_addic_(){	int rD, rA;	uint32 imm;	PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, rD, rA, imm);	uint32 a = gCPU.gpr[rA];	gCPU.gpr[rD] = a + imm;	// update XER	if (gCPU.gpr[rD] < a) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	// update cr0 flags	ppc_update_cr0(gCPU.gpr[rD]);}/* *	addis		Add Immediate Shifted *	.428 */void ppc_opc_addis(){	int rD, rA;	uint32 imm;	PPC_OPC_TEMPL_D_Shift16(gCPU.current_opc, rD, rA, imm);	gCPU.gpr[rD] = (rA ? gCPU.gpr[rA] : 0) + imm;}/* *	addmex		Add to Minus One Extended *	.429 */void ppc_opc_addmex(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	PPC_OPC_ASSERT(rB == 0);	uint32 a = gCPU.gpr[rA];	uint32 ca = ((gCPU.xer&XER_CA)?1:0);	gCPU.gpr[rD] = a + ca + 0xffffffff;	if (a || ca) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}}/* *	addmeox		Add to Minus One Extended with Overflow *	.429 */void ppc_opc_addmeox(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	PPC_OPC_ASSERT(rB == 0);	uint32 a = gCPU.gpr[rA];	uint32 ca = ((gCPU.xer&XER_CA)?1:0);	gCPU.gpr[rD] = a + ca + 0xffffffff;	if (a || ca) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}	// update XER flags	PPC_ALU_ERR("addmeox unimplemented\n");}/* *	addzex		Add to Zero Extended *	.430 */void ppc_opc_addzex(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	PPC_OPC_ASSERT(rB == 0);	uint32 a = gCPU.gpr[rA];	uint32 ca = ((gCPU.xer&XER_CA)?1:0);	gCPU.gpr[rD] = a + ca;	if ((a == 0xffffffff) && ca) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	// update xer	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}}/* *	addzeox		Add to Zero Extended with Overflow *	.430 */void ppc_opc_addzeox(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	PPC_OPC_ASSERT(rB == 0);	uint32 a = gCPU.gpr[rA];	uint32 ca = ((gCPU.xer&XER_CA)?1:0);	gCPU.gpr[rD] = a + ca;	if ((a == 0xffffffff) && ca) {		gCPU.xer |= XER_CA;	} else {		gCPU.xer &= ~XER_CA;	}	// update xer	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}	// update XER flags	PPC_ALU_ERR("addzeox unimplemented\n");}/* *	andx		AND *	.431 */void ppc_opc_andx(){	int rS, rA, rB;	PPC_OPC_TEMPL_X(gCPU.current_opc, rS, rA, rB);	gCPU.gpr[rA] = gCPU.gpr[rS] & gCPU.gpr[rB];	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rA]);	}}/* *	andcx		AND with Complement *	.432 */void ppc_opc_andcx(){	int rS, rA, rB;	PPC_OPC_TEMPL_X(gCPU.current_opc, rS, rA, rB);	gCPU.gpr[rA] = gCPU.gpr[rS] & ~gCPU.gpr[rB];	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rA]);	}}/* *	andi.		AND Immediate *	.433 */void ppc_opc_andi_(){	int rS, rA;	uint32 imm;	PPC_OPC_TEMPL_D_UImm(gCPU.current_opc, rS, rA, imm);	gCPU.gpr[rA] = gCPU.gpr[rS] & imm;	// update cr0 flags	ppc_update_cr0(gCPU.gpr[rA]);}/* *	andis.		AND Immediate Shifted *	.434 */void ppc_opc_andis_(){	int rS, rA;	uint32 imm;	PPC_OPC_TEMPL_D_Shift16(gCPU.current_opc, rS, rA, imm);	gCPU.gpr[rA] = gCPU.gpr[rS] & imm;	// update cr0 flags	ppc_update_cr0(gCPU.gpr[rA]);}/* *	cmp		Compare *	.442 */static uint32 ppc_cmp_and_mask[8] = {	0xfffffff0,	0xffffff0f,	0xfffff0ff,	0xffff0fff,	0xfff0ffff,	0xff0fffff,	0xf0ffffff,	0x0fffffff,};void ppc_opc_cmp(){	uint32 cr;	int rA, rB;	PPC_OPC_TEMPL_X(gCPU.current_opc, cr, rA, rB);	cr >>= 2;	sint32 a = gCPU.gpr[rA];	sint32 b = gCPU.gpr[rB];	uint32 c;	if (a < b) {		c = 8;	} else if (a > b) {		c = 4;	} else {		c = 2;	}	if (gCPU.xer & XER_SO) c |= 1;	cr = 7-cr;	gCPU.cr &= ppc_cmp_and_mask[cr];	gCPU.cr |= c<<(cr*4);}/* *	cmpi		Compare Immediate *	.443 */void ppc_opc_cmpi(){	uint32 cr;	int rA;	uint32 imm;	PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, cr, rA, imm);	cr >>= 2;	sint32 a = gCPU.gpr[rA];	sint32 b = imm;	uint32 c;/*	if (!VALGRIND_CHECK_READABLE(a, sizeof a)) {		ht_printf("%08x <--i\n", gCPU.pc);//		SINGLESTEP("");	}*/	if (a < b) {		c = 8;	} else if (a > b) {		c = 4;	} else {		c = 2;	}	if (gCPU.xer & XER_SO) c |= 1;	cr = 7-cr;	gCPU.cr &= ppc_cmp_and_mask[cr];	gCPU.cr |= c<<(cr*4);	//fprintf(stderr,"in %s,rA=%d,gpr[rA]=0x%d,im=%d,c=%d\n",__FUNCTION__,rA,gCPU.gpr[rA],imm,c);}/* *	cmpl		Compare Logical *	.444 */void ppc_opc_cmpl(){	uint32 cr;	int rA, rB;	PPC_OPC_TEMPL_X(gCPU.current_opc, cr, rA, rB);	cr >>= 2;	uint32 a = gCPU.gpr[rA];	uint32 b = gCPU.gpr[rB];	uint32 c;	if (a < b) {		c = 8;	} else if (a > b) {		c = 4;	} else {		c = 2;	}	if (gCPU.xer & XER_SO) c |= 1;	cr = 7-cr;	gCPU.cr &= ppc_cmp_and_mask[cr];	gCPU.cr |= c<<(cr*4);}/* *	cmpli		Compare Logical Immediate *	.445 */void ppc_opc_cmpli(){	uint32 cr;	int rA;	uint32 imm;	PPC_OPC_TEMPL_D_UImm(gCPU.current_opc, cr, rA, imm);	cr >>= 2;	uint32 a = gCPU.gpr[rA];	uint32 b = imm;	uint32 c;	if (a < b) {		c = 8;	} else if (a > b) {		c = 4;	} else {		c = 2;	}	if (gCPU.xer & XER_SO) c |= 1;	cr = 7-cr;	gCPU.cr &= ppc_cmp_and_mask[cr];	gCPU.cr |= c<<(cr*4);}/* *	cntlzwx		Count Leading Zeros Word *	.447 */void ppc_opc_cntlzwx(){	int rS, rA, rB;	PPC_OPC_TEMPL_X(gCPU.current_opc, rS, rA, rB);	PPC_OPC_ASSERT(rB==0);	uint32 n=0;	uint32 x=0x80000000;	uint32 v=gCPU.gpr[rS];	while (!(v & x)) {		n++;		if (n==32) break;		x>>=1;	}	gCPU.gpr[rA] = n;	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rA]);	}}/* *	crand		Condition Register AND *	.448 */void ppc_opc_crand(){	int crD, crA, crB;	PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crA, crB);	if ((gCPU.cr & (1<<(31-crA))) && (gCPU.cr & (1<<(31-crB)))) {		gCPU.cr |= (1<<(31-crD));	} else {		gCPU.cr &= ~(1<<(31-crD));	}}/* *	crandc		Condition Register AND with Complement *	.449 */void ppc_opc_crandc(){	int crD, crA, crB;	PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crA, crB);	if ((gCPU.cr & (1<<(31-crA))) && !(gCPU.cr & (1<<(31-crB)))) {		gCPU.cr |= (1<<(31-crD));	} else {		gCPU.cr &= ~(1<<(31-crD));	}}/* *	creqv		Condition Register Equivalent *	.450 */void ppc_opc_creqv(){	int crD, crA, crB;	PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crA, crB);	if (((gCPU.cr & (1<<(31-crA))) && (gCPU.cr & (1<<(31-crB))))	  || (!(gCPU.cr & (1<<(31-crA))) && !(gCPU.cr & (1<<(31-crB))))) {		gCPU.cr |= (1<<(31-crD));	} else {		gCPU.cr &= ~(1<<(31-crD));	}}/* *	crnand		Condition Register NAND *	.451 */void ppc_opc_crnand(){	int crD, crA, crB;	PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crA, crB);	if (!((gCPU.cr & (1<<(31-crA))) && (gCPU.cr & (1<<(31-crB))))) {		gCPU.cr |= (1<<(31-crD));	} else {		gCPU.cr &= ~(1<<(31-crD));	}}/* *	crnor		Condition Register NOR *	.452 */void ppc_opc_crnor(){	int crD, crA, crB;	PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crA, crB);	uint32 t = (1<<(31-crA)) | (1<<(31-crB));	if (!(gCPU.cr & t)) {		gCPU.cr |= (1<<(31-crD));	} else {		gCPU.cr &= ~(1<<(31-crD));	}}/* *	cror		Condition Register OR *	.453 */void ppc_opc_cror(){	int crD, crA, crB;	PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crA, crB);	uint32 t = (1<<(31-crA)) | (1<<(31-crB));	if (gCPU.cr & t) {		gCPU.cr |= (1<<(31-crD));	} else {		gCPU.cr &= ~(1<<(31-crD));	}}/* *	crorc		Condition Register OR with Complement *	.454 */void ppc_opc_crorc(){	int crD, crA, crB;	PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crA, crB);	if ((gCPU.cr & (1<<(31-crA))) || !(gCPU.cr & (1<<(31-crB)))) {		gCPU.cr |= (1<<(31-crD));	} else {		gCPU.cr &= ~(1<<(31-crD));	}}/* *	crxor		Condition Register XOR *	.448 */void ppc_opc_crxor(){	int crD, crA, crB;	PPC_OPC_TEMPL_X(gCPU.current_opc, crD, crA, crB);	if ((!(gCPU.cr & (1<<(31-crA))) && (gCPU.cr & (1<<(31-crB))))	  || ((gCPU.cr & (1<<(31-crA))) && !(gCPU.cr & (1<<(31-crB))))) {		gCPU.cr |= (1<<(31-crD));	} else {		gCPU.cr &= ~(1<<(31-crD));	}}/* *	divwx		Divide Word *	.470 */void ppc_opc_divwx(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	if (!gCPU.gpr[rB]) {		PPC_ALU_WARN("division by zero @%08x\n", gCPU.pc);	}	sint32 a = gCPU.gpr[rA];	sint32 b = gCPU.gpr[rB];	gCPU.gpr[rD] = a / b;	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}}/* *	divwox		Divide Word with Overflow *	.470 */void ppc_opc_divwox(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	if (!gCPU.gpr[rB]) {		PPC_ALU_ERR("division by zero\n");	}	sint32 a = gCPU.gpr[rA];	sint32 b = gCPU.gpr[rB];	gCPU.gpr[rD] = a / b;	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}	// update XER flags	PPC_ALU_ERR("divwox unimplemented\n");}/* *	divwux		Divide Word Unsigned *	.472 */void ppc_opc_divwux(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	if (!gCPU.gpr[rB]) {		PPC_ALU_WARN("division by zero @%08x\n", gCPU.pc);	}	gCPU.gpr[rD] = gCPU.gpr[rA] / gCPU.gpr[rB];	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}}/* *	divwuox		Divide Word Unsigned with Overflow *	.472 */void ppc_opc_divwuox(){	int rD, rA, rB;	PPC_OPC_TEMPL_XO(gCPU.current_opc, rD, rA, rB);	if (!gCPU.gpr[rB]) {//		PPC_ALU_ERR("division by zero\n");	}	gCPU.gpr[rD] = gCPU.gpr[rA] / gCPU.gpr[rB];	if (gCPU.current_opc & PPC_OPC_Rc) {		// update cr0 flags		ppc_update_cr0(gCPU.gpr[rD]);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -