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

📄 dpi.cpp

📁 RISC processor ARM-7 emulator
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************
    Copyright (C) 2002,2003,2004,2005 Wei Qin
    See file COPYING for more information.

    This program is free software; you can redistribute it and/or modify    
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    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.
*************************************************************************/

#include <cstdio>
#include <armemul.h>
#include "dpi.h"

#ifdef _MODULARIZE_

using namespace emulator;
#define SHIFTER_CARRY emu->shifter_carry
#define ALU_CARRY emu->alu_carry

#else

#define SHIFTER_CARRY shifter_carry
#define ALU_CARRY alu_carry

#endif

static const char *arm_dpinames[] = 
{"and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
 "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn"};


/*utilities for alu operations*/
static inline UInt32 rotate_right(UInt32 val, UInt32 imm)
{
	return (val >> imm ) | (val << (32 - imm));
}

/*
  Shifter_operand1 and shifter_operand1_s actually was in one before.
  So does shifter_operand2's and shifter_oeprand3's.
  Separating them helps simulation speed a little bit (8.31->8.49Mips)
*/

/*immediate shifter operand*/
static inline UInt32 shifter_operand1(IMPL_FORMALS)
{
	UInt32 imm = inst & 0xff;
	UInt32 shift = (inst>>7) & 0x1e;
	UInt32 result;

	result = rotate_right(imm, shift);
	return result;
}

/*immediate shifter operand*/
static inline UInt32 shifter_operand1_s(IMPL_FORMALS)
{
	UInt32 imm = inst & 0xff;
	UInt32 shift = (inst>>7) & 0x1e;
	UInt32 result;

	result = rotate_right(imm, shift);

	if (!shift)
		SHIFTER_CARRY = C_FLAG;
	else
		SHIFTER_CARRY = BIT31(result);
	return result;
}

/*shift imediate shifter operand*/
static inline UInt32 shifter_operand2(IMPL_FORMALS)
{
	UInt32 shift_imm = (inst>>7) & 0x01f, val = RM, result;
	UInt8 type = (inst>>5) & 0x03;

	switch (type) {
		case 0: /*LSL*/	
			result = val << shift_imm;
			break;
		case 1: /*LSR*/
			if (shift_imm) {
				result = val >> shift_imm;
			} else {
				result = 0;
			}
			break;
		case 2: /*ASR*/
			if (shift_imm) {
				result = (SInt32)val>>shift_imm;
			}
			else {
				result = BIT31(val)?~0:BIT31(val);
			}
			break;
		default: /*ROR*/
			if (shift_imm) {
				result = rotate_right(val, shift_imm);
			}
			else { /*RRX*/
				result = (val>>1) |	(C_FLAG<<31);
			}
			break;
			
	}
	return result;
}

/*shift imediate shifter operand*/
static inline UInt32 shifter_operand2_s(IMPL_FORMALS)
{
	UInt32 shift_imm = (inst>>7) & 0x01f, val = RM, result;
	UInt8 type = (inst>>5) & 0x03;

	switch (type) {
		case 0: /*LSL*/	
			result = val << shift_imm;
			SHIFTER_CARRY = shift_imm?BITn(val,32-shift_imm):C_FLAG;
			break;
		case 1: /*LSR*/
			if (shift_imm) {
				result = val >> shift_imm;
				SHIFTER_CARRY = BITn(val, shift_imm-1);
			} else {
				result = 0;
				SHIFTER_CARRY = BIT31(val);
			}
			break;
		case 2: /*ASR*/
			if (shift_imm) {
				result = (SInt32)val>>shift_imm;
				SHIFTER_CARRY = BITn(val,shift_imm-1);
			}
			else {
				result = BIT31(val)?~0:BIT31(val);
				SHIFTER_CARRY = BIT31(val);
			}
			break;
		default: /*ROR*/
			if (shift_imm) {
				result = rotate_right(val, shift_imm);
				SHIFTER_CARRY = BITn(val, shift_imm-1);
			}
			else { /*RRX*/
				result = (val>>1) |	(C_FLAG<<31);
				SHIFTER_CARRY = BIT0(val);
			}
			break;
	}
	return result;
}

