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