OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1691 to Rev 1692
    Reverse comparison

Rev 1691 → Rev 1692

/trunk/or1ksim/cpu/or32/op_support.c
42,8 → 42,6
#include "dyn_rec.h"
#include "op_support.h"
 
#include "rec_i386.h"
 
/* Stuff that is really a `micro' operation but is rather big (or for some other
* reason like calling exit()) */
 
99,68 → 97,8
* to some bogus value. */
void do_jump(oraddr_t addr)
{
struct dyn_page *target_dp;
oraddr_t phys_page;
 
/* The pc is set to the location of the jump in op_set_pc_preemt(_check) and
* then it is incermented by 4 when the scheduler is run. If a scheduled job
* so happens to raise an exception cpu_state.delay_insn will still be set and
* so except_handle will do its pc adjusting magic (ie. -4 from it) and every-
* thing ends up just working right, except when a scheduled job does not
* raise an exeception. In that case we set the pc here explicitly */
cpu_state.pc = addr;
 
/* immu_translate must be called after set_pc. If it would be called before
* it and it issued an ITLB miss then it would appear that the instruction
* that faulted was the instruction in the delay slot which is incorrect */
phys_page = immu_translate(addr);
 
/* do_jump is called from the delay slot, which is the jump instruction
* address + 4. */
/*
printf("Recompiled code jumping out to %"PRIxADDR" from %"PRIxADDR"\n",
phys_page, cpu_state.sprs[SPR_PPC] - 4);
*/
 
/* immu_translate() adds the hit delay to runtime.sim.mem_cycles but we add it
* to the cycles when the instruction is executed so if we don't reset it now
* it will produce wrong results */
runtime.sim.mem_cycles = 0;
 
target_dp = cpu_state.dyn_pages[phys_page >> config.immu.pagesize_log2];
 
if(!target_dp)
target_dp = new_dp(phys_page);
 
/* Since writes to the 0x0-0xff range do not dirtyfy a page recompile the 0x0
* page if the jump is to that location */
if(phys_page < 0x100)
target_dp->dirty = 1;
 
if(target_dp->dirty)
recompile_page(target_dp);
 
cpu_state.curr_page = target_dp;
 
/* FIXME: If the page is backed by more than one type of memory, this will
* produce wrong results */
if(cpu_state.sprs[SPR_SR] & SPR_SR_IME)
/* Add the mmu hit delay to the cycle counter */
cpu_state.cycles_dec = target_dp->delayr - config.immu.hitdelay;
else
cpu_state.cycles_dec = target_dp->delayr;
 
/* Initially this returned the address that we should jump to and then the
* recompiled code performed the jump. This was no problem if the jump was
* trully an interpage jump or if the location didn't need recompileation. If
* the jump is page local and the page needs recompileation there is a very
* high probability that the page will move in memory and then the return
* address that is on the stack will point to memory that has already been
* freed, sometimes leading to crashes */
/* This looks like it could really be simpler, but no it can't. The only
* issue here is the stack: it has to be unwound. This function is called
* from except_handle, which generally ends up quite high on the stack... */
enter_dyn_code(phys_page, target_dp);
longjmp(cpu_state.excpt_loc, 0);
}
 