/*shift register shifter operand*/
static inline UInt32 shifter_operand3(IMPL_FORMALS)
{
	UInt32 shift_imm = RS & 0xff, val = RM, result;
	UInt8 type = (inst>>5) & 0x03;

	switch (type) {
		case 0: /*LSL*/	
			if (shift_imm==0) {
				result = val;
			} else if (shift_imm<32) {
				result = val << shift_imm;
			} else if (shift_imm==32) {
				result = 0;
			} else {
				result = 0;
			}
			break;
		case 1: /*LSR*/
			if (shift_imm==0) {
				result = val;
			} else if (shift_imm<32) {
				result = val >> shift_imm;
			} else if (shift_imm==32) {
				result = 0;
			} else {
				result = 0;
			}
			break;
		case 2: /*ASR*/
			if (shift_imm==0) {
				result = val;
			} else if (shift_imm<32) {
				result = (SInt32)val >> shift_imm;
			} else if (BIT31(val)) {
				result = ~0;
			} else {
				result = 0;
			}
			break;
		default: /*ROR*/
			if (shift_imm==0) {
				result = val;
			}
			else if ((shift_imm&0x1f)==0) {
				result = val;
			}
			else {
				result = rotate_right(val, shift_imm&0x1f);
			}
			break;
	}
	return result;
}

/*shift register shifter operand*/
static inline UInt32 shifter_operand3_s(IMPL_FORMALS)
{
	UInt32 shift_imm = RS & 0xff, val = RM, result;
	UInt8 type = (inst>>5) & 0x03;

	switch (type) {
		case 0: /*LSL*/	
			if (shift_imm==0) {
				result = val;
				SHIFTER_CARRY = C_FLAG;
			} else if (shift_imm<32) {
				result = val << shift_imm;
				SHIFTER_CARRY = BITn(val,32-shift_imm);
			} else if (shift_imm==32) {
				result = 0;
				SHIFTER_CARRY = BIT0(val);
			} else {
				result = 0;
				SHIFTER_CARRY = 0;
			}
			break;
		case 1: /*LSR*/
			if (shift_imm==0) {
				result = val;
				SHIFTER_CARRY = C_FLAG;
			} else if (shift_imm<32) {
				result = val >> shift_imm;
				SHIFTER_CARRY = BITn(val,shift_imm-1);
			} else if (shift_imm==32) {
				result = 0;
				SHIFTER_CARRY = BIT31(val);
			} else {
				result = 0;
				SHIFTER_CARRY = 0;
			}
			break;
		case 2: /*ASR*/
			if (shift_imm==0) {
				result = val;
				SHIFTER_CARRY = C_FLAG;
			} else if (shift_imm<32) {
				result = (SInt32)val >> shift_imm;
				SHIFTER_CARRY = BITn(val,shift_imm-1);
			} else if (BIT31(val)) {
				result = ~0;
				SHIFTER_CARRY = BIT31(val);
			} else {
				result = 0;
				SHIFTER_CARRY = BIT31(val);
			}
			break;
		default: /*ROR*/
			if (shift_imm==0) {
				result = val;
				SHIFTER_CARRY = C_FLAG;
			}
			else if ((shift_imm&0x1f)==0) {
				result = val;
				SHIFTER_CARRY = BIT31(val);
			}
			else {
				result = rotate_right(val, shift_imm&0x1f);
				SHIFTER_CARRY = BITn(val, (shift_imm&0x1f)-1);
			}
			break;
	}
	return result;
}

/*data processing instructions*/

/*move*/

#ifdef _MODULARIZE_
#define SET_MOVE_FLAGS(val) set_move_flags(emu, val)
static inline void set_move_flags(armulator *emu, UInt32 val)
#else
#define SET_MOVE_FLAGS(val) set_move_flags(val)
static inline void set_move_flags(UInt32 val)
#endif
{
#if 0
	ASGN_N(BIT31(val));
	ASGN_Z(val==0);
	ASGN_C(SHIFTER_CARRY);
#endif
	ASGN_CONDS(ASM_CONDS(BIT31(val), val==0, SHIFTER_CARRY, V_FLAG));
}

void impl_mov_1(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, shifter_operand1(IMPL_ARGS));

	EMULATOR_STUB(mov_1,inst);
}

void impl_mov_1s(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, shifter_operand1_s(IMPL_ARGS));
	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_MOVE_FLAGS(RD);

	EMULATOR_STUB(mov_1s,inst);
}

void impl_mov_2(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, shifter_operand2(IMPL_ARGS));

	EMULATOR_STUB(mov_2,inst);
}

void impl_mov_2s(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, shifter_operand2_s(IMPL_ARGS));
	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_MOVE_FLAGS(RD);

	EMULATOR_STUB(mov_2s,inst);
}

void impl_mov_3(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, shifter_operand3(IMPL_ARGS));

	EMULATOR_STUB(mov_3,inst);
}

void impl_mov_3s(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, shifter_operand3_s(IMPL_ARGS));
	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_MOVE_FLAGS(RD);

	EMULATOR_STUB(mov_3s,inst);
}

/*MVN*/
void impl_mvn_1(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, ~shifter_operand1(IMPL_ARGS));

	EMULATOR_STUB(mvn_1,inst);
}

