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