/* compute <val1> / <val2> */ static struct eval_value_t f_div(struct eval_value_t val1, struct eval_value_t val2) { enum eval_type_t et; struct eval_value_t val; /* symbols are not allowed in arithmetic expressions */ if (val1.type == et_symbol || val2.type == et_symbol) { eval_error = ERR_BADEXPR; return err_value; } /* get result type, and perform operation in that type */ et = result_type(val1.type, val2.type); switch (et) { case et_double: val.type = et_double; val.value.as_double = eval_as_double(val1) / eval_as_double(val2); break; case et_float: val.type = et_float; val.value.as_float = eval_as_float(val1) / eval_as_float(val2); break; #ifdef HOST_HAS_QWORD case et_qword: val.type = et_qword; val.value.as_qword = eval_as_qword(val1) / eval_as_qword(val2); break; case et_sqword: val.type = et_sqword; val.value.as_sqword = eval_as_sqword(val1) / eval_as_sqword(val2); break; #endif /* HOST_HAS_QWORD */ case et_addr: val.type = et_addr; val.value.as_addr = eval_as_addr(val1) / eval_as_addr(val2); break; case et_uint: val.type = et_uint; val.value.as_uint = eval_as_uint(val1) / eval_as_uint(val2); break; case et_int: val.type = et_int; val.value.as_int = eval_as_int(val1) / eval_as_int(val2); break; default: panic("bogus expression type"); } return val; }
char * /* err str, NULL for no err */ md_reg_obj(struct regs_t *regs, /* registers to access */ int is_write, /* access type */ enum md_reg_type rt, /* reg bank to probe */ int reg, /* register number */ struct eval_value_t *val) /* input, output */ { switch (rt) { case rt_gpr: if (reg < 0 || reg >= MD_NUM_IREGS) return "register number out of range"; if (!is_write) { val->type = et_uint; val->value.as_uint = regs->regs_R[reg]; } else regs->regs_R[reg] = eval_as_uint(*val); break; case rt_lpr: if (reg < 0 || reg >= MD_NUM_FREGS) return "register number out of range"; if (!is_write) { val->type = et_uint; val->value.as_uint = regs->regs_F.l[reg]; } else regs->regs_F.l[reg] = eval_as_uint(*val); break; case rt_fpr: if (reg < 0 || reg >= MD_NUM_FREGS) return "register number out of range"; if (!is_write) { val->type = et_float; val->value.as_float = regs->regs_F.f[reg]; } else regs->regs_F.f[reg] = eval_as_float(*val); break; case rt_dpr: if (reg < 0 || reg >= MD_NUM_FREGS/2) return "register number out of range"; if (!is_write) { val->type = et_double; val->value.as_double = regs->regs_F.d[reg]; } else regs->regs_F.d[reg] = eval_as_double(*val); break; case rt_ctrl: switch (reg) { case /* HI */0: if (!is_write) { val->type = et_uint; val->value.as_uint = regs->regs_C.hi; } else regs->regs_C.hi = eval_as_uint(*val); break; case /* LO */1: if (!is_write) { val->type = et_uint; val->value.as_uint = regs->regs_C.lo; } else regs->regs_C.lo = eval_as_uint(*val); break; case /* FCC */2: if (!is_write) { val->type = et_int; val->value.as_int = regs->regs_C.fcc; } else regs->regs_C.fcc = eval_as_uint(*val); break; default: return "register number out of range"; } break; case rt_PC: if (!is_write) { val->type = et_addr; val->value.as_addr = regs->regs_PC; } else regs->regs_PC = eval_as_addr(*val); break; case rt_NPC: if (!is_write) { val->type = et_addr; val->value.as_addr = regs->regs_NPC; } else regs->regs_NPC = eval_as_addr(*val); break; default: panic("bogus register bank"); } /* no error */ return NULL; }