void impl_mvn_1s(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, ~shifter_operand1_s(IMPL_ARGS));
	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_MOVE_FLAGS(RD);

	EMULATOR_STUB(mvn_1s,inst);
}

void impl_mvn_2(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, ~shifter_operand2(IMPL_ARGS));

	EMULATOR_STUB(mvn_2,inst);
}

void impl_mvn_2s(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, ~shifter_operand2_s(IMPL_ARGS));
	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_MOVE_FLAGS(RD);

	EMULATOR_STUB(mvn_2s,inst);
}

void impl_mvn_3(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, ~shifter_operand3(IMPL_ARGS));

	EMULATOR_STUB(mvn_3,inst);
}

void impl_mvn_3s(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, ~shifter_operand3_s(IMPL_ARGS));
	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else
		SET_MOVE_FLAGS(RD);

	EMULATOR_STUB(mvn_3s,inst);
}

/*ADD*/

#ifdef _MODULARIZE_
#define SET_ADD_FLAGS(_res) set_add_flags(emu, _res)
static inline void set_add_flags(armulator *emu, UInt64 result)
#else
#define SET_ADD_FLAGS(_res) set_add_flags(_res)
static inline void set_add_flags(UInt64 result)
#endif
{

	UInt32 l_res = result, u_res = result>>32;
#if 0
	ASGN_N(BIT31(l_res));
	ASGN_Z(l_res==0);
	ASGN_C(ALU_CARRY);
	ASGN_V(BIT0(u_res)!=BIT31(l_res));
#endif
	ASGN_CONDS(ASM_CONDS(BIT31(l_res), l_res==0, ALU_CARRY,
		BIT0(u_res)!=BIT31(l_res)));
}

#ifdef _MODULARIZE_
#define IMPL_ADD64(_src_a, _src_b) impl_add64(emu, _src_a, _src_b)
static inline UInt64 impl_add64(armulator *emu, SInt32 a, SInt32 b)
#else
#define IMPL_ADD64(_src_a, _src_b) impl_add64(_src_a, _src_b)
static inline UInt64 impl_add64(SInt32 a, SInt32 b)
#endif
{
	UInt64 lhs = a, rhs = b;
	UInt64 result = lhs+rhs;

	ALU_CARRY = ((UInt32)a>>31) ^ ((UInt32)b>>31);
	ALU_CARRY ^= (((UInt32)(result>>32))&0x1);

	return result;
}

#ifdef _MODULARIZE_
#define IMPL_ADD64_W_CARRY(_src_a, _src_b, _src_c) \
	impl_add64_w_carry(emu, _src_a, _src_b, _src_c);
static inline UInt64 impl_add64_w_carry(armulator *emu, 
	SInt32 a, SInt32 b, UInt32 c)
#else
#define IMPL_ADD64_W_CARRY(_src_a, _src_b, _src_c) \
	impl_add64_w_carry(_src_a, _src_b, _src_c);
static inline UInt64 impl_add64_w_carry(
	SInt32 a, SInt32 b, UInt32 c)
#endif
{
	UInt64 lhs = a, rhs = b;
	UInt64 result = lhs+rhs+c;

	ALU_CARRY = ((UInt32)a>>31) ^ ((UInt32)b>>31);
	ALU_CARRY ^= (((UInt32)(result>>32))&0x1);

	return result;
}

void impl_add_1(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, RN + shifter_operand1(IMPL_ARGS));

	EMULATOR_STUB(add_1,inst);
}

void impl_add_1s(IMPL_FORMALS)
{
	UInt64 result;
	result = IMPL_ADD64(RN, shifter_operand1(IMPL_ARGS));
	WRITE_REG(RDFLD, (UInt32)result);

	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_ADD_FLAGS(result);

	EMULATOR_STUB(add_1s,inst);
}

void impl_add_2(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, RN + shifter_operand2(IMPL_ARGS));

	EMULATOR_STUB(add_2,inst);
}

void impl_add_2s(IMPL_FORMALS)
{
	UInt64 result;
	result = IMPL_ADD64(RN, shifter_operand2(IMPL_ARGS));
	WRITE_REG(RDFLD, (UInt32)result);

	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_ADD_FLAGS(result);

	EMULATOR_STUB(add_2s,inst);
}

void impl_add_3(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, RN + shifter_operand3(IMPL_ARGS));

	EMULATOR_STUB(add_3,inst);
}

void impl_add_3s(IMPL_FORMALS)
{
	UInt64 result;
	result = IMPL_ADD64(RN, shifter_operand3(IMPL_ARGS));
	WRITE_REG(RDFLD, (UInt32)result);

	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else
		SET_ADD_FLAGS(result);

	EMULATOR_STUB(add_3s,inst);
}

/*ADC*/
void impl_adc_1(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, RN + shifter_operand1(IMPL_ARGS) + C_FLAG);

	EMULATOR_STUB(adc_1,inst);
}

