?? dpi.cpp
字號:
/*************************************************************************
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 + -