Line 89... |
Line 89... |
extern uorreg_t __op_param1;
|
extern uorreg_t __op_param1;
|
extern uorreg_t __op_param2;
|
extern uorreg_t __op_param2;
|
extern uorreg_t __op_param3;
|
extern uorreg_t __op_param3;
|
|
|
|
|
/* Helper function. Whenever we escape the recompiled code and there is a
|
static inline void save_t_bound(oraddr_t pc)
|
* potential that an exception may happen this function must be called */
|
|
static inline void save_t_temporary(void)
|
|
{
|
{
|
env->t0 = t0;
|
int reg;
|
env->t1 = t1;
|
|
env->t2 = t2;
|
pc = (pc & config.immu.page_offset_mask) / 4;
|
|
reg = env->curr_page->ts_bound[pc];
|
|
|
|
if(reg & 0x1f)
|
|
env->reg[reg & 0x1f] = t0;
|
|
|
|
if((reg >> 5) & 0x1f)
|
|
env->reg[(reg >> 5) & 0x1f] = t1;
|
|
|
|
if((reg >> 10) & 0x1f)
|
|
env->reg[(reg >> 10) & 0x1f] = t2;
|
}
|
}
|
|
|
/* Wrapper around do_scheduler. This is needed because op_do_sched must be as
|
|
* small as possible. */
|
|
void do_sched_wrap(void)
|
void do_sched_wrap(void)
|
{
|
{
|
save_t_temporary();
|
|
upd_sim_cycles();
|
upd_sim_cycles();
|
|
save_t_bound(env->pc - 4);
|
do_scheduler();
|
do_scheduler();
|
}
|
}
|
|
|
/* do_scheduler wrapper for instructions that are in the delay slot */
|
/* do_scheduler wrapper for instructions that are in the delay slot */
|
void do_sched_wrap_delay(void)
|
void do_sched_wrap_delay(void)
|
{
|
{
|
save_t_temporary();
|
|
upd_sim_cycles();
|
upd_sim_cycles();
|
env->ts_current = 1;
|
|
/* The PC gets set to the location of the jump, but do_sched increments that
|
|
* so pull it back here to point to the right location again. This could be
|
|
* done in op_add_pc/op_set_pc_pc_delay but that would enlarge the recompiled
|
|
* code. */
|
|
//env->pc -= 4;
|
|
do_scheduler();
|
do_scheduler();
|
env->ts_current = 0;
|
|
}
|
}
|
|
|
void enter_dyn_code(oraddr_t addr, struct dyn_page *dp)
|
void enter_dyn_code(oraddr_t addr, struct dyn_page *dp)
|
{
|
{
|
uint16_t reg;
|
uint16_t reg = 0;
|
|
|
addr &= config.immu.pagesize - 1;
|
addr &= config.immu.pagesize - 1;
|
addr >>= 2;
|
addr >>= 2;
|
|
|
reg = dp->ts_bound[addr];
|
if(addr)
|
|
reg = dp->ts_bound[addr - 1];
|
|
|
if(reg & 0x1f)
|
if(reg & 0x1f)
|
t0 = cpu_state.reg[reg & 0x1f];
|
t0 = cpu_state.reg[reg & 0x1f];
|
|
|
if((reg >> 5) & 0x1f)
|
if((reg >> 5) & 0x1f)
|
Line 249... |
Line 248... |
env->delay_insn = 1;
|
env->delay_insn = 1;
|
env->pc_delay = get_pc() + (orreg_t)OP_PARAM1;
|
env->pc_delay = get_pc() + (orreg_t)OP_PARAM1;
|
}
|
}
|
}
|
}
|
|
|
__or_dynop void op_set_ts_current(void)
|
|
{
|
|
env->ts_current = 1;
|
|
}
|
|
|
|
__or_dynop void op_add_pc(void)
|
__or_dynop void op_add_pc(void)
|
{
|
{
|
/* FIXME: Optimise */
|
/* FIXME: Optimise */
|
set_pc(get_pc() + OP_PARAM1);
|
set_pc(get_pc() + OP_PARAM1);
|
}
|
}
|
|
|
__or_dynop void op_nop_exit(void)
|
__or_dynop void op_nop_exit(void)
|
{
|
{
|
upd_sim_cycles();
|
upd_sim_cycles();
|
save_t_temporary();
|
|
op_support_nop_exit();
|
op_support_nop_exit();
|
FORCE_RET;
|
FORCE_RET;
|
}
|
}
|
|
|
__or_dynop void op_nop_reset(void)
|
__or_dynop void op_nop_reset(void)
|
Line 277... |
Line 270... |
do_jump(EXCEPT_RESET);
|
do_jump(EXCEPT_RESET);
|
}
|
}
|
|
|
__or_dynop void op_nop_printf(void)
|
__or_dynop void op_nop_printf(void)
|
{
|
{
|
save_t_temporary();
|
|
upd_sim_cycles();
|
upd_sim_cycles();
|
op_support_nop_printf();
|
op_support_nop_printf();
|
FORCE_RET;
|
FORCE_RET;
|
}
|
}
|
|
|
__or_dynop void op_nop_report(void)
|
__or_dynop void op_nop_report(void)
|
{
|
{
|
save_t_temporary();
|
|
upd_sim_cycles();
|
upd_sim_cycles();
|
op_support_nop_report();
|
op_support_nop_report();
|
FORCE_RET;
|
FORCE_RET;
|
}
|
}
|
|
|
__or_dynop void op_nop_report_imm(void)
|
__or_dynop void op_nop_report_imm(void)
|
{
|
{
|
save_t_temporary();
|
|
upd_sim_cycles();
|
upd_sim_cycles();
|
op_support_nop_report_imm(OP_PARAM1);
|
op_support_nop_report_imm(OP_PARAM1);
|
}
|
}
|
|
|
__or_dynop void op_analysis(void)
|
__or_dynop void op_analysis(void)
|
{
|
{
|
env->iqueue.insn_index = OP_PARAM1;
|
env->iqueue.insn_index = OP_PARAM1;
|
env->iqueue.insn = OP_PARAM2;
|
env->iqueue.insn = OP_PARAM2;
|
env->iqueue.insn_addr = get_pc();
|
env->iqueue.insn_addr = get_pc();
|
save_t_temporary();
|
|
op_support_analysis();
|
op_support_analysis();
|
FORCE_RET;
|
FORCE_RET;
|
}
|
}
|
|
|
__or_dynop void op_move_gpr1_pc_delay(void)
|
__or_dynop void op_move_gpr1_pc_delay(void)
|
Line 885... |
Line 874... |
|
|
__or_dynop void op_prep_rfe(void)
|
__or_dynop void op_prep_rfe(void)
|
{
|
{
|
env->sprs[SPR_SR] = env->sprs[SPR_ESR_BASE] | SPR_SR_FO;
|
env->sprs[SPR_SR] = env->sprs[SPR_ESR_BASE] | SPR_SR_FO;
|
env->sprs[SPR_PPC] = get_pc();
|
env->sprs[SPR_PPC] = get_pc();
|
env->ts_current = 1;
|
|
set_pc(env->sprs[SPR_EPCR_BASE] - 4);
|
set_pc(env->sprs[SPR_EPCR_BASE] - 4);
|
}
|
}
|
|
|
static inline void prep_except(oraddr_t epcr_base)
|
static inline void prep_except(oraddr_t epcr_base)
|
{
|
{
|
Line 916... |
Line 904... |
* Therefore the pc will point to the instruction after the l.sys or l.trap
|
* Therefore the pc will point to the instruction after the l.sys or l.trap
|
* instruction */
|
* instruction */
|
__or_dynop void op_prep_sys_delay(void)
|
__or_dynop void op_prep_sys_delay(void)
|
{
|
{
|
env->delay_insn = 0;
|
env->delay_insn = 0;
|
env->ts_current = 1;
|
|
prep_except(get_pc() - 4);
|
prep_except(get_pc() - 4);
|
set_pc(EXCEPT_SYSCALL - 4);
|
set_pc(EXCEPT_SYSCALL - 4);
|
}
|
}
|
|
|
__or_dynop void op_prep_sys(void)
|
__or_dynop void op_prep_sys(void)
|
{
|
{
|
env->ts_current = 1;
|
|
prep_except(get_pc() + 4);
|
prep_except(get_pc() + 4);
|
set_pc(EXCEPT_SYSCALL - 4);
|
set_pc(EXCEPT_SYSCALL - 4);
|
}
|
}
|
|
|
__or_dynop void op_prep_trap_delay(void)
|
__or_dynop void op_prep_trap_delay(void)
|
{
|
{
|
env->ts_current = 1;
|
|
env->delay_insn = 0;
|
env->delay_insn = 0;
|
prep_except(get_pc() - 4);
|
prep_except(get_pc() - 4);
|
set_pc(EXCEPT_TRAP - 4);
|
set_pc(EXCEPT_TRAP - 4);
|
}
|
}
|
|
|
__or_dynop void op_prep_trap(void)
|
__or_dynop void op_prep_trap(void)
|
{
|
{
|
env->ts_current = 1;
|
|
prep_except(get_pc());
|
prep_except(get_pc());
|
set_pc(EXCEPT_TRAP - 4);
|
set_pc(EXCEPT_TRAP - 4);
|
}
|
}
|
|
|
/* FIXME: This `instruction' should be split up like the l.trap and l.sys
|
/* FIXME: This `instruction' should be split up like the l.trap and l.sys
|
* instructions are done */
|
* instructions are done */
|
__or_dynop void op_illegal_delay(void)
|
__or_dynop void op_illegal_delay(void)
|
{
|
{
|
env->delay_insn = 0;
|
env->delay_insn = 0;
|
env->ts_current = 1;
|
|
env->sprs[SPR_EEAR_BASE] = get_pc() - 4;
|
env->sprs[SPR_EEAR_BASE] = get_pc() - 4;
|
do_jump(EXCEPT_ILLEGAL - 4);
|
do_jump(EXCEPT_ILLEGAL - 4);
|
}
|
}
|
|
|
__or_dynop void op_illegal(void)
|
__or_dynop void op_illegal(void)
|