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