예제 #1
0
파일: cgtr3k2.c 프로젝트: gdos/SmallerC
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;
      }
예제 #2
0
파일: cgmips.c 프로젝트: Benderx2/SmallerC
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;
    }
  }
}
예제 #3
0
파일: cgtr3k2.c 프로젝트: gdos/SmallerC
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;
    }
  }
}
예제 #4
0
파일: cgmips.c 프로젝트: Benderx2/SmallerC
// 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;
    }
  }
}
예제 #5
0
파일: cgmips.c 프로젝트: Benderx2/SmallerC
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;
  }
}
예제 #6
0
파일: cgtr3k2.c 프로젝트: gdos/SmallerC
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;
  }
}
예제 #7
0
파일: fp.c 프로젝트: alexfru/SmallerC
// 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;
}