/* Wrapper around analysis() that contains all the recompiler specific stuff */
/trunk/or1ksim/cpu/or32/op.c
134,6 → 134,8
void enter_dyn_code(oraddr_t addr, struct dyn_page *dp)
{
uint16_t reg = 0;
uint32_t t0_reg = t0, t1_reg = t1, t2_reg = t2;
struct cpu_state *cpu_reg = env;
 
addr &= config.immu.pagesize - 1;
addr >>= 2;
153,10 → 155,15
if(addr)
t2 = cpu_state.reg[(reg >> 10) & 0x1f];
 
or_longjmp(dp->locs[addr]);
env = &cpu_state;
 
((gen_code_ent *)dp->locs)[addr]();
t0 = t0_reg;
t1 = t1_reg;
t2 = t2_reg;
env = (struct cpu_state *)cpu_reg;
}
 
 
__or_dynop void op_set_pc_pc_delay(void)
{
env->sprs[SPR_PPC] = env->pc;
185,12 → 192,13
 
__or_dynop void op_do_jump(void)
{
do_jump(env->pc);
RET_FROM_DYN_CODE;
}
 
__or_dynop void op_do_jump_delay(void)
{
do_jump(env->pc_delay);
env->pc = env->pc_delay;
RET_FROM_DYN_CODE;
}
 
__or_dynop void op_clear_delay_insn(void)
276,7 → 284,8
__or_dynop void op_nop_reset(void)
{
op_support_nop_reset();
do_jump(EXCEPT_RESET);
env->pc = EXCEPT_RESET;
RET_FROM_DYN_CODE;
}
 
__or_dynop void op_nop_printf(void)
940,13 → 949,15
{
env->delay_insn = 0;
env->sprs[SPR_EEAR_BASE] = env->pc - 4;
do_jump(EXCEPT_ILLEGAL - 4);
env->pc = EXCEPT_ILLEGAL - 4;
RET_FROM_DYN_CODE;
}
 
__or_dynop void op_illegal(void)
{
env->sprs[SPR_EEAR_BASE] = env->pc;
do_jump(EXCEPT_ILLEGAL);
env->pc = EXCEPT_ILLEGAL;
RET_FROM_DYN_CODE;
}
 
__or_dynop void op_do_sched(void)
/trunk/or1ksim/cpu/or32/dyn_rec.c
43,7 → 43,6
#include "sim-config.h"
#include "sched.h"
 
#include "rec_i386.h"
#include "i386_regs.h"
 
#include "def_op_t.h"
84,8 → 83,6
 
#define T_NONE (-1)
 
void *rec_stack_base;
 
/* Temporary is used as a source operand */
#define TFLAG_SRC 1
/* Temporary is used as a destination operand */
110,11 → 107,7
struct dyn_page *dp;
FILE *f;
char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */
void *stack;
int i, j;
void *trace[11];
int num_trace;
char **trace_names;
int i;
struct sigcontext *sigc = dat;
 
if(!sigsegv_state) {
156,32 → 149,6
}
sigsegv_state++;
case 2:
/* Dump the contents of the stack */
fprintf(stderr, "Stack dump: ");
fflush(stderr);
 
num_trace = backtrace(trace, 10);
 
trace[num_trace++] = (void *)sigc->eip;
trace_names = backtrace_symbols(trace, num_trace);
 
stack = get_sp();
fprintf(stderr, "(of stack at %p, base: %p)\n", stack, rec_stack_base);
fflush(stderr);
for(i = 0; stack < rec_stack_base; i++, stack += 4) {
fprintf(stderr, " <%i> 0x%08x", i, *(uint32_t *)stack);
/* Try to find a symbolic name with this entry */
for(j = 0; j < num_trace; j++) {
if(trace[j] == *(void **)stack)
fprintf(stderr, " <%s>", trace_names[j]);
}
fprintf(stderr, "\n");
fflush(stderr);
}
fprintf(stderr, "Fault at: 0x%08lx <%s>\n", sigc->eip,
trace_names[num_trace - 1]);
sigsegv_state++;
case 3:
sim_done();
}
}
207,6 → 174,53
return dp;
}
 
void dyn_main(void)
{
struct dyn_page *target_dp;
oraddr_t phys_page;
 
setjmp(cpu_state.excpt_loc);
for(;;) {
phys_page = immu_translate(cpu_state.pc);
 
/*
printf("Recompiled code jumping out to %"PRIxADDR" from %"PRIxADDR"\n",
phys_page, cpu_state.sprs[SPR_PPC] - 4);
*/
 
/* immu_translate() adds the hit delay to runtime.sim.mem_cycles but we add
* it to the cycles when the instruction is executed so if we don't reset it
* now it will produce wrong results */
runtime.sim.mem_cycles = 0;
 
target_dp = cpu_state.dyn_pages[phys_page >> config.immu.pagesize_log2];
 
if(!target_dp)
target_dp = new_dp(phys_page);
 
/* Since writes to the 0x0-0xff range do not dirtyfy a page recompile the
* 0x0 page if the jump is to that location */
if(phys_page < 0x100)
target_dp->dirty = 1;
 
if(target_dp->dirty)
recompile_page(target_dp);
 
cpu_state.curr_page = target_dp;
 
/* FIXME: If the page is backed by more than one type of memory, this will
* produce wrong results */
cpu_state.cycles_dec = target_dp->delayr;
if(cpu_state.sprs[SPR_SR] & SPR_SR_IME)
/* Add the mmu hit delay to the cycle counter */
cpu_state.cycles_dec -= config.immu.hitdelay;
 
/* FIXME: ebp, ebx, esi and edi are expected to be preserved across function
* calls but the recompiled code trashes them... */
enter_dyn_code(phys_page, target_dp);
}
}
 
