old-cross-binutils/sim/common/sim-gx-run.c
Frank Ch. Eigler 3d7075f5f5 * A few more improvements to gx jit prototype.
[common/ChangeLog]
1998-12-01  Frank Ch. Eigler  <fche@elastic.org>
	* sim-gx-run.c (sim_engine_run): Use new tgx_info struct to
	collect run-time arguments to gx block.
	* sim-gx.h (sim_gx_function): Corresponding signature change.
	* sim-gx.c (sim_gx_compiled_block_f): Remove nonfunctional code to
	again compile a gx block source file.
	(sim_gx_compiled_block_dispose): Uninstall obsoleted gx block
	shared libraries.
	(sim_gx_block_translate): Always emit new "gx_label_NNNN" labels,
	for basic block entry points, even if !__GNUC__.
[m32r-gx/ChangeLog]
1998-12-01  Frank Ch. Eigler  <fche@elastic.org>
	* Makefile.in (SIM_OBJS): Don't build sim-core.o.
	* configure.in:	Added --enable-sim-inline support.
	Look for "getenv()" function.
	* configure: Rebuilt.
	* config.in: Rebuilt.
	* gx-translate.c: Include "sim-inline.c" for sim-core inlining.
	(m32r_gx_{load,store}*): Update signature.
	(tgx_emit_pre_function): Emit new "tgx_info" struct, update
	callback function signatures.
	(m32r_emit_*_insn): Use new callback signatures.  For all short
	branches in optimized mode, emit direct "goto gx_label_NNNN".
	(tgx_optimize_test): If the GX_OPTIMIZE environment variable is
	set, allow its integer value to override the optimization heuristic.
	* m32r-sim.h: New empty placeholder file.
	* sim-main.c: New empty placeholder file.
	* sim-if.c (sim_create_inferior): Use NULL instead of &abort
	for unimplemented register fondling functions.
	* sim-main.h: Add multiple inclusion guard.  Update callback
	function signatures.
	(tgx_info): New struct for collecting gx block invocation
	arguments.
1998-12-01 13:28:53 +00:00

153 lines
3.6 KiB
C

/* 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 */
{
struct tgx_info info = {& cpu->regs,
block->pc_flags,
block->callbacks };
rc = (*f)(& info);
}
/* 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);
}
}