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 "qemu/log.h"
  14#include "cpu.h"
  15#include "exec/exec-all.h"
  16#include "exec/helper-proto.h"
  17#include "semihosting/console.h"
  18
  19#undef DEBUG_UC32
  20
  21#ifdef DEBUG_UC32
  22#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
  23#else
  24#define DPRINTF(fmt, ...) do {} while (0)
  25#endif
  26
  27#ifndef CONFIG_USER_ONLY
  28void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg,
  29        uint32_t cop)
  30{
  31    /*
  32     * movc pp.nn, rn, #imm9
  33     *      rn: UCOP_REG_D
  34     *      nn: UCOP_REG_N
  35     *          1: sys control reg.
  36     *          2: page table base reg.
  37     *          3: data fault status reg.
  38     *          4: insn fault status reg.
  39     *          5: cache op. reg.
  40     *          6: tlb op. reg.
  41     *      imm9: split UCOP_IMM10 with bit5 is 0
  42     */
  43    switch (creg) {
  44    case 1:
  45        if (cop != 0) {
  46            goto unrecognized;
  47        }
  48        env->cp0.c1_sys = val;
  49        break;
  50    case 2:
  51        if (cop != 0) {
  52            goto unrecognized;
  53        }
  54        env->cp0.c2_base = val;
  55        break;
  56    case 3:
  57        if (cop != 0) {
  58            goto unrecognized;
  59        }
  60        env->cp0.c3_faultstatus = val;
  61        break;
  62    case 4:
  63        if (cop != 0) {
  64            goto unrecognized;
  65        }
  66        env->cp0.c4_faultaddr = val;
  67        break;
  68    case 5:
  69        switch (cop) {
  70        case 28:
  71            DPRINTF("Invalidate Entire I&D cache\n");
  72            return;
  73        case 20:
  74            DPRINTF("Invalidate Entire Icache\n");
  75            return;
  76        case 12:
  77            DPRINTF("Invalidate Entire Dcache\n");
  78            return;
  79        case 10:
  80            DPRINTF("Clean Entire Dcache\n");
  81            return;
  82        case 14:
  83            DPRINTF("Flush Entire Dcache\n");
  84            return;
  85        case 13:
  86            DPRINTF("Invalidate Dcache line\n");
  87            return;
  88        case 11:
  89            DPRINTF("Clean Dcache line\n");
  90            return;
  91        case 15:
  92            DPRINTF("Flush Dcache line\n");
  93            return;
  94        }
  95        break;
  96    case 6:
  97        if ((cop <= 6) && (cop >= 2)) {
  98            /* invalid all tlb */
  99            tlb_flush(env_cpu(env));
 100            return;
 101        }
 102        break;
 103    default:
 104        goto unrecognized;
 105    }
 106    return;
 107unrecognized:
 108    qemu_log_mask(LOG_GUEST_ERROR,
 109                  "Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
 110                  creg, cop);
 111}
 112
 113uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop)
 114{
 115    /*
 116     * movc rd, pp.nn, #imm9
 117     *      rd: UCOP_REG_D
 118     *      nn: UCOP_REG_N
 119     *          0: cpuid and cachetype
 120     *          1: sys control reg.
 121     *          2: page table base reg.
 122     *          3: data fault status reg.
 123     *          4: insn fault status reg.
 124     *      imm9: split UCOP_IMM10 with bit5 is 0
 125     */
 126    switch (creg) {
 127    case 0:
 128        switch (cop) {
 129        case 0:
 130            return env->cp0.c0_cpuid;
 131        case 1:
 132            return env->cp0.c0_cachetype;
 133        }
 134        break;
 135    case 1:
 136        if (cop == 0) {
 137            return env->cp0.c1_sys;
 138        }
 139        break;
 140    case 2:
 141        if (cop == 0) {
 142            return env->cp0.c2_base;
 143        }
 144        break;
 145    case 3:
 146        if (cop == 0) {
 147            return env->cp0.c3_faultstatus;
 148        }
 149        break;
 150    case 4:
 151        if (cop == 0) {
 152            return env->cp0.c4_faultaddr;
 153        }
 154        break;
 155    }
 156    qemu_log_mask(LOG_GUEST_ERROR,
 157                  "Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
 158                  creg, cop);
 159    return 0;
 160}
 161
 162void helper_cp1_putc(target_ulong regval)
 163{
 164    const char c = regval;
 165
 166    qemu_semihosting_log_out(&c, sizeof(c));
 167}
 168#endif /* !CONFIG_USER_ONLY */
 169
 170bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 171{
 172    if (interrupt_request & CPU_INTERRUPT_HARD) {
 173        UniCore32CPU *cpu = UNICORE32_CPU(cs);
 174        CPUUniCore32State *env = &cpu->env;
 175
 176        if (!(env->uncached_asr & ASR_I)) {
 177            cs->exception_index = UC32_EXCP_INTR;
 178            uc32_cpu_do_interrupt(cs);
 179            return true;
 180        }
 181    }
 182    return false;
 183}
 184