static void immu_retranslate(void *dat)
{
int got_en_dis = (int)dat;
439,22 → 453,6
opq->num_ops_param++;
}
 
/* Function to guard against rogue ret instructions in the operations */
void dyn_ret_stack_prot(void)
{
fprintf(stderr, "An operation (I have no clue which) has a ret statement in it\n");
fprintf(stderr, "Good luck debugging it!\n");
 
exit(1);
}
 
/* Jumps out to some Openrisc address */
void jump_dyn_code(oraddr_t addr)
{
cpu_state.pc = addr;
do_jump(addr);
}
 
/* Initialises the recompiler */
void init_dyn_recomp(void)
{
487,9 → 485,6
 
opq->prev = NULL;
 
/* Just some value that we'll use as the base for our stack */
rec_stack_base = get_sp();
 
cpu_state.curr_page = NULL;
if(!(cpu_state.dyn_pages = malloc(sizeof(void *) * (2 << (32 -
config.immu.pagesize_log2))))) {
/trunk/or1ksim/cpu/or32/dyn_rec.h
21,6 → 21,8
#ifndef DYN_REC_H
#define DYN_REC_H
 
typedef void (*gen_code_ent)(void);
 
/* Each dynamically recompiled page has one of these */
struct dyn_page {
oraddr_t or_page;
42,11 → 44,11
void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
unsigned int amount);
void init_dyn_recomp(void);
void jump_dyn_code(oraddr_t addr);
void run_sched_out_of_line(void);
void recheck_immu(int got_en_dis);
void enter_dyn_code(oraddr_t addr, struct dyn_page *dp);
void dyn_checkwrite(oraddr_t addr);
void dyn_main(void);
 
extern void *rec_stack_base;
 
/trunk/or1ksim/cpu/or32/execute.c
659,9 → 659,12
pcnext += 4;
 
/* MM1409: All programs should set their stack pointer! */
#if !(DYNAMIC_EXECUTION)
except_handle(EXCEPT_RESET, 0);
update_pc();
#endif
except_pending = 0;
cpu_state.pc = EXCEPT_RESET;
}
 
/* Simulates one CPU clock cycle */
/trunk/or1ksim/cpu/or32/op_i386.h
21,26 → 21,10
 
#define FORCE_RET asm volatile ("")
 
static inline void or_longjmp(void *loc) __attribute__((noreturn));
static inline void or_longjmp(void *loc)
{
/* We push a trampoline address (dyn_ret_stack_prot) onto the stack to be able
* to detect if any ret instructions found their way into an operation. */
asm("\tmovl %0, %%eax\n"
"\tmovl %1, %%esp\n"
"\tmovl $%2, %%ebp\n"
"\tpush $dyn_ret_stack_prot\n"
"\tpush $dyn_ret_stack_prot\n"
"\tpush $dyn_ret_stack_prot\n"
"\tjmp *%%eax\n"
:
: "m" (loc),
"m" (rec_stack_base),
"m" (cpu_state));
}
 
/* Does a function call (with no arguments) makeing sure that gcc doesn't peddle
* the stack. (FIXME: Is this safe??) */
#define SPEEDY_CALL(func) asm("call "#func"\n")
 
/* Return out of the recompiled code */
#define RET_FROM_DYN_CODE asm volatile ("ret")
 
/trunk/or1ksim/cpu/common/execute.h
18,6 → 18,7
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#if DYNAMIC_EXECUTION
#include "setjmp.h"
#include "dyn_rec.h"
#endif
 
49,6 → 50,9
struct iqueue_entry icomplet;
 
#if DYNAMIC_EXECUTION
/* longjmp() to this location in case of an exception */
jmp_buf excpt_loc;
 
/* Current page in execution */
struct dyn_page *curr_page;
 
/trunk/or1ksim/cpu/or1k/except.c
41,7 → 41,6
 
#if DYNAMIC_EXECUTION
#include "sched.h"
#include "rec_i386.h"
#include "op_support.h"
#endif
 
179,7 → 178,6
cpu_state.delay_insn = 0;
 
#if DYNAMIC_EXECUTION
cpu_state.pc = except_vector;
jump_dyn_code(except_vector);
do_jump(except_vector);
#endif
}
/trunk/or1ksim/toplevel.c
342,7 → 342,11
 
sim_init ();
 
#if DYNAMIC_EXECUTION
dyn_main();
#else
exec_main();
#endif
 
sim_done();
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.