|
|
1.1 ! root 1: /* ! 2: * LatticeMico32 helper routines. ! 3: * ! 4: * Copyright (c) 2010 Michael Walle <[email protected]> ! 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, int is_softmmu) ! 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 = qemu_mallocz(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: ! 222: if (!tcg_initialized) { ! 223: tcg_initialized = 1; ! 224: lm32_translate_init(); ! 225: } ! 226: ! 227: return env; ! 228: } ! 229: ! 230: /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory ! 231: * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas ! 232: * 0x80000000-0xffffffff is not cached and used to access IO devices. */ ! 233: void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value) ! 234: { ! 235: if (value) { ! 236: env->flags |= LM32_FLAG_IGNORE_MSB; ! 237: } else { ! 238: env->flags &= ~LM32_FLAG_IGNORE_MSB; ! 239: } ! 240: } ! 241: ! 242: void cpu_reset(CPUState *env) ! 243: { ! 244: if (qemu_loglevel_mask(CPU_LOG_RESET)) { ! 245: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); ! 246: log_cpu_state(env, 0); ! 247: } ! 248: ! 249: tlb_flush(env, 1); ! 250: ! 251: /* reset cpu state */ ! 252: memset(env, 0, offsetof(CPULM32State, breakpoints)); ! 253: } ! 254:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.