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