Logo Search packages:      
Sourcecode: yasm version File versions  Download package

void yasm_intnum_calc ( yasm_intnum acc,
yasm_expr_op  op,
yasm_intnum operand,
unsigned long  line 
)

Floating point calculation function: acc = acc op operand.

Note:
Not all operations in yasm_expr_op may be supported; unsupported operations will result in an error.
Parameters:
acc intnum accumulator
op operation
operand intnum operand
line virtual line (of expression)

Definition at line 290 of file intnum.c.

References YASM_EXPR_ADD, YASM_EXPR_AND, YASM_EXPR_DIV, YASM_EXPR_EQ, YASM_EXPR_GE, YASM_EXPR_GT, YASM_EXPR_IDENT, YASM_EXPR_LAND, YASM_EXPR_LE, YASM_EXPR_LNOT, YASM_EXPR_LOR, YASM_EXPR_LT, YASM_EXPR_MOD, YASM_EXPR_MUL, YASM_EXPR_NE, YASM_EXPR_NEG, YASM_EXPR_NOT, YASM_EXPR_OR, YASM_EXPR_SEG, YASM_EXPR_SEGOFF, YASM_EXPR_SHL, YASM_EXPR_SHR, YASM_EXPR_SIGNDIV, YASM_EXPR_SIGNMOD, YASM_EXPR_SUB, YASM_EXPR_WRT, YASM_EXPR_XOR, and yasm_internal_error.

{
    boolean carry = 0;
    wordptr op1, op2 = NULL;

    /* Always do computations with in full bit vector.
     * Bit vector results must be calculated through intermediate storage.
     */
    if (acc->type == INTNUM_BV)
      op1 = acc->val.bv;
    else {
      op1 = op1static;
      BitVector_Empty(op1);
      BitVector_Chunk_Store(op1, 32, 0, acc->val.ul);
    }

    if (operand) {
      if (operand->type == INTNUM_BV)
          op2 = operand->val.bv;
      else {
          op2 = op2static;
          BitVector_Empty(op2);
          BitVector_Chunk_Store(op2, 32, 0, operand->val.ul);
      }
    }

    if (!operand && op != YASM_EXPR_NEG && op != YASM_EXPR_NOT &&
      op != YASM_EXPR_LNOT)
      yasm_internal_error(N_("Operation needs an operand"));

    /* A operation does a bitvector computation if result is allocated. */
    switch (op) {
      case YASM_EXPR_ADD:
          BitVector_add(result, op1, op2, &carry);
          break;
      case YASM_EXPR_SUB:
          BitVector_sub(result, op1, op2, &carry);
          break;
      case YASM_EXPR_MUL:
          BitVector_Multiply(result, op1, op2);
          break;
      case YASM_EXPR_DIV:
          /* TODO: make sure op1 and op2 are unsigned */
          BitVector_Divide(result, op1, op2, spare);
          break;
      case YASM_EXPR_SIGNDIV:
          BitVector_Divide(result, op1, op2, spare);
          break;
      case YASM_EXPR_MOD:
          /* TODO: make sure op1 and op2 are unsigned */
          BitVector_Divide(spare, op1, op2, result);
          break;
      case YASM_EXPR_SIGNMOD:
          BitVector_Divide(spare, op1, op2, result);
          break;
      case YASM_EXPR_NEG:
          BitVector_Negate(result, op1);
          break;
      case YASM_EXPR_NOT:
          Set_Complement(result, op1);
          break;
      case YASM_EXPR_OR:
          Set_Union(result, op1, op2);
          break;
      case YASM_EXPR_AND:
          Set_Intersection(result, op1, op2);
          break;
      case YASM_EXPR_XOR:
          Set_ExclusiveOr(result, op1, op2);
          break;
      case YASM_EXPR_SHL:
          if (operand->type == INTNUM_UL) {
            BitVector_Copy(result, op1);
            BitVector_Move_Left(result, (N_int)operand->val.ul);
          } else  /* don't even bother, just zero result */
            BitVector_Empty(result);
          break;
      case YASM_EXPR_SHR:
          if (operand->type == INTNUM_UL) {
            BitVector_Copy(result, op1);
            BitVector_Move_Right(result, (N_int)operand->val.ul);
          } else  /* don't even bother, just zero result */
            BitVector_Empty(result);
          break;
      case YASM_EXPR_LOR:
          BitVector_Empty(result);
          BitVector_LSB(result, !BitVector_is_empty(op1) ||
                    !BitVector_is_empty(op2));
          break;
      case YASM_EXPR_LAND:
          BitVector_Empty(result);
          BitVector_LSB(result, !BitVector_is_empty(op1) &&
                    !BitVector_is_empty(op2));
          break;
      case YASM_EXPR_LNOT:
          BitVector_Empty(result);
          BitVector_LSB(result, BitVector_is_empty(op1));
          break;
      case YASM_EXPR_EQ:
          BitVector_Empty(result);
          BitVector_LSB(result, BitVector_equal(op1, op2));
          break;
      case YASM_EXPR_LT:
          BitVector_Empty(result);
          BitVector_LSB(result, BitVector_Lexicompare(op1, op2) < 0);
          break;
      case YASM_EXPR_GT:
          BitVector_Empty(result);
          BitVector_LSB(result, BitVector_Lexicompare(op1, op2) > 0);
          break;
      case YASM_EXPR_LE:
          BitVector_Empty(result);
          BitVector_LSB(result, BitVector_Lexicompare(op1, op2) <= 0);
          break;
      case YASM_EXPR_GE:
          BitVector_Empty(result);
          BitVector_LSB(result, BitVector_Lexicompare(op1, op2) >= 0);
          break;
      case YASM_EXPR_NE:
          BitVector_Empty(result);
          BitVector_LSB(result, !BitVector_equal(op1, op2));
          break;
      case YASM_EXPR_SEG:
          yasm__error(line, N_("invalid use of '%s'"), "SEG");
          break;
      case YASM_EXPR_WRT:
          yasm__error(line, N_("invalid use of '%s'"), "WRT");
          break;
      case YASM_EXPR_SEGOFF:
          yasm__error(line, N_("invalid use of '%s'"), ":");
          break;
      case YASM_EXPR_IDENT:
          if (result)
            BitVector_Copy(result, op1);
          break;
      default:
          yasm_internal_error(N_("invalid operation in intnum calculation"));
    }

    /* Try to fit the result into 32 bits if possible */
    if (Set_Max(result) < 32) {
      if (acc->type == INTNUM_BV) {
          BitVector_Destroy(acc->val.bv);
          acc->type = INTNUM_UL;
      }
      acc->val.ul = BitVector_Chunk_Read(result, 32, 0);
    } else {
      if (acc->type == INTNUM_BV) {
          BitVector_Copy(acc->val.bv, result);
      } else {
          acc->type = INTNUM_BV;
          acc->val.bv = BitVector_Clone(result);
      }
    }
}


Generated by  Doxygen 1.6.0   Back to index