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