qemu/target/unicore32/helper.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2010-2012 Guan Xuetao
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * Contributions from 2012-04-01 on are considered under GPL version 2,
   9 * or (at your option) any later version.
  10 */
  11
  12#include "qemu/osdep.h"
  13#include "cpu.h"
  14#include "exec/exec-all.h"
  15#include "exec/gdbstub.h"
  16#include "exec/helper-proto.h"
  17#include "qemu/host-utils.h"
  18#ifndef CONFIG_USER_ONLY
  19#include "ui/console.h"
  20#endif
  21
  22#undef DEBUG_UC32
  23
  24#ifdef DEBUG_UC32
  25#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
  26#else
  27#define DPRINTF(fmt, ...) do {} while (0)
  28#endif
  29
  30UniCore32CPU *uc32_cpu_init(const char *cpu_model)
  31{
  32    return UNICORE32_CPU(cpu_generic_init(TYPE_UNICORE32_CPU, cpu_model));
  33}
  34
  35#ifndef CONFIG_USER_ONLY
  36void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg,
  37        uint32_t cop)
  38{
  39    UniCore32CPU *cpu = uc32_env_get_cpu(env);
  40
  41    /*
  42     * movc pp.nn, rn, #imm9
  43     *      rn: UCOP_REG_D
  44     *      nn: UCOP_REG_N
  45     *          1: sys control reg.
  46     *          2: page table base reg.
  47     *          3: data fault status reg.
  48     *          4: insn fault status reg.
  49     *          5: cache op. reg.
  50     *          6: tlb op. reg.
  51     *      imm9: split UCOP_IMM10 with bit5 is 0
  52     */
  53    switch (creg) {
  54    case 1:
  55        if (cop != 0) {
  56            goto unrecognized;
  57        }
  58        env->cp0.c1_sys = val;
  59        break;
  60    case 2:
  61        if (cop != 0) {
  62            goto unrecognized;
  63        }
  64        env->cp0.c2_base = val;
  65        break;
  66    case 3:
  67        if (cop != 0) {
  68            goto unrecognized;
  69        }
  70        env->cp0.c3_faultstatus = val;
  71        break;
  72    case 4:
  73        if (cop != 0) {
  74            goto unrecognized;
  75        }
  76        env->cp0.c4_faultaddr = val;
  77        break;
  78    case 5:
  79        switch (cop) {
  80        case 28:
  81            DPRINTF("Invalidate Entire I&D cache\n");
  82            return;
  83        case 20:
  84            DPRINTF("Invalidate Entire Icache\n");
  85            return;
  86        case 12:
  87            DPRINTF("Invalidate Entire Dcache\n");
  88            return;
  89        case 10:
  90            DPRINTF("Clean Entire Dcache\n");
  91            return;
  92        case 14:
  93            DPRINTF("Flush Entire Dcache\n");
  94            return;
  95        case 13:
  96            DPRINTF("Invalidate Dcache line\n");
  97            return;
  98        case 11:
  99            DPRINTF("Clean Dcache line\n");
 100            return;
 101        case 15:
 102            DPRINTF("Flush Dcache line\n");
 103            return;
 104        }
 105        break;
 106    case 6:
 107        if ((cop <= 6) && (cop >= 2)) {
 108            /* invalid all tlb */
 109            tlb_flush(CPU(cpu));
 110            return;
 111        }
 112        break;
 113    default:
 114        goto unrecognized;
 115    }
 116    return;
 117unrecognized:
 118    DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
 119            creg, cop);
 120}
 121
 122uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop)
 123{
 124    /*
 125     * movc rd, pp.nn, #imm9
 126     *      rd: UCOP_REG_D
 127     *      nn: UCOP_REG_N
 128     *          0: cpuid and cachetype
 129     *          1: sys control reg.
 130     *          2: page table base reg.
 131     *          3: data fault status reg.
 132     *          4: insn fault status reg.
 133     *      imm9: split UCOP_IMM10 with bit5 is 0
 134     */
 135    switch (creg) {
 136    case 0:
 137        switch (cop) {
 138        case 0:
 139            return env->cp0.c0_cpuid;
 140        case 1:
 141            return env->cp0.c0_cachetype;
 142        }
 143        break;
 144    case 1:
 145        if (cop == 0) {
 146            return env->cp0.c1_sys;
 147        }
 148        break;
 149    case 2:
 150        if (cop == 0) {
 151            return env->cp0.c2_base;
 152        }
 153        break;
 154    case 3:
 155        if (cop == 0) {
 156            return env->cp0.c3_faultstatus;
 157        }
 158        break;
 159    case 4:
 160        if (cop == 0) {
 161            return env->cp0.c4_faultaddr;
 162        }
 163        break;
 164    }
 165    DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
 166            creg, cop);
 167    return 0;
 168}
 169
 170#ifdef CONFIG_CURSES
 171/*
 172 * FIXME:
 173 *     1. curses windows will be blank when switching back
 174 *     2. backspace is not handled yet
 175 */
 176static void putc_on_screen(unsigned char ch)
 177{
 178    static WINDOW *localwin;
 179    static int init;
 180
 181    if (!init) {
 182        /* Assume 80 * 30 screen to minimize the implementation */
 183        localwin = newwin(30, 80, 0, 0);
 184        scrollok(localwin, TRUE);
 185        init = TRUE;
 186    }
 187
 188    if (isprint(ch)) {
 189        wprintw(localwin, "%c", ch);
 190    } else {
 191        switch (ch) {
 192        case '\n':
 193            wprintw(localwin, "%c", ch);
 194            break;
 195        case '\r':
 196            /* If '\r' is put before '\n', the curses window will destroy the
 197             * last print line. And meanwhile, '\n' implifies '\r' inside. */
 198            break;
 199        default: /* Not handled, so just print it hex code */
 200            wprintw(localwin, "-- 0x%x --", ch);
 201        }
 202    }
 203
 204    wrefresh(localwin);
 205}
 206#else
 207#define putc_on_screen(c)               do { } while (0)
 208#endif
 209
 210void helper_cp1_putc(target_ulong x)
 211{
 212    putc_on_screen((unsigned char)x);   /* Output to screen */
 213    DPRINTF("%c", x);                   /* Output to stdout */
 214}
 215#endif
 216
 217#ifdef CONFIG_USER_ONLY
 218void switch_mode(CPUUniCore32State *env, int mode)
 219{
 220    UniCore32CPU *cpu = uc32_env_get_cpu(env);
 221
 222    if (mode != ASR_MODE_USER) {
 223        cpu_abort(CPU(cpu), "Tried to switch out of user mode\n");
 224    }
 225}
 226
 227void uc32_cpu_do_interrupt(CPUState *cs)
 228{
 229    cpu_abort(cs, "NO interrupt in user mode\n");
 230}
 231
 232int uc32_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
 233                              int access_type, int mmu_idx)
 234{
 235    cpu_abort(cs, "NO mmu fault in user mode\n");
 236    return 1;
 237}
 238#endif
 239
 240bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 241{
 242    if (interrupt_request & CPU_INTERRUPT_HARD) {
 243        UniCore32CPU *cpu = UNICORE32_CPU(cs);
 244        CPUUniCore32State *env = &cpu->env;
 245
 246        if (!(env->uncached_asr & ASR_I)) {
 247            cs->exception_index = UC32_EXCP_INTR;
 248            uc32_cpu_do_interrupt(cs);
 249            return true;
 250        }
 251    }
 252    return false;
 253}
 254