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