static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,

                              uint64_t asc, uint64_t asce, int level,

                              target_ulong *raddr, int *flags, int rw)

{

    CPUState *cs = CPU(s390_env_get_cpu(env));

    uint64_t offs = 0;

    uint64_t origin;

    uint64_t new_asce;



    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, asce);



    if (((level != _ASCE_TYPE_SEGMENT) && (asce & _REGION_ENTRY_INV)) ||

        ((level == _ASCE_TYPE_SEGMENT) && (asce & _SEGMENT_ENTRY_INV))) {

        /* XXX different regions have different faults */

        DPRINTF("%s: invalid region\n", __func__);

        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);

        return -1;

    }



    if ((level <= _ASCE_TYPE_MASK) && ((asce & _ASCE_TYPE_MASK) != level)) {

        trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);

        return -1;

    }



    if (asce & _ASCE_REAL_SPACE) {

        /* direct mapping */



        *raddr = vaddr;

        return 0;

    }



    origin = asce & _ASCE_ORIGIN;



    switch (level) {

    case _ASCE_TYPE_REGION1 + 4:

        offs = (vaddr >> 50) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION1:

        offs = (vaddr >> 39) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION2:

        offs = (vaddr >> 28) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION3:

        offs = (vaddr >> 17) & 0x3ff8;

        break;

    case _ASCE_TYPE_SEGMENT:

        offs = (vaddr >> 9) & 0x07f8;

        origin = asce & _SEGMENT_ENTRY_ORIGIN;

        break;

    }



    /* XXX region protection flags */

    /* *flags &= ~PAGE_WRITE */



    new_asce = ldq_phys(cs->as, origin + offs);

    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",

                __func__, origin, offs, new_asce);



    if (level == _ASCE_TYPE_SEGMENT) {

        /* 4KB page */

        return mmu_translate_pte(env, vaddr, asc, new_asce, raddr, flags, rw);

    } else if (level - 4 == _ASCE_TYPE_SEGMENT &&

               (new_asce & _SEGMENT_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) {

        /* 1MB page */

        return mmu_translate_sfaa(env, vaddr, asc, new_asce, raddr, flags, rw);

    } else {

        /* yet another region */

        return mmu_translate_asce(env, vaddr, asc, new_asce, level - 4, raddr,

                                  flags, rw);

    }

}

static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,

                              uint64_t asc, uint64_t asce, int level,

                              target_ulong *raddr, int *flags, int rw)

{

    CPUState *cs = CPU(s390_env_get_cpu(env));

    uint64_t offs = 0;

    uint64_t origin;

    uint64_t new_asce;



    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, asce);



    if (((level != _ASCE_TYPE_SEGMENT) && (asce & _REGION_ENTRY_INV)) ||

        ((level == _ASCE_TYPE_SEGMENT) && (asce & _SEGMENT_ENTRY_INV))) {

        

        DPRINTF("%s: invalid region\n", __func__);

        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);

        return -1;

    }



    if ((level <= _ASCE_TYPE_MASK) && ((asce & _ASCE_TYPE_MASK) != level)) {

        trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);

        return -1;

    }



    if (asce & _ASCE_REAL_SPACE) {

        



        *raddr = vaddr;

        return 0;

    }



    origin = asce & _ASCE_ORIGIN;



    switch (level) {

    case _ASCE_TYPE_REGION1 + 4:

        offs = (vaddr >> 50) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION1:

        offs = (vaddr >> 39) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION2:

        offs = (vaddr >> 28) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION3:

        offs = (vaddr >> 17) & 0x3ff8;

        break;

    case _ASCE_TYPE_SEGMENT:

        offs = (vaddr >> 9) & 0x07f8;

        origin = asce & _SEGMENT_ENTRY_ORIGIN;

        break;

    }



    

    



    new_asce = ldq_phys(cs->as, origin + offs);

    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",

                __func__, origin, offs, new_asce);



    if (level == _ASCE_TYPE_SEGMENT) {

        

        return mmu_translate_pte(env, vaddr, asc, new_asce, raddr, flags, rw);

    } else if (level - 4 == _ASCE_TYPE_SEGMENT &&

               (new_asce & _SEGMENT_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) {

        

        return mmu_translate_sfaa(env, vaddr, asc, new_asce, raddr, flags, rw);

    } else {

        

        return mmu_translate_asce(env, vaddr, asc, new_asce, level - 4, raddr,

                                  flags, rw);

    }

}

static int FUNC_0(CPUS390XState *VAR_0, target_ulong VAR_1,

                              uint64_t VAR_2, uint64_t VAR_3, int VAR_4,

                              target_ulong *VAR_5, int *VAR_6, int VAR_7)

