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