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
  30#ifndef CONFIG_USER_ONLY
  31void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg,
  32        uint32_t cop)
  33{
  34    /*
  35     * movc pp.nn, rn, #imm9
  36     *      rn: UCOP_REG_D
  37     *      nn: UCOP_REG_N
  38     *          1: sys control reg.
  39     *          2: page table base reg.
  40     *          3: data fault status reg.
  41     *          4: insn fault status reg.
  42     *          5: cache op. reg.
  43     *          6: tlb op. reg.
  44     *      imm9: split UCOP_IMM10 with bit5 is 0
  45     */
  46    switch (creg) {
  47    case 1:
  48        if (cop != 0) {
  49            goto unrecognized;
  50        }
  51        env->cp0.c1_sys = val;
  52        break;
  53    case 2:
  54        if (cop != 0) {
  55            goto unrecognized;
  56        }
  57        env->cp0.c2_base = val;
  58        break;
  59    case 3:
  60        if (cop != 0) {
  61            goto unrecognized;
  62        }
  63        env->cp0.c3_faultstatus = val;
  64        break;
  65    case 4:
  66        if (cop != 0) {
  67            goto unrecognized;
  68        }
  69        env->cp0.c4_faultaddr = val;
  70        break;
  71    case 5:
  72        switch (cop) {
  73        case 28:
  74            DPRINTF("Invalidate Entire I&D cache\n");
  75            return;
  76        case 20:
  77            DPRINTF("Invalidate Entire Icache\n");
  78            return;
  79        case 12:
  80            DPRINTF("Invalidate Entire Dcache\n");
  81            return;
  82        case 10:
  83            DPRINTF("Clean Entire Dcache\n");
  84            return;
  85        case 14:
  86            DPRINTF("Flush Entire Dcache\n");
  87            return;
  88        case 13:
  89            DPRINTF("Invalidate Dcache line\n");
  90            return;
  91        case 11:
  92            DPRINTF("Clean Dcache line\n");
  93            return;
  94        case 15:
  95            DPRINTF("Flush Dcache line\n");
  96            return;
  97        }
  98        break;
  99    case 6:
 100        if ((cop <= 6) && (cop >= 2)) {
 101            /* invalid all tlb */
 102            tlb_flush(env_cpu(env));
 103            return;
 104        }
 105        break;
 106    default:
 107        goto unrecognized;
 108    }
 109    return;
 110unrecognized:
 111    DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
 112            creg, cop);
 113}
 114
 115uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop)
 116{
 117    /*
 118     * movc rd, pp.nn, #imm9
 119     *      rd: UCOP_REG_D
 120     *      nn: UCOP_REG_N
 121     *          0: cpuid and cachetype
 122     *          1: sys control reg.
 123     *          2: page table base reg.
 124     *          3: data fault status reg.
 125     *          4: insn fault status reg.
 126     *      imm9: split UCOP_IMM10 with bit5 is 0
 127     */
 128    switch (creg) {
 129    case 0:
 130        switch (cop) {
 131        case 0:
 132            return env->cp0.c0_cpuid;
 133        case 1:
 134            return env->cp0.c0_cachetype;
 135        }
 136        break;
 137    case 1:
 138        if (cop == 0) {
 139            return env->cp0.c1_sys;
 140        }
 141        break;
 142    case 2:
 143        if (cop == 0) {
 144            return env->cp0.c2_base;
 145        }
 146        break;
 147    case 3:
 148        if (cop == 0) {
 149            return env->cp0.c3_faultstatus;
 150        }
 151        break;
 152    case 4:
 153        if (cop == 0) {
 154            return env->cp0.c4_faultaddr;
 155        }
 156        break;
 157    }
 158    DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
 159            creg, cop);
 160    return 0;
 161}
 162
 163#ifdef CONFIG_CURSES
 164
 165/* KEY_EVENT is defined in wincon.h and in curses.h. Avoid redefinition. */
 166#undef KEY_EVENT
 167#include <curses.h>
 168#undef KEY_EVENT
 169
 170/*
 171 * FIXME:
 172 *     1. curses windows will be blank when switching back
 173 *     2. backspace is not handled yet
 174 */
 175static void putc_on_screen(unsigned char ch)
 176{
 177    static WINDOW *localwin;
 178    static int init;
 179
 180    if (!init) {
 181        /* Assume 80 * 30 screen to minimize the implementation */
 182        localwin = newwin(30, 80, 0, 0);
 183        scrollok(localwin, TRUE);
 184        init = TRUE;
 185    }
 186
 187    if (isprint(ch)) {
 188        wprintw(localwin, "%c", ch);
 189    } else {
 190        switch (ch) {
 191        case '\n':
 192            wprintw(localwin, "%c", ch);
 193            break;
 194        case '\r':
 195            /* If '\r' is put before '\n', the curses window will destroy the
 196             * last print line. And meanwhile, '\n' implifies '\r' inside. */
 197            break;
 198        default: /* Not handled, so just print it hex code */
 199            wprintw(localwin, "-- 0x%x --", ch);
 200        }
 201    }
 202
 203    wrefresh(localwin);
 204}
 205#else
 206#define putc_on_screen(c)               do { } while (0)
 207#endif
 208
 209void helper_cp1_putc(target_ulong x)
 210{
 211    putc_on_screen((unsigned char)x);   /* Output to screen */
 212    DPRINTF("%c", x);                   /* Output to stdout */
 213}
 214#endif
 215
 216bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 217{
 218    if (interrupt_request & CPU_INTERRUPT_HARD) {
 219        UniCore32CPU *cpu = UNICORE32_CPU(cs);
 220        CPUUniCore32State *env = &cpu->env;
 221
 222        if (!(env->uncached_asr & ASR_I)) {
 223            cs->exception_index = UC32_EXCP_INTR;
 224            uc32_cpu_do_interrupt(cs);
 225            return true;
 226        }
 227    }
 228    return false;
 229}
 230