1
2
3
4
5
6
7
8
9
10
11
12#include "qemu/osdep.h"
13#include "qemu/log.h"
14#include "cpu.h"
15#include "exec/exec-all.h"
16#include "exec/helper-proto.h"
17#include "hw/semihosting/console.h"
18
19#undef DEBUG_UC32
20
21#ifdef DEBUG_UC32
22#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
23#else
24#define DPRINTF(fmt, ...) do {} while (0)
25#endif
26
27#ifndef CONFIG_USER_ONLY
28void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg,
29 uint32_t cop)
30{
31
32
33
34
35
36
37
38
39
40
41
42
43 switch (creg) {
44 case 1:
45 if (cop != 0) {
46 goto unrecognized;
47 }
48 env->cp0.c1_sys = val;
49 break;
50 case 2:
51 if (cop != 0) {
52 goto unrecognized;
53 }
54 env->cp0.c2_base = val;
55 break;
56 case 3:
57 if (cop != 0) {
58 goto unrecognized;
59 }
60 env->cp0.c3_faultstatus = val;
61 break;
62 case 4:
63 if (cop != 0) {
64 goto unrecognized;
65 }
66 env->cp0.c4_faultaddr = val;
67 break;
68 case 5:
69 switch (cop) {
70 case 28:
71 DPRINTF("Invalidate Entire I&D cache\n");
72 return;
73 case 20:
74 DPRINTF("Invalidate Entire Icache\n");
75 return;
76 case 12:
77 DPRINTF("Invalidate Entire Dcache\n");
78 return;
79 case 10:
80 DPRINTF("Clean Entire Dcache\n");
81 return;
82 case 14:
83 DPRINTF("Flush Entire Dcache\n");
84 return;
85 case 13:
86 DPRINTF("Invalidate Dcache line\n");
87 return;
88 case 11:
89 DPRINTF("Clean Dcache line\n");
90 return;
91 case 15:
92 DPRINTF("Flush Dcache line\n");
93 return;
94 }
95 break;
96 case 6:
97 if ((cop <= 6) && (cop >= 2)) {
98
99 tlb_flush(env_cpu(env));
100 return;
101 }
102 break;
103 default:
104 goto unrecognized;
105 }
106 return;
107unrecognized:
108 qemu_log_mask(LOG_GUEST_ERROR,
109 "Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
110 creg, cop);
111}
112
113uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop)
114{
115
116
117
118
119
120
121
122
123
124
125
126 switch (creg) {
127 case 0:
128 switch (cop) {
129 case 0:
130 return env->cp0.c0_cpuid;
131 case 1:
132 return env->cp0.c0_cachetype;
133 }
134 break;
135 case 1:
136 if (cop == 0) {
137 return env->cp0.c1_sys;
138 }
139 break;
140 case 2:
141 if (cop == 0) {
142 return env->cp0.c2_base;
143 }
144 break;
145 case 3:
146 if (cop == 0) {
147 return env->cp0.c3_faultstatus;
148 }
149 break;
150 case 4:
151 if (cop == 0) {
152 return env->cp0.c4_faultaddr;
153 }
154 break;
155 }
156 qemu_log_mask(LOG_GUEST_ERROR,
157 "Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
158 creg, cop);
159 return 0;
160}
161
162void helper_cp1_putc(target_ulong regval)
163{
164 const char c = regval;
165
166 qemu_semihosting_log_out(&c, sizeof(c));
167}
168#endif
169
170bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
171{
172 if (interrupt_request & CPU_INTERRUPT_HARD) {
173 UniCore32CPU *cpu = UNICORE32_CPU(cs);
174 CPUUniCore32State *env = &cpu->env;
175
176 if (!(env->uncached_asr & ASR_I)) {
177 cs->exception_index = UC32_EXCP_INTR;
178 uc32_cpu_do_interrupt(cs);
179 return true;
180 }
181 }
182 return false;
183}
184