]> git.proxmox.com Git - mirror_qemu.git/blob - target-tricore/op_helper.c
target-tricore: Add instructions of RR opcode format, that have 0x4b as the first...
[mirror_qemu.git] / target-tricore / op_helper.c
1 /*
2 * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 */
17 #include <stdlib.h>
18 #include "cpu.h"
19 #include "qemu/host-utils.h"
20 #include "exec/helper-proto.h"
21 #include "exec/cpu_ldst.h"
22
23 /* Addressing mode helper */
24
25 static uint16_t reverse16(uint16_t val)
26 {
27 uint8_t high = (uint8_t)(val >> 8);
28 uint8_t low = (uint8_t)(val & 0xff);
29
30 uint16_t rh, rl;
31
32 rl = (uint16_t)((high * 0x0202020202ULL & 0x010884422010ULL) % 1023);
33 rh = (uint16_t)((low * 0x0202020202ULL & 0x010884422010ULL) % 1023);
34
35 return (rh << 8) | rl;
36 }
37
38 uint32_t helper_br_update(uint32_t reg)
39 {
40 uint32_t index = reg & 0xffff;
41 uint32_t incr = reg >> 16;
42 uint32_t new_index = reverse16(reverse16(index) + reverse16(incr));
43 return reg - index + new_index;
44 }
45
46 uint32_t helper_circ_update(uint32_t reg, uint32_t off)
47 {
48 uint32_t index = reg & 0xffff;
49 uint32_t length = reg >> 16;
50 int32_t new_index = index + off;
51 if (new_index < 0) {
52 new_index += length;
53 } else {
54 new_index %= length;
55 }
56 return reg - index + new_index;
57 }
58
59 static uint32_t ssov32(CPUTriCoreState *env, int64_t arg)
60 {
61 uint32_t ret;
62 int64_t max_pos = INT32_MAX;
63 int64_t max_neg = INT32_MIN;
64 if (arg > max_pos) {
65 env->PSW_USB_V = (1 << 31);
66 env->PSW_USB_SV = (1 << 31);
67 ret = (target_ulong)max_pos;
68 } else {
69 if (arg < max_neg) {
70 env->PSW_USB_V = (1 << 31);
71 env->PSW_USB_SV = (1 << 31);
72 ret = (target_ulong)max_neg;
73 } else {
74 env->PSW_USB_V = 0;
75 ret = (target_ulong)arg;
76 }
77 }
78 env->PSW_USB_AV = arg ^ arg * 2u;
79 env->PSW_USB_SAV |= env->PSW_USB_AV;
80 return ret;
81 }
82
83 static uint32_t suov32(CPUTriCoreState *env, int64_t arg)
84 {
85 uint32_t ret;
86 int64_t max_pos = UINT32_MAX;
87 if (arg > max_pos) {
88 env->PSW_USB_V = (1 << 31);
89 env->PSW_USB_SV = (1 << 31);
90 ret = (target_ulong)max_pos;
91 } else {
92 if (arg < 0) {
93 env->PSW_USB_V = (1 << 31);
94 env->PSW_USB_SV = (1 << 31);
95 ret = 0;
96 } else {
97 env->PSW_USB_V = 0;
98 ret = (target_ulong)arg;
99 }
100 }
101 env->PSW_USB_AV = arg ^ arg * 2u;
102 env->PSW_USB_SAV |= env->PSW_USB_AV;
103 return ret;
104 }
105
106 static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1)
107 {
108 int32_t max_pos = INT16_MAX;
109 int32_t max_neg = INT16_MIN;
110 int32_t av0, av1;
111
112 env->PSW_USB_V = 0;
113 av0 = hw0 ^ hw0 * 2u;
114 if (hw0 > max_pos) {
115 env->PSW_USB_V = (1 << 31);
116 hw0 = max_pos;
117 } else if (hw0 < max_neg) {
118 env->PSW_USB_V = (1 << 31);
119 hw0 = max_neg;
120 }
121
122 av1 = hw1 ^ hw1 * 2u;
123 if (hw1 > max_pos) {
124 env->PSW_USB_V = (1 << 31);
125 hw1 = max_pos;
126 } else if (hw1 < max_neg) {
127 env->PSW_USB_V = (1 << 31);
128 hw1 = max_neg;
129 }
130
131 env->PSW_USB_SV |= env->PSW_USB_V;
132 env->PSW_USB_AV = (av0 | av1) << 16;
133 env->PSW_USB_SAV |= env->PSW_USB_AV;
134 return (hw0 & 0xffff) | (hw1 << 16);
135 }
136
137 static uint32_t suov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1)
138 {
139 int32_t max_pos = UINT16_MAX;
140 int32_t av0, av1;
141
142 env->PSW_USB_V = 0;
143 av0 = hw0 ^ hw0 * 2u;
144 if (hw0 > max_pos) {
145 env->PSW_USB_V = (1 << 31);
146 hw0 = max_pos;
147 } else if (hw0 < 0) {
148 env->PSW_USB_V = (1 << 31);
149 hw0 = 0;
150 }
151
152 av1 = hw1 ^ hw1 * 2u;
153 if (hw1 > max_pos) {
154 env->PSW_USB_V = (1 << 31);
155 hw1 = max_pos;
156 } else if (hw1 < 0) {
157 env->PSW_USB_V = (1 << 31);
158 hw1 = 0;
159 }
160
161 env->PSW_USB_SV |= env->PSW_USB_V;
162 env->PSW_USB_AV = (av0 | av1) << 16;
163 env->PSW_USB_SAV |= env->PSW_USB_AV;
164 return (hw0 & 0xffff) | (hw1 << 16);
165 }
166
167 target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
168 target_ulong r2)
169 {
170 int64_t t1 = sextract64(r1, 0, 32);
171 int64_t t2 = sextract64(r2, 0, 32);
172 int64_t result = t1 + t2;
173 return ssov32(env, result);
174 }
175
176 target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
177 target_ulong r2)
178 {
179 int32_t ret_hw0, ret_hw1;
180
181 ret_hw0 = sextract32(r1, 0, 16) + sextract32(r2, 0, 16);
182 ret_hw1 = sextract32(r1, 16, 16) + sextract32(r2, 16, 16);
183 return ssov16(env, ret_hw0, ret_hw1);
184 }
185
186 target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
187 target_ulong r2)
188 {
189 int64_t t1 = extract64(r1, 0, 32);
190 int64_t t2 = extract64(r2, 0, 32);
191 int64_t result = t1 + t2;
192 return suov32(env, result);
193 }
194
195 target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1,
196 target_ulong r2)
197 {
198 int32_t ret_hw0, ret_hw1;
199
200 ret_hw0 = extract32(r1, 0, 16) + extract32(r2, 0, 16);
201 ret_hw1 = extract32(r1, 16, 16) + extract32(r2, 16, 16);
202 return suov16(env, ret_hw0, ret_hw1);
203 }
204
205 target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1,
206 target_ulong r2)
207 {
208 int64_t t1 = sextract64(r1, 0, 32);
209 int64_t t2 = sextract64(r2, 0, 32);
210 int64_t result = t1 - t2;
211 return ssov32(env, result);
212 }
213
214 target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1,
215 target_ulong r2)
216 {
217 int32_t ret_hw0, ret_hw1;
218
219 ret_hw0 = sextract32(r1, 0, 16) - sextract32(r2, 0, 16);
220 ret_hw1 = sextract32(r1, 16, 16) - sextract32(r2, 16, 16);
221 return ssov16(env, ret_hw0, ret_hw1);
222 }
223
224 target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1,
225 target_ulong r2)
226 {
227 int64_t t1 = extract64(r1, 0, 32);
228 int64_t t2 = extract64(r2, 0, 32);
229 int64_t result = t1 - t2;
230 return suov32(env, result);
231 }
232
233 target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1,
234 target_ulong r2)
235 {
236 int32_t ret_hw0, ret_hw1;
237
238 ret_hw0 = extract32(r1, 0, 16) - extract32(r2, 0, 16);
239 ret_hw1 = extract32(r1, 16, 16) - extract32(r2, 16, 16);
240 return suov16(env, ret_hw0, ret_hw1);
241 }
242
243 target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1,
244 target_ulong r2)
245 {
246 int64_t t1 = sextract64(r1, 0, 32);
247 int64_t t2 = sextract64(r2, 0, 32);
248 int64_t result = t1 * t2;
249 return ssov32(env, result);
250 }
251
252 target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1,
253 target_ulong r2)
254 {
255 int64_t t1 = extract64(r1, 0, 32);
256 int64_t t2 = extract64(r2, 0, 32);
257 int64_t result = t1 * t2;
258 return suov32(env, result);
259 }
260
261 target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
262 target_ulong r2)
263 {
264 int64_t t1 = sextract64(r1, 0, 32);
265 int32_t t2 = sextract64(r2, 0, 6);
266 int64_t result;
267 if (t2 == 0) {
268 result = t1;
269 } else if (t2 > 0) {
270 result = t1 << t2;
271 } else {
272 result = t1 >> -t2;
273 }
274 return ssov32(env, result);
275 }
276
277 uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1)
278 {
279 target_ulong result;
280 result = ((int32_t)r1 >= 0) ? r1 : (0 - r1);
281 return ssov32(env, result);
282 }
283
284 uint32_t helper_abs_h_ssov(CPUTriCoreState *env, target_ulong r1)
285 {
286 int32_t ret_h0, ret_h1;
287
288 ret_h0 = sextract32(r1, 0, 16);
289 ret_h0 = (ret_h0 >= 0) ? ret_h0 : (0 - ret_h0);
290
291 ret_h1 = sextract32(r1, 16, 16);
292 ret_h1 = (ret_h1 >= 0) ? ret_h1 : (0 - ret_h1);
293
294 return ssov16(env, ret_h0, ret_h1);
295 }
296
297 target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
298 target_ulong r2)
299 {
300 int64_t t1 = sextract64(r1, 0, 32);
301 int64_t t2 = sextract64(r2, 0, 32);
302 int64_t result;
303
304 if (t1 > t2) {
305 result = t1 - t2;
306 } else {
307 result = t2 - t1;
308 }
309 return ssov32(env, result);
310 }
311
312 uint32_t helper_absdif_h_ssov(CPUTriCoreState *env, target_ulong r1,
313 target_ulong r2)
314 {
315 int32_t t1, t2;
316 int32_t ret_h0, ret_h1;
317
318 t1 = sextract32(r1, 0, 16);
319 t2 = sextract32(r2, 0, 16);
320 if (t1 > t2) {
321 ret_h0 = t1 - t2;
322 } else {
323 ret_h0 = t2 - t1;
324 }
325
326 t1 = sextract32(r1, 16, 16);
327 t2 = sextract32(r2, 16, 16);
328 if (t1 > t2) {
329 ret_h1 = t1 - t2;
330 } else {
331 ret_h1 = t2 - t1;
332 }
333
334 return ssov16(env, ret_h0, ret_h1);
335 }
336
337 target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1,
338 target_ulong r2, target_ulong r3)
339 {
340 int64_t t1 = sextract64(r1, 0, 32);
341 int64_t t2 = sextract64(r2, 0, 32);
342 int64_t t3 = sextract64(r3, 0, 32);
343 int64_t result;
344
345 result = t2 + (t1 * t3);
346 return ssov32(env, result);
347 }
348
349 target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1,
350 target_ulong r2, target_ulong r3)
351 {
352 uint64_t t1 = extract64(r1, 0, 32);
353 uint64_t t2 = extract64(r2, 0, 32);
354 uint64_t t3 = extract64(r3, 0, 32);
355 int64_t result;
356
357 result = t2 + (t1 * t3);
358 return suov32(env, result);
359 }
360
361 uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
362 uint64_t r2, target_ulong r3)
363 {
364 uint64_t ret, ovf;
365 int64_t t1 = sextract64(r1, 0, 32);
366 int64_t t3 = sextract64(r3, 0, 32);
367 int64_t mul;
368
369 mul = t1 * t3;
370 ret = mul + r2;
371 ovf = (ret ^ mul) & ~(mul ^ r2);
372
373 if ((int64_t)ovf < 0) {
374 env->PSW_USB_V = (1 << 31);
375 env->PSW_USB_SV = (1 << 31);
376 /* ext_ret > MAX_INT */
377 if (mul >= 0) {
378 ret = INT64_MAX;
379 /* ext_ret < MIN_INT */
380 } else {
381 ret = INT64_MIN;
382 }
383 } else {
384 env->PSW_USB_V = 0;
385 }
386 t1 = ret >> 32;
387 env->PSW_USB_AV = t1 ^ t1 * 2u;
388 env->PSW_USB_SAV |= env->PSW_USB_AV;
389
390 return ret;
391 }
392
393 uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
394 uint64_t r2, target_ulong r3)
395 {
396 uint64_t ret, mul;
397 uint64_t t1 = extract64(r1, 0, 32);
398 uint64_t t3 = extract64(r3, 0, 32);
399
400 mul = t1 * t3;
401 ret = mul + r2;
402
403 if (ret < r2) {
404 env->PSW_USB_V = (1 << 31);
405 env->PSW_USB_SV = (1 << 31);
406 /* saturate */
407 ret = UINT64_MAX;
408 } else {
409 env->PSW_USB_V = 0;
410 }
411 t1 = ret >> 32;
412 env->PSW_USB_AV = t1 ^ t1 * 2u;
413 env->PSW_USB_SAV |= env->PSW_USB_AV;
414 return ret;
415 }
416
417 target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1,
418 target_ulong r2, target_ulong r3)
419 {
420 int64_t t1 = sextract64(r1, 0, 32);
421 int64_t t2 = sextract64(r2, 0, 32);
422 int64_t t3 = sextract64(r3, 0, 32);
423 int64_t result;
424
425 result = t2 - (t1 * t3);
426 return ssov32(env, result);
427 }
428
429 target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1,
430 target_ulong r2, target_ulong r3)
431 {
432 int64_t t1 = extract64(r1, 0, 32);
433 int64_t t2 = extract64(r2, 0, 32);
434 int64_t t3 = extract64(r3, 0, 32);
435 int64_t result;
436
437 result = t2 - (t1 * t3);
438 return suov32(env, result);
439 }
440
441 uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
442 uint64_t r2, target_ulong r3)
443 {
444 uint64_t ret, ovf;
445 int64_t t1 = sextract64(r1, 0, 32);
446 int64_t t3 = sextract64(r3, 0, 32);
447 int64_t mul;
448
449 mul = t1 * t3;
450 ret = r2 - mul;
451 ovf = (ret ^ r2) & (mul ^ r2);
452
453 if ((int64_t)ovf < 0) {
454 env->PSW_USB_V = (1 << 31);
455 env->PSW_USB_SV = (1 << 31);
456 /* ext_ret > MAX_INT */
457 if (mul < 0) {
458 ret = INT64_MAX;
459 /* ext_ret < MIN_INT */
460 } else {
461 ret = INT64_MIN;
462 }
463 } else {
464 env->PSW_USB_V = 0;
465 }
466 t1 = ret >> 32;
467 env->PSW_USB_AV = t1 ^ t1 * 2u;
468 env->PSW_USB_SAV |= env->PSW_USB_AV;
469 return ret;
470 }
471
472 uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
473 uint64_t r2, target_ulong r3)
474 {
475 uint64_t ret, mul;
476 uint64_t t1 = extract64(r1, 0, 32);
477 uint64_t t3 = extract64(r3, 0, 32);
478
479 mul = t1 * t3;
480 ret = r2 - mul;
481
482 if (ret > r2) {
483 env->PSW_USB_V = (1 << 31);
484 env->PSW_USB_SV = (1 << 31);
485 /* saturate */
486 ret = 0;
487 } else {
488 env->PSW_USB_V = 0;
489 }
490 t1 = ret >> 32;
491 env->PSW_USB_AV = t1 ^ t1 * 2u;
492 env->PSW_USB_SAV |= env->PSW_USB_AV;
493 return ret;
494 }
495
496 uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg)
497 {
498 int32_t b, i;
499 int32_t ovf = 0;
500 int32_t avf = 0;
501 int32_t ret = 0;
502
503 for (i = 0; i < 4; i++) {
504 b = sextract32(arg, i * 8, 8);
505 b = (b >= 0) ? b : (0 - b);
506 ovf |= (b > 0x7F) || (b < -0x80);
507 avf |= b ^ b * 2u;
508 ret |= (b & 0xff) << (i * 8);
509 }
510
511 env->PSW_USB_V = ovf << 31;
512 env->PSW_USB_SV |= env->PSW_USB_V;
513 env->PSW_USB_AV = avf << 24;
514 env->PSW_USB_SAV |= env->PSW_USB_AV;
515
516 return ret;
517 }
518
519 uint32_t helper_abs_h(CPUTriCoreState *env, target_ulong arg)
520 {
521 int32_t h, i;
522 int32_t ovf = 0;
523 int32_t avf = 0;
524 int32_t ret = 0;
525
526 for (i = 0; i < 2; i++) {
527 h = sextract32(arg, i * 16, 16);
528 h = (h >= 0) ? h : (0 - h);
529 ovf |= (h > 0x7FFF) || (h < -0x8000);
530 avf |= h ^ h * 2u;
531 ret |= (h & 0xffff) << (i * 16);
532 }
533
534 env->PSW_USB_V = ovf << 31;
535 env->PSW_USB_SV |= env->PSW_USB_V;
536 env->PSW_USB_AV = avf << 16;
537 env->PSW_USB_SAV |= env->PSW_USB_AV;
538
539 return ret;
540 }
541
542 uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
543 {
544 int32_t b, i;
545 int32_t extr_r2;
546 int32_t ovf = 0;
547 int32_t avf = 0;
548 int32_t ret = 0;
549
550 for (i = 0; i < 4; i++) {
551 extr_r2 = sextract32(r2, i * 8, 8);
552 b = sextract32(r1, i * 8, 8);
553 b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b);
554 ovf |= (b > 0x7F) || (b < -0x80);
555 avf |= b ^ b * 2u;
556 ret |= (b & 0xff) << (i * 8);
557 }
558
559 env->PSW_USB_V = ovf << 31;
560 env->PSW_USB_SV |= env->PSW_USB_V;
561 env->PSW_USB_AV = avf << 24;
562 env->PSW_USB_SAV |= env->PSW_USB_AV;
563 return ret;
564 }
565
566 uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
567 {
568 int32_t h, i;
569 int32_t extr_r2;
570 int32_t ovf = 0;
571 int32_t avf = 0;
572 int32_t ret = 0;
573
574 for (i = 0; i < 2; i++) {
575 extr_r2 = sextract32(r2, i * 16, 16);
576 h = sextract32(r1, i * 16, 16);
577 h = (h > extr_r2) ? (h - extr_r2) : (extr_r2 - h);
578 ovf |= (h > 0x7FFF) || (h < -0x8000);
579 avf |= h ^ h * 2u;
580 ret |= (h & 0xffff) << (i * 16);
581 }
582
583 env->PSW_USB_V = ovf << 31;
584 env->PSW_USB_SV |= env->PSW_USB_V;
585 env->PSW_USB_AV = avf << 16;
586 env->PSW_USB_SAV |= env->PSW_USB_AV;
587
588 return ret;
589 }
590
591 uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
592 {
593 int32_t b, i;
594 int32_t extr_r1, extr_r2;
595 int32_t ovf = 0;
596 int32_t avf = 0;
597 uint32_t ret = 0;
598
599 for (i = 0; i < 4; i++) {
600 extr_r1 = sextract32(r1, i * 8, 8);
601 extr_r2 = sextract32(r2, i * 8, 8);
602
603 b = extr_r1 + extr_r2;
604 ovf |= ((b > 0x7f) || (b < -0x80));
605 avf |= b ^ b * 2u;
606 ret |= ((b & 0xff) << (i*8));
607 }
608
609 env->PSW_USB_V = (ovf << 31);
610 env->PSW_USB_SV |= env->PSW_USB_V;
611 env->PSW_USB_AV = avf << 24;
612 env->PSW_USB_SAV |= env->PSW_USB_AV;
613
614 return ret;
615 }
616
617 uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
618 {
619 int32_t h, i;
620 int32_t extr_r1, extr_r2;
621 int32_t ovf = 0;
622 int32_t avf = 0;
623 int32_t ret = 0;
624
625 for (i = 0; i < 2; i++) {
626 extr_r1 = sextract32(r1, i * 16, 16);
627 extr_r2 = sextract32(r2, i * 16, 16);
628 h = extr_r1 + extr_r2;
629 ovf |= ((h > 0x7fff) || (h < -0x8000));
630 avf |= h ^ h * 2u;
631 ret |= (h & 0xffff) << (i * 16);
632 }
633
634 env->PSW_USB_V = (ovf << 31);
635 env->PSW_USB_SV |= env->PSW_USB_V;
636 env->PSW_USB_AV = (avf << 16);
637 env->PSW_USB_SAV |= env->PSW_USB_AV;
638
639 return ret;
640 }
641
642 uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
643 {
644 int32_t b, i;
645 int32_t extr_r1, extr_r2;
646 int32_t ovf = 0;
647 int32_t avf = 0;
648 uint32_t ret = 0;
649
650 for (i = 0; i < 4; i++) {
651 extr_r1 = sextract32(r1, i * 8, 8);
652 extr_r2 = sextract32(r2, i * 8, 8);
653
654 b = extr_r1 - extr_r2;
655 ovf |= ((b > 0x7f) || (b < -0x80));
656 avf |= b ^ b * 2u;
657 ret |= ((b & 0xff) << (i*8));
658 }
659
660 env->PSW_USB_V = (ovf << 31);
661 env->PSW_USB_SV |= env->PSW_USB_V;
662 env->PSW_USB_AV = avf << 24;
663 env->PSW_USB_SAV |= env->PSW_USB_AV;
664
665 return ret;
666 }
667
668 uint32_t helper_sub_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
669 {
670 int32_t h, i;
671 int32_t extr_r1, extr_r2;
672 int32_t ovf = 0;
673 int32_t avf = 0;
674 int32_t ret = 0;
675
676 for (i = 0; i < 2; i++) {
677 extr_r1 = sextract32(r1, i * 16, 16);
678 extr_r2 = sextract32(r2, i * 16, 16);
679 h = extr_r1 - extr_r2;
680 ovf |= ((h > 0x7fff) || (h < -0x8000));
681 avf |= h ^ h * 2u;
682 ret |= (h & 0xffff) << (i * 16);
683 }
684
685 env->PSW_USB_V = (ovf << 31);
686 env->PSW_USB_SV |= env->PSW_USB_V;
687 env->PSW_USB_AV = avf << 16;
688 env->PSW_USB_SAV |= env->PSW_USB_AV;
689
690 return ret;
691 }
692
693 uint32_t helper_eq_b(target_ulong r1, target_ulong r2)
694 {
695 int32_t ret;
696 int32_t i, msk;
697
698 ret = 0;
699 msk = 0xff;
700 for (i = 0; i < 4; i++) {
701 if ((r1 & msk) == (r2 & msk)) {
702 ret |= msk;
703 }
704 msk = msk << 8;
705 }
706
707 return ret;
708 }
709
710 uint32_t helper_eq_h(target_ulong r1, target_ulong r2)
711 {
712 int32_t ret = 0;
713
714 if ((r1 & 0xffff) == (r2 & 0xffff)) {
715 ret = 0xffff;
716 }
717
718 if ((r1 & 0xffff0000) == (r2 & 0xffff0000)) {
719 ret |= 0xffff0000;
720 }
721
722 return ret;
723 }
724
725 uint32_t helper_eqany_b(target_ulong r1, target_ulong r2)
726 {
727 int32_t i;
728 uint32_t ret = 0;
729
730 for (i = 0; i < 4; i++) {
731 ret |= (sextract32(r1, i * 8, 8) == sextract32(r2, i * 8, 8));
732 }
733
734 return ret;
735 }
736
737 uint32_t helper_eqany_h(target_ulong r1, target_ulong r2)
738 {
739 uint32_t ret;
740
741 ret = (sextract32(r1, 0, 16) == sextract32(r2, 0, 16));
742 ret |= (sextract32(r1, 16, 16) == sextract32(r2, 16, 16));
743
744 return ret;
745 }
746
747 uint32_t helper_lt_b(target_ulong r1, target_ulong r2)
748 {
749 int32_t i;
750 uint32_t ret = 0;
751
752 for (i = 0; i < 4; i++) {
753 if (sextract32(r1, i * 8, 8) < sextract32(r2, i * 8, 8)) {
754 ret |= (0xff << (i * 8));
755 }
756 }
757
758 return ret;
759 }
760
761 uint32_t helper_lt_bu(target_ulong r1, target_ulong r2)
762 {
763 int32_t i;
764 uint32_t ret = 0;
765
766 for (i = 0; i < 4; i++) {
767 if (extract32(r1, i * 8, 8) < extract32(r2, i * 8, 8)) {
768 ret |= (0xff << (i * 8));
769 }
770 }
771
772 return ret;
773 }
774
775 uint32_t helper_lt_h(target_ulong r1, target_ulong r2)
776 {
777 uint32_t ret = 0;
778
779 if (sextract32(r1, 0, 16) < sextract32(r2, 0, 16)) {
780 ret |= 0xffff;
781 }
782
783 if (sextract32(r1, 16, 16) < sextract32(r2, 16, 16)) {
784 ret |= 0xffff0000;
785 }
786
787 return ret;
788 }
789
790 uint32_t helper_lt_hu(target_ulong r1, target_ulong r2)
791 {
792 uint32_t ret = 0;
793
794 if (extract32(r1, 0, 16) < extract32(r2, 0, 16)) {
795 ret |= 0xffff;
796 }
797
798 if (extract32(r1, 16, 16) < extract32(r2, 16, 16)) {
799 ret |= 0xffff0000;
800 }
801
802 return ret;
803 }
804
805 #define EXTREMA_H_B(name, op) \
806 uint32_t helper_##name ##_b(target_ulong r1, target_ulong r2) \
807 { \
808 int32_t i, extr_r1, extr_r2; \
809 uint32_t ret = 0; \
810 \
811 for (i = 0; i < 4; i++) { \
812 extr_r1 = sextract32(r1, i * 8, 8); \
813 extr_r2 = sextract32(r2, i * 8, 8); \
814 extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
815 ret |= (extr_r1 & 0xff) << (i * 8); \
816 } \
817 return ret; \
818 } \
819 \
820 uint32_t helper_##name ##_bu(target_ulong r1, target_ulong r2)\
821 { \
822 int32_t i; \
823 uint32_t extr_r1, extr_r2; \
824 uint32_t ret = 0; \
825 \
826 for (i = 0; i < 4; i++) { \
827 extr_r1 = extract32(r1, i * 8, 8); \
828 extr_r2 = extract32(r2, i * 8, 8); \
829 extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
830 ret |= (extr_r1 & 0xff) << (i * 8); \
831 } \
832 return ret; \
833 } \
834 \
835 uint32_t helper_##name ##_h(target_ulong r1, target_ulong r2) \
836 { \
837 int32_t extr_r1, extr_r2; \
838 uint32_t ret = 0; \
839 \
840 extr_r1 = sextract32(r1, 0, 16); \
841 extr_r2 = sextract32(r2, 0, 16); \
842 ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
843 ret = ret & 0xffff; \
844 \
845 extr_r1 = sextract32(r1, 16, 16); \
846 extr_r2 = sextract32(r2, 16, 16); \
847 extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
848 ret |= extr_r1 << 16; \
849 \
850 return ret; \
851 } \
852 \
853 uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\
854 { \
855 uint32_t extr_r1, extr_r2; \
856 uint32_t ret = 0; \
857 \
858 extr_r1 = extract32(r1, 0, 16); \
859 extr_r2 = extract32(r2, 0, 16); \
860 ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
861 ret = ret & 0xffff; \
862 \
863 extr_r1 = extract32(r1, 16, 16); \
864 extr_r2 = extract32(r2, 16, 16); \
865 extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
866 ret |= extr_r1 << (16); \
867 \
868 return ret; \
869 } \
870
871 EXTREMA_H_B(max, >)
872 EXTREMA_H_B(min, <)
873
874 #undef EXTREMA_H_B
875
876 uint32_t helper_clo(target_ulong r1)
877 {
878 return clo32(r1);
879 }
880
881 uint32_t helper_clo_h(target_ulong r1)
882 {
883 uint32_t ret_hw0 = extract32(r1, 0, 16);
884 uint32_t ret_hw1 = extract32(r1, 16, 16);
885
886 ret_hw0 = clo32(ret_hw0 << 16);
887 ret_hw1 = clo32(ret_hw1 << 16);
888
889 if (ret_hw0 > 16) {
890 ret_hw0 = 16;
891 }
892 if (ret_hw1 > 16) {
893 ret_hw1 = 16;
894 }
895
896 return ret_hw0 | (ret_hw1 << 16);
897 }
898
899 uint32_t helper_clz(target_ulong r1)
900 {
901 return clz32(r1);
902 }
903
904 uint32_t helper_clz_h(target_ulong r1)
905 {
906 uint32_t ret_hw0 = extract32(r1, 0, 16);
907 uint32_t ret_hw1 = extract32(r1, 16, 16);
908
909 ret_hw0 = clz32(ret_hw0 << 16);
910 ret_hw1 = clz32(ret_hw1 << 16);
911
912 if (ret_hw0 > 16) {
913 ret_hw0 = 16;
914 }
915 if (ret_hw1 > 16) {
916 ret_hw1 = 16;
917 }
918
919 return ret_hw0 | (ret_hw1 << 16);
920 }
921
922 uint32_t helper_cls(target_ulong r1)
923 {
924 return clrsb32(r1);
925 }
926
927 uint32_t helper_cls_h(target_ulong r1)
928 {
929 uint32_t ret_hw0 = extract32(r1, 0, 16);
930 uint32_t ret_hw1 = extract32(r1, 16, 16);
931
932 ret_hw0 = clrsb32(ret_hw0 << 16);
933 ret_hw1 = clrsb32(ret_hw1 << 16);
934
935 if (ret_hw0 > 15) {
936 ret_hw0 = 15;
937 }
938 if (ret_hw1 > 15) {
939 ret_hw1 = 15;
940 }
941
942 return ret_hw0 | (ret_hw1 << 16);
943 }
944
945 uint32_t helper_sh(target_ulong r1, target_ulong r2)
946 {
947 int32_t shift_count = sextract32(r2, 0, 6);
948
949 if (shift_count == -32) {
950 return 0;
951 } else if (shift_count < 0) {
952 return r1 >> -shift_count;
953 } else {
954 return r1 << shift_count;
955 }
956 }
957
958 uint32_t helper_sh_h(target_ulong r1, target_ulong r2)
959 {
960 int32_t ret_hw0, ret_hw1;
961 int32_t shift_count;
962
963 shift_count = sextract32(r2, 0, 5);
964
965 if (shift_count == -16) {
966 return 0;
967 } else if (shift_count < 0) {
968 ret_hw0 = extract32(r1, 0, 16) >> -shift_count;
969 ret_hw1 = extract32(r1, 16, 16) >> -shift_count;
970 return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
971 } else {
972 ret_hw0 = extract32(r1, 0, 16) << shift_count;
973 ret_hw1 = extract32(r1, 16, 16) << shift_count;
974 return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
975 }
976 }
977
978 uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
979 {
980 int32_t shift_count;
981 int64_t result, t1;
982 uint32_t ret;
983
984 shift_count = sextract32(r2, 0, 6);
985 t1 = sextract32(r1, 0, 32);
986
987 if (shift_count == 0) {
988 env->PSW_USB_C = env->PSW_USB_V = 0;
989 ret = r1;
990 } else if (shift_count == -32) {
991 env->PSW_USB_C = r1;
992 env->PSW_USB_V = 0;
993 ret = t1 >> 31;
994 } else if (shift_count > 0) {
995 result = t1 << shift_count;
996 /* calc carry */
997 env->PSW_USB_C = ((result & 0xffffffff00000000) != 0);
998 /* calc v */
999 env->PSW_USB_V = (((result > 0x7fffffffLL) ||
1000 (result < -0x80000000LL)) << 31);
1001 /* calc sv */
1002 env->PSW_USB_SV |= env->PSW_USB_V;
1003 ret = (uint32_t)result;
1004 } else {
1005 env->PSW_USB_V = 0;
1006 env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1));
1007 ret = t1 >> -shift_count;
1008 }
1009
1010 env->PSW_USB_AV = ret ^ ret * 2u;
1011 env->PSW_USB_SAV |= env->PSW_USB_AV;
1012
1013 return ret;
1014 }
1015
1016 uint32_t helper_sha_h(target_ulong r1, target_ulong r2)
1017 {
1018 int32_t shift_count;
1019 int32_t ret_hw0, ret_hw1;
1020
1021 shift_count = sextract32(r2, 0, 5);
1022
1023 if (shift_count == 0) {
1024 return r1;
1025 } else if (shift_count < 0) {
1026 ret_hw0 = sextract32(r1, 0, 16) >> -shift_count;
1027 ret_hw1 = sextract32(r1, 16, 16) >> -shift_count;
1028 return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
1029 } else {
1030 ret_hw0 = sextract32(r1, 0, 16) << shift_count;
1031 ret_hw1 = sextract32(r1, 16, 16) << shift_count;
1032 return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
1033 }
1034 }
1035
1036 uint32_t helper_bmerge(target_ulong r1, target_ulong r2)
1037 {
1038 uint32_t i, ret;
1039
1040 ret = 0;
1041 for (i = 0; i < 16; i++) {
1042 ret |= (r1 & 1) << (2 * i + 1);
1043 ret |= (r2 & 1) << (2 * i);
1044 r1 = r1 >> 1;
1045 r2 = r2 >> 1;
1046 }
1047 return ret;
1048 }
1049
1050 uint64_t helper_bsplit(uint32_t r1)
1051 {
1052 int32_t i;
1053 uint64_t ret;
1054
1055 ret = 0;
1056 for (i = 0; i < 32; i = i + 2) {
1057 /* even */
1058 ret |= (r1 & 1) << (i/2);
1059 r1 = r1 >> 1;
1060 /* odd */
1061 ret |= (uint64_t)(r1 & 1) << (i/2 + 32);
1062 r1 = r1 >> 1;
1063 }
1064 return ret;
1065 }
1066
1067 uint32_t helper_parity(target_ulong r1)
1068 {
1069 uint32_t ret;
1070 uint32_t nOnes, i;
1071
1072 ret = 0;
1073 nOnes = 0;
1074 for (i = 0; i < 8; i++) {
1075 ret ^= (r1 & 1);
1076 r1 = r1 >> 1;
1077 }
1078 /* second byte */
1079 nOnes = 0;
1080 for (i = 0; i < 8; i++) {
1081 nOnes ^= (r1 & 1);
1082 r1 = r1 >> 1;
1083 }
1084 ret |= nOnes << 8;
1085 /* third byte */
1086 nOnes = 0;
1087 for (i = 0; i < 8; i++) {
1088 nOnes ^= (r1 & 1);
1089 r1 = r1 >> 1;
1090 }
1091 ret |= nOnes << 16;
1092 /* fourth byte */
1093 nOnes = 0;
1094 for (i = 0; i < 8; i++) {
1095 nOnes ^= (r1 & 1);
1096 r1 = r1 >> 1;
1097 }
1098 ret |= nOnes << 24;
1099
1100 return ret;
1101 }
1102
1103 uint64_t helper_unpack(target_ulong arg1)
1104 {
1105 int32_t fp_exp = extract32(arg1, 23, 8);
1106 int32_t fp_frac = extract32(arg1, 0, 23);
1107 uint64_t ret;
1108 int32_t int_exp, int_mant;
1109
1110 if (fp_exp == 255) {
1111 int_exp = 255;
1112 int_mant = (fp_frac << 7);
1113 } else if ((fp_exp == 0) && (fp_frac == 0)) {
1114 int_exp = -127;
1115 int_mant = 0;
1116 } else if ((fp_exp == 0) && (fp_frac != 0)) {
1117 int_exp = -126;
1118 int_mant = (fp_frac << 7);
1119 } else {
1120 int_exp = fp_exp - 127;
1121 int_mant = (fp_frac << 7);
1122 int_mant |= (1 << 30);
1123 }
1124 ret = int_exp;
1125 ret = ret << 32;
1126 ret |= int_mant;
1127
1128 return ret;
1129 }
1130
1131 uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
1132 {
1133 uint64_t ret;
1134 int32_t abs_sig_dividend, abs_base_dividend, abs_divisor;
1135 int32_t quotient_sign;
1136
1137 ret = sextract32(r1, 0, 32);
1138 ret = ret << 24;
1139 quotient_sign = 0;
1140 if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
1141 ret |= 0xffffff;
1142 quotient_sign = 1;
1143 }
1144
1145 abs_sig_dividend = abs(r1) >> 7;
1146 abs_base_dividend = abs(r1) & 0x7f;
1147 abs_divisor = abs(r1);
1148 /* calc overflow */
1149 env->PSW_USB_V = 0;
1150 if ((quotient_sign) && (abs_divisor)) {
1151 env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) &&
1152 (abs_base_dividend >= abs_divisor)) ||
1153 (abs_sig_dividend > abs_divisor));
1154 } else {
1155 env->PSW_USB_V = (abs_sig_dividend >= abs_divisor);
1156 }
1157 env->PSW_USB_V = env->PSW_USB_V << 31;
1158 env->PSW_USB_SV |= env->PSW_USB_V;
1159 env->PSW_USB_AV = 0;
1160
1161 return ret;
1162 }
1163
1164 uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
1165 {
1166 uint64_t ret = sextract32(r1, 0, 32);
1167
1168 ret = ret << 24;
1169 if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
1170 ret |= 0xffffff;
1171 }
1172 /* calc overflow */
1173 env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffffff80)));
1174 env->PSW_USB_V = env->PSW_USB_V << 31;
1175 env->PSW_USB_SV |= env->PSW_USB_V;
1176 env->PSW_USB_AV = 0;
1177
1178 return ret;
1179 }
1180
1181 uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
1182 {
1183 uint64_t ret;
1184 int32_t abs_sig_dividend, abs_base_dividend, abs_divisor;
1185 int32_t quotient_sign;
1186
1187 ret = sextract32(r1, 0, 32);
1188 ret = ret << 16;
1189 quotient_sign = 0;
1190 if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
1191 ret |= 0xffff;
1192 quotient_sign = 1;
1193 }
1194
1195 abs_sig_dividend = abs(r1) >> 7;
1196 abs_base_dividend = abs(r1) & 0x7f;
1197 abs_divisor = abs(r1);
1198 /* calc overflow */
1199 env->PSW_USB_V = 0;
1200 if ((quotient_sign) && (abs_divisor)) {
1201 env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) &&
1202 (abs_base_dividend >= abs_divisor)) ||
1203 (abs_sig_dividend > abs_divisor));
1204 } else {
1205 env->PSW_USB_V = (abs_sig_dividend >= abs_divisor);
1206 }
1207 env->PSW_USB_V = env->PSW_USB_V << 31;
1208 env->PSW_USB_SV |= env->PSW_USB_V;
1209 env->PSW_USB_AV = 0;
1210
1211 return ret;
1212 }
1213
1214 uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
1215 {
1216 uint64_t ret = sextract32(r1, 0, 32);
1217
1218 ret = ret << 16;
1219 if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
1220 ret |= 0xffff;
1221 }
1222 /* calc overflow */
1223 env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffff8000)));
1224 env->PSW_USB_V = env->PSW_USB_V << 31;
1225 env->PSW_USB_SV |= env->PSW_USB_V;
1226 env->PSW_USB_AV = 0;
1227
1228 return ret;
1229 }
1230
1231 /* context save area (CSA) related helpers */
1232
1233 static int cdc_increment(target_ulong *psw)
1234 {
1235 if ((*psw & MASK_PSW_CDC) == 0x7f) {
1236 return 0;
1237 }
1238
1239 (*psw)++;
1240 /* check for overflow */
1241 int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7));
1242 int mask = (1u << (7 - lo)) - 1;
1243 int count = *psw & mask;
1244 if (count == 0) {
1245 (*psw)--;
1246 return 1;
1247 }
1248 return 0;
1249 }
1250
1251 static int cdc_decrement(target_ulong *psw)
1252 {
1253 if ((*psw & MASK_PSW_CDC) == 0x7f) {
1254 return 0;
1255 }
1256 /* check for underflow */
1257 int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7));
1258 int mask = (1u << (7 - lo)) - 1;
1259 int count = *psw & mask;
1260 if (count == 0) {
1261 return 1;
1262 }
1263 (*psw)--;
1264 return 0;
1265 }
1266
1267 static bool cdc_zero(target_ulong *psw)
1268 {
1269 int cdc = *psw & MASK_PSW_CDC;
1270 /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC ==
1271 7'b1111111, otherwise returns FALSE. */
1272 if (cdc == 0x7f) {
1273 return true;
1274 }
1275 /* find CDC.COUNT */
1276 int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7));
1277 int mask = (1u << (7 - lo)) - 1;
1278 int count = *psw & mask;
1279 return count == 0;
1280 }
1281
1282 static void save_context_upper(CPUTriCoreState *env, int ea)
1283 {
1284 cpu_stl_data(env, ea, env->PCXI);
1285 cpu_stl_data(env, ea+4, env->PSW);
1286 cpu_stl_data(env, ea+8, env->gpr_a[10]);
1287 cpu_stl_data(env, ea+12, env->gpr_a[11]);
1288 cpu_stl_data(env, ea+16, env->gpr_d[8]);
1289 cpu_stl_data(env, ea+20, env->gpr_d[9]);
1290 cpu_stl_data(env, ea+24, env->gpr_d[10]);
1291 cpu_stl_data(env, ea+28, env->gpr_d[11]);
1292 cpu_stl_data(env, ea+32, env->gpr_a[12]);
1293 cpu_stl_data(env, ea+36, env->gpr_a[13]);
1294 cpu_stl_data(env, ea+40, env->gpr_a[14]);
1295 cpu_stl_data(env, ea+44, env->gpr_a[15]);
1296 cpu_stl_data(env, ea+48, env->gpr_d[12]);
1297 cpu_stl_data(env, ea+52, env->gpr_d[13]);
1298 cpu_stl_data(env, ea+56, env->gpr_d[14]);
1299 cpu_stl_data(env, ea+60, env->gpr_d[15]);
1300 }
1301
1302 static void save_context_lower(CPUTriCoreState *env, int ea)
1303 {
1304 cpu_stl_data(env, ea, env->PCXI);
1305 cpu_stl_data(env, ea+4, env->gpr_a[11]);
1306 cpu_stl_data(env, ea+8, env->gpr_a[2]);
1307 cpu_stl_data(env, ea+12, env->gpr_a[3]);
1308 cpu_stl_data(env, ea+16, env->gpr_d[0]);
1309 cpu_stl_data(env, ea+20, env->gpr_d[1]);
1310 cpu_stl_data(env, ea+24, env->gpr_d[2]);
1311 cpu_stl_data(env, ea+28, env->gpr_d[3]);
1312 cpu_stl_data(env, ea+32, env->gpr_a[4]);
1313 cpu_stl_data(env, ea+36, env->gpr_a[5]);
1314 cpu_stl_data(env, ea+40, env->gpr_a[6]);
1315 cpu_stl_data(env, ea+44, env->gpr_a[7]);
1316 cpu_stl_data(env, ea+48, env->gpr_d[4]);
1317 cpu_stl_data(env, ea+52, env->gpr_d[5]);
1318 cpu_stl_data(env, ea+56, env->gpr_d[6]);
1319 cpu_stl_data(env, ea+60, env->gpr_d[7]);
1320 }
1321
1322 static void restore_context_upper(CPUTriCoreState *env, int ea,
1323 target_ulong *new_PCXI, target_ulong *new_PSW)
1324 {
1325 *new_PCXI = cpu_ldl_data(env, ea);
1326 *new_PSW = cpu_ldl_data(env, ea+4);
1327 env->gpr_a[10] = cpu_ldl_data(env, ea+8);
1328 env->gpr_a[11] = cpu_ldl_data(env, ea+12);
1329 env->gpr_d[8] = cpu_ldl_data(env, ea+16);
1330 env->gpr_d[9] = cpu_ldl_data(env, ea+20);
1331 env->gpr_d[10] = cpu_ldl_data(env, ea+24);
1332 env->gpr_d[11] = cpu_ldl_data(env, ea+28);
1333 env->gpr_a[12] = cpu_ldl_data(env, ea+32);
1334 env->gpr_a[13] = cpu_ldl_data(env, ea+36);
1335 env->gpr_a[14] = cpu_ldl_data(env, ea+40);
1336 env->gpr_a[15] = cpu_ldl_data(env, ea+44);
1337 env->gpr_d[12] = cpu_ldl_data(env, ea+48);
1338 env->gpr_d[13] = cpu_ldl_data(env, ea+52);
1339 env->gpr_d[14] = cpu_ldl_data(env, ea+56);
1340 env->gpr_d[15] = cpu_ldl_data(env, ea+60);
1341 }
1342
1343 static void restore_context_lower(CPUTriCoreState *env, int ea,
1344 target_ulong *ra, target_ulong *pcxi)
1345 {
1346 *pcxi = cpu_ldl_data(env, ea);
1347 *ra = cpu_ldl_data(env, ea+4);
1348 env->gpr_a[2] = cpu_ldl_data(env, ea+8);
1349 env->gpr_a[3] = cpu_ldl_data(env, ea+12);
1350 env->gpr_d[0] = cpu_ldl_data(env, ea+16);
1351 env->gpr_d[1] = cpu_ldl_data(env, ea+20);
1352 env->gpr_d[2] = cpu_ldl_data(env, ea+24);
1353 env->gpr_d[3] = cpu_ldl_data(env, ea+28);
1354 env->gpr_a[4] = cpu_ldl_data(env, ea+32);
1355 env->gpr_a[5] = cpu_ldl_data(env, ea+36);
1356 env->gpr_a[6] = cpu_ldl_data(env, ea+40);
1357 env->gpr_a[7] = cpu_ldl_data(env, ea+44);
1358 env->gpr_d[4] = cpu_ldl_data(env, ea+48);
1359 env->gpr_d[5] = cpu_ldl_data(env, ea+52);
1360 env->gpr_d[6] = cpu_ldl_data(env, ea+56);
1361 env->gpr_d[7] = cpu_ldl_data(env, ea+60);
1362 }
1363
1364 void helper_call(CPUTriCoreState *env, uint32_t next_pc)
1365 {
1366 target_ulong tmp_FCX;
1367 target_ulong ea;
1368 target_ulong new_FCX;
1369 target_ulong psw;
1370
1371 psw = psw_read(env);
1372 /* if (FCX == 0) trap(FCU); */
1373 if (env->FCX == 0) {
1374 /* FCU trap */
1375 }
1376 /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */
1377 if (psw & MASK_PSW_CDE) {
1378 if (cdc_increment(&psw)) {
1379 /* CDO trap */
1380 }
1381 }
1382 /* PSW.CDE = 1;*/
1383 psw |= MASK_PSW_CDE;
1384 /* tmp_FCX = FCX; */
1385 tmp_FCX = env->FCX;
1386 /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */
1387 ea = ((env->FCX & MASK_FCX_FCXS) << 12) +
1388 ((env->FCX & MASK_FCX_FCXO) << 6);
1389 /* new_FCX = M(EA, word); */
1390 new_FCX = cpu_ldl_data(env, ea);
1391 /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11],
1392 A[12], A[13], A[14], A[15], D[12], D[13], D[14],
1393 D[15]}; */
1394 save_context_upper(env, ea);
1395
1396 /* PCXI.PCPN = ICR.CCPN; */
1397 env->PCXI = (env->PCXI & 0xffffff) +
1398 ((env->ICR & MASK_ICR_CCPN) << 24);
1399 /* PCXI.PIE = ICR.IE; */
1400 env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) +
1401 ((env->ICR & MASK_ICR_IE) << 15));
1402 /* PCXI.UL = 1; */
1403 env->PCXI |= MASK_PCXI_UL;
1404
1405 /* PCXI[19: 0] = FCX[19: 0]; */
1406 env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
1407 /* FCX[19: 0] = new_FCX[19: 0]; */
1408 env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff);
1409 /* A[11] = next_pc[31: 0]; */
1410 env->gpr_a[11] = next_pc;
1411
1412 /* if (tmp_FCX == LCX) trap(FCD);*/
1413 if (tmp_FCX == env->LCX) {
1414 /* FCD trap */
1415 }
1416 psw_write(env, psw);
1417 }
1418
1419 void helper_ret(CPUTriCoreState *env)
1420 {
1421 target_ulong ea;
1422 target_ulong new_PCXI;
1423 target_ulong new_PSW, psw;
1424
1425 psw = psw_read(env);
1426 /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/
1427 if (env->PSW & MASK_PSW_CDE) {
1428 if (cdc_decrement(&(env->PSW))) {
1429 /* CDU trap */
1430 }
1431 }
1432 /* if (PCXI[19: 0] == 0) then trap(CSU); */
1433 if ((env->PCXI & 0xfffff) == 0) {
1434 /* CSU trap */
1435 }
1436 /* if (PCXI.UL == 0) then trap(CTYP); */
1437 if ((env->PCXI & MASK_PCXI_UL) == 0) {
1438 /* CTYP trap */
1439 }
1440 /* PC = {A11 [31: 1], 1’b0}; */
1441 env->PC = env->gpr_a[11] & 0xfffffffe;
1442
1443 /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
1444 ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) +
1445 ((env->PCXI & MASK_PCXI_PCXO) << 6);
1446 /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12],
1447 A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */
1448 restore_context_upper(env, ea, &new_PCXI, &new_PSW);
1449 /* M(EA, word) = FCX; */
1450 cpu_stl_data(env, ea, env->FCX);
1451 /* FCX[19: 0] = PCXI[19: 0]; */
1452 env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff);
1453 /* PCXI = new_PCXI; */
1454 env->PCXI = new_PCXI;
1455
1456 if (tricore_feature(env, TRICORE_FEATURE_13)) {
1457 /* PSW = new_PSW */
1458 psw_write(env, new_PSW);
1459 } else {
1460 /* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */
1461 psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000)));
1462 }
1463 }
1464
1465 void helper_bisr(CPUTriCoreState *env, uint32_t const9)
1466 {
1467 target_ulong tmp_FCX;
1468 target_ulong ea;
1469 target_ulong new_FCX;
1470
1471 if (env->FCX == 0) {
1472 /* FCU trap */
1473 }
1474
1475 tmp_FCX = env->FCX;
1476 ea = ((env->FCX & 0xf0000) << 12) + ((env->FCX & 0xffff) << 6);
1477
1478 /* new_FCX = M(EA, word); */
1479 new_FCX = cpu_ldl_data(env, ea);
1480 /* M(EA, 16 * word) = {PCXI, A[11], A[2], A[3], D[0], D[1], D[2], D[3], A[4]
1481 , A[5], A[6], A[7], D[4], D[5], D[6], D[7]}; */
1482 save_context_lower(env, ea);
1483
1484
1485 /* PCXI.PCPN = ICR.CCPN */
1486 env->PCXI = (env->PCXI & 0xffffff) +
1487 ((env->ICR & MASK_ICR_CCPN) << 24);
1488 /* PCXI.PIE = ICR.IE */
1489 env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) +
1490 ((env->ICR & MASK_ICR_IE) << 15));
1491 /* PCXI.UL = 0 */
1492 env->PCXI &= ~(MASK_PCXI_UL);
1493 /* PCXI[19: 0] = FCX[19: 0] */
1494 env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
1495 /* FXC[19: 0] = new_FCX[19: 0] */
1496 env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff);
1497 /* ICR.IE = 1 */
1498 env->ICR |= MASK_ICR_IE;
1499
1500 env->ICR |= const9; /* ICR.CCPN = const9[7: 0];*/
1501
1502 if (tmp_FCX == env->LCX) {
1503 /* FCD trap */
1504 }
1505 }
1506
1507 void helper_rfe(CPUTriCoreState *env)
1508 {
1509 target_ulong ea;
1510 target_ulong new_PCXI;
1511 target_ulong new_PSW;
1512 /* if (PCXI[19: 0] == 0) then trap(CSU); */
1513 if ((env->PCXI & 0xfffff) == 0) {
1514 /* raise csu trap */
1515 }
1516 /* if (PCXI.UL == 0) then trap(CTYP); */
1517 if ((env->PCXI & MASK_PCXI_UL) == 0) {
1518 /* raise CTYP trap */
1519 }
1520 /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */
1521 if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) {
1522 /* raise MNG trap */
1523 }
1524 /* ICR.IE = PCXI.PIE; */
1525 env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15);
1526 /* ICR.CCPN = PCXI.PCPN; */
1527 env->ICR = (env->ICR & ~MASK_ICR_CCPN) +
1528 ((env->PCXI & MASK_PCXI_PCPN) >> 24);
1529 /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/
1530 ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) +
1531 ((env->PCXI & MASK_PCXI_PCXO) << 6);
1532 /*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12],
1533 A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */
1534 restore_context_upper(env, ea, &new_PCXI, &new_PSW);
1535 /* M(EA, word) = FCX;*/
1536 cpu_stl_data(env, ea, env->FCX);
1537 /* FCX[19: 0] = PCXI[19: 0]; */
1538 env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff);
1539 /* PCXI = new_PCXI; */
1540 env->PCXI = new_PCXI;
1541 /* write psw */
1542 psw_write(env, new_PSW);
1543 }
1544
1545 void helper_ldlcx(CPUTriCoreState *env, uint32_t ea)
1546 {
1547 uint32_t dummy;
1548 /* insn doesn't load PCXI and RA */
1549 restore_context_lower(env, ea, &dummy, &dummy);
1550 }
1551
1552 void helper_lducx(CPUTriCoreState *env, uint32_t ea)
1553 {
1554 uint32_t dummy;
1555 /* insn doesn't load PCXI and PSW */
1556 restore_context_upper(env, ea, &dummy, &dummy);
1557 }
1558
1559 void helper_stlcx(CPUTriCoreState *env, uint32_t ea)
1560 {
1561 save_context_lower(env, ea);
1562 }
1563
1564 void helper_stucx(CPUTriCoreState *env, uint32_t ea)
1565 {
1566 save_context_upper(env, ea);
1567 }
1568
1569 void helper_psw_write(CPUTriCoreState *env, uint32_t arg)
1570 {
1571 psw_write(env, arg);
1572 }
1573
1574 uint32_t helper_psw_read(CPUTriCoreState *env)
1575 {
1576 return psw_read(env);
1577 }
1578
1579
1580 static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env,
1581 uint32_t exception,
1582 int error_code,
1583 uintptr_t pc)
1584 {
1585 CPUState *cs = CPU(tricore_env_get_cpu(env));
1586 cs->exception_index = exception;
1587 env->error_code = error_code;
1588
1589 if (pc) {
1590 /* now we have a real cpu fault */
1591 cpu_restore_state(cs, pc);
1592 }
1593
1594 cpu_loop_exit(cs);
1595 }
1596
1597 void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
1598 uintptr_t retaddr)
1599 {
1600 int ret;
1601 ret = cpu_tricore_handle_mmu_fault(cs, addr, is_write, mmu_idx);
1602 if (ret) {
1603 TriCoreCPU *cpu = TRICORE_CPU(cs);
1604 CPUTriCoreState *env = &cpu->env;
1605 do_raise_exception_err(env, cs->exception_index,
1606 env->error_code, retaddr);
1607 }
1608 }