1998-11-14 04:35:47 +00:00
|
|
|
/* GX generic simulator run.
|
|
|
|
Copyright (C) 1998 Cygnus Solutions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sim-main.h"
|
|
|
|
#include "sim-assert.h"
|
|
|
|
#include "sim-gx.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_TIME_H
|
|
|
|
#include <time.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* GX implementation of sim_engine_run that works within the
|
|
|
|
sim_engine setjmp/longjmp framework. */
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
sim_engine_run (SIM_DESC sd,
|
|
|
|
int next_cpu_nr,
|
|
|
|
int nr_cpus, /* ignore */
|
|
|
|
int siggnal) /* ignore */
|
|
|
|
{
|
|
|
|
sim_cpu* cpu;
|
|
|
|
int cont = 1;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
|
|
|
cpu = STATE_CPU (sd, next_cpu_nr);
|
|
|
|
|
|
|
|
while(cont)
|
|
|
|
{
|
|
|
|
sim_gx_block* block;
|
|
|
|
sim_gx_compiled_block* compiled_block;
|
|
|
|
sim_gx_function f;
|
|
|
|
sim_cia cia = CIA_GET(cpu);
|
|
|
|
int optimized;
|
|
|
|
int pre_checksum, post_checksum;
|
|
|
|
|
|
|
|
/* find optimized gx block that includes this PC */
|
|
|
|
block = sim_gx_block_find(cia);
|
|
|
|
if(block == NULL)
|
|
|
|
{
|
|
|
|
/* start new learning block */
|
|
|
|
block = sim_gx_block_create(cia);
|
|
|
|
}
|
|
|
|
ASSERT(block != NULL);
|
|
|
|
|
|
|
|
/* pick preferred compiled block */
|
|
|
|
if(block->optimized_block != NULL)
|
|
|
|
{
|
|
|
|
compiled_block = block->optimized_block;
|
|
|
|
/* no stats */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* test for optimization policy */
|
|
|
|
if(tgx_optimize_test(block))
|
|
|
|
{
|
|
|
|
block->opt_compile_count ++;
|
|
|
|
sim_gx_block_translate(block, 1 /* optimized */);
|
|
|
|
compiled_block = block->optimized_block;
|
|
|
|
optimized = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
compiled_block = block->learning_block;
|
|
|
|
optimized = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ASSERT(compiled_block != NULL);
|
|
|
|
|
|
|
|
/* load & resolve gx function */
|
|
|
|
f = sim_gx_compiled_block_f(compiled_block);
|
|
|
|
|
|
|
|
/* XXX: debug
|
|
|
|
printf("calling into gx function %p, pc=%08lx, opt %d\n",
|
|
|
|
(void*) f, (unsigned long) cpu->regs.h_pc, optimized);
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* compute pc_flags checksum */
|
|
|
|
if(! optimized)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
pre_checksum = 0;
|
|
|
|
for(i=0; i < block->length / block->divisor; i++)
|
|
|
|
pre_checksum += block->pc_flags[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* call into gx function */
|
1998-12-01 13:28:53 +00:00
|
|
|
{
|
|
|
|
struct tgx_info info = {& cpu->regs,
|
|
|
|
block->pc_flags,
|
|
|
|
block->callbacks };
|
|
|
|
rc = (*f)(& info);
|
|
|
|
}
|
1998-11-14 04:35:47 +00:00
|
|
|
|
|
|
|
/* compute pc_flags checksum */
|
|
|
|
if(! optimized)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
post_checksum = 0;
|
|
|
|
for(i=0; i < block->length / block->divisor; i++)
|
|
|
|
post_checksum += block->pc_flags[i];
|
|
|
|
|
|
|
|
if(post_checksum != pre_checksum) /* system changing */
|
|
|
|
{
|
|
|
|
block->learn_last_change = time(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: debug
|
|
|
|
printf("returned from gx function %p, rc=%d, pc=%08lx\n",
|
|
|
|
(void*) f, rc, (unsigned long) cpu->regs.h_pc);
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch(rc)
|
|
|
|
{
|
|
|
|
case GX_F_YIELD: /* gx block voluntarily gave up control */
|
|
|
|
case GX_F_RANGE: /* PC travelled outside this block */
|
|
|
|
; /* continue block dispatch loop */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GX_F_NONPC: /* non-instruction PC in this block */
|
|
|
|
if(compiled_block == block->optimized_block)
|
|
|
|
{
|
|
|
|
/* sim_io_printf(sd, "NOTE: cancelling premature optimization, GX block %p, PC %08lx\n",
|
|
|
|
block, (long) cpu->regs.h_pc); */
|
|
|
|
sim_gx_compiled_block_dispose(compiled_block);
|
|
|
|
block->learn_last_change = time(NULL);
|
|
|
|
block->optimized_block = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* learning-mode gx block should not fail this way */
|
|
|
|
sim_io_error(sd, "Internal error - GX block cia %08lx NONPC\n", (long) cia);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GX_F_HALT: /* gx function returning control */
|
|
|
|
cont = 0; /* merely exit loop */
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* should not happen */
|
|
|
|
default:
|
|
|
|
sim_io_error(sd, "Translation error (bad rc 0x%d in gx block)", rc);
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sim_events_tick(sd))
|
|
|
|
sim_events_process(sd);
|
|
|
|
}
|
|
|
|
}
|