void impl_adc_1s(IMPL_FORMALS)
{
	UInt64 result;
	result = IMPL_ADD64_W_CARRY(RN, shifter_operand1(IMPL_ARGS), C_FLAG);
	WRITE_REG(RDFLD, (UInt32)result);

	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_ADD_FLAGS(result);

	EMULATOR_STUB(adc_1s,inst);
}

void impl_adc_2(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, RN + shifter_operand2(IMPL_ARGS) + C_FLAG);

	EMULATOR_STUB(adc_2,inst);
}

void impl_adc_2s(IMPL_FORMALS)
{
	UInt64 result;
	result = IMPL_ADD64_W_CARRY(RN, shifter_operand2(IMPL_ARGS), C_FLAG);
	WRITE_REG(RDFLD, (UInt32)result);

	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_ADD_FLAGS(result);

	EMULATOR_STUB(adc_2s,inst);
}

void impl_adc_3(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, RN + shifter_operand3(IMPL_ARGS) + C_FLAG);

	EMULATOR_STUB(adc_3,inst);
}

void impl_adc_3s(IMPL_FORMALS)
{
	UInt64 result;
	result = IMPL_ADD64_W_CARRY(RN, shifter_operand3(IMPL_ARGS), C_FLAG);
	WRITE_REG(RDFLD, (UInt32)result);

	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else
		SET_ADD_FLAGS(result);

	EMULATOR_STUB(adc_3s,inst);
}

/*SUB*/
#ifdef _MODULARIZE_
#define SET_SUB_FLAGS(_res) set_sub_flags(emu, _res)
static inline void set_sub_flags(armulator *emu, UInt64 result)
#else
#define SET_SUB_FLAGS(_res) set_sub_flags(_res)
static inline void set_sub_flags(UInt64 result)
#endif
{
	UInt32 l_res = result, u_res = result>>32;
#if 0
	ASGN_N(BIT31(l_res));
	ASGN_Z(l_res==0);
	ASGN_C(!ALU_CARRY);
	ASGN_V(BIT0(u_res)!=BIT31(l_res));
#endif
	ASGN_CONDS(ASM_CONDS(BIT31(l_res), l_res==0, !ALU_CARRY,
		BIT0(u_res)!=BIT31(l_res)));
}

#ifdef _MODULARIZE_
#define IMPL_SUB64(_src_a, _src_b) impl_sub64(emu, _src_a, _src_b)
static inline UInt64 impl_sub64(armulator *emu, SInt32 a, SInt32 b)
#else
#define IMPL_SUB64(_src_a, _src_b) impl_sub64(_src_a, _src_b)
static inline UInt64 impl_sub64(SInt32 a, SInt32 b)
#endif
{
	UInt64 lhs = a, rhs = b;
	UInt64 result = lhs - rhs;

	ALU_CARRY = ((UInt32)a>>31) ^ ((UInt32)b>>31);
	ALU_CARRY ^= (((UInt32)(result>>32))&0x1);

	return result;
}

#ifdef _MODULARIZE_
#define IMPL_SUB64_W_CARRY(_src_a, _src_b, _src_c) \
	impl_sub64_w_carry(emu, _src_a, _src_b, _src_c)
static inline UInt64 impl_sub64_w_carry(armulator *emu, SInt32 a, SInt32 b, UInt32 c)
#else
#define IMPL_SUB64_W_CARRY(_src_a, _src_b, _src_c) \
	impl_sub64_w_carry(_src_a, _src_b, _src_c)
static inline UInt64 impl_sub64_w_carry(SInt32 a, SInt32 b, UInt32 c)
#endif
{
	UInt64 lhs = a, rhs = b;
	UInt64 result = lhs - rhs - c;

	ALU_CARRY = ((UInt32)a>>31) ^ ((UInt32)b>>31);
	ALU_CARRY ^= (((UInt32)(result>>32))&0x1);

	return result;
}

void impl_sub_1(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, RN - shifter_operand1(IMPL_ARGS));

	EMULATOR_STUB(sub_1,inst);
}

void impl_sub_1s(IMPL_FORMALS)
{
	UInt64 result;
	result = IMPL_SUB64(RN, shifter_operand1(IMPL_ARGS));
	WRITE_REG(RDFLD, (UInt32)result);

	if (RDFLD==15)
		WRITE_CPSR(SPSR);
	else 
		SET_SUB_FLAGS(result);

	EMULATOR_STUB(sub_1s,inst);
}

void impl_sub_2(IMPL_FORMALS)
{
	WRITE_REG(RDFLD, RN - shifter_operand2(IMPL_ARGS));

	EMULATOR_STUB(sub_2,inst);
}

⌨️ 快捷键说明

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