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
      56  f ()
      57  {
      58    abort ();
      59  }
      60  
      61  reg_t
      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
     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
     168  int main(){ exit (0); }
     169  #endif