1#include <stdlib.h>
2
3#if !defined(NO_LABEL_VALUES) && (!defined(STACK_SIZE) || STACK_SIZE >= 4000) && __INT_MAX__ >= 2147483647
4typedef unsigned int uint32;
5typedef signed int sint32;
6
7typedef uint32 reg_t;
8
9typedef unsigned long int host_addr_t;
10typedef uint32 target_addr_t;
11typedef sint32 target_saddr_t;
12
13typedef union
14{
15  struct
16    {
17      unsigned int	offset:18;
18      unsigned int	ignore:4;
19      unsigned int	s1:8;
20      int		:2;
21      signed int	simm:14;
22      unsigned int	s3:8;
23      unsigned int	s2:8;
24      int		pad2:2;
25    } f1;
26  long long ll;
27  double d;
28} insn_t;
29
30typedef struct
31{
32  target_addr_t vaddr_tag;
33  unsigned long int rigged_paddr;
34} tlb_entry_t;
35
36typedef struct
37{
38  insn_t *pc;
39  reg_t registers[256];
40  insn_t *program;
41  tlb_entry_t tlb_tab[0x100];
42} environment_t;
43
44enum operations
45{
46  LOAD32_RR,
47  METAOP_DONE
48};
49
50host_addr_t
51f ()
52{
53  abort ();
54}
55
56reg_t
57simulator_kernel (int what, environment_t *env)
58{
59  register insn_t *pc = env->pc;
60  register reg_t *regs = env->registers;
61  register insn_t insn;
62  register int s1;
63  register reg_t r2;
64  register void *base_addr = &&sim_base_addr;
65  register tlb_entry_t *tlb = env->tlb_tab;
66
67  if (what != 0)
68    {
69      int i;
70      static void *op_map[] =
71	{
72	  &&L_LOAD32_RR,
73	  &&L_METAOP_DONE,
74	};
75      insn_t *program = env->program;
76      for (i = 0; i < what; i++)
77	program[i].f1.offset = op_map[program[i].f1.offset] - base_addr;
78    }
79
80 sim_base_addr:;
81
82  insn = *pc++;
83  r2 = (*(reg_t *) (((char *) regs) + (insn.f1.s2 << 2)));
84  s1 = (insn.f1.s1 << 2);
85  goto *(base_addr + insn.f1.offset);
86
87 L_LOAD32_RR:
88  {
89    target_addr_t vaddr_page = r2 / 4096;
90    unsigned int x = vaddr_page % 0x100;
91    insn = *pc++;
92
93    for (;;)
94      {
95	target_addr_t tag = tlb[x].vaddr_tag;
96	host_addr_t rigged_paddr = tlb[x].rigged_paddr;
97
98	if (tag == vaddr_page)
99	  {
100	    *(reg_t *) (((char *) regs) + s1) = *(uint32 *) (rigged_paddr + r2);
101	    r2 = *(reg_t *) (((char *) regs) + (insn.f1.s2 << 2));
102	    s1 = insn.f1.s1 << 2;
103	    goto *(base_addr + insn.f1.offset);
104	  }
105
106	if (((target_saddr_t) tag < 0))
107	  {
108	    *(reg_t *) (((char *) regs) + s1) = *(uint32 *) f ();
109	    r2 = *(reg_t *) (((char *) regs) + (insn.f1.s2 << 2));
110	    s1 = insn.f1.s1 << 2;
111	    goto *(base_addr + insn.f1.offset);
112	  }
113
114	x = (x - 1) % 0x100;
115      }
116
117    L_METAOP_DONE:
118      return (*(reg_t *) (((char *) regs) + s1));
119  }
120}
121
122insn_t program[2 + 1];
123
124void *malloc ();
125
126int
127main ()
128{
129  environment_t env;
130  insn_t insn;
131  int i, res;
132  host_addr_t a_page = (host_addr_t) malloc (2 * 4096);
133  target_addr_t a_vaddr = 0x123450;
134  target_addr_t vaddr_page = a_vaddr / 4096;
135  a_page = (a_page + 4096 - 1) & -4096;
136
137  env.tlb_tab[((vaddr_page) % 0x100)].vaddr_tag = vaddr_page;
138  env.tlb_tab[((vaddr_page) % 0x100)].rigged_paddr = a_page - vaddr_page * 4096;
139  insn.f1.offset = LOAD32_RR;
140  env.registers[0] = 0;
141  env.registers[2] = a_vaddr;
142  *(sint32 *) (a_page + a_vaddr % 4096) = 88;
143  insn.f1.s1 = 0;
144  insn.f1.s2 = 2;
145
146  for (i = 0; i < 2; i++)
147    program[i] = insn;
148
149  insn.f1.offset = METAOP_DONE;
150  insn.f1.s1 = 0;
151  program[2] = insn;
152
153  env.pc = program;
154  env.program = program;
155
156  res = simulator_kernel (2 + 1, &env);
157
158  if (res != 88)
159    abort ();
160  exit (0);
161}
162#else
163main(){ exit (0); }
164#endif
165