hw/arm/nseries: Fix loading kernel image on n8x0 machines
[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 "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
28 void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg,
29 uint32_t cop)
30 {
31 /*
32 * movc pp.nn, rn, #imm9
33 * rn: UCOP_REG_D
34 * nn: UCOP_REG_N
35 * 1: sys control reg.
36 * 2: page table base reg.
37 * 3: data fault status reg.
38 * 4: insn fault status reg.
39 * 5: cache op. reg.
40 * 6: tlb op. reg.
41 * imm9: split UCOP_IMM10 with bit5 is 0
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 /* invalid all tlb */
99 tlb_flush(env_cpu(env));
100 return;
101 }
102 break;
103 default:
104 goto unrecognized;
105 }
106 return;
107 unrecognized:
108 qemu_log_mask(LOG_GUEST_ERROR,
109 "Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
110 creg, cop);
111 }
112
113 uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop)
114 {
115 /*
116 * movc rd, pp.nn, #imm9
117 * rd: UCOP_REG_D
118 * nn: UCOP_REG_N
119 * 0: cpuid and cachetype
120 * 1: sys control reg.
121 * 2: page table base reg.
122 * 3: data fault status reg.
123 * 4: insn fault status reg.
124 * imm9: split UCOP_IMM10 with bit5 is 0
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
162 void helper_cp1_putc(target_ulong regval)
163 {
164 const char c = regval;
165
166 qemu_semihosting_log_out(&c, sizeof(c));
167 }
168 #endif /* !CONFIG_USER_ONLY */
169
170 bool 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 }