Revision 527d9979
b/target-unicore32/helper.c | ||
---|---|---|
14 | 14 |
#include "helper.h" |
15 | 15 |
#include "host-utils.h" |
16 | 16 |
|
17 |
#undef DEBUG_UC32 |
|
18 |
|
|
19 |
#ifdef DEBUG_UC32 |
|
20 |
#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__) |
|
21 |
#else |
|
22 |
#define DPRINTF(fmt, ...) do {} while (0) |
|
23 |
#endif |
|
24 |
|
|
17 | 25 |
CPUUniCore32State *uc32_cpu_init(const char *cpu_model) |
18 | 26 |
{ |
19 | 27 |
UniCore32CPU *cpu; |
... | ... | |
45 | 53 |
return clz32(x); |
46 | 54 |
} |
47 | 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 |
void helper_cp1_putc(target_ulong x) |
|
190 |
{ |
|
191 |
/* TODO: curses display should be added here for screen output. */ |
|
192 |
DPRINTF("%c", x); |
|
193 |
} |
|
194 |
#endif |
|
195 |
|
|
48 | 196 |
#ifdef CONFIG_USER_ONLY |
49 | 197 |
void switch_mode(CPUUniCore32State *env, int mode) |
50 | 198 |
{ |
... | ... | |
66 | 214 |
} |
67 | 215 |
#endif |
68 | 216 |
|
69 |
/* These should probably raise undefined insn exceptions. */ |
|
70 |
void HELPER(set_cp)(CPUUniCore32State *env, uint32_t insn, uint32_t val) |
|
71 |
{ |
|
72 |
int op1 = (insn >> 8) & 0xf; |
|
73 |
cpu_abort(env, "cp%i insn %08x\n", op1, insn); |
|
74 |
return; |
|
75 |
} |
|
76 |
|
|
77 |
uint32_t HELPER(get_cp)(CPUUniCore32State *env, uint32_t insn) |
|
78 |
{ |
|
79 |
int op1 = (insn >> 8) & 0xf; |
|
80 |
cpu_abort(env, "cp%i insn %08x\n", op1, insn); |
|
81 |
return 0; |
|
82 |
} |
|
83 |
|
|
84 |
void HELPER(set_cp0)(CPUUniCore32State *env, uint32_t insn, uint32_t val) |
|
85 |
{ |
|
86 |
cpu_abort(env, "cp0 insn %08x\n", insn); |
|
87 |
} |
|
88 |
|
|
89 |
uint32_t HELPER(get_cp0)(CPUUniCore32State *env, uint32_t insn) |
|
90 |
{ |
|
91 |
cpu_abort(env, "cp0 insn %08x\n", insn); |
|
92 |
return 0; |
|
93 |
} |
|
94 |
|
|
95 |
void HELPER(set_r29_banked)(CPUUniCore32State *env, uint32_t mode, uint32_t val) |
|
96 |
{ |
|
97 |
cpu_abort(env, "banked r29 write\n"); |
|
98 |
} |
|
99 |
|
|
100 |
uint32_t HELPER(get_r29_banked)(CPUUniCore32State *env, uint32_t mode) |
|
101 |
{ |
|
102 |
cpu_abort(env, "banked r29 read\n"); |
|
103 |
return 0; |
|
104 |
} |
|
105 |
|
|
106 | 217 |
/* UniCore-F64 support. We follow the convention used for F64 instrunctions: |
107 | 218 |
Single precition routines have a "s" suffix, double precision a |
108 | 219 |
"d" suffix. */ |
b/target-unicore32/helper.h | ||
---|---|---|
1 | 1 |
/* |
2 |
* Copyright (C) 2010-2011 GUAN Xue-tao
|
|
2 |
* Copyright (C) 2010-2012 Guan Xuetao
|
|
3 | 3 |
* |
4 | 4 |
* This program is free software; you can redistribute it and/or modify |
5 | 5 |
* it under the terms of the GNU General Public License version 2 as |
... | ... | |
8 | 8 |
*/ |
9 | 9 |
#include "def-helper.h" |
10 | 10 |
|
11 |
#ifndef CONFIG_USER_ONLY |
|
12 |
DEF_HELPER_4(cp0_set, void, env, i32, i32, i32) |
|
13 |
DEF_HELPER_3(cp0_get, i32, env, i32, i32) |
|
14 |
DEF_HELPER_1(cp1_putc, void, i32) |
|
15 |
#endif |
|
16 |
|
|
11 | 17 |
DEF_HELPER_1(clz, i32, i32) |
12 | 18 |
DEF_HELPER_1(clo, i32, i32) |
13 | 19 |
|
... | ... | |
16 | 22 |
DEF_HELPER_2(asr_write, void, i32, i32) |
17 | 23 |
DEF_HELPER_0(asr_read, i32) |
18 | 24 |
|
19 |
DEF_HELPER_3(set_cp0, void, env, i32, i32) |
|
20 |
DEF_HELPER_2(get_cp0, i32, env, i32) |
|
21 |
|
|
22 |
DEF_HELPER_3(set_cp, void, env, i32, i32) |
|
23 |
DEF_HELPER_2(get_cp, i32, env, i32) |
|
24 |
|
|
25 | 25 |
DEF_HELPER_1(get_user_reg, i32, i32) |
26 | 26 |
DEF_HELPER_2(set_user_reg, void, i32, i32) |
27 | 27 |
|
... | ... | |
38 | 38 |
DEF_HELPER_2(sar_cc, i32, i32, i32) |
39 | 39 |
DEF_HELPER_2(ror_cc, i32, i32, i32) |
40 | 40 |
|
41 |
DEF_HELPER_2(get_r29_banked, i32, env, i32) |
|
42 |
DEF_HELPER_3(set_r29_banked, void, env, i32, i32) |
|
43 |
|
|
44 | 41 |
DEF_HELPER_1(ucf64_get_fpscr, i32, env) |
45 | 42 |
DEF_HELPER_2(ucf64_set_fpscr, void, env, i32) |
46 | 43 |
|
b/target-unicore32/translate.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* UniCore32 translation |
3 | 3 |
* |
4 |
* Copyright (C) 2010-2011 GUAN Xue-tao
|
|
4 |
* Copyright (C) 2010-2012 Guan Xuetao
|
|
5 | 5 |
* |
6 | 6 |
* This program is free software; you can redistribute it and/or modify |
7 | 7 |
* it under the terms of the GNU General Public License version 2 as |
... | ... | |
176 | 176 |
"Illegal UniCore32 instruction %x at line %d!", \ |
177 | 177 |
insn, __LINE__) |
178 | 178 |
|
179 |
#ifndef CONFIG_USER_ONLY |
|
180 |
static void disas_cp0_insn(CPUUniCore32State *env, DisasContext *s, |
|
181 |
uint32_t insn) |
|
182 |
{ |
|
183 |
TCGv tmp, tmp2, tmp3; |
|
184 |
if ((insn & 0xfe000000) == 0xe0000000) { |
|
185 |
tmp2 = new_tmp(); |
|
186 |
tmp3 = new_tmp(); |
|
187 |
tcg_gen_movi_i32(tmp2, UCOP_REG_N); |
|
188 |
tcg_gen_movi_i32(tmp3, UCOP_IMM10); |
|
189 |
if (UCOP_SET_L) { |
|
190 |
tmp = new_tmp(); |
|
191 |
gen_helper_cp0_get(tmp, cpu_env, tmp2, tmp3); |
|
192 |
store_reg(s, UCOP_REG_D, tmp); |
|
193 |
} else { |
|
194 |
tmp = load_reg(s, UCOP_REG_D); |
|
195 |
gen_helper_cp0_set(cpu_env, tmp, tmp2, tmp3); |
|
196 |
dead_tmp(tmp); |
|
197 |
} |
|
198 |
dead_tmp(tmp2); |
|
199 |
dead_tmp(tmp3); |
|
200 |
return; |
|
201 |
} |
|
202 |
ILLEGAL; |
|
203 |
} |
|
204 |
|
|
205 |
static void disas_ocd_insn(CPUUniCore32State *env, DisasContext *s, |
|
206 |
uint32_t insn) |
|
207 |
{ |
|
208 |
TCGv tmp; |
|
209 |
|
|
210 |
if ((insn & 0xff003fff) == 0xe1000400) { |
|
211 |
/* |
|
212 |
* movc rd, pp.nn, #imm9 |
|
213 |
* rd: UCOP_REG_D |
|
214 |
* nn: UCOP_REG_N (must be 0) |
|
215 |
* imm9: 0 |
|
216 |
*/ |
|
217 |
if (UCOP_REG_N == 0) { |
|
218 |
tmp = new_tmp(); |
|
219 |
tcg_gen_movi_i32(tmp, 0); |
|
220 |
store_reg(s, UCOP_REG_D, tmp); |
|
221 |
return; |
|
222 |
} else { |
|
223 |
ILLEGAL; |
|
224 |
} |
|
225 |
} |
|
226 |
if ((insn & 0xff003fff) == 0xe0000401) { |
|
227 |
/* |
|
228 |
* movc pp.nn, rn, #imm9 |
|
229 |
* rn: UCOP_REG_D |
|
230 |
* nn: UCOP_REG_N (must be 1) |
|
231 |
* imm9: 1 |
|
232 |
*/ |
|
233 |
if (UCOP_REG_N == 1) { |
|
234 |
tmp = load_reg(s, UCOP_REG_D); |
|
235 |
gen_helper_cp1_putc(tmp); |
|
236 |
dead_tmp(tmp); |
|
237 |
return; |
|
238 |
} else { |
|
239 |
ILLEGAL; |
|
240 |
} |
|
241 |
} |
|
242 |
ILLEGAL; |
|
243 |
} |
|
244 |
#endif |
|
245 |
|
|
179 | 246 |
static inline void gen_set_asr(TCGv var, uint32_t mask) |
180 | 247 |
{ |
181 | 248 |
TCGv tmp_mask = tcg_const_i32(mask); |
... | ... | |
1124 | 1191 |
s->is_jmp = DISAS_UPDATE; |
1125 | 1192 |
} |
1126 | 1193 |
|
1127 |
static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s, uint32_t insn) |
|
1194 |
static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s, |
|
1195 |
uint32_t insn) |
|
1128 | 1196 |
{ |
1129 | 1197 |
switch (UCOP_CPNUM) { |
1198 |
#ifndef CONFIG_USER_ONLY |
|
1199 |
case 0: |
|
1200 |
disas_cp0_insn(env, s, insn); |
|
1201 |
break; |
|
1202 |
case 1: |
|
1203 |
disas_ocd_insn(env, s, insn); |
|
1204 |
break; |
|
1205 |
#endif |
|
1130 | 1206 |
case 2: |
1131 | 1207 |
disas_ucf64_insn(env, s, insn); |
1132 | 1208 |
break; |
Also available in: Unified diff