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