📄 integerunit.cpp
字号:
/*************************************************************************** IntegerUnit.cpp - unite de calcul entier ------------------- begin : Fri Apr 6 2001 copyright : (C) 2001 Universite Paris Sud and CEA author : Gilles Mouchard email : gilles.mouchard@lri.fr, gilles.mouchard@.cea.fr ***************************************************************************/#include <IntegerUnit.h>inline int IntegerUnit::GetMulLatency(UInt32 op1, UInt32 op2){ op2 = (SInt32) op2 > 0 ? op2 : -op2; if(op2 & 0xff000000) return 6; if(op2 & 0x00ff0000) return 5; if(op2 & 0x0000ff00) return 4; if(op2 & 0x000000ff) return 3; return 2;}inline UInt32 IntegerUnit::RotateLeft(UInt32 v, UInt8 n){ return (v << n) | ((v >> (32 - n)) & ((1 << n) - 1));}inline UInt32 IntegerUnit::Mask(UInt8 mb, UInt8 me){ return(((mb > me) ? ~(((UInt32)-1 >> mb) ^ ((me >= 31) ? 0 : (UInt32) -1 >> (me + 1))): (((UInt32)-1 >> mb) ^ ((me >= 31) ? 0 : (UInt32) -1 >> (me + 1)))));}bool IntegerUnit::Carry(UInt32 a, UInt32 b){ UInt32 c, x, y; int i; if((a == 0) || (b == 0)) return 0; c = 0; for(i = 0; i < 32; i++) { x = (a >> i) & 0x1; y = (b >> i) & 0x1; c = x * y | x * c | y * c; } return c;}const SInt32 MaxInt = 0x7fffffff;bool IntegerUnit::Overflow(SInt32 a, SInt32 b){ return ((a > 0) && (b > 0) && (MaxInt - a < b)) || ((a < 0) && (b < 0) && (-MaxInt - a > b));}bool IntegerUnit::Underflow(SInt32 a, SInt32 b){ return ((a > 0) && (b < 0) && (MaxInt + b < a)) || ((a < 0) && (b > 0) && (-MaxInt + b > a));}void IntegerUnit::Execute(){ const IntegerOperation& operation = inOperation; const IntegerOperands& operands = inOperands; const IntegerTags& tags = inTags;#if defined(DEBUG) || defined(TRACE) UInt32 dbgInstructionCounter = inInstructionCounter; UInt32 dbgProgramCounter = inProgramCounter; UInt32 dbgInstruction = inInstruction;#endif if(inDispatched) { /* A new integer instruction has been started */ branchCounter = inBranchCounter;#ifdef DEBUG if(Debug(DebugIntegerUnit)) { cout << name() << ": dispatched (" << dbgInstructionCounter << ") "; ppc_disassemble_to_stream(dbgInstruction, dbgProgramCounter, stdout); cout << endl; }#endif#ifdef TRACE if(Trace(TraceIntegerUnit)) { trace_file->Begin("execute"); trace_file->Value("unit", "integer"); trace_file->Value("number", dbgInstructionCounter); trace_file->Value("pc", dbgInstructionCounter); trace_file->End("execute"); }#endif dispatched = true; } if(dispatched) { /* An instruction is being executed */ if(latency == 0) { /* The instruction is beginning its execution */#ifdef DEBUG if(Debug(DebugIntegerUnit)) { cout << name() << ": Starting execution (" << dbgInstructionCounter << ") "; ppc_disassemble_to_stream(dbgInstruction, dbgProgramCounter, stdout); cout << endl; cout << name() << ": (RA/RS) = "; WriteHex(cout, operands.data[0]); cout << ", (RA/RB) = "; WriteHex(cout, operands.data[1]); cout << endl; }#endif /* RA : operands.data[0] */ /* RB, immed : operands.data[1] */ UInt64 result64; ca = ov = false; switch(operation.ident) { case ID_MULLI: result32 = operands.data[0] * operands.data[1]; latency = GetMulLatency(operands.data[0], operands.data[1]); break; case ID_SUBFIC: result32 = operands.data[1] - operands.data[0]; ca = operands.data[0] == 0 || Carry(-operands.data[0], operands.data[1]); latency = 1; break; case ID_ADDIC: result32 = operands.data[0] + operands.data[1]; ca = Carry(operands.data[0], operands.data[1]); latency = 1; break; case ID_CMPLI: lt = operands.data[0] < operands.data[1]; gt = operands.data[0] > operands.data[1]; eq = operands.data[0] == operands.data[1]; latency = 1; break; case ID_CMPI: result32 = operands.data[0] - operands.data[1]; lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_ADDICD: result32 = operands.data[0] + operands.data[1]; ca = Carry(operands.data[0], operands.data[1]); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_ADDI: result32 = operation.nullRA ? operands.data[1] : operands.data[0] + operands.data[1]; latency = 1; break; case ID_ADDIS: result32 = operation.nullRA ? (operands.data[1] << 16) : operands.data[0] + (operands.data[1] << 16); latency = 1; break; case ID_ORI: result32 = operands.data[0] | operands.data[1]; latency = 1; break; case ID_ORIS: result32 = operands.data[0] | (operands.data[1] << 16); latency = 1; break; case ID_XORI: result32 = operands.data[0] ^ operands.data[1]; latency = 1; break; case ID_XORIS: result32 = operands.data[0] ^ (operands.data[1] << 16); latency = 1; break; case ID_ANDID: result32 = operands.data[0] & operands.data[1]; lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_ANDISD: result32 = operands.data[0] & (operands.data[1] << 16); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_RLWIMI: { UInt32 r = RotateLeft(operands.data[0], operation.extra.rotate.sh); UInt32 m = Mask(operation.extra.rotate.mb, operation.extra.rotate.me); result32 = (r & m) | (operands.data[1] & (~m)); latency = 1; } break; case ID_RLWIMID: { UInt32 r = RotateLeft(operands.data[0], operation.extra.rotate.sh); UInt32 m = Mask(operation.extra.rotate.mb, operation.extra.rotate.me); result32 = (r & m) | (operands.data[1] & (~m)); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; } break; case ID_RLWINM: { UInt32 r = RotateLeft(operands.data[0], operation.extra.rotate.sh); UInt32 m = Mask(operation.extra.rotate.mb, operation.extra.rotate.me); result32 = r & m; latency = 1; } break; case ID_RLWINMD: { UInt32 r = RotateLeft(operands.data[0], operation.extra.rotate.sh); UInt32 m = Mask(operation.extra.rotate.mb, operation.extra.rotate.me); result32 = r & m; lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; } break; case ID_RLWNM: { UInt32 r = RotateLeft(operands.data[0], operands.data[1] & 31); UInt32 m = Mask(operation.extra.rotate.mb, operation.extra.rotate.me); result32 = r & m; latency = 1; } break; case ID_RLWNMD: { UInt32 r = RotateLeft(operands.data[0], operands.data[1] & 31); UInt32 m = Mask(operation.extra.rotate.mb, operation.extra.rotate.me); result32 = r & m; lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; } break; case ID_CMP: result32 = operands.data[0] - operands.data[1]; lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_SUBFC: result32 = operands.data[1] - operands.data[0]; ca = operands.data[0] == 0 || Carry(-operands.data[0], operands.data[1]); latency = 1; break; case ID_SUBFCD: result32 = operands.data[1] - operands.data[0]; ca = operands.data[0] == 0 || Carry(-operands.data[0], operands.data[1]); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_SUBFCO: result32 = operands.data[1] - operands.data[0]; ca = operands.data[0] == 0 || Carry(-operands.data[0], operands.data[1]); ov = Underflow(operands.data[1], operands.data[0]); latency = 1; break; case ID_SUBFCOD: result32 = operands.data[1] - operands.data[0]; ca = operands.data[0] == 0 || Carry(-operands.data[0], operands.data[1]); ov = Underflow(operands.data[1], operands.data[0]); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_CMPL: lt = operands.data[0] < operands.data[1]; gt = operands.data[0] > operands.data[1]; eq = operands.data[0] == operands.data[1]; latency = 1; break; case ID_ADDC: result32 = operands.data[0] + operands.data[1]; ca = Carry(operands.data[0], operands.data[1]); latency = 1; break; case ID_ADDCD: result32 = operands.data[0] + operands.data[1]; ca = Carry(operands.data[0], operands.data[1]); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_ADDCO: result32 = operands.data[0] + operands.data[1]; ca = Carry(operands.data[0], operands.data[1]); ov = Overflow(operands.data[0], operands.data[1]); latency = 1; break; case ID_ADDCOD: result32 = operands.data[0] + operands.data[1]; ca = Carry(operands.data[0], operands.data[1]); ov = Overflow(operands.data[0], operands.data[1]); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_MULHWU: { UInt64 res = (UInt64) operands.data[0] * (UInt64) operands.data[1]; res = (res >> 32); result32 = (UInt32) res; latency = GetMulLatency(operands.data[0], operands.data[1]); } break; case ID_MULHWUD: result32 = ((UInt64) operands.data[0] * (UInt64) operands.data[1]) >> 32; lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = GetMulLatency(operands.data[0], operands.data[1]); break; case ID_SLW: result32 = (operands.data[1] & 32) ? 0 : (operands.data[0] << (operands.data[1] & 31)); latency = 1; break; case ID_SLWD: result32 = (operands.data[1] & 32) ? 0 : (operands.data[0] << (operands.data[1] & 31)); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_SRW: result32 = (operands.data[1] & 32) ? 0 : (operands.data[0] >> (operands.data[1] & 31)); latency = 1; break; case ID_SRWD: result32 = (operands.data[1] & 32) ? 0 : (operands.data[0] >> (operands.data[1] & 31)); lt = ((SInt32) result32 < 0); gt = ((SInt32) result32 > 0); eq = ((UInt32) result32 == 0); latency = 1; break; case ID_SRAW: { SInt32 src = operands.data[0]; UInt32 n = operands.data[1]; if(n == 0) { result32 = src; ca = false; } else if(n & 0x20) { if(src < 0) { result32 = 0xffffffff; if(src & 0x7fffffff) ca = true; else ca = false; } else { result32 = 0; ca = false; } } else { n = n & 0x1f; result32 = (sword_t) src >> n; if(src < 0 && (src << (32 - n)) != 0) ca = true; else ca = false; } } latency = 1; break; case ID_SRAWD: { SInt32 src = operands.data[0]; UInt32 n = operands.data[1]; if(n == 0) { result32 = src; ca = false; } else if(n & 0x20) { if(src < 0) { result32 = 0xffffffff; if(src & 0x7fffffff) ca = true; else ca = false; } else { result32 = 0; ca = false; } } else { n = n & 0x1f; result32 = (sword_t) src >> n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -