Commit c05c73b0 authored by Laurent Vivier's avatar Laurent Vivier
Browse files

target/m68k: add Transparent Translation



Add ittr0, ittr1, dttr0, dttr1 and manage Transparent Translations

Signed-off-by: default avatarLaurent Vivier <laurent@vivier.eu>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-Id: <20180118193846.24953-4-laurent@vivier.eu>
parent 88b2fef6
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -76,6 +76,14 @@
#define EXCP_RTE            0x100
#define EXCP_HALT_INSN      0x101

#define M68K_DTTR0   0
#define M68K_DTTR1   1
#define M68K_ITTR0   2
#define M68K_ITTR1   3

#define M68K_MAX_TTR 2
#define TTR(type, index) ttr[((type & ACCESS_CODE) == ACCESS_CODE) * 2 + index]

#define NB_MMU_MODES 2
#define TARGET_INSN_START_EXTRA_WORDS 1

@@ -122,6 +130,7 @@ typedef struct CPUM68KState {
        uint32_t urp;
        uint32_t srp;
        bool fault;
        uint32_t ttr[4];
    } mmu;

    /* Control registers.  */
@@ -318,6 +327,15 @@ typedef enum {
#define M68K_PDT_INDIRECT(entry)    ((entry & 3) == 2)
#define M68K_INDIRECT_POINTER(addr) (addr & ~3)

/* bits for 68040 MMU Transparent Translation Registers */
#define M68K_TTR_ADDR_BASE 0xff000000
#define M68K_TTR_ADDR_MASK 0x00ff0000
#define M68K_TTR_ADDR_MASK_SHIFT    8
#define M68K_TTR_ENABLED   0x00008000
#define M68K_TTR_SFIELD    0x00006000
#define M68K_TTR_SFIELD_USER   0x0000
#define M68K_TTR_SFIELD_SUPER  0x2000

/* m68k Control Registers */

/* ColdFire */
+79 −0
Original line number Diff line number Diff line
@@ -230,6 +230,19 @@ void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
    case M68K_CR_ISP:
        env->sp[M68K_ISP] = val;
        return;
    /* MC68040/MC68LC040 */
    case M68K_CR_ITT0:
        env->mmu.ttr[M68K_ITTR0] = val;
        return;
    case M68K_CR_ITT1:
         env->mmu.ttr[M68K_ITTR1] = val;
        return;
    case M68K_CR_DTT0:
        env->mmu.ttr[M68K_DTTR0] = val;
        return;
    case M68K_CR_DTT1:
        env->mmu.ttr[M68K_DTTR1] = val;
        return;
    }
    cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
              reg, val);
@@ -260,6 +273,14 @@ uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg)
    /* MC68040/MC68LC040 */
    case M68K_CR_URP:
        return env->mmu.urp;
    case M68K_CR_ITT0:
        return env->mmu.ttr[M68K_ITTR0];
    case M68K_CR_ITT1:
        return env->mmu.ttr[M68K_ITTR1];
    case M68K_CR_DTT0:
        return env->mmu.ttr[M68K_DTTR0];
    case M68K_CR_DTT1:
        return env->mmu.ttr[M68K_DTTR1];
    }
    cpu_abort(CPU(cpu), "Unimplemented control register read 0x%x\n",
              reg);
@@ -338,6 +359,53 @@ int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,

/* MMU: 68040 only */

static int check_TTR(uint32_t ttr, int *prot, target_ulong addr,
                     int access_type)
{
    uint32_t base, mask;

    /* check if transparent translation is enabled */
    if ((ttr & M68K_TTR_ENABLED) == 0) {
        return 0;
    }

    /* check mode access */
    switch (ttr & M68K_TTR_SFIELD) {
    case M68K_TTR_SFIELD_USER:
        /* match only if user */
        if ((access_type & ACCESS_SUPER) != 0) {
            return 0;
        }
        break;
    case M68K_TTR_SFIELD_SUPER:
        /* match only if supervisor */
        if ((access_type & ACCESS_SUPER) == 0) {
            return 0;
        }
        break;
    default:
        /* all other values disable mode matching (FC2) */
        break;
    }

    /* check address matching */

    base = ttr & M68K_TTR_ADDR_BASE;
    mask = (ttr & M68K_TTR_ADDR_MASK) ^ M68K_TTR_ADDR_MASK;
    mask <<= M68K_TTR_ADDR_MASK_SHIFT;

    if ((addr & mask) != (base & mask)) {
        return 0;
    }

    *prot = PAGE_READ | PAGE_EXEC;
    if ((ttr & M68K_DESC_WRITEPROT) == 0) {
        *prot |= PAGE_WRITE;
    }

    return 1;
}

static int get_physical_address(CPUM68KState *env, hwaddr *physical,
                                int *prot, target_ulong address,
                                int access_type, target_ulong *page_size)
@@ -349,6 +417,17 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
    target_ulong page_mask;
    bool debug = access_type & ACCESS_DEBUG;
    int page_bits;
    int i;

    /* Transparent Translation (physical = logical) */
    for (i = 0; i < M68K_MAX_TTR; i++) {
        if (check_TTR(env->mmu.TTR(access_type, i),
                      prot, address, access_type)) {
            *physical = address & TARGET_PAGE_MASK;
            *page_size = TARGET_PAGE_SIZE;
            return 0;
        }
    }

    /* Page Table Root Pointer */
    *prot = PAGE_READ | PAGE_WRITE;
+4 −0
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@ static const MonitorDef monitor_defs[] = {
    { "isp", offsetof(CPUM68KState, sp[2]) },
    { "urp", offsetof(CPUM68KState, mmu.urp) },
    { "srp", offsetof(CPUM68KState, mmu.srp) },
    { "dttr0", offsetof(CPUM68KState, mmu.ttr[M68K_DTTR0]) },
    { "dttr1", offsetof(CPUM68KState, mmu.ttr[M68K_DTTR1]) },
    { "ittr0", offsetof(CPUM68KState, mmu.ttr[M68K_ITTR0]) },
    { "ittr1", offsetof(CPUM68KState, mmu.ttr[M68K_ITTR1]) },
    { NULL },
};

+3 −0
Original line number Diff line number Diff line
@@ -5982,6 +5982,9 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
    cpu_fprintf(f, "VBR = 0x%08x\n", env->vbr);
    cpu_fprintf(f, "SSW %08x TCR %08x URP %08x SRP %08x\n",
                env->mmu.ssw, env->mmu.tcr, env->mmu.urp, env->mmu.srp);
    cpu_fprintf(f, "DTTR0/1: %08x/%08x ITTR0/1: %08x/%08x\n",
                env->mmu.ttr[M68K_DTTR0], env->mmu.ttr[M68K_DTTR1],
                env->mmu.ttr[M68K_ITTR0], env->mmu.ttr[M68K_ITTR1]);
#endif
}