{

    CPUState *cs = CPU(s390_env_get_cpu(VAR_0));

    uint64_t offs = 0;

    uint64_t origin;

    uint64_t new_asce;



    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, VAR_3);



    if (((VAR_4 != _ASCE_TYPE_SEGMENT) && (VAR_3 & _REGION_ENTRY_INV)) ||

        ((VAR_4 == _ASCE_TYPE_SEGMENT) && (VAR_3 & _SEGMENT_ENTRY_INV))) {

        

        DPRINTF("%s: invalid region\n", __func__);

        trigger_page_fault(VAR_0, VAR_1, PGM_SEGMENT_TRANS, VAR_2, VAR_7);

        return -1;

    }



    if ((VAR_4 <= _ASCE_TYPE_MASK) && ((VAR_3 & _ASCE_TYPE_MASK) != VAR_4)) {

        trigger_page_fault(VAR_0, VAR_1, PGM_TRANS_SPEC, VAR_2, VAR_7);

        return -1;

    }



    if (VAR_3 & _ASCE_REAL_SPACE) {

        



        *VAR_5 = VAR_1;

        return 0;

    }



    origin = VAR_3 & _ASCE_ORIGIN;



    switch (VAR_4) {

    case _ASCE_TYPE_REGION1 + 4:

        offs = (VAR_1 >> 50) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION1:

        offs = (VAR_1 >> 39) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION2:

        offs = (VAR_1 >> 28) & 0x3ff8;

        break;

    case _ASCE_TYPE_REGION3:

        offs = (VAR_1 >> 17) & 0x3ff8;

        break;

    case _ASCE_TYPE_SEGMENT:

        offs = (VAR_1 >> 9) & 0x07f8;

        origin = VAR_3 & _SEGMENT_ENTRY_ORIGIN;

        break;

    }



    

    



    new_asce = ldq_phys(cs->as, origin + offs);

    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",

                __func__, origin, offs, new_asce);



    if (VAR_4 == _ASCE_TYPE_SEGMENT) {

        

        return mmu_translate_pte(VAR_0, VAR_1, VAR_2, new_asce, VAR_5, VAR_6, VAR_7);

    } else if (VAR_4 - 4 == _ASCE_TYPE_SEGMENT &&

               (new_asce & _SEGMENT_ENTRY_FC) && (VAR_0->cregs[0] & CR0_EDAT)) {

        

        return mmu_translate_sfaa(VAR_0, VAR_1, VAR_2, new_asce, VAR_5, VAR_6, VAR_7);

    } else {

        

        return FUNC_0(VAR_0, VAR_1, VAR_2, new_asce, VAR_4 - 4, VAR_5,

                                  VAR_6, VAR_7);

    }

}

static int FUNC_0(CPUS390XState *VAR_0, target_ulong VAR_1,
uint64_t VAR_2, uint64_t VAR_3, int VAR_4,
target_ulong *VAR_5, int *VAR_6, int VAR_7)
{ CPUState *cs = CPU(s390_env_get_cpu(VAR_0)); uint64_t offs = 0; uint64_t origin; uint64_t new_asce; PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, VAR_3); if (((VAR_4 != _ASCE_TYPE_SEGMENT) && (VAR_3 & _REGION_ENTRY_INV)) ||
((VAR_4 == _ASCE_TYPE_SEGMENT) && (VAR_3 & _SEGMENT_ENTRY_INV))) { DPRINTF("%s: invalid region\n", __func__); trigger_page_fault(VAR_0, VAR_1, PGM_SEGMENT_TRANS, VAR_2, VAR_7); return -1; } if ((VAR_4 <= _ASCE_TYPE_MASK) && ((VAR_3 & _ASCE_TYPE_MASK) != VAR_4)) { trigger_page_fault(VAR_0, VAR_1, PGM_TRANS_SPEC, VAR_2, VAR_7); return -1; } if (VAR_3 & _ASCE_REAL_SPACE) { *VAR_5 = VAR_1; return 0; } origin = VAR_3 & _ASCE_ORIGIN; switch (VAR_4) { case _ASCE_TYPE_REGION1 + 4:
offs = (VAR_1 >> 50) & 0x3ff8; break; case _ASCE_TYPE_REGION1:
offs = (VAR_1 >> 39) & 0x3ff8; break; case _ASCE_TYPE_REGION2:
offs = (VAR_1 >> 28) & 0x3ff8; break; case _ASCE_TYPE_REGION3:
offs = (VAR_1 >> 17) & 0x3ff8; break; case _ASCE_TYPE_SEGMENT:
offs = (VAR_1 >> 9) & 0x07f8; origin = VAR_3 & _SEGMENT_ENTRY_ORIGIN; break; } new_asce = ldq_phys(cs->as, origin + offs); PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
__func__, origin, offs, new_asce); if (VAR_4 == _ASCE_TYPE_SEGMENT) { return mmu_translate_pte(VAR_0, VAR_1, VAR_2, new_asce, VAR_5, VAR_6, VAR_7); } else if (VAR_4 - 4 == _ASCE_TYPE_SEGMENT && (new_asce & _SEGMENT_ENTRY_FC) && (VAR_0->cregs[0] & CR0_EDAT)) { return mmu_translate_sfaa(VAR_0, VAR_1, VAR_2, new_asce, VAR_5, VAR_6, VAR_7); } else { return FUNC_0(VAR_0, VAR_1, VAR_2, new_asce, VAR_4 - 4, VAR_5,
VAR_6, VAR_7); } }