blob: f9f6c126df308a8d271f4d0299ea51e30bfe8ec1 [file] [log] [blame]
#include <stdlib.h>
#ifndef NO_LABEL_VALUES
typedef unsigned int uint32;
typedef signed int sint32;
typedef uint32 reg_t;
typedef unsigned long int host_addr_t;
typedef uint32 target_addr_t;
typedef sint32 target_saddr_t;
typedef union
{
struct
{
unsigned int offset:18;
unsigned int ignore:4;
unsigned int s1:8;
int :2;
signed int simm:14;
unsigned int s3:8;
unsigned int s2:8;
int pad2:2;
} f1;
long long ll;
double d;
} insn_t;
typedef struct
{
target_addr_t vaddr_tag;
unsigned long int rigged_paddr;
} tlb_entry_t;
typedef struct
{
insn_t *pc;
reg_t registers[256];
insn_t *program;
tlb_entry_t tlb_tab[0x100];
} environment_t;
enum operations
{
LOAD32_RR,
METAOP_DONE
};
host_addr_t
f ()
{
abort ();
}
reg_t
simulator_kernel (int what, environment_t *env)
{
register insn_t *pc = env->pc;
register reg_t *regs = env->registers;
register insn_t insn;
register int s1;
register reg_t r2;
register void *base_addr = &&sim_base_addr;
register tlb_entry_t *tlb = env->tlb_tab;
if (what != 0)
{
int i;
static void *op_map[] =
{
&&L_LOAD32_RR,
&&L_METAOP_DONE,
};
insn_t *program = env->program;
for (i = 0; i < what; i++)
program[i].f1.offset = op_map[program[i].f1.offset] - base_addr;
}
sim_base_addr:;
insn = *pc++;
r2 = (*(reg_t *) (((char *) regs) + (insn.f1.s2 << 2)));
s1 = (insn.f1.s1 << 2);
goto *(base_addr + insn.f1.offset);
L_LOAD32_RR:
{
target_addr_t vaddr_page = r2 / 4096;
unsigned int x = vaddr_page % 0x100;
insn = *pc++;
for (;;)
{
target_addr_t tag = tlb[x].vaddr_tag;
host_addr_t rigged_paddr = tlb[x].rigged_paddr;
if (tag == vaddr_page)
{
*(reg_t *) (((char *) regs) + s1) = *(uint32 *) (rigged_paddr + r2);
r2 = *(reg_t *) (((char *) regs) + (insn.f1.s2 << 2));
s1 = insn.f1.s1 << 2;
goto *(base_addr + insn.f1.offset);
}
if (((target_saddr_t) tag < 0))
{
*(reg_t *) (((char *) regs) + s1) = *(uint32 *) f ();
r2 = *(reg_t *) (((char *) regs) + (insn.f1.s2 << 2));
s1 = insn.f1.s1 << 2;
goto *(base_addr + insn.f1.offset);
}
x = (x - 1) % 0x100;
}
L_METAOP_DONE:
return (*(reg_t *) (((char *) regs) + s1));
}
}
insn_t program[2 + 1];
void *malloc ();
int
main ()
{
environment_t env;
insn_t insn;
int i, res;
host_addr_t a_page = (host_addr_t) malloc (2 * 4096);
target_addr_t a_vaddr = 0x123450;
target_addr_t vaddr_page = a_vaddr / 4096;
a_page = (a_page + 4096 - 1) & -4096;
env.tlb_tab[((vaddr_page) % 0x100)].vaddr_tag = vaddr_page;
env.tlb_tab[((vaddr_page) % 0x100)].rigged_paddr = a_page - vaddr_page * 4096;
insn.f1.offset = LOAD32_RR;
env.registers[0] = 0;
env.registers[2] = a_vaddr;
*(int *) (a_page + a_vaddr % 4096) = 88;
insn.f1.s1 = 0;
insn.f1.s2 = 2;
for (i = 0; i < 2; i++)
program[i] = insn;
insn.f1.offset = METAOP_DONE;
insn.f1.s1 = 0;
program[2] = insn;
env.pc = program;
env.program = program;
res = simulator_kernel (2 + 1, &env);
if (res != 88)
abort ();
exit (0);
}
#else
main(){ exit (0); }
#endif