void prim_subtract(PRIM_PROTOTYPE) { CHECKOP(2); oper1 = POP(); oper2 = POP(); if (!arith_type(oper2, oper1)) abort_interp("Invalid argument type."); if ((oper1->type == PROG_FLOAT) || (oper2->type == PROG_FLOAT)) { tf1 = (oper2->type == PROG_FLOAT) ? oper2->data.fnumber : oper2->data.number; tf2 = (oper1->type == PROG_FLOAT) ? oper1->data.fnumber : oper1->data.number; if (!nogood(tf1) && !nogood(tf2)) { fresult = tf1 - tf2; } else { fresult = 0.0; fr->error.error_flags.f_bounds = 1; } } else { result = oper2->data.number - oper1->data.number; tl = (double) oper2->data.number - (double) oper1->data.number; if (!arith_good(tl)) fr->error.error_flags.i_bounds = 1; } tmp = (oper2->type == PROG_FLOAT || oper1->type == PROG_FLOAT) ? PROG_FLOAT : oper2->type; CLEAR(oper1); CLEAR(oper2); if (tmp == PROG_FLOAT) push(arg, top, tmp, MIPSCAST & fresult); else push(arg, top, tmp, MIPSCAST & result); }
void prim_divide(PRIM_PROTOTYPE) { CHECKOP(2); oper1 = POP(); oper2 = POP(); if (!arith_type(oper2, oper1)) abort_interp("Invalid argument type"); if ((oper1->type == PROG_FLOAT) || (oper2->type == PROG_FLOAT)) { if ((oper1->type == PROG_INTEGER && !oper1->data.number) || (oper1->type == PROG_FLOAT && fabs(oper1->data.fnumber) < DBL_EPSILON)) { fresult = tp_alt_infinity_handler ? ((oper2->type == PROG_INTEGER) ? oper2->data.number : oper2->data.fnumber) * INF : 0.0; fr->error.error_flags.div_zero = 1; } else { tf1 = (oper2->type == PROG_FLOAT) ? oper2->data.fnumber : oper2->data.number; tf2 = (oper1->type == PROG_FLOAT) ? oper1->data.fnumber : oper1->data.number; if (!no_good(tf1) && !no_good(tf2)) { fresult = tf1 / tf2; } else { if (ISNAN(tf1) || ISNAN(tf2)) { fresult = tp_alt_infinity_handler ? NAN : 0.0; if (!tp_alt_infinity_handler) fr->error.error_flags.nan = 1; } else { fresult = tp_alt_infinity_handler ? (tf1 / tf2) : 0.0; if (!tp_alt_infinity_handler) fr->error.error_flags.f_bounds = 1; } } } } else { if (oper1->data.number) { result = oper2->data.number / oper1->data.number; } else { result = 0; fr->error.error_flags.div_zero = 1; } } tmp = (oper2->type == PROG_FLOAT || oper1->type == PROG_FLOAT) ? PROG_FLOAT : oper2->type; CLEAR(oper1); CLEAR(oper2); if (tmp == PROG_FLOAT) push(arg, top, tmp, MIPSCAST & fresult); else push(arg, top, tmp, MIPSCAST & result); }
void prim_bitshift(PRIM_PROTOTYPE) { CHECKOP(2); oper1 = POP(); oper2 = POP(); if (!arith_type(oper2, oper1) || oper1->type != PROG_INTEGER) abort_interp("Invalid argument type."); if (oper1->data.number > 0) result = oper2->data.number << oper1->data.number; else if (oper1->data.number < 0) result = oper2->data.number >> (-(oper1->data.number)); else
void prim_bitand(PRIM_PROTOTYPE) { CHECKOP(2); oper1 = POP(); oper2 = POP(); if (!arith_type(oper2, oper1)) abort_interp("Invalid argument type."); result = oper2->data.number & oper1->data.number; tmp = oper2->type; CLEAR(oper1); CLEAR(oper2); push(arg, top, tmp, MIPSCAST & result); }
void prim_mod(PRIM_PROTOTYPE) { CHECKOP(2); oper1 = POP(); oper2 = POP(); if ((!arith_type(oper2, oper1)) || (oper1->type == PROG_FLOAT) || (oper2->type == PROG_FLOAT)) abort_interp("Invalid argument type."); if (oper1->data.number) result = oper2->data.number % oper1->data.number; else result = 0; tmp = oper2->type; CLEAR(oper1); CLEAR(oper2); push(arg, top, tmp, MIPSCAST & result); }
void prim_add(PRIM_PROTOTYPE) { CHECKOP(2); oper1 = POP(); oper2 = POP(); if (!arith_type(oper2, oper1)) abort_interp("Invalid argument type"); if ((oper1->type == PROG_FLOAT) || (oper2->type == PROG_FLOAT)) { tf1 = (oper1->type == PROG_FLOAT) ? oper1->data.fnumber : oper1->data.number; tf2 = (oper2->type == PROG_FLOAT) ? oper2->data.fnumber : oper2->data.number; if (!no_good(tf1) && !no_good(tf2)) { fresult = tf1 + tf2; } else { if (ISNAN(tf1) || ISNAN(tf2)) { fresult = tp_alt_infinity_handler ? NAN : 0.0; if (!tp_alt_infinity_handler) fr->error.error_flags.nan = 1; } else { fresult = tp_alt_infinity_handler ? (tf1 + tf2) : 0.0; if (!tp_alt_infinity_handler) fr->error.error_flags.f_bounds = 1; } } } else { result = oper1->data.number + oper2->data.number; tl = (double) oper1->data.number + (double) oper2->data.number; if (!arith_good(tl)) fr->error.error_flags.i_bounds = 1; } tmp = (oper2->type == PROG_FLOAT || oper1->type == PROG_FLOAT) ? PROG_FLOAT : oper2->type; CLEAR(oper1); CLEAR(oper2); if (tmp == PROG_FLOAT) push(arg, top, tmp, MIPSCAST & fresult); else push(arg, top, tmp, MIPSCAST & result); }
void prim_divide(PRIM_PROTOTYPE) { CHECKOP(2); oper1 = POP(); oper2 = POP(); if (!arith_type(oper2, oper1)) abort_interp("Invalid argument type."); if ((oper1->type == PROG_FLOAT) || (oper2->type == PROG_FLOAT)) { if ((oper1->type == PROG_INTEGER && !oper1->data.number) || (oper1->type == PROG_FLOAT && fabs(oper1->data.fnumber) < DBL_EPSILON)) { /* FIXME: This should be NaN. */ fresult = INF; fr->error.error_flags.div_zero = 1; } else { tf1 = (oper2->type == PROG_FLOAT) ? oper2->data.fnumber : oper2->data.number; tf2 = (oper1->type == PROG_FLOAT) ? oper1->data.fnumber : oper1->data.number; if (!nogood(tf1) && !nogood(tf2)) { fresult = tf1 / tf2; } else { fresult = 0.0; fr->error.error_flags.f_bounds = 1; } } } else { if (oper1->data.number) { result = oper2->data.number / oper1->data.number; } else { result = 0; fr->error.error_flags.div_zero = 1; } } tmp = (oper2->type == PROG_FLOAT || oper1->type == PROG_FLOAT) ? PROG_FLOAT : oper2->type; CLEAR(oper1); CLEAR(oper2); if (tmp == PROG_FLOAT) push(arg, top, tmp, MIPSCAST & fresult); else push(arg, top, tmp, MIPSCAST & result); }