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