func: static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
  
                               int s_bits, int tlb_offset)
  
  {
  
      TCGReg base = TCG_AREG0;
  
  
  
      /* Should generate something like the following:
  
       * pre-v7:
  
       *   shr    tmp, addr_reg, #TARGET_PAGE_BITS                  (1)
  
       *   add    r2, env, #off & 0xff00
  
       *   and    r0, tmp, #(CPU_TLB_SIZE - 1)                      (2)
  
       *   add    r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS               (3)
  
       *   ldr    r0, [r2, #off & 0xff]!                            (4)
  
       *   tst    addr_reg, #s_mask
  
       *   cmpeq  r0, tmp, lsl #TARGET_PAGE_BITS                    (5)
  
       *
  
       * v7 (not implemented yet):
  
       *   ubfx   r2, addr_reg, #TARGET_PAGE_BITS, #CPU_TLB_BITS    (1)
  
       *   movw   tmp, #~TARGET_PAGE_MASK & ~s_mask
  
       *   movw   r0, #off
  
       *   add    r2, env, r2, lsl #CPU_TLB_ENTRY_BITS              (2)
  
       *   bic    tmp, addr_reg, tmp
  
       *   ldr    r0, [r2, r0]!                                     (3)
  
       *   cmp    r0, tmp                                           (4)
  
       */
  
  #  if CPU_TLB_BITS > 8
  
  #   error
  
  #  endif
  
      tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
  
                      0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
  
  
  
      /* We assume that the offset is contained within 16 bits.  */
  
      assert((tlb_offset & ~0xffff) == 0);
  
      if (tlb_offset > 0xff) {
  
          tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
  
                          (24 << 7) | (tlb_offset >> 8));
  
          tlb_offset &= 0xff;
  
          base = TCG_REG_R2;
  
      }
  
  
  
      tcg_out_dat_imm(s, COND_AL, ARITH_AND,
  
                      TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
  
      tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
  
                      TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
  
  
  
      /* Load the tlb comparator.  Use ldrd if needed and available,
  
         but due to how the pointer needs setting up, ldm isn't useful.
  
         Base arm5 doesn't have ldrd, but armv5te does.  */
  
      if (use_armv6_instructions && TARGET_LONG_BITS == 64) {
  
          tcg_out_memop_8(s, COND_AL, INSN_LDRD_IMM, TCG_REG_R0,
  
                          TCG_REG_R2, tlb_offset, 1, 1);
  
      } else {
  
          tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R0,
  
                           TCG_REG_R2, tlb_offset, 1, 1);
  
          if (TARGET_LONG_BITS == 64) {
  
              tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R1,
  
                               TCG_REG_R2, 4, 1, 0);
  
          }
  
      }
  
  
  
      /* Check alignment.  */
  
      if (s_bits) {
  
          tcg_out_dat_imm(s, COND_AL, ARITH_TST,
  
                          0, addrlo, (1 << s_bits) - 1);
  
      }
  
  
  
      tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0,
  
                      TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
  
  
  
      if (TARGET_LONG_BITS == 64) {
  
          tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
  
                          TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
  
      }
  
  }
  