]>
Commit | Line | Data |
---|---|---|
48e06fe0 BK |
1 | /* |
2 | * TriCore emulation for qemu: main translation routines. | |
3 | * | |
4 | * Copyright (c) 2013-2014 Bastian Koppelmann C-Lab/University Paderborn | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2 of the License, or (at your option) any later version. | |
10 | * | |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | ||
21 | #include "cpu.h" | |
22 | #include "disas/disas.h" | |
23 | #include "tcg-op.h" | |
24 | #include "exec/cpu_ldst.h" | |
25 | ||
26 | #include "exec/helper-proto.h" | |
27 | #include "exec/helper-gen.h" | |
28 | ||
7c87d074 | 29 | #include "tricore-opcodes.h" |
0707ec1b | 30 | |
0aaeb118 BK |
31 | /* |
32 | * TCG registers | |
33 | */ | |
34 | static TCGv cpu_PC; | |
35 | static TCGv cpu_PCXI; | |
36 | static TCGv cpu_PSW; | |
37 | static TCGv cpu_ICR; | |
38 | /* GPR registers */ | |
39 | static TCGv cpu_gpr_a[16]; | |
40 | static TCGv cpu_gpr_d[16]; | |
41 | /* PSW Flag cache */ | |
42 | static TCGv cpu_PSW_C; | |
43 | static TCGv cpu_PSW_V; | |
44 | static TCGv cpu_PSW_SV; | |
45 | static TCGv cpu_PSW_AV; | |
46 | static TCGv cpu_PSW_SAV; | |
47 | /* CPU env */ | |
48 | static TCGv_ptr cpu_env; | |
49 | ||
50 | #include "exec/gen-icount.h" | |
48e06fe0 BK |
51 | |
52 | static const char *regnames_a[] = { | |
53 | "a0" , "a1" , "a2" , "a3" , "a4" , "a5" , | |
54 | "a6" , "a7" , "a8" , "a9" , "sp" , "a11" , | |
55 | "a12" , "a13" , "a14" , "a15", | |
56 | }; | |
57 | ||
58 | static const char *regnames_d[] = { | |
59 | "d0" , "d1" , "d2" , "d3" , "d4" , "d5" , | |
60 | "d6" , "d7" , "d8" , "d9" , "d10" , "d11" , | |
61 | "d12" , "d13" , "d14" , "d15", | |
62 | }; | |
63 | ||
0aaeb118 BK |
64 | typedef struct DisasContext { |
65 | struct TranslationBlock *tb; | |
66 | target_ulong pc, saved_pc, next_pc; | |
67 | uint32_t opcode; | |
68 | int singlestep_enabled; | |
69 | /* Routine used to access memory */ | |
70 | int mem_idx; | |
71 | uint32_t hflags, saved_hflags; | |
72 | int bstate; | |
73 | } DisasContext; | |
74 | ||
75 | enum { | |
76 | ||
77 | BS_NONE = 0, | |
78 | BS_STOP = 1, | |
79 | BS_BRANCH = 2, | |
80 | BS_EXCP = 3, | |
81 | }; | |
82 | ||
48e06fe0 BK |
83 | void tricore_cpu_dump_state(CPUState *cs, FILE *f, |
84 | fprintf_function cpu_fprintf, int flags) | |
85 | { | |
86 | TriCoreCPU *cpu = TRICORE_CPU(cs); | |
87 | CPUTriCoreState *env = &cpu->env; | |
88 | int i; | |
89 | ||
90 | cpu_fprintf(f, "PC=%08x\n", env->PC); | |
91 | for (i = 0; i < 16; ++i) { | |
92 | if ((i & 3) == 0) { | |
93 | cpu_fprintf(f, "GPR A%02d:", i); | |
94 | } | |
95 | cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_a[i], env->gpr_a[i]); | |
96 | } | |
97 | for (i = 0; i < 16; ++i) { | |
98 | if ((i & 3) == 0) { | |
99 | cpu_fprintf(f, "GPR D%02d:", i); | |
100 | } | |
101 | cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_d[i], env->gpr_d[i]); | |
102 | } | |
103 | ||
104 | } | |
105 | ||
0707ec1b BK |
106 | /* |
107 | * Functions to generate micro-ops | |
108 | */ | |
109 | ||
110 | /* Functions for arithmetic instructions */ | |
111 | ||
112 | static inline void gen_add_d(TCGv ret, TCGv r1, TCGv r2) | |
113 | { | |
114 | TCGv t0 = tcg_temp_new_i32(); | |
115 | TCGv result = tcg_temp_new_i32(); | |
116 | /* Addition and set V/SV bits */ | |
117 | tcg_gen_add_tl(result, r1, r2); | |
118 | /* calc V bit */ | |
119 | tcg_gen_xor_tl(cpu_PSW_V, result, r1); | |
120 | tcg_gen_xor_tl(t0, r1, r2); | |
121 | tcg_gen_andc_tl(cpu_PSW_V, cpu_PSW_V, t0); | |
122 | /* Calc SV bit */ | |
123 | tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); | |
124 | /* Calc AV/SAV bits */ | |
125 | tcg_gen_add_tl(cpu_PSW_AV, result, result); | |
126 | tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV); | |
127 | /* calc SAV */ | |
128 | tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); | |
129 | /* write back result */ | |
130 | tcg_gen_mov_tl(ret, result); | |
131 | ||
132 | tcg_temp_free(result); | |
133 | tcg_temp_free(t0); | |
134 | } | |
135 | ||
136 | static inline void gen_addi_d(TCGv ret, TCGv r1, target_ulong r2) | |
137 | { | |
138 | TCGv temp = tcg_const_i32(r2); | |
139 | gen_add_d(ret, r1, temp); | |
140 | tcg_temp_free(temp); | |
141 | } | |
142 | ||
143 | static inline void gen_cond_add(TCGCond cond, TCGv r1, TCGv r2, TCGv r3, | |
144 | TCGv r4) | |
145 | { | |
146 | TCGv temp = tcg_temp_new(); | |
147 | TCGv temp2 = tcg_temp_new(); | |
148 | TCGv result = tcg_temp_new(); | |
149 | TCGv mask = tcg_temp_new(); | |
150 | TCGv t0 = tcg_const_i32(0); | |
151 | ||
152 | /* create mask for sticky bits */ | |
153 | tcg_gen_setcond_tl(cond, mask, r4, t0); | |
154 | tcg_gen_shli_tl(mask, mask, 31); | |
155 | ||
156 | tcg_gen_add_tl(result, r1, r2); | |
157 | /* Calc PSW_V */ | |
158 | tcg_gen_xor_tl(temp, result, r1); | |
159 | tcg_gen_xor_tl(temp2, r1, r2); | |
160 | tcg_gen_andc_tl(temp, temp, temp2); | |
161 | tcg_gen_movcond_tl(cond, cpu_PSW_V, r4, t0, temp, cpu_PSW_V); | |
162 | /* Set PSW_SV */ | |
163 | tcg_gen_and_tl(temp, temp, mask); | |
164 | tcg_gen_or_tl(cpu_PSW_SV, temp, cpu_PSW_SV); | |
165 | /* calc AV bit */ | |
166 | tcg_gen_add_tl(temp, result, result); | |
167 | tcg_gen_xor_tl(temp, temp, result); | |
168 | tcg_gen_movcond_tl(cond, cpu_PSW_AV, r4, t0, temp, cpu_PSW_AV); | |
169 | /* calc SAV bit */ | |
170 | tcg_gen_and_tl(temp, temp, mask); | |
171 | tcg_gen_or_tl(cpu_PSW_SAV, temp, cpu_PSW_SAV); | |
172 | /* write back result */ | |
173 | tcg_gen_movcond_tl(cond, r3, r4, t0, result, r3); | |
174 | ||
175 | tcg_temp_free(t0); | |
176 | tcg_temp_free(temp); | |
177 | tcg_temp_free(temp2); | |
178 | tcg_temp_free(result); | |
179 | tcg_temp_free(mask); | |
180 | } | |
181 | ||
182 | static inline void gen_condi_add(TCGCond cond, TCGv r1, int32_t r2, | |
183 | TCGv r3, TCGv r4) | |
184 | { | |
185 | TCGv temp = tcg_const_i32(r2); | |
186 | gen_cond_add(cond, r1, temp, r3, r4); | |
187 | tcg_temp_free(temp); | |
188 | } | |
189 | ||
2692802a BK |
190 | static inline void gen_sub_d(TCGv ret, TCGv r1, TCGv r2) |
191 | { | |
192 | TCGv temp = tcg_temp_new_i32(); | |
193 | TCGv result = tcg_temp_new_i32(); | |
194 | ||
195 | tcg_gen_sub_tl(result, r1, r2); | |
196 | /* calc V bit */ | |
197 | tcg_gen_xor_tl(cpu_PSW_V, result, r1); | |
198 | tcg_gen_xor_tl(temp, r1, r2); | |
199 | tcg_gen_and_tl(cpu_PSW_V, cpu_PSW_V, temp); | |
200 | /* calc SV bit */ | |
201 | tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); | |
202 | /* Calc AV bit */ | |
203 | tcg_gen_add_tl(cpu_PSW_AV, result, result); | |
204 | tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV); | |
205 | /* calc SAV bit */ | |
206 | tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); | |
207 | /* write back result */ | |
208 | tcg_gen_mov_tl(ret, result); | |
209 | ||
210 | tcg_temp_free(temp); | |
211 | tcg_temp_free(result); | |
212 | } | |
213 | ||
214 | static inline void gen_mul_i32s(TCGv ret, TCGv r1, TCGv r2) | |
215 | { | |
216 | TCGv high = tcg_temp_new(); | |
217 | TCGv low = tcg_temp_new(); | |
218 | ||
219 | tcg_gen_muls2_tl(low, high, r1, r2); | |
220 | tcg_gen_mov_tl(ret, low); | |
221 | /* calc V bit */ | |
222 | tcg_gen_sari_tl(low, low, 31); | |
223 | tcg_gen_setcond_tl(TCG_COND_NE, cpu_PSW_V, high, low); | |
224 | tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); | |
225 | /* calc SV bit */ | |
226 | tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); | |
227 | /* Calc AV bit */ | |
228 | tcg_gen_add_tl(cpu_PSW_AV, ret, ret); | |
229 | tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV); | |
230 | /* calc SAV bit */ | |
231 | tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); | |
232 | ||
233 | tcg_temp_free(high); | |
234 | tcg_temp_free(low); | |
235 | } | |
236 | ||
0707ec1b BK |
237 | static void gen_shi(TCGv ret, TCGv r1, int32_t shift_count) |
238 | { | |
239 | if (shift_count == -32) { | |
240 | tcg_gen_movi_tl(ret, 0); | |
241 | } else if (shift_count >= 0) { | |
242 | tcg_gen_shli_tl(ret, r1, shift_count); | |
243 | } else { | |
244 | tcg_gen_shri_tl(ret, r1, -shift_count); | |
245 | } | |
246 | } | |
247 | ||
248 | static void gen_shaci(TCGv ret, TCGv r1, int32_t shift_count) | |
249 | { | |
250 | uint32_t msk, msk_start; | |
251 | TCGv temp = tcg_temp_new(); | |
252 | TCGv temp2 = tcg_temp_new(); | |
253 | TCGv t_0 = tcg_const_i32(0); | |
254 | ||
255 | if (shift_count == 0) { | |
256 | /* Clear PSW.C and PSW.V */ | |
257 | tcg_gen_movi_tl(cpu_PSW_C, 0); | |
258 | tcg_gen_mov_tl(cpu_PSW_V, cpu_PSW_C); | |
259 | tcg_gen_mov_tl(ret, r1); | |
260 | } else if (shift_count == -32) { | |
261 | /* set PSW.C */ | |
262 | tcg_gen_mov_tl(cpu_PSW_C, r1); | |
263 | /* fill ret completly with sign bit */ | |
264 | tcg_gen_sari_tl(ret, r1, 31); | |
265 | /* clear PSW.V */ | |
266 | tcg_gen_movi_tl(cpu_PSW_V, 0); | |
267 | } else if (shift_count > 0) { | |
268 | TCGv t_max = tcg_const_i32(0x7FFFFFFF >> shift_count); | |
269 | TCGv t_min = tcg_const_i32(((int32_t) -0x80000000) >> shift_count); | |
270 | ||
271 | /* calc carry */ | |
272 | msk_start = 32 - shift_count; | |
273 | msk = ((1 << shift_count) - 1) << msk_start; | |
274 | tcg_gen_andi_tl(cpu_PSW_C, r1, msk); | |
275 | /* calc v/sv bits */ | |
276 | tcg_gen_setcond_tl(TCG_COND_GT, temp, r1, t_max); | |
277 | tcg_gen_setcond_tl(TCG_COND_LT, temp2, r1, t_min); | |
278 | tcg_gen_or_tl(cpu_PSW_V, temp, temp2); | |
279 | tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); | |
280 | /* calc sv */ | |
281 | tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_V, cpu_PSW_SV); | |
282 | /* do shift */ | |
283 | tcg_gen_shli_tl(ret, r1, shift_count); | |
284 | ||
285 | tcg_temp_free(t_max); | |
286 | tcg_temp_free(t_min); | |
287 | } else { | |
288 | /* clear PSW.V */ | |
289 | tcg_gen_movi_tl(cpu_PSW_V, 0); | |
290 | /* calc carry */ | |
291 | msk = (1 << -shift_count) - 1; | |
292 | tcg_gen_andi_tl(cpu_PSW_C, r1, msk); | |
293 | /* do shift */ | |
294 | tcg_gen_sari_tl(ret, r1, -shift_count); | |
295 | } | |
296 | /* calc av overflow bit */ | |
297 | tcg_gen_add_tl(cpu_PSW_AV, ret, ret); | |
298 | tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV); | |
299 | /* calc sav overflow bit */ | |
300 | tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); | |
301 | ||
302 | tcg_temp_free(temp); | |
303 | tcg_temp_free(temp2); | |
304 | tcg_temp_free(t_0); | |
305 | } | |
306 | ||
2692802a BK |
307 | static inline void gen_adds(TCGv ret, TCGv r1, TCGv r2) |
308 | { | |
309 | gen_helper_add_ssov(ret, cpu_env, r1, r2); | |
310 | } | |
311 | ||
312 | static inline void gen_subs(TCGv ret, TCGv r1, TCGv r2) | |
313 | { | |
314 | gen_helper_sub_ssov(ret, cpu_env, r1, r2); | |
315 | } | |
316 | ||
0707ec1b BK |
317 | /* |
318 | * Functions for decoding instructions | |
319 | */ | |
320 | ||
321 | static void decode_src_opc(DisasContext *ctx, int op1) | |
322 | { | |
323 | int r1; | |
324 | int32_t const4; | |
325 | TCGv temp, temp2; | |
326 | ||
327 | r1 = MASK_OP_SRC_S1D(ctx->opcode); | |
328 | const4 = MASK_OP_SRC_CONST4_SEXT(ctx->opcode); | |
329 | ||
330 | switch (op1) { | |
331 | case OPC1_16_SRC_ADD: | |
332 | gen_addi_d(cpu_gpr_d[r1], cpu_gpr_d[r1], const4); | |
333 | break; | |
334 | case OPC1_16_SRC_ADD_A15: | |
335 | gen_addi_d(cpu_gpr_d[r1], cpu_gpr_d[15], const4); | |
336 | break; | |
337 | case OPC1_16_SRC_ADD_15A: | |
338 | gen_addi_d(cpu_gpr_d[15], cpu_gpr_d[r1], const4); | |
339 | break; | |
340 | case OPC1_16_SRC_ADD_A: | |
341 | tcg_gen_addi_tl(cpu_gpr_a[r1], cpu_gpr_a[r1], const4); | |
342 | break; | |
343 | case OPC1_16_SRC_CADD: | |
344 | gen_condi_add(TCG_COND_NE, cpu_gpr_d[r1], const4, cpu_gpr_d[r1], | |
345 | cpu_gpr_d[15]); | |
346 | break; | |
347 | case OPC1_16_SRC_CADDN: | |
348 | gen_condi_add(TCG_COND_EQ, cpu_gpr_d[r1], const4, cpu_gpr_d[r1], | |
349 | cpu_gpr_d[15]); | |
350 | break; | |
351 | case OPC1_16_SRC_CMOV: | |
352 | temp = tcg_const_tl(0); | |
353 | temp2 = tcg_const_tl(const4); | |
354 | tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr_d[r1], cpu_gpr_d[15], temp, | |
355 | temp2, cpu_gpr_d[r1]); | |
356 | tcg_temp_free(temp); | |
357 | tcg_temp_free(temp2); | |
358 | break; | |
359 | case OPC1_16_SRC_CMOVN: | |
360 | temp = tcg_const_tl(0); | |
361 | temp2 = tcg_const_tl(const4); | |
362 | tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr_d[r1], cpu_gpr_d[15], temp, | |
363 | temp2, cpu_gpr_d[r1]); | |
364 | tcg_temp_free(temp); | |
365 | tcg_temp_free(temp2); | |
366 | break; | |
367 | case OPC1_16_SRC_EQ: | |
368 | tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr_d[15], cpu_gpr_d[r1], | |
369 | const4); | |
370 | break; | |
371 | case OPC1_16_SRC_LT: | |
372 | tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr_d[15], cpu_gpr_d[r1], | |
373 | const4); | |
374 | break; | |
375 | case OPC1_16_SRC_MOV: | |
376 | tcg_gen_movi_tl(cpu_gpr_d[r1], const4); | |
377 | break; | |
378 | case OPC1_16_SRC_MOV_A: | |
379 | const4 = MASK_OP_SRC_CONST4(ctx->opcode); | |
380 | tcg_gen_movi_tl(cpu_gpr_a[r1], const4); | |
381 | break; | |
382 | case OPC1_16_SRC_SH: | |
383 | gen_shi(cpu_gpr_d[r1], cpu_gpr_d[r1], const4); | |
384 | break; | |
385 | case OPC1_16_SRC_SHA: | |
386 | gen_shaci(cpu_gpr_d[r1], cpu_gpr_d[r1], const4); | |
387 | break; | |
388 | } | |
389 | } | |
390 | ||
2692802a BK |
391 | static void decode_srr_opc(DisasContext *ctx, int op1) |
392 | { | |
393 | int r1, r2; | |
394 | TCGv temp; | |
395 | ||
396 | r1 = MASK_OP_SRR_S1D(ctx->opcode); | |
397 | r2 = MASK_OP_SRR_S2(ctx->opcode); | |
398 | ||
399 | switch (op1) { | |
400 | case OPC1_16_SRR_ADD: | |
401 | gen_add_d(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
402 | break; | |
403 | case OPC1_16_SRR_ADD_A15: | |
404 | gen_add_d(cpu_gpr_d[r1], cpu_gpr_d[15], cpu_gpr_d[r2]); | |
405 | break; | |
406 | case OPC1_16_SRR_ADD_15A: | |
407 | gen_add_d(cpu_gpr_d[15], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
408 | break; | |
409 | case OPC1_16_SRR_ADD_A: | |
410 | tcg_gen_add_tl(cpu_gpr_a[r1], cpu_gpr_a[r1], cpu_gpr_a[r2]); | |
411 | break; | |
412 | case OPC1_16_SRR_ADDS: | |
413 | gen_adds(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
414 | break; | |
415 | case OPC1_16_SRR_AND: | |
416 | tcg_gen_and_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
417 | break; | |
418 | case OPC1_16_SRR_CMOV: | |
419 | temp = tcg_const_tl(0); | |
420 | tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr_d[r1], cpu_gpr_d[15], temp, | |
421 | cpu_gpr_d[r2], cpu_gpr_d[r1]); | |
422 | tcg_temp_free(temp); | |
423 | break; | |
424 | case OPC1_16_SRR_CMOVN: | |
425 | temp = tcg_const_tl(0); | |
426 | tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr_d[r1], cpu_gpr_d[15], temp, | |
427 | cpu_gpr_d[r2], cpu_gpr_d[r1]); | |
428 | tcg_temp_free(temp); | |
429 | break; | |
430 | case OPC1_16_SRR_EQ: | |
431 | tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[15], cpu_gpr_d[r1], | |
432 | cpu_gpr_d[r2]); | |
433 | break; | |
434 | case OPC1_16_SRR_LT: | |
435 | tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr_d[15], cpu_gpr_d[r1], | |
436 | cpu_gpr_d[r2]); | |
437 | break; | |
438 | case OPC1_16_SRR_MOV: | |
439 | tcg_gen_mov_tl(cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
440 | break; | |
441 | case OPC1_16_SRR_MOV_A: | |
442 | tcg_gen_mov_tl(cpu_gpr_a[r1], cpu_gpr_d[r2]); | |
443 | break; | |
444 | case OPC1_16_SRR_MOV_AA: | |
445 | tcg_gen_mov_tl(cpu_gpr_a[r1], cpu_gpr_a[r2]); | |
446 | break; | |
447 | case OPC1_16_SRR_MOV_D: | |
448 | tcg_gen_mov_tl(cpu_gpr_d[r1], cpu_gpr_a[r2]); | |
449 | break; | |
450 | case OPC1_16_SRR_MUL: | |
451 | gen_mul_i32s(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
452 | break; | |
453 | case OPC1_16_SRR_OR: | |
454 | tcg_gen_or_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
455 | break; | |
456 | case OPC1_16_SRR_SUB: | |
457 | gen_sub_d(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
458 | break; | |
459 | case OPC1_16_SRR_SUB_A15B: | |
460 | gen_sub_d(cpu_gpr_d[r1], cpu_gpr_d[15], cpu_gpr_d[r2]); | |
461 | break; | |
462 | case OPC1_16_SRR_SUB_15AB: | |
463 | gen_sub_d(cpu_gpr_d[15], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
464 | break; | |
465 | case OPC1_16_SRR_SUBS: | |
466 | gen_subs(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
467 | break; | |
468 | case OPC1_16_SRR_XOR: | |
469 | tcg_gen_xor_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]); | |
470 | break; | |
471 | } | |
472 | } | |
473 | ||
0aaeb118 BK |
474 | static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx) |
475 | { | |
0707ec1b BK |
476 | int op1; |
477 | ||
478 | op1 = MASK_OP_MAJOR(ctx->opcode); | |
479 | ||
480 | switch (op1) { | |
481 | case OPC1_16_SRC_ADD: | |
482 | case OPC1_16_SRC_ADD_A15: | |
483 | case OPC1_16_SRC_ADD_15A: | |
484 | case OPC1_16_SRC_ADD_A: | |
485 | case OPC1_16_SRC_CADD: | |
486 | case OPC1_16_SRC_CADDN: | |
487 | case OPC1_16_SRC_CMOV: | |
488 | case OPC1_16_SRC_CMOVN: | |
489 | case OPC1_16_SRC_EQ: | |
490 | case OPC1_16_SRC_LT: | |
491 | case OPC1_16_SRC_MOV: | |
492 | case OPC1_16_SRC_MOV_A: | |
493 | case OPC1_16_SRC_SH: | |
494 | case OPC1_16_SRC_SHA: | |
495 | decode_src_opc(ctx, op1); | |
496 | break; | |
2692802a BK |
497 | /* SRR-format */ |
498 | case OPC1_16_SRR_ADD: | |
499 | case OPC1_16_SRR_ADD_A15: | |
500 | case OPC1_16_SRR_ADD_15A: | |
501 | case OPC1_16_SRR_ADD_A: | |
502 | case OPC1_16_SRR_ADDS: | |
503 | case OPC1_16_SRR_AND: | |
504 | case OPC1_16_SRR_CMOV: | |
505 | case OPC1_16_SRR_CMOVN: | |
506 | case OPC1_16_SRR_EQ: | |
507 | case OPC1_16_SRR_LT: | |
508 | case OPC1_16_SRR_MOV: | |
509 | case OPC1_16_SRR_MOV_A: | |
510 | case OPC1_16_SRR_MOV_AA: | |
511 | case OPC1_16_SRR_MOV_D: | |
512 | case OPC1_16_SRR_MUL: | |
513 | case OPC1_16_SRR_OR: | |
514 | case OPC1_16_SRR_SUB: | |
515 | case OPC1_16_SRR_SUB_A15B: | |
516 | case OPC1_16_SRR_SUB_15AB: | |
517 | case OPC1_16_SRR_SUBS: | |
518 | case OPC1_16_SRR_XOR: | |
519 | decode_srr_opc(ctx, op1); | |
520 | break; | |
0707ec1b | 521 | } |
0aaeb118 BK |
522 | } |
523 | ||
524 | static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) | |
525 | { | |
526 | } | |
527 | ||
528 | static void decode_opc(CPUTriCoreState *env, DisasContext *ctx, int *is_branch) | |
529 | { | |
530 | /* 16-Bit Instruction */ | |
531 | if ((ctx->opcode & 0x1) == 0) { | |
532 | ctx->next_pc = ctx->pc + 2; | |
533 | decode_16Bit_opc(env, ctx); | |
534 | /* 32-Bit Instruction */ | |
535 | } else { | |
536 | ctx->next_pc = ctx->pc + 4; | |
537 | decode_32Bit_opc(env, ctx); | |
538 | } | |
539 | } | |
540 | ||
48e06fe0 BK |
541 | static inline void |
542 | gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, | |
543 | int search_pc) | |
544 | { | |
0aaeb118 BK |
545 | CPUState *cs = CPU(cpu); |
546 | CPUTriCoreState *env = &cpu->env; | |
547 | DisasContext ctx; | |
548 | target_ulong pc_start; | |
549 | int num_insns; | |
550 | uint16_t *gen_opc_end; | |
551 | ||
552 | if (search_pc) { | |
553 | qemu_log("search pc %d\n", search_pc); | |
554 | } | |
555 | ||
556 | num_insns = 0; | |
557 | pc_start = tb->pc; | |
558 | gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE; | |
559 | ctx.pc = pc_start; | |
560 | ctx.saved_pc = -1; | |
561 | ctx.tb = tb; | |
562 | ctx.singlestep_enabled = cs->singlestep_enabled; | |
563 | ctx.bstate = BS_NONE; | |
564 | ctx.mem_idx = cpu_mmu_index(env); | |
565 | ||
566 | tcg_clear_temp_count(); | |
567 | gen_tb_start(); | |
568 | while (ctx.bstate == BS_NONE) { | |
569 | ctx.opcode = cpu_ldl_code(env, ctx.pc); | |
570 | decode_opc(env, &ctx, 0); | |
571 | ||
572 | num_insns++; | |
573 | ||
574 | if (tcg_ctx.gen_opc_ptr >= gen_opc_end) { | |
575 | break; | |
576 | } | |
577 | if (singlestep) { | |
578 | break; | |
579 | } | |
580 | ctx.pc = ctx.next_pc; | |
581 | } | |
582 | ||
583 | gen_tb_end(tb, num_insns); | |
584 | *tcg_ctx.gen_opc_ptr = INDEX_op_end; | |
585 | if (search_pc) { | |
586 | printf("done_generating search pc\n"); | |
587 | } else { | |
588 | tb->size = ctx.pc - pc_start; | |
589 | tb->icount = num_insns; | |
590 | } | |
591 | if (tcg_check_temp_count()) { | |
592 | printf("LEAK at %08x\n", env->PC); | |
593 | } | |
594 | ||
595 | #ifdef DEBUG_DISAS | |
596 | if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { | |
597 | qemu_log("IN: %s\n", lookup_symbol(pc_start)); | |
598 | log_target_disas(env, pc_start, ctx.pc - pc_start, 0); | |
599 | qemu_log("\n"); | |
600 | } | |
601 | #endif | |
48e06fe0 BK |
602 | } |
603 | ||
604 | void | |
605 | gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb) | |
606 | { | |
607 | gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, false); | |
608 | } | |
609 | ||
610 | void | |
611 | gen_intermediate_code_pc(CPUTriCoreState *env, struct TranslationBlock *tb) | |
612 | { | |
613 | gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, true); | |
614 | } | |
615 | ||
616 | void | |
617 | restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb, int pc_pos) | |
618 | { | |
619 | env->PC = tcg_ctx.gen_opc_pc[pc_pos]; | |
620 | } | |
621 | /* | |
622 | * | |
623 | * Initialization | |
624 | * | |
625 | */ | |
626 | ||
627 | void cpu_state_reset(CPUTriCoreState *env) | |
628 | { | |
0aaeb118 BK |
629 | /* Reset Regs to Default Value */ |
630 | env->PSW = 0xb80; | |
631 | } | |
632 | ||
633 | static void tricore_tcg_init_csfr(void) | |
634 | { | |
635 | cpu_PCXI = tcg_global_mem_new(TCG_AREG0, | |
636 | offsetof(CPUTriCoreState, PCXI), "PCXI"); | |
637 | cpu_PSW = tcg_global_mem_new(TCG_AREG0, | |
638 | offsetof(CPUTriCoreState, PSW), "PSW"); | |
639 | cpu_PC = tcg_global_mem_new(TCG_AREG0, | |
640 | offsetof(CPUTriCoreState, PC), "PC"); | |
641 | cpu_ICR = tcg_global_mem_new(TCG_AREG0, | |
642 | offsetof(CPUTriCoreState, ICR), "ICR"); | |
48e06fe0 BK |
643 | } |
644 | ||
645 | void tricore_tcg_init(void) | |
646 | { | |
0aaeb118 BK |
647 | int i; |
648 | static int inited; | |
649 | if (inited) { | |
650 | return; | |
651 | } | |
652 | cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); | |
653 | /* reg init */ | |
654 | for (i = 0 ; i < 16 ; i++) { | |
655 | cpu_gpr_a[i] = tcg_global_mem_new(TCG_AREG0, | |
656 | offsetof(CPUTriCoreState, gpr_a[i]), | |
657 | regnames_a[i]); | |
658 | } | |
659 | for (i = 0 ; i < 16 ; i++) { | |
660 | cpu_gpr_d[i] = tcg_global_mem_new(TCG_AREG0, | |
661 | offsetof(CPUTriCoreState, gpr_d[i]), | |
662 | regnames_d[i]); | |
663 | } | |
664 | tricore_tcg_init_csfr(); | |
665 | /* init PSW flag cache */ | |
666 | cpu_PSW_C = tcg_global_mem_new(TCG_AREG0, | |
667 | offsetof(CPUTriCoreState, PSW_USB_C), | |
668 | "PSW_C"); | |
669 | cpu_PSW_V = tcg_global_mem_new(TCG_AREG0, | |
670 | offsetof(CPUTriCoreState, PSW_USB_V), | |
671 | "PSW_V"); | |
672 | cpu_PSW_SV = tcg_global_mem_new(TCG_AREG0, | |
673 | offsetof(CPUTriCoreState, PSW_USB_SV), | |
674 | "PSW_SV"); | |
675 | cpu_PSW_AV = tcg_global_mem_new(TCG_AREG0, | |
676 | offsetof(CPUTriCoreState, PSW_USB_AV), | |
677 | "PSW_AV"); | |
678 | cpu_PSW_SAV = tcg_global_mem_new(TCG_AREG0, | |
679 | offsetof(CPUTriCoreState, PSW_USB_SAV), | |
680 | "PSW_SAV"); | |
48e06fe0 | 681 | } |