ARMemu 发现的BUG及解决方案参考
上周5,我在虚拟机运行MINIGUI时,发现和其和实际机器上运行的结果不一致,经跟踪分析发现SKYEYE存在BUG。在处理Load/Store此类指令时,如果在Load/Store时发生Abort异常,在目前的SKYEYE解决方案中,会进行SwitchMode,进行一些特殊寄存器的切换(R13,R14,及FIQ模式的F8-F12),然后再进行指令的后半部分的执行(LSBase的赋值)。在这里有BUG存在。
举个例子:
LDR R0, , #0x4
假设在执行这条指令前是在USER模式,当解析【R13】时,产生Data Abort,
这时SKYEYE会进行模式切换,切换到ABOR模式
(
oldbank=USERBANK, newbank=ABORTBANK
state->RegBank = state->Reg;
state->RegBank = state->Reg;
state->Reg = state->RegBank;
state->Reg = state->RegBank;
)
然后再执行 state->Reg += 0x4的动作,注意这里的state->Reg代表的是Abort模式里的R13,
而实际要操作的应该是USER模式的R13,在这里发生了错误。
参考解决方案:
1。state下ARMWord Reg; 改成 ARMWord* Reg;用于指向各个模式的RegBank
2。ARMul_SwitchMode改用如下实现
ARMword
ARMul_SwitchMode ( ARMword oldmode, ARMword newmode)
{
unsigned i;
ARMword oldbank;
ARMword newbank;
oldbank = ModeToBank (oldmode);
newbank = state->Bank = ModeToBank (newmode);
/* Do we really need to do it?*/
if (oldbank != newbank) {
/* Save away the old registers.*/
switch (oldbank) {
case USERBANK:
break;
case IRQBANK:
case SVCBANK:
case ABORTBANK:
case UNDEFBANK:
for( i=0; i<13; i++ )
state->RegBank = state->RegBank;
state->RegBank = state->RegBank;
/*
if (newbank == FIQBANK)
for (i = 8; i < 13; i++)
state->RegBank =
state->Reg;
state->RegBank = state->Reg;
state->RegBank = state->Reg;
*/
break;
case FIQBANK:
/*
for (i = 8; i < 15; i++)
state->RegBank = state->Reg;
*/
for( i=0; i<8; i++ )
state->RegBank = state->RegBank;
state->RegBank = state->RegBank;
break;
case DUMMYBANK:
for (i = 8; i < 15; i++)
state->RegBank = 0;
break;
default:
abort ();
}
/* Restore the new registers.*/
state->Reg = state->RegBank;
switch (newbank) {
case USERBANK:
break;
case IRQBANK:
case SVCBANK:
case ABORTBANK:
case UNDEFBANK:
/*
if (oldbank == FIQBANK)
for (i = 8; i < 13; i++)
state->Reg =
state->RegBank;
state->Reg = state->RegBank;
state->Reg = state->RegBank;
*/
for( i=0; i<13; i++ )
state->Reg = state->RegBank;
state->Reg = state->RegBank;
break;
case FIQBANK:
/*
for (i = 8; i < 15; i++)
state->Reg = state->RegBank;
*/
for( i=0; i<8; i++ )
state->Reg = state->RegBank;
state->Reg = state->RegBank;
break;
case DUMMYBANK:
for (i = 8; i < 15; i++)
state->Reg = 0;
break;
default:
abort ();
}
}
return newmode;
}
3。在ARMemu.c的switch ((int) BITS (20, 27))代码前增加下面的语句,用于记录指令执行前的reg和bank
ARMword* Reg = state->Reg;
int obank = this->Bank;
switch ((int) BITS (20, 27)) {
4。将LSBase = val; 的地方改用nlLSBase(val);目的就是进行存在模式切换时,非公用寄存器的维护
#define nlLSBase( val ) Reg = (val); if( obank != state->Bank )BankRegisterMapping( Reg, LHSReg, obank )static void BankRegisterMapping( ARMword* oreg, int index, int obank )
{
if( index == 13 || index == 14 )
return;
if( index <= 7 || index == 15 )
{
state->Reg = oreg;
return;
}
//8 - 14
if( obank == FIQBANK )
return;
int nbank = state->Bank;
if( nbank != FIQBANK )
state->Reg = oreg;
}
[ 本帖最后由 zyjjingle 于 2008-11-11 23:10 编辑 ]
回复 1# zyjjingle 的帖子
另外:LoadMult,LoadSMult,StoreMult,StoreSMult的异常处理部分要做些调整ARMword* Reg = state->Reg;
int obank = state->Bank;
。。。。。。
L_ldm_makeabort:
if (state->Aborted)
{
//异常处理
TAKEABORT;
//回写到异常前的模式
if( state->lateabtSig )
if (BIT (21) && LHSReg != 15)
{
nlLSBase( WBBase );
}
}
else if (BIT (21) && LHSReg != 15)
{
LSBase = WBBase;
}
[ 本帖最后由 zyjjingle 于 2008-11-12 11:19 编辑 ]
可否上传修改后文件
可否上传修改后文件,我照楼主的方法修改了不行,楼主可否上传修改后文件?另:楼主的skyeye是哪个版本。
页:
[1]