|
|
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 "cpu.h"
21: #include "host-utils.h"
22:
1.1.1.3 ! root 23: int cpu_lm32_handle_mmu_fault(CPULM32State *env, target_ulong address, int rw,
1.1.1.2 root 24: int mmu_idx)
1.1 root 25: {
26: int prot;
27:
28: address &= TARGET_PAGE_MASK;
29: prot = PAGE_BITS;
30: if (env->flags & LM32_FLAG_IGNORE_MSB) {
31: tlb_set_page(env, address, address & 0x7fffffff, prot, mmu_idx,
32: TARGET_PAGE_SIZE);
33: } else {
34: tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
35: }
36:
37: return 0;
38: }
39:
1.1.1.3 ! root 40: target_phys_addr_t cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr)
1.1 root 41: {
42: return addr & TARGET_PAGE_MASK;
43: }
44:
1.1.1.3 ! root 45: void do_interrupt(CPULM32State *env)
1.1 root 46: {
47: qemu_log_mask(CPU_LOG_INT,
48: "exception at pc=%x type=%x\n", env->pc, env->exception_index);
49:
50: switch (env->exception_index) {
51: case EXCP_INSN_BUS_ERROR:
52: case EXCP_DATA_BUS_ERROR:
53: case EXCP_DIVIDE_BY_ZERO:
54: case EXCP_IRQ:
55: case EXCP_SYSTEMCALL:
56: /* non-debug exceptions */
57: env->regs[R_EA] = env->pc;
58: env->ie |= (env->ie & IE_IE) ? IE_EIE : 0;
59: env->ie &= ~IE_IE;
60: if (env->dc & DC_RE) {
61: env->pc = env->deba + (env->exception_index * 32);
62: } else {
63: env->pc = env->eba + (env->exception_index * 32);
64: }
65: log_cpu_state_mask(CPU_LOG_INT, env, 0);
66: break;
67: case EXCP_BREAKPOINT:
68: case EXCP_WATCHPOINT:
69: /* debug exceptions */
70: env->regs[R_BA] = env->pc;
71: env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
72: env->ie &= ~IE_IE;
73: env->pc = env->deba + (env->exception_index * 32);
74: log_cpu_state_mask(CPU_LOG_INT, env, 0);
75: break;
76: default:
77: cpu_abort(env, "unhandled exception type=%d\n",
78: env->exception_index);
79: break;
80: }
81: }
82:
83: typedef struct {
84: const char *name;
85: uint32_t revision;
86: uint8_t num_interrupts;
87: uint8_t num_breakpoints;
88: uint8_t num_watchpoints;
89: uint32_t features;
90: } LM32Def;
91:
92: static const LM32Def lm32_defs[] = {
93: {
94: .name = "lm32-basic",
95: .revision = 3,
96: .num_interrupts = 32,
97: .num_breakpoints = 4,
98: .num_watchpoints = 4,
99: .features = (LM32_FEATURE_SHIFT
100: | LM32_FEATURE_SIGN_EXTEND
101: | LM32_FEATURE_CYCLE_COUNT),
102: },
103: {
104: .name = "lm32-standard",
105: .revision = 3,
106: .num_interrupts = 32,
107: .num_breakpoints = 4,
108: .num_watchpoints = 4,
109: .features = (LM32_FEATURE_MULTIPLY
110: | LM32_FEATURE_DIVIDE
111: | LM32_FEATURE_SHIFT
112: | LM32_FEATURE_SIGN_EXTEND
113: | LM32_FEATURE_I_CACHE
114: | LM32_FEATURE_CYCLE_COUNT),
115: },
116: {
117: .name = "lm32-full",
118: .revision = 3,
119: .num_interrupts = 32,
120: .num_breakpoints = 4,
121: .num_watchpoints = 4,
122: .features = (LM32_FEATURE_MULTIPLY
123: | LM32_FEATURE_DIVIDE
124: | LM32_FEATURE_SHIFT
125: | LM32_FEATURE_SIGN_EXTEND
126: | LM32_FEATURE_I_CACHE
127: | LM32_FEATURE_D_CACHE
128: | LM32_FEATURE_CYCLE_COUNT),
129: }
130: };
131:
132: void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf)
133: {
134: int i;
135:
136: cpu_fprintf(f, "Available CPUs:\n");
137: for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
138: cpu_fprintf(f, " %s\n", lm32_defs[i].name);
139: }
140: }
141:
142: static const LM32Def *cpu_lm32_find_by_name(const char *name)
143: {
144: int i;
145:
146: for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
147: if (strcasecmp(name, lm32_defs[i].name) == 0) {
148: return &lm32_defs[i];
149: }
150: }
151:
152: return NULL;
153: }
154:
155: static uint32_t cfg_by_def(const LM32Def *def)
156: {
157: uint32_t cfg = 0;
158:
159: if (def->features & LM32_FEATURE_MULTIPLY) {
160: cfg |= CFG_M;
161: }
162:
163: if (def->features & LM32_FEATURE_DIVIDE) {
164: cfg |= CFG_D;
165: }
166:
167: if (def->features & LM32_FEATURE_SHIFT) {
168: cfg |= CFG_S;
169: }
170:
171: if (def->features & LM32_FEATURE_SIGN_EXTEND) {
172: cfg |= CFG_X;
173: }
174:
175: if (def->features & LM32_FEATURE_I_CACHE) {
176: cfg |= CFG_IC;
177: }
178:
179: if (def->features & LM32_FEATURE_D_CACHE) {
180: cfg |= CFG_DC;
181: }
182:
183: if (def->features & LM32_FEATURE_CYCLE_COUNT) {
184: cfg |= CFG_CC;
185: }
186:
187: cfg |= (def->num_interrupts << CFG_INT_SHIFT);
188: cfg |= (def->num_breakpoints << CFG_BP_SHIFT);
189: cfg |= (def->num_watchpoints << CFG_WP_SHIFT);
190: cfg |= (def->revision << CFG_REV_SHIFT);
191:
192: return cfg;
193: }
194:
1.1.1.3 ! root 195: CPULM32State *cpu_lm32_init(const char *cpu_model)
1.1 root 196: {
1.1.1.3 ! root 197: LM32CPU *cpu;
! 198: CPULM32State *env;
1.1 root 199: const LM32Def *def;
200: static int tcg_initialized;
201:
202: def = cpu_lm32_find_by_name(cpu_model);
203: if (!def) {
204: return NULL;
205: }
206:
1.1.1.3 ! root 207: cpu = LM32_CPU(object_new(TYPE_LM32_CPU));
! 208: env = &cpu->env;
1.1 root 209:
210: env->features = def->features;
211: env->num_bps = def->num_breakpoints;
212: env->num_wps = def->num_watchpoints;
213: env->cfg = cfg_by_def(def);
214:
1.1.1.2 root 215: qemu_init_vcpu(env);
1.1 root 216:
1.1.1.3 ! root 217: if (tcg_enabled() && !tcg_initialized) {
1.1 root 218: tcg_initialized = 1;
219: lm32_translate_init();
220: }
221:
222: return env;
223: }
224:
225: /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
226: * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
227: * 0x80000000-0xffffffff is not cached and used to access IO devices. */
1.1.1.3 ! root 228: void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value)
1.1 root 229: {
230: if (value) {
231: env->flags |= LM32_FLAG_IGNORE_MSB;
232: } else {
233: env->flags &= ~LM32_FLAG_IGNORE_MSB;
234: }
235: }
236:
1.1.1.3 ! root 237: void cpu_state_reset(CPULM32State *env)
1.1 root 238: {
1.1.1.3 ! root 239: cpu_reset(ENV_GET_CPU(env));
1.1 root 240: }
241:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.