Line 43... |
Line 43... |
|
|
#include "i386_regs.h"
|
#include "i386_regs.h"
|
|
|
#include "dyn_rec.h"
|
#include "dyn_rec.h"
|
|
|
/* This must be here since the function in op_i386.h use this variable */
|
|
register struct cpu_state *env asm(CPU_STATE_REG);
|
register struct cpu_state *env asm(CPU_STATE_REG);
|
|
|
#include "op_i386.h"
|
#include "op_i386.h"
|
|
|
/*
|
/*
|
Line 108... |
Line 107... |
env->reg[(reg >> 10) & 0x1f] = t2;
|
env->reg[(reg >> 10) & 0x1f] = t2;
|
}
|
}
|
|
|
void do_sched_wrap(void)
|
void do_sched_wrap(void)
|
{
|
{
|
upd_sim_cycles();
|
env->pc += 4;
|
|
//runtime.cpu.instructions++;
|
|
runtime.sim.cycles -= env->cycles_dec;
|
|
scheduler.job_queue->time += env->cycles_dec;
|
|
if(scheduler.job_queue->time <= 0) {
|
save_t_bound(env->pc - 4);
|
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)
|
{
|
{
|
upd_sim_cycles();
|
/* FIXME: Can't this be eliminated? */
|
|
env->pc += 4;
|
|
//runtime.cpu.instructions++;
|
|
runtime.sim.cycles -= env->cycles_dec;
|
|
scheduler.job_queue->time += env->cycles_dec;
|
|
if(scheduler.job_queue->time <= 0)
|
do_scheduler();
|
do_scheduler();
|
}
|
}
|
|
|
void enter_dyn_code(oraddr_t addr, struct dyn_page *dp)
|
void enter_dyn_code(oraddr_t addr, struct dyn_page *dp)
|
{
|
{
|
Line 145... |
Line 154... |
}
|
}
|
|
|
|
|
__or_dynop void op_set_pc_pc_delay(void)
|
__or_dynop void op_set_pc_pc_delay(void)
|
{
|
{
|
env->sprs[SPR_PPC] = get_pc();
|
env->sprs[SPR_PPC] = env->pc;
|
/* pc_delay is pulled back 4 since imediatly after this is run, the scheduler
|
/* pc_delay is pulled back 4 since imediatly after this is run, the scheduler
|
* runs which also increments it by 4 */
|
* runs which also increments it by 4 */
|
set_pc(env->pc_delay - 4);
|
env->pc = env->pc_delay - 4;
|
}
|
}
|
|
|
__or_dynop void op_set_pc_delay_imm(void)
|
__or_dynop void op_set_pc_delay_imm(void)
|
{
|
{
|
env->pc_delay = get_pc() + (orreg_t)OP_PARAM1;
|
env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
|
env->delay_insn = 1;
|
env->delay_insn = 1;
|
}
|
}
|
|
|
__or_dynop void op_set_pc_delay_pc(void)
|
__or_dynop void op_set_pc_delay_pc(void)
|
{
|
{
|
env->pc_delay = get_pc();
|
env->pc_delay = env->pc;
|
env->delay_insn = 1;
|
env->delay_insn = 1;
|
}
|
}
|
|
|
__or_dynop void op_clear_pc_delay(void)
|
__or_dynop void op_clear_pc_delay(void)
|
{
|
{
|
Line 171... |
Line 180... |
env->delay_insn = 1;
|
env->delay_insn = 1;
|
}
|
}
|
|
|
__or_dynop void op_do_jump(void)
|
__or_dynop void op_do_jump(void)
|
{
|
{
|
do_jump(get_pc());
|
do_jump(env->pc);
|
}
|
}
|
|
|
__or_dynop void op_do_jump_delay(void)
|
__or_dynop void op_do_jump_delay(void)
|
{
|
{
|
do_jump(env->pc_delay);
|
do_jump(env->pc_delay);
|
Line 215... |
Line 224... |
/* Used for the l.bf instruction. Therefore if the flag is not set, jump over
|
/* Used for the l.bf instruction. Therefore if the flag is not set, jump over
|
* all the jumping stuff */
|
* all the jumping stuff */
|
__or_dynop void op_check_flag(void)
|
__or_dynop void op_check_flag(void)
|
{
|
{
|
if(!(env->sprs[SPR_SR] & SPR_SR_F)) {
|
if(!(env->sprs[SPR_SR] & SPR_SR_F)) {
|
HANDLE_SCHED(do_sched_wrap, "no_sched_chk_flg");
|
SPEEDY_CALL(do_sched_wrap);
|
OP_JUMP(OP_PARAM1);
|
OP_JUMP(OP_PARAM1);
|
}
|
}
|
}
|
}
|
|
|
/* Used for l.bf if the delay slot instruction is on another page */
|
/* Used for l.bf if the delay slot instruction is on another page */
|
__or_dynop void op_check_flag_delay(void)
|
__or_dynop void op_check_flag_delay(void)
|
{
|
{
|
if(env->sprs[SPR_SR] & SPR_SR_F) {
|
if(env->sprs[SPR_SR] & SPR_SR_F) {
|
env->delay_insn = 1;
|
env->delay_insn = 1;
|
env->pc_delay = get_pc() + (orreg_t)OP_PARAM1;
|
env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
|
}
|
}
|
}
|
}
|
|
|
/* Used for the l.bnf instruction. Therefore if the flag is set, jump over all
|
/* Used for the l.bnf instruction. Therefore if the flag is set, jump over all
|
* the jumping stuff */
|
* the jumping stuff */
|
__or_dynop void op_check_not_flag(void)
|
__or_dynop void op_check_not_flag(void)
|
{
|
{
|
if(env->sprs[SPR_SR] & SPR_SR_F) {
|
if(env->sprs[SPR_SR] & SPR_SR_F) {
|
HANDLE_SCHED(do_sched_wrap, "no_sched_chk_not_flg");
|
SPEEDY_CALL(do_sched_wrap);
|
OP_JUMP(OP_PARAM1);
|
OP_JUMP(OP_PARAM1);
|
}
|
}
|
}
|
}
|
|
|
/* Used for l.bnf if the delay slot instruction is on another page */
|
/* Used for l.bnf if the delay slot instruction is on another page */
|
__or_dynop void op_check_not_flag_delay(void)
|
__or_dynop void op_check_not_flag_delay(void)
|
{
|
{
|
if(!(env->sprs[SPR_SR] & SPR_SR_F)) {
|
if(!(env->sprs[SPR_SR] & SPR_SR_F)) {
|
env->delay_insn = 1;
|
env->delay_insn = 1;
|
env->pc_delay = get_pc() + (orreg_t)OP_PARAM1;
|
env->pc_delay = env->pc + (orreg_t)OP_PARAM1;
|
}
|
}
|
}
|
}
|
|
|
__or_dynop void op_add_pc(void)
|
__or_dynop void op_add_pc(void)
|
{
|
{
|
/* FIXME: Optimise */
|
env->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();
|
|
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)
|
{
|
{
|
upd_sim_cycles();
|
|
op_support_nop_reset();
|
op_support_nop_reset();
|
do_jump(EXCEPT_RESET);
|
do_jump(EXCEPT_RESET);
|
}
|
}
|
|
|
__or_dynop void op_nop_printf(void)
|
__or_dynop void op_nop_printf(void)
|
{
|
{
|
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)
|
{
|
{
|
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)
|
{
|
{
|
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)
|
{
|
{
|
Line 859... |
Line 862... |
#undef S_FUNC
|
#undef S_FUNC
|
#undef S_OP_NAME
|
#undef S_OP_NAME
|
|
|
__or_dynop void op_join_mem_cycles(void)
|
__or_dynop void op_join_mem_cycles(void)
|
{
|
{
|
join_mem_cycles();
|
runtime.sim.cycles += runtime.sim.mem_cycles;
|
|
scheduler.job_queue->time -= runtime.sim.mem_cycles;
|
|
runtime.sim.mem_cycles = 0;
|
}
|
}
|
|
|
__or_dynop void op_store_link_addr_gpr(void)
|
__or_dynop void op_store_link_addr_gpr(void)
|
{
|
{
|
env->reg[LINK_REGNO] = get_pc() + 8;
|
env->reg[LINK_REGNO] = env->pc + 8;
|
}
|
}
|
|
|
__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] = env->pc;
|
set_pc(env->sprs[SPR_EPCR_BASE] - 4);
|
env->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)
|
{
|
{
|
env->sprs[SPR_EPCR_BASE] = epcr_base;
|
env->sprs[SPR_EPCR_BASE] = epcr_base;
|
Line 892... |
Line 897... |
env->sprs[SPR_SR] &= ~(SPR_SR_IEE | SPR_SR_TEE); /* Disable interrupts. */
|
env->sprs[SPR_SR] &= ~(SPR_SR_IEE | SPR_SR_TEE); /* Disable interrupts. */
|
}
|
}
|
|
|
__or_dynop void op_set_except_pc(void)
|
__or_dynop void op_set_except_pc(void)
|
{
|
{
|
set_pc(OP_PARAM1);
|
env->pc = OP_PARAM1;
|
}
|
}
|
|
|
/* Before the code in op_{sys,trap}{,_delay} gets run, the scheduler runs.
|
/* Before the code in op_{sys,trap}{,_delay} gets run, the scheduler runs.
|
* 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;
|
prep_except(get_pc() - 4);
|
prep_except(env->pc - 4);
|
set_pc(EXCEPT_SYSCALL - 4);
|
env->pc = EXCEPT_SYSCALL - 4;
|
}
|
}
|
|
|
__or_dynop void op_prep_sys(void)
|
__or_dynop void op_prep_sys(void)
|
{
|
{
|
prep_except(get_pc() + 4);
|
prep_except(env->pc + 4);
|
set_pc(EXCEPT_SYSCALL - 4);
|
env->pc = EXCEPT_SYSCALL - 4;
|
}
|
}
|
|
|
__or_dynop void op_prep_trap_delay(void)
|
__or_dynop void op_prep_trap_delay(void)
|
{
|
{
|
env->delay_insn = 0;
|
env->delay_insn = 0;
|
prep_except(get_pc() - 4);
|
prep_except(env->pc - 4);
|
set_pc(EXCEPT_TRAP - 4);
|
env->pc = EXCEPT_TRAP - 4;
|
}
|
}
|
|
|
__or_dynop void op_prep_trap(void)
|
__or_dynop void op_prep_trap(void)
|
{
|
{
|
prep_except(get_pc());
|
prep_except(env->pc);
|
set_pc(EXCEPT_TRAP - 4);
|
env->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->sprs[SPR_EEAR_BASE] = get_pc() - 4;
|
env->sprs[SPR_EEAR_BASE] = env->pc - 4;
|
do_jump(EXCEPT_ILLEGAL - 4);
|
do_jump(EXCEPT_ILLEGAL - 4);
|
}
|
}
|
|
|
__or_dynop void op_illegal(void)
|
__or_dynop void op_illegal(void)
|
{
|
{
|
env->sprs[SPR_EEAR_BASE] = get_pc();
|
env->sprs[SPR_EEAR_BASE] = env->pc;
|
do_jump(EXCEPT_ILLEGAL);
|
do_jump(EXCEPT_ILLEGAL);
|
}
|
}
|
|
|
__or_dynop void op_do_sched(void)
|
__or_dynop void op_do_sched(void)
|
{
|
{
|
HANDLE_SCHED(do_sched_wrap, "no_sched");
|
SPEEDY_CALL(do_sched_wrap);
|
}
|
}
|
|
|
__or_dynop void op_do_sched_delay(void)
|
__or_dynop void op_do_sched_delay(void)
|
{
|
{
|
HANDLE_SCHED(do_sched_wrap_delay, "no_sched_delay");
|
SPEEDY_CALL(do_sched_wrap_delay);
|
}
|
}
|
|
|
__or_dynop void op_macc(void)
|
__or_dynop void op_macc(void)
|
{
|
{
|
env->sprs[SPR_MACLO] = 0;
|
env->sprs[SPR_MACLO] = 0;
|