📄 shfloat.c
字号:
// store emulation result back to context
*fpRegN1 = dp2.high;
*fpRegN2 = dp2.low;
}
}else {
fp1.i = *fpRegN1;
fp2.i = *fpRegM1;
switch(OpcodeExt)
{
case FADD_OP:
function = (void*)&_adds;
break;
case FSUB_OP:
function = (void*)&_subs;
break;
case FMUL_OP:
function = (void*)&_muls;
break;
case FDIV_OP:
function = (void*)&_divs;
break;
case FCMP_EQ:
function = (void*)&_eqs;
break;
case FCMP_GT:
function = (void*)&_gts;
break;
}
if ((OpcodeExt == FCMP_EQ) || (OpcodeExt == FCMP_GT))
{
fp1.i = ((int(*)(float,float))(function))(fp1.f, fp2.f);
//
// If SR-tbit is not matched retval from CRT compare,
// then update SR-tbit to match retval from
// CRT compare.
//
pctx->Psr &= (0xfffffffe & (fp1.i != 0));
}else {
fp1.f = ((float(*)(float,float))(function))(fp1.f,fp2.f);
*fpRegN1 = fp1.i;
}
}
break;
case 0xd:
//
// All these functions take one operand only.
//
switch(RegM)
{
case FLOAT_OP:
if (prbit)
{
// float fpul,drn
fp1.i = pctx->Fpul;
dp1.d = _itod(fp1.i);
*fpRegN1 = dp1.high;
*fpRegN2 = dp1.low;
}else {
// float fpul, frn
fp1.i = pctx->Fpul;
fp1.f = _itos(fp1.i);
*fpRegN1 = fp1.i;
}
break;
case FTRC_OP:
if (prbit)
{
// ftrc drn,fpul
dp1.high = *fpRegM1;
dp1.low = *fpRegM2;
dp1.high = _dtoi(dp1.d);
*fpRegN1 = dp1.high;
}else{
// ftrc frn,fpul
fp1.i = *fpRegM1;
fp1.i = _stoi(fp1.f);
*fpRegN1 = fp1.i;
}
break;
case FSQRT_OP:
// fsqrt drn
if (prbit)
{
dp1.high = *fpRegN1;
dp1.low = *fpRegN2;
dp1.d = sqrt(dp1.d);
*fpRegN1 = dp1.high;
*fpRegN2 = dp1.low;
}else {
fp1.i = *fpRegN1;
fp1.f = (float)sqrt((double)fp1.f);
*fpRegN1 = fp1.i;
}
break;
case FCNVSD_OP:
//fcnvsd fpul, drn
if (prbit)
{
fp1.i = pctx->Fpul;
dp1.d = _stod(fp1.f);
// copy result back to user context
*fpRegN1 = dp1.high;
*fpRegN2 = dp1.low;
}else{
// else undefined operation
// propagate exception to user
retVal = 0;
}
break;
case FCNVDS_OP:
// fcnvds drn,fpul
if (prbit)
{
dp1.high = *fpRegN1;
dp1.low = *fpRegN2;
fp1.f = _dtos(dp1.d);
// copy result back to user context
pctx->Fpul = fp1.i;
}else{
// else undefined operation
// propagate exception to user
retVal = 0;
}
break;
case FIPR_OP:
//
// Recalculated RegN and RegM for FIPR instr
// fipr has opcode 1111 nnmm 1110 1101
// nn -- represent fvn
// mm -- represent fvm
//
if (prbit)
{
// else undefined operation
// propagate exception to user
retVal = 0;
}else {
RegN = (RegN & 0xc);
RegM = ((RegM & 0x3) << 2);
if (!frbit)
{
pFVn = pctx->FRegs + RegN;
pFVm = pctx->FRegs + RegM;
} else {
pFVn = pctx->xFRegs + RegN;
pFVm = pctx->xFRegs + RegM;
}
fipr(pFVm, pFVn);
}
break;
case FTRV_OP:
if (prbit)
{
// else undefined operation
// propagate exception to user
retVal = 0;
}else{
//
// Recalculated RegN for ftrv instruction
// ftrv has opcode 1111 nn01 1111 1101
// instruction format for ftrv xmtrx,fvn
// nn -- represent fvn
//
if (!frbit)
{
pXMTRX = pctx->xFRegs;
pFVn = pctx->FRegs + (RegN -1);
}else {
pXMTRX = pctx->FRegs;
pFVn = pctx->xFRegs + (RegN -1);
}
ftrv(pXMTRX, pFVn);
}
break;
} // switch(RegM)
break; // end case 0xd
case FMAC_OP:
//
// need to handle differently,
// call _muls, then _adds
//
if (prbit)
{
// undefined operation
// propagate exception to user
retVal = 0;
} else {
if (!frbit)
{
fp1.i = pctx->FRegs[0];
}else{
fp1.i = pctx->xFRegs[0];
}
fp2.i = *fpRegM1;
fp2.f = _muls(fp1.f,fp2.f);
fp1.i = *fpRegN1;
fp2.f= _adds(fp1.f,fp2.f);
*fpRegN1 = fp2.i;
}
break;
default:
NKDbgPrintfW(L"HandleHWFloatException: UNKNOWN INSTRUCTION.\r\n");
break;
} // switch(opcode)
}_finally{
// pr in fpscr is currently cleared
// write fpscr into user thread
pctx->Fpscr = get_fpscr();
// ensure that pr is set correctly in user context fpscr
if (prbit)
{
pctx->Fpscr |= PR;
}
CauseField = (pctx->Fpscr & 0x0003f000)>>12;
if (CauseField & 0x10)
ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
else if (CauseField & 0x8)
ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
else if (CauseField & 0x4)
ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW;
else if (CauseField & 0x2)
ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW;
else if (CauseField & 0x1)
ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT;
//#define DEBUG_STRING
#ifdef DEBUG_STRING
else if(_abnormal_termination())
{
NKDbgPrintfW(L"An exception occur after enumlation call in HandleHWFloatException\r\n");
NKDbgPrintfW(L"fpscr status: 0x%x\r\n", get_fpscr());
}
#endif
}
}__except(1){
//
// fp emulation raised exception,
// return 0 causes exception to be propagated to user.
//
return 0;
}
//
// fp operation successfully emulated, return 1 causes control to
// return to succeeding instruction.
//
return retVal;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -