STATIC void GenPrep(int* idx) { int tok; int oldIdxRight, oldIdxLeft, t0, t1; if (*idx < 0) //error("GenPrep(): idx < 0\n"); errorInternal(100); tok = stack[*idx][0]; oldIdxRight = --*idx; switch (tok) { case tokAssignMul: case tokUDiv: case tokUMod: case tokAssignUDiv: case tokAssignUMod: if (stack[oldIdxRight][0] == tokNumInt || stack[oldIdxRight][0] == tokNumUint) { unsigned m = truncUint(stack[oldIdxRight][1]); if (m && !(m & (m - 1))) { // Change multiplication to left shift, this helps indexing arrays of ints/pointers/etc if (tok == tokAssignMul) { t1 = 0; while (m >>= 1) t1++; stack[oldIdxRight][1] = t1; tok = tokAssignLSh; } // Change unsigned division to right shift and unsigned modulo to bitwise and else if (tok == tokUMod || tok == tokAssignUMod) { stack[oldIdxRight][1] = (int)(m - 1); tok = (tok == tokUMod) ? '&' : tokAssignAnd; } else { t1 = 0; while (m >>= 1) t1++; stack[oldIdxRight][1] = t1; tok = (tok == tokUDiv) ? tokURShift : tokAssignURSh; } stack[oldIdxRight + 1][0] = tok; }
void GenPrintOperand(int op, int val) { if (op >= MipsOpRegZero && op <= MipsOpRegRa) { printf2("$%d", op); } else if (op >= MipsOpIndRegZero && op <= MipsOpIndRegRa) { printf2("%d($%d)", truncInt(val), op - MipsOpIndRegZero); } else { switch (op) { case MipsOpConst: printf2("%d", truncInt(val)); break; case MipsOpLabelGpOption: if (UseGp) { printf2("%%gp_rel("); GenPrintLabel(IdentTable + val); printf2(")($28)"); } else { printf2("%%lo("); GenPrintLabel(IdentTable + val); printf2(")($1)"); } break; case MipsOpLabel: GenPrintLabel(IdentTable + val); break; case MipsOpNumLabel: GenPrintNumLabel(val); break; default: //error("WTF!\n"); errorInternal(100); break; } } }
STATIC void GenPrintOperand(int op, int val) { if (op >= Tr32OpReg0 && op <= Tr32OpRegFlags) { GenRegsUsed |= 1 << op; switch (op) { case Tr32OpRegBp: printf2("%%bp"); break; case Tr32OpRegSp: printf2("%%sp"); break; case Tr32OpRegY: printf2("%%y"); break; case Tr32OpRegFlags: printf2("%%flags"); break; default: printf2("%%r%d", op); } } else if (op >= Tr32OpIndReg0 && op <= Tr32OpIndRegFlags) { GenPrintOperand(op - Tr32OpIndReg0, 0); val = truncInt(val); if (val) printf2(", %d", val); } else { switch (op) { case Tr32OpConst: printf2("%d", truncInt(val)); break; case Tr32OpLabel: GenPrintLabel(IdentTable + val); break; case Tr32OpNumLabel: GenPrintNumLabel(val); break; default: //error("WTF!\n"); errorInternal(100); break; } } }
// Original, primitive stack-based code generator // DONE: test 32-bit code generation void GenExpr0(void) { int i; int gotUnary = 0; int maxCallDepth = 0; int callDepth = 0; int paramOfs = 0; for (i = 0; i < sp; i++) if (stack[i][0] == '(') { if (++callDepth > maxCallDepth) maxCallDepth = callDepth; } else if (stack[i][0] == ')') { callDepth--; } CanUseTempRegs = maxCallDepth == 0; TempsUsed = 0; for (i = 0; i < sp; i++) { int tok = stack[i][0]; int v = stack[i][1]; #ifndef NO_ANNOTATIONS switch (tok) { case tokNumInt: printf2(" # %d\n", truncInt(v)); break; case tokNumUint: printf2(" # %uu\n", truncUint(v)); break; case tokIdent: printf2(" # %s\n", IdentTable + v); break; case tokLocalOfs: printf2(" # local ofs\n"); break; case ')': printf2(" # ) fxn call\n"); break; case tokUnaryStar: printf2(" # * (read dereference)\n"); break; case '=': printf2(" # = (write dereference)\n"); break; case tokShortCirc: printf2(" # short-circuit "); break; case tokGoto: printf2(" # sh-circ-goto "); break; case tokLogAnd: printf2(" # short-circuit && target\n"); break; case tokLogOr: printf2(" # short-circuit || target\n"); break; case tokIf: case tokIfNot: break; default: printf2(" # %s\n", GetTokenName(tok)); break; } #endif switch (tok) { case tokNumInt: case tokNumUint: if (!(i + 1 < sp && (strchr("+-&^|", stack[i + 1][0]) || stack[i + 1][0] == tokLShift || stack[i + 1][0] == tokRShift || stack[i + 1][0] == tokURShift))) { if (gotUnary) GenPushReg(MipsOpRegV0); GenPrintInstr2Operands(MipsInstrLI, 0, MipsOpRegV0, 0, MipsOpConst, v); } gotUnary = 1; break; case tokIdent: if (gotUnary) GenPushReg(MipsOpRegV0); if (!(i + 1 < sp && (stack[i + 1][0] == ')' || stack[i + 1][0] == tokUnaryStar || stack[i + 1][0] == tokInc || stack[i + 1][0] == tokDec || stack[i + 1][0] == tokPostInc || stack[i + 1][0] == tokPostDec))) { GenPrintInstr2Operands(MipsInstrLA, 0, MipsOpRegV0, 0, MipsOpLabel, v); } gotUnary = 1; break; case tokLocalOfs: if (gotUnary) GenPushReg(MipsOpRegV0); if (!(i + 1 < sp && (stack[i + 1][0] == tokUnaryStar || stack[i + 1][0] == tokInc || stack[i + 1][0] == tokDec || stack[i + 1][0] == tokPostInc || stack[i + 1][0] == tokPostDec))) { GenPrintInstr3Operands(MipsInstrAddU, 0, MipsOpRegV0, 0, MipsOpRegFp, 0, MipsOpConst, v); } gotUnary = 1; break; case '(': if (gotUnary) GenPushReg(MipsOpRegV0); gotUnary = 0; if (v < 16) GenLocalAlloc(16 - v); paramOfs = v - 4; break; case ',': if (maxCallDepth == 1) { if (paramOfs == 16) { GenPushReg(MipsOpRegV0); gotUnary = 0; } if (paramOfs >= 0 && paramOfs <= 12) { GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegA0 + paramOfs / 4, 0, MipsOpRegV0, 0); gotUnary = 0; } paramOfs -= 4; } break; case ')': if (maxCallDepth != 1) { if (v >= 4) GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegA0, 0, MipsOpIndRegSp, 0); if (v >= 8) GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegA1, 0, MipsOpIndRegSp, 4); if (v >= 12) GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegA2, 0, MipsOpIndRegSp, 8); if (v >= 16) GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegA3, 0, MipsOpIndRegSp, 12); } else { int vv = v; if (vv > 16) vv = 16; if (vv) GenLocalAlloc(vv); } if (stack[i - 1][0] == tokIdent) { GenPrintInstr1Operand(MipsInstrJAL, 0, MipsOpLabel, stack[i - 1][1]); } else { GenPrintInstr1Operand(MipsInstrJAL, 0, MipsOpRegV0, 0); } if (v < 16) v = 16; GenLocalAlloc(-v); break; case tokUnaryStar: if (stack[i - 1][0] == tokIdent) GenReadIdent(MipsOpRegV0, v, stack[i - 1][1]); else if (stack[i - 1][0] == tokLocalOfs) GenReadLocal(MipsOpRegV0, v, stack[i - 1][1]); else GenReadIndirect(MipsOpRegV0, MipsOpRegV0, v); break; case tokUnaryPlus: break; case '~': GenPrintInstr3Operands(MipsInstrNor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpRegV0, 0); break; case tokUnaryMinus: GenPrintInstr3Operands(MipsInstrSubU, 0, MipsOpRegV0, 0, MipsOpRegZero, 0, MipsOpRegV0, 0); break; case '+': case '-': case '*': case '&': case '^': case '|': case tokLShift: case tokRShift: case tokURShift: if ((stack[i - 1][0] == tokNumInt || stack[i - 1][0] == tokNumUint) && tok != '*') { int instr = GenGetBinaryOperatorInstr(tok); GenPrintInstr3Operands(instr, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, stack[i - 1][1]); } else { int instr = GenGetBinaryOperatorInstr(tok); int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(instr, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); } break; case '/': case tokUDiv: case '%': case tokUMod: { int reg = GenPopReg(MipsOpRegT0); if (tok == '/' || tok == '%') GenPrintInstr2Operands(MipsInstrDiv, 0, reg, 0, MipsOpRegV0, 0); else GenPrintInstr2Operands(MipsInstrDivU, 0, reg, 0, MipsOpRegV0, 0); if (tok == '%' || tok == tokUMod) GenPrintInstr1Operand(MipsInstrMfHi, 0, MipsOpRegV0, 0); else GenPrintInstr1Operand(MipsInstrMfLo, 0, MipsOpRegV0, 0); } break; case tokInc: case tokDec: if (stack[i - 1][0] == tokIdent) { GenIncDecIdent(MipsOpRegV0, v, stack[i - 1][1], tok); } else if (stack[i - 1][0] == tokLocalOfs) { GenIncDecLocal(MipsOpRegV0, v, stack[i - 1][1], tok); } else { GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegT0, 0, MipsOpRegV0, 0); GenIncDecIndirect(MipsOpRegV0, MipsOpRegT0, v, tok); } break; case tokPostInc: case tokPostDec: if (stack[i - 1][0] == tokIdent) { GenPostIncDecIdent(MipsOpRegV0, v, stack[i - 1][1], tok); } else if (stack[i - 1][0] == tokLocalOfs) { GenPostIncDecLocal(MipsOpRegV0, v, stack[i - 1][1], tok); } else { GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegT0, 0, MipsOpRegV0, 0); GenPostIncDecIndirect(MipsOpRegV0, MipsOpRegT0, v, tok); } break; case tokPostAdd: case tokPostSub: { int instr = GenGetBinaryOperatorInstr(tok); int reg = GenPopReg(MipsOpRegT0); GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); GenReadIndirect(MipsOpRegV0, reg, v); GenPrintInstr3Operands(instr, 0, MipsOpRegT1, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); GenWriteIndirect(reg, MipsOpRegT1, v); } break; case tokAssignAdd: case tokAssignSub: case tokAssignMul: case tokAssignAnd: case tokAssignXor: case tokAssignOr: case tokAssignLSh: case tokAssignRSh: case tokAssignURSh: { int instr = GenGetBinaryOperatorInstr(tok); int reg = GenPopReg(MipsOpRegT0); GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); GenReadIndirect(MipsOpRegV0, reg, v); GenPrintInstr3Operands(instr, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpRegT1, 0); GenWriteIndirect(reg, MipsOpRegV0, v); GenExtendRegIfNeeded(MipsOpRegV0, v); } break; case tokAssignDiv: case tokAssignUDiv: case tokAssignMod: case tokAssignUMod: { int reg = GenPopReg(MipsOpRegT0); GenReadIndirect(MipsOpRegT1, reg, v); if (tok == tokAssignDiv || tok == tokAssignMod) GenPrintInstr2Operands(MipsInstrDiv, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); else GenPrintInstr2Operands(MipsInstrDivU, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); if (tok == tokAssignMod || tok == tokAssignUMod) GenPrintInstr1Operand(MipsInstrMfHi, 0, MipsOpRegV0, 0); else GenPrintInstr1Operand(MipsInstrMfLo, 0, MipsOpRegV0, 0); GenWriteIndirect(reg, MipsOpRegV0, v); GenExtendRegIfNeeded(MipsOpRegV0, v); } break; case '=': { int reg = GenPopReg(MipsOpRegT0); GenWriteIndirect(reg, MipsOpRegV0, v); GenExtendRegIfNeeded(MipsOpRegV0, v); } break; /* i = il < ir; // i = slt(il, ir); i = il <= ir; // i = slt(ir, il) ^ 1; i = il > ir; // i = slt(ir, il); i = il >= ir; // i = slt(il, ir) ^ 1; i = il == ir; // i = sltu(il ^ ir, 1); i = il != ir; // i = sltu(0, il ^ ir); */ case '<': { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLT, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); } break; case tokULess: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); } break; case '>': { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLT, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, reg, 0); } break; case tokUGreater: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, reg, 0); } break; case tokLEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLT, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, reg, 0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokULEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, reg, 0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokGEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLT, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokUGEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokNEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegZero, 0, MipsOpRegV0, 0); } break; case tok_Bool: GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegZero, 0, MipsOpRegV0, 0); break; case tokSChar: GenPrintInstr3Operands(MipsInstrSLL, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 24); GenPrintInstr3Operands(MipsInstrSRA, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 24); break; case tokUChar: GenPrintInstr3Operands(MipsInstrAnd, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 0xFF); break; case tokShort: GenPrintInstr3Operands(MipsInstrSLL, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 16); GenPrintInstr3Operands(MipsInstrSRA, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 16); break; case tokUShort: GenPrintInstr3Operands(MipsInstrAnd, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 0xFFFF); break; case tokShortCirc: #ifndef NO_ANNOTATIONS if (v >= 0) printf2("&&\n"); else printf2("||\n"); #endif if (v >= 0) GenJumpIfZero(v); // && else GenJumpIfNotZero(-v); // || gotUnary = 0; break; case tokGoto: #ifndef NO_ANNOTATIONS printf2("goto\n"); #endif GenJumpUncond(v); gotUnary = 0; break; case tokLogAnd: case tokLogOr: GenNumLabel(v); break; case tokVoid: gotUnary = 0; break; case tokComma: break; case tokIf: GenJumpIfNotZero(stack[i][1]); break; case tokIfNot: GenJumpIfZero(stack[i][1]); break; default: //error("Error: Internal Error: GenExpr0(): unexpected token %s\n", GetTokenName(tok)); errorInternal(102); break; } } }
int GenGetBinaryOperatorInstr(int tok) { switch (tok) { case tokPostAdd: case tokAssignAdd: case '+': return MipsInstrAddU; case tokPostSub: case tokAssignSub: case '-': return MipsInstrSubU; case '&': case tokAssignAnd: return MipsInstrAnd; case '^': case tokAssignXor: return MipsInstrXor; case '|': case tokAssignOr: return MipsInstrOr; case '<': case '>': case tokLEQ: case tokGEQ: case tokEQ: case tokNEQ: case tokULess: case tokUGreater: case tokULEQ: case tokUGEQ: return MipsInstrNop; case '*': case tokAssignMul: return MipsInstrMul; case '/': case '%': case tokAssignDiv: case tokAssignMod: return MipsInstrDiv; case tokUDiv: case tokUMod: case tokAssignUDiv: case tokAssignUMod: return MipsInstrDivU; case tokLShift: case tokAssignLSh: return MipsInstrSLL; case tokRShift: case tokAssignRSh: return MipsInstrSRA; case tokURShift: case tokAssignURSh: return MipsInstrSRL; default: //error("Error: Invalid operator\n"); errorInternal(101); return 0; } }
STATIC int GenGetBinaryOperatorInstr(int tok) { switch (tok) { case tokPostAdd: case tokAssignAdd: case '+': return Tr32InstrAdd; case tokPostSub: case tokAssignSub: case '-': return Tr32InstrSub; case tokRevMinus: return Tr32InstrRSub; case '&': case tokAssignAnd: return Tr32InstrAnd; case '^': case tokAssignXor: return Tr32InstrXor; case '|': case tokAssignOr: return Tr32InstrOr; case '<': case '>': case tokLEQ: case tokGEQ: case tokEQ: case tokNEQ: case tokULess: case tokUGreater: case tokULEQ: case tokUGEQ: return Tr32InstrNop; case '*': case tokAssignMul: return Tr32InstrMul; case '/': case '%': case tokAssignDiv: case tokAssignMod: GenRegsUsed |= 1 << Tr32OpRegY; // TBD??? hacky return Tr32InstrSDiv; case tokUDiv: case tokUMod: case tokAssignUDiv: case tokAssignUMod: GenRegsUsed |= 1 << Tr32OpRegY; // TBD??? hacky return Tr32InstrDiv; case tokLShift: case tokAssignLSh: return Tr32InstrLLS; case tokRShift: case tokAssignRSh: return Tr32InstrARS; case tokURShift: case tokAssignURSh: return Tr32InstrLRS; default: //error("Error: Invalid operator\n"); errorInternal(101); return 0; } }
// Multiplies an integer (cnt decimal digits (0 to 9) from digits[]) by // 10**eexp, converts the product to a float and returns it as unsigned int. // This is an inefficient but straightforward algorithm with proper rounding. STATIC unsigned d2f(unsigned char* digits, int cnt, int eexp) { unsigned numDecDigits; unsigned denDecDigits; unsigned numBinDigits; unsigned numBytes; int tmp; unsigned char remainder; int binExp = 0; int inexact = 0; int lastInexact = 0; unsigned res; // 0? if (cnt == 1 && *digits == 0) return 0; // less than the denormalized minimum? if (eexp < FP_MIN_EXP - (cnt - 1)) return 0; // greater than the normalized maximum? if (eexp > FP_MAX_EXP - (cnt - 1)) return 0x7F800000; // +INF numDecDigits = cnt + ((eexp >= 0) ? eexp : 0); denDecDigits = 1 + ((eexp < 0) ? -eexp : 0); // 10/3=3.3(3) > log2(10)~=3.32 if (eexp >= 0) { unsigned t1 = (numDecDigits * 10 + 2) / 3; unsigned t2 = FP_MANT_BITS + 1; numBinDigits = (t1 >= t2) ? t1 : t2; } else { unsigned t1 = (numDecDigits * 10 + 2) / 3; unsigned t2 = (denDecDigits * 10 + 2) / 3 + FP_MANT_BITS + 1 + 1; numBinDigits = (t1 >= t2) ? t1 : t2; } numBytes = (numBinDigits + 7) / 8; if (numBytes > (unsigned)FP_BUF_SIZE) errorInternal(200); memset(ConstBinDigits, 0, numBytes); // Convert the numerator to binary for (tmp = 0; tmp < cnt; tmp++) ChainMultiplyAdd(ConstBinDigits, numBytes, 10, digits[tmp]); for (tmp = eexp; tmp > 0; tmp--) ChainMultiplyAdd(ConstBinDigits, numBytes, 10, 0); // If the denominator isn't 1, divide the numerator by the denominator // getting at least FractionBitCnt+2 significant bits of quotient if (eexp < 0) { binExp = -(int)(numBinDigits - (numDecDigits * 10 + 2) / 3); for (tmp = binExp; tmp < 0; tmp++) ChainMultiplyAdd(ConstBinDigits, numBytes, 2, 0); for (tmp = eexp; tmp < 0; tmp++) ChainDivide(ConstBinDigits, numBytes, 10, &remainder), lastInexact = inexact, inexact |= !!remainder; } // Find the most significant bit and normalize the mantissa // by shifting it left for (tmp = numBytes - 1; tmp >= 0 && !ConstBinDigits[tmp]; tmp--); if (tmp >= 0) { tmp = tmp * 8 + 7; while (!(ConstBinDigits[tmp / 8] & (1 << tmp % 8))) tmp--; while (tmp < FP_MANT_BITS) ChainMultiplyAdd(ConstBinDigits, numBytes, 2, 0), binExp--, tmp++; } // Find the most significant bit and normalize the mantissa // by shifting it right do { remainder = 0; for (tmp = numBytes - 1; tmp >= 0 && !ConstBinDigits[tmp]; tmp--); if (tmp >= 0) { tmp = tmp * 8 + 7; while (!(ConstBinDigits[tmp / 8] & (1 << tmp % 8))) tmp--; while (tmp > FP_MANT_BITS) ChainDivide(ConstBinDigits, numBytes, 2, &remainder), lastInexact = inexact, inexact |= !!remainder, binExp++, tmp--; while (binExp < 2 - (1 << (FP_EXP_BITS - 1)) - FP_MANT_BITS) ChainDivide(ConstBinDigits, numBytes, 2, &remainder), lastInexact = inexact, inexact |= !!remainder, binExp++; } // Round to nearest even remainder &= (lastInexact | (ConstBinDigits[0] & 1)); if (remainder) ChainMultiplyAdd(ConstBinDigits, numBytes, 1, 1); } while (remainder); // Collect the result's mantissa res = 0; while (tmp >= 0) { res <<= 8; res |= ConstBinDigits[tmp / 8]; tmp -= 8; } // Collect the result's exponent binExp += (1 << (FP_EXP_BITS - 1)) - 1 + FP_MANT_BITS; if (!(res & (1u << FP_MANT_BITS))) binExp = 0; // subnormal or 0 res &= ~(1u << FP_MANT_BITS); if (binExp >= (1 << FP_EXP_BITS) - 1) binExp = (1 << FP_EXP_BITS) - 1, res = 0, inexact |= 1; // +INF res |= (unsigned)binExp << FP_MANT_BITS; return res; }