File:  [Qemu by Fabrice Bellard] / qemu / target-lm32 / helper.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:31:27 2018 UTC (3 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, HEAD
qemu 1.0.1

    1: /*
    2:  *  LatticeMico32 helper routines.
    3:  *
    4:  *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
    5:  *
    6:  * This library is free software; you can redistribute it and/or
    7:  * modify it under the terms of the GNU Lesser General Public
    8:  * License as published by the Free Software Foundation; either
    9:  * version 2 of the License, or (at your option) any later version.
   10:  *
   11:  * This library is distributed in the hope that it will be useful,
   12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * Lesser General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU Lesser General Public
   17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
   18:  */
   19: 
   20: #include <stdio.h>
   21: #include <string.h>
   22: #include <assert.h>
   23: 
   24: #include "config.h"
   25: #include "cpu.h"
   26: #include "host-utils.h"
   27: 
   28: int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
   29:                               int mmu_idx)
   30: {
   31:     int prot;
   32: 
   33:     address &= TARGET_PAGE_MASK;
   34:     prot = PAGE_BITS;
   35:     if (env->flags & LM32_FLAG_IGNORE_MSB) {
   36:         tlb_set_page(env, address, address & 0x7fffffff, prot, mmu_idx,
   37:                 TARGET_PAGE_SIZE);
   38:     } else {
   39:         tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
   40:     }
   41: 
   42:     return 0;
   43: }
   44: 
   45: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
   46: {
   47:     return addr & TARGET_PAGE_MASK;
   48: }
   49: 
   50: void do_interrupt(CPUState *env)
   51: {
   52:     qemu_log_mask(CPU_LOG_INT,
   53:             "exception at pc=%x type=%x\n", env->pc, env->exception_index);
   54: 
   55:     switch (env->exception_index) {
   56:     case EXCP_INSN_BUS_ERROR:
   57:     case EXCP_DATA_BUS_ERROR:
   58:     case EXCP_DIVIDE_BY_ZERO:
   59:     case EXCP_IRQ:
   60:     case EXCP_SYSTEMCALL:
   61:         /* non-debug exceptions */
   62:         env->regs[R_EA] = env->pc;
   63:         env->ie |= (env->ie & IE_IE) ? IE_EIE : 0;
   64:         env->ie &= ~IE_IE;
   65:         if (env->dc & DC_RE) {
   66:             env->pc = env->deba + (env->exception_index * 32);
   67:         } else {
   68:             env->pc = env->eba + (env->exception_index * 32);
   69:         }
   70:         log_cpu_state_mask(CPU_LOG_INT, env, 0);
   71:         break;
   72:     case EXCP_BREAKPOINT:
   73:     case EXCP_WATCHPOINT:
   74:         /* debug exceptions */
   75:         env->regs[R_BA] = env->pc;
   76:         env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
   77:         env->ie &= ~IE_IE;
   78:         env->pc = env->deba + (env->exception_index * 32);
   79:         log_cpu_state_mask(CPU_LOG_INT, env, 0);
   80:         break;
   81:     default:
   82:         cpu_abort(env, "unhandled exception type=%d\n",
   83:                   env->exception_index);
   84:         break;
   85:     }
   86: }
   87: 
   88: typedef struct {
   89:     const char *name;
   90:     uint32_t revision;
   91:     uint8_t num_interrupts;
   92:     uint8_t num_breakpoints;
   93:     uint8_t num_watchpoints;
   94:     uint32_t features;
   95: } LM32Def;
   96: 
   97: static const LM32Def lm32_defs[] = {
   98:     {
   99:         .name = "lm32-basic",
  100:         .revision = 3,
  101:         .num_interrupts = 32,
  102:         .num_breakpoints = 4,
  103:         .num_watchpoints = 4,
  104:         .features = (LM32_FEATURE_SHIFT
  105:                      | LM32_FEATURE_SIGN_EXTEND
  106:                      | LM32_FEATURE_CYCLE_COUNT),
  107:     },
  108:     {
  109:         .name = "lm32-standard",
  110:         .revision = 3,
  111:         .num_interrupts = 32,
  112:         .num_breakpoints = 4,
  113:         .num_watchpoints = 4,
  114:         .features = (LM32_FEATURE_MULTIPLY
  115:                      | LM32_FEATURE_DIVIDE
  116:                      | LM32_FEATURE_SHIFT
  117:                      | LM32_FEATURE_SIGN_EXTEND
  118:                      | LM32_FEATURE_I_CACHE
  119:                      | LM32_FEATURE_CYCLE_COUNT),
  120:     },
  121:     {
  122:         .name = "lm32-full",
  123:         .revision = 3,
  124:         .num_interrupts = 32,
  125:         .num_breakpoints = 4,
  126:         .num_watchpoints = 4,
  127:         .features = (LM32_FEATURE_MULTIPLY
  128:                      | LM32_FEATURE_DIVIDE
  129:                      | LM32_FEATURE_SHIFT
  130:                      | LM32_FEATURE_SIGN_EXTEND
  131:                      | LM32_FEATURE_I_CACHE
  132:                      | LM32_FEATURE_D_CACHE
  133:                      | LM32_FEATURE_CYCLE_COUNT),
  134:     }
  135: };
  136: 
  137: void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf)
  138: {
  139:     int i;
  140: 
  141:     cpu_fprintf(f, "Available CPUs:\n");
  142:     for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
  143:         cpu_fprintf(f, "  %s\n", lm32_defs[i].name);
  144:     }
  145: }
  146: 
  147: static const LM32Def *cpu_lm32_find_by_name(const char *name)
  148: {
  149:     int i;
  150: 
  151:     for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
  152:         if (strcasecmp(name, lm32_defs[i].name) == 0) {
  153:             return &lm32_defs[i];
  154:         }
  155:     }
  156: 
  157:     return NULL;
  158: }
  159: 
  160: static uint32_t cfg_by_def(const LM32Def *def)
  161: {
  162:     uint32_t cfg = 0;
  163: 
  164:     if (def->features & LM32_FEATURE_MULTIPLY) {
  165:         cfg |= CFG_M;
  166:     }
  167: 
  168:     if (def->features & LM32_FEATURE_DIVIDE) {
  169:         cfg |= CFG_D;
  170:     }
  171: 
  172:     if (def->features & LM32_FEATURE_SHIFT) {
  173:         cfg |= CFG_S;
  174:     }
  175: 
  176:     if (def->features & LM32_FEATURE_SIGN_EXTEND) {
  177:         cfg |= CFG_X;
  178:     }
  179: 
  180:     if (def->features & LM32_FEATURE_I_CACHE) {
  181:         cfg |= CFG_IC;
  182:     }
  183: 
  184:     if (def->features & LM32_FEATURE_D_CACHE) {
  185:         cfg |= CFG_DC;
  186:     }
  187: 
  188:     if (def->features & LM32_FEATURE_CYCLE_COUNT) {
  189:         cfg |= CFG_CC;
  190:     }
  191: 
  192:     cfg |= (def->num_interrupts << CFG_INT_SHIFT);
  193:     cfg |= (def->num_breakpoints << CFG_BP_SHIFT);
  194:     cfg |= (def->num_watchpoints << CFG_WP_SHIFT);
  195:     cfg |= (def->revision << CFG_REV_SHIFT);
  196: 
  197:     return cfg;
  198: }
  199: 
  200: CPUState *cpu_lm32_init(const char *cpu_model)
  201: {
  202:     CPUState *env;
  203:     const LM32Def *def;
  204:     static int tcg_initialized;
  205: 
  206:     def = cpu_lm32_find_by_name(cpu_model);
  207:     if (!def) {
  208:         return NULL;
  209:     }
  210: 
  211:     env = g_malloc0(sizeof(CPUState));
  212: 
  213:     env->features = def->features;
  214:     env->num_bps = def->num_breakpoints;
  215:     env->num_wps = def->num_watchpoints;
  216:     env->cfg = cfg_by_def(def);
  217:     env->flags = 0;
  218: 
  219:     cpu_exec_init(env);
  220:     cpu_reset(env);
  221:     qemu_init_vcpu(env);
  222: 
  223:     if (!tcg_initialized) {
  224:         tcg_initialized = 1;
  225:         lm32_translate_init();
  226:     }
  227: 
  228:     return env;
  229: }
  230: 
  231: /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
  232:  * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
  233:  * 0x80000000-0xffffffff is not cached and used to access IO devices. */
  234: void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value)
  235: {
  236:     if (value) {
  237:         env->flags |= LM32_FLAG_IGNORE_MSB;
  238:     } else {
  239:         env->flags &= ~LM32_FLAG_IGNORE_MSB;
  240:     }
  241: }
  242: 
  243: void cpu_reset(CPUState *env)
  244: {
  245:     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
  246:         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
  247:         log_cpu_state(env, 0);
  248:     }
  249: 
  250:     tlb_flush(env, 1);
  251: 
  252:     /* reset cpu state */
  253:     memset(env, 0, offsetof(CPULM32State, breakpoints));
  254: }
  255: 

unix.superglobalmegacorp.com