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.1 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 "qemu/osdep.h" |
18 | #include "cpu.h" |
19 | #include "qemu/host-utils.h" |
20 | #include "exec/helper-proto.h" |
21 | #include "exec/exec-all.h" |
22 | #include "exec/cpu_ldst.h" |
23 | #include <zlib.h> /* for crc32 */ |
24 | |
25 | |
26 | /* Exception helpers */ |
27 | |
28 | static void QEMU_NORETURN |
29 | raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin, |
30 | uintptr_t pc, uint32_t fcd_pc) |
31 | { |
32 | CPUState *cs = env_cpu(env); |
33 | /* in case we come from a helper-call we need to restore the PC */ |
34 | cpu_restore_state(cs, pc, true); |
35 | |
36 | /* Tin is loaded into d[15] */ |
37 | env->gpr_d[15] = tin; |
38 | |
39 | if (class == TRAPC_CTX_MNG && tin == TIN3_FCU) { |
40 | /* upper context cannot be saved, if the context list is empty */ |
41 | } else { |
42 | helper_svucx(env); |
43 | } |
44 | |
45 | /* The return address in a[11] is updated */ |
46 | if (class == TRAPC_CTX_MNG && tin == TIN3_FCD) { |
47 | env->SYSCON |= MASK_SYSCON_FCD_SF; |
48 | /* when we run out of CSAs after saving a context a FCD trap is taken |
49 | and the return address is the start of the trap handler which used |
50 | the last CSA */ |
51 | env->gpr_a[11] = fcd_pc; |
52 | } else if (class == TRAPC_SYSCALL) { |
53 | env->gpr_a[11] = env->PC + 4; |
54 | } else { |
55 | env->gpr_a[11] = env->PC; |
56 | } |
57 | /* The stack pointer in A[10] is set to the Interrupt Stack Pointer (ISP) |
58 | when the processor was not previously using the interrupt stack |
59 | (in case of PSW.IS = 0). The stack pointer bit is set for using the |
60 | interrupt stack: PSW.IS = 1. */ |
61 | if ((env->PSW & MASK_PSW_IS) == 0) { |
62 | env->gpr_a[10] = env->ISP; |
63 | } |
64 | env->PSW |= MASK_PSW_IS; |
65 | /* The I/O mode is set to Supervisor mode, which means all permissions |
66 | are enabled: PSW.IO = 10 B .*/ |
67 | env->PSW |= (2 << 10); |
68 | |
69 | /*The current Protection Register Set is set to 0: PSW.PRS = 00 B .*/ |
70 | env->PSW &= ~MASK_PSW_PRS; |
71 | |
72 | /* The Call Depth Counter (CDC) is cleared, and the call depth limit is |
73 | set for 64: PSW.CDC = 0000000 B .*/ |
74 | env->PSW &= ~MASK_PSW_CDC; |
75 | |
76 | /* Call Depth Counter is enabled, PSW.CDE = 1. */ |
77 | env->PSW |= MASK_PSW_CDE; |
78 | |
79 | /* Write permission to global registers A[0], A[1], A[8], A[9] is |
80 | disabled: PSW.GW = 0. */ |
81 | env->PSW &= ~MASK_PSW_GW; |
82 | |
83 | /*The interrupt system is globally disabled: ICR.IE = 0. The ‘old’ |
84 | ICR.IE and ICR.CCPN are saved */ |
85 | |
86 | /* PCXI.PIE = ICR.IE */ |
87 | env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) + |
88 | ((env->ICR & MASK_ICR_IE_1_3) << 15)); |
89 | /* PCXI.PCPN = ICR.CCPN */ |
90 | env->PCXI = (env->PCXI & 0xffffff) + |
91 | ((env->ICR & MASK_ICR_CCPN) << 24); |
92 | /* Update PC using the trap vector table */ |
93 | env->PC = env->BTV | (class << 5); |
94 | |
95 | cpu_loop_exit(cs); |
96 | } |
97 | |
98 | void helper_raise_exception_sync(CPUTriCoreState *env, uint32_t class, |
99 | uint32_t tin) |
100 | { |
101 | raise_exception_sync_internal(env, class, tin, 0, 0); |
102 | } |
103 | |
104 | static void raise_exception_sync_helper(CPUTriCoreState *env, uint32_t class, |
105 | uint32_t tin, uintptr_t pc) |
106 | { |
107 | raise_exception_sync_internal(env, class, tin, pc, 0); |
108 | } |
109 | |
110 | void helper_qemu_excp(CPUTriCoreState *env, uint32_t excp) |
111 | { |
112 | CPUState *cs = env_cpu(env); |
113 | cs->exception_index = excp; |
114 | cpu_loop_exit(cs); |
115 | } |
116 | |
117 | /* Addressing mode helper */ |
118 | |
119 | static uint16_t reverse16(uint16_t val) |
120 | { |
121 | uint8_t high = (uint8_t)(val >> 8); |
122 | uint8_t low = (uint8_t)(val & 0xff); |
123 | |
124 | uint16_t rh, rl; |
125 | |
126 | rl = (uint16_t)((high * 0x0202020202ULL & 0x010884422010ULL) % 1023); |
127 | rh = (uint16_t)((low * 0x0202020202ULL & 0x010884422010ULL) % 1023); |
128 | |
129 | return (rh << 8) | rl; |
130 | } |
131 | |
132 | uint32_t helper_br_update(uint32_t reg) |
133 | { |
134 | uint32_t index = reg & 0xffff; |
135 | uint32_t incr = reg >> 16; |
136 | uint32_t new_index = reverse16(reverse16(index) + reverse16(incr)); |
137 | return reg - index + new_index; |
138 | } |
139 | |
140 | uint32_t helper_circ_update(uint32_t reg, uint32_t off) |
141 | { |
142 | uint32_t index = reg & 0xffff; |
143 | uint32_t length = reg >> 16; |
144 | int32_t new_index = index + off; |
145 | if (new_index < 0) { |
146 | new_index += length; |
147 | } else { |
148 | new_index %= length; |
149 | } |
150 | return reg - index + new_index; |
151 | } |
152 | |
153 | static uint32_t ssov32(CPUTriCoreState *env, int64_t arg) |
154 | { |
155 | uint32_t ret; |
156 | int64_t max_pos = INT32_MAX; |
157 | int64_t max_neg = INT32_MIN; |
158 | if (arg > max_pos) { |
159 | env->PSW_USB_V = (1 << 31); |
160 | env->PSW_USB_SV = (1 << 31); |
161 | ret = (target_ulong)max_pos; |
162 | } else { |
163 | if (arg < max_neg) { |
164 | env->PSW_USB_V = (1 << 31); |
165 | env->PSW_USB_SV = (1 << 31); |
166 | ret = (target_ulong)max_neg; |
167 | } else { |
168 | env->PSW_USB_V = 0; |
169 | ret = (target_ulong)arg; |
170 | } |
171 | } |
172 | env->PSW_USB_AV = arg ^ arg * 2u; |
173 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
174 | return ret; |
175 | } |
176 | |
177 | static uint32_t suov32_pos(CPUTriCoreState *env, uint64_t arg) |
178 | { |
179 | uint32_t ret; |
180 | uint64_t max_pos = UINT32_MAX; |
181 | if (arg > max_pos) { |
182 | env->PSW_USB_V = (1 << 31); |
183 | env->PSW_USB_SV = (1 << 31); |
184 | ret = (target_ulong)max_pos; |
185 | } else { |
186 | env->PSW_USB_V = 0; |
187 | ret = (target_ulong)arg; |
188 | } |
189 | env->PSW_USB_AV = arg ^ arg * 2u; |
190 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
191 | return ret; |
192 | } |
193 | |
194 | static uint32_t suov32_neg(CPUTriCoreState *env, int64_t arg) |
195 | { |
196 | uint32_t ret; |
197 | |
198 | if (arg < 0) { |
199 | env->PSW_USB_V = (1 << 31); |
200 | env->PSW_USB_SV = (1 << 31); |
201 | ret = 0; |
202 | } else { |
203 | env->PSW_USB_V = 0; |
204 | ret = (target_ulong)arg; |
205 | } |
206 | env->PSW_USB_AV = arg ^ arg * 2u; |
207 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
208 | return ret; |
209 | } |
210 | |
211 | static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) |
212 | { |
213 | int32_t max_pos = INT16_MAX; |
214 | int32_t max_neg = INT16_MIN; |
215 | int32_t av0, av1; |
216 | |
217 | env->PSW_USB_V = 0; |
218 | av0 = hw0 ^ hw0 * 2u; |
219 | if (hw0 > max_pos) { |
220 | env->PSW_USB_V = (1 << 31); |
221 | hw0 = max_pos; |
222 | } else if (hw0 < max_neg) { |
223 | env->PSW_USB_V = (1 << 31); |
224 | hw0 = max_neg; |
225 | } |
226 | |
227 | av1 = hw1 ^ hw1 * 2u; |
228 | if (hw1 > max_pos) { |
229 | env->PSW_USB_V = (1 << 31); |
230 | hw1 = max_pos; |
231 | } else if (hw1 < max_neg) { |
232 | env->PSW_USB_V = (1 << 31); |
233 | hw1 = max_neg; |
234 | } |
235 | |
236 | env->PSW_USB_SV |= env->PSW_USB_V; |
237 | env->PSW_USB_AV = (av0 | av1) << 16; |
238 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
239 | return (hw0 & 0xffff) | (hw1 << 16); |
240 | } |
241 | |
242 | static uint32_t suov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) |
243 | { |
244 | int32_t max_pos = UINT16_MAX; |
245 | int32_t av0, av1; |
246 | |
247 | env->PSW_USB_V = 0; |
248 | av0 = hw0 ^ hw0 * 2u; |
249 | if (hw0 > max_pos) { |
250 | env->PSW_USB_V = (1 << 31); |
251 | hw0 = max_pos; |
252 | } else if (hw0 < 0) { |
253 | env->PSW_USB_V = (1 << 31); |
254 | hw0 = 0; |
255 | } |
256 | |
257 | av1 = hw1 ^ hw1 * 2u; |
258 | if (hw1 > max_pos) { |
259 | env->PSW_USB_V = (1 << 31); |
260 | hw1 = max_pos; |
261 | } else if (hw1 < 0) { |
262 | env->PSW_USB_V = (1 << 31); |
263 | hw1 = 0; |
264 | } |
265 | |
266 | env->PSW_USB_SV |= env->PSW_USB_V; |
267 | env->PSW_USB_AV = (av0 | av1) << 16; |
268 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
269 | return (hw0 & 0xffff) | (hw1 << 16); |
270 | } |
271 | |
272 | target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, |
273 | target_ulong r2) |
274 | { |
275 | int64_t t1 = sextract64(r1, 0, 32); |
276 | int64_t t2 = sextract64(r2, 0, 32); |
277 | int64_t result = t1 + t2; |
278 | return ssov32(env, result); |
279 | } |
280 | |
281 | uint64_t helper_add64_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) |
282 | { |
283 | uint64_t result; |
284 | int64_t ovf; |
285 | |
286 | result = r1 + r2; |
287 | ovf = (result ^ r1) & ~(r1 ^ r2); |
288 | env->PSW_USB_AV = (result ^ result * 2u) >> 32; |
289 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
290 | if (ovf < 0) { |
291 | env->PSW_USB_V = (1 << 31); |
292 | env->PSW_USB_SV = (1 << 31); |
293 | /* ext_ret > MAX_INT */ |
294 | if ((int64_t)r1 >= 0) { |
295 | result = INT64_MAX; |
296 | /* ext_ret < MIN_INT */ |
297 | } else { |
298 | result = INT64_MIN; |
299 | } |
300 | } else { |
301 | env->PSW_USB_V = 0; |
302 | } |
303 | return result; |
304 | } |
305 | |
306 | target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1, |
307 | target_ulong r2) |
308 | { |
309 | int32_t ret_hw0, ret_hw1; |
310 | |
311 | ret_hw0 = sextract32(r1, 0, 16) + sextract32(r2, 0, 16); |
312 | ret_hw1 = sextract32(r1, 16, 16) + sextract32(r2, 16, 16); |
313 | return ssov16(env, ret_hw0, ret_hw1); |
314 | } |
315 | |
316 | uint32_t helper_addr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, |
317 | uint32_t r2_h) |
318 | { |
319 | int64_t mul_res0 = sextract64(r1, 0, 32); |
320 | int64_t mul_res1 = sextract64(r1, 32, 32); |
321 | int64_t r2_low = sextract64(r2_l, 0, 32); |
322 | int64_t r2_high = sextract64(r2_h, 0, 32); |
323 | int64_t result0, result1; |
324 | uint32_t ovf0, ovf1; |
325 | uint32_t avf0, avf1; |
326 | |
327 | ovf0 = ovf1 = 0; |
328 | |
329 | result0 = r2_low + mul_res0 + 0x8000; |
330 | result1 = r2_high + mul_res1 + 0x8000; |
331 | |
332 | avf0 = result0 * 2u; |
333 | avf0 = result0 ^ avf0; |
334 | avf1 = result1 * 2u; |
335 | avf1 = result1 ^ avf1; |
336 | |
337 | if (result0 > INT32_MAX) { |
338 | ovf0 = (1 << 31); |
339 | result0 = INT32_MAX; |
340 | } else if (result0 < INT32_MIN) { |
341 | ovf0 = (1 << 31); |
342 | result0 = INT32_MIN; |
343 | } |
344 | |
345 | if (result1 > INT32_MAX) { |
346 | ovf1 = (1 << 31); |
347 | result1 = INT32_MAX; |
348 | } else if (result1 < INT32_MIN) { |
349 | ovf1 = (1 << 31); |
350 | result1 = INT32_MIN; |
351 | } |
352 | |
353 | env->PSW_USB_V = ovf0 | ovf1; |
354 | env->PSW_USB_SV |= env->PSW_USB_V; |
355 | |
356 | env->PSW_USB_AV = avf0 | avf1; |
357 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
358 | |
359 | return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); |
360 | } |
361 | |
362 | uint32_t helper_addsur_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, |
363 | uint32_t r2_h) |
364 | { |
365 | int64_t mul_res0 = sextract64(r1, 0, 32); |
366 | int64_t mul_res1 = sextract64(r1, 32, 32); |
367 | int64_t r2_low = sextract64(r2_l, 0, 32); |
368 | int64_t r2_high = sextract64(r2_h, 0, 32); |
369 | int64_t result0, result1; |
370 | uint32_t ovf0, ovf1; |
371 | uint32_t avf0, avf1; |
372 | |
373 | ovf0 = ovf1 = 0; |
374 | |
375 | result0 = r2_low - mul_res0 + 0x8000; |
376 | result1 = r2_high + mul_res1 + 0x8000; |
377 | |
378 | avf0 = result0 * 2u; |
379 | avf0 = result0 ^ avf0; |
380 | avf1 = result1 * 2u; |
381 | avf1 = result1 ^ avf1; |
382 | |
383 | if (result0 > INT32_MAX) { |
384 | ovf0 = (1 << 31); |
385 | result0 = INT32_MAX; |
386 | } else if (result0 < INT32_MIN) { |
387 | ovf0 = (1 << 31); |
388 | result0 = INT32_MIN; |
389 | } |
390 | |
391 | if (result1 > INT32_MAX) { |
392 | ovf1 = (1 << 31); |
393 | result1 = INT32_MAX; |
394 | } else if (result1 < INT32_MIN) { |
395 | ovf1 = (1 << 31); |
396 | result1 = INT32_MIN; |
397 | } |
398 | |
399 | env->PSW_USB_V = ovf0 | ovf1; |
400 | env->PSW_USB_SV |= env->PSW_USB_V; |
401 | |
402 | env->PSW_USB_AV = avf0 | avf1; |
403 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
404 | |
405 | return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); |
406 | } |
407 | |
408 | |
409 | target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, |
410 | target_ulong r2) |
411 | { |
412 | int64_t t1 = extract64(r1, 0, 32); |
413 | int64_t t2 = extract64(r2, 0, 32); |
414 | int64_t result = t1 + t2; |
415 | return suov32_pos(env, result); |
416 | } |
417 | |
418 | target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1, |
419 | target_ulong r2) |
420 | { |
421 | int32_t ret_hw0, ret_hw1; |
422 | |
423 | ret_hw0 = extract32(r1, 0, 16) + extract32(r2, 0, 16); |
424 | ret_hw1 = extract32(r1, 16, 16) + extract32(r2, 16, 16); |
425 | return suov16(env, ret_hw0, ret_hw1); |
426 | } |
427 | |
428 | target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, |
429 | target_ulong r2) |
430 | { |
431 | int64_t t1 = sextract64(r1, 0, 32); |
432 | int64_t t2 = sextract64(r2, 0, 32); |
433 | int64_t result = t1 - t2; |
434 | return ssov32(env, result); |
435 | } |
436 | |
437 | uint64_t helper_sub64_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) |
438 | { |
439 | uint64_t result; |
440 | int64_t ovf; |
441 | |
442 | result = r1 - r2; |
443 | ovf = (result ^ r1) & (r1 ^ r2); |
444 | env->PSW_USB_AV = (result ^ result * 2u) >> 32; |
445 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
446 | if (ovf < 0) { |
447 | env->PSW_USB_V = (1 << 31); |
448 | env->PSW_USB_SV = (1 << 31); |
449 | /* ext_ret > MAX_INT */ |
450 | if ((int64_t)r1 >= 0) { |
451 | result = INT64_MAX; |
452 | /* ext_ret < MIN_INT */ |
453 | } else { |
454 | result = INT64_MIN; |
455 | } |
456 | } else { |
457 | env->PSW_USB_V = 0; |
458 | } |
459 | return result; |
460 | } |
461 | |
462 | target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1, |
463 | target_ulong r2) |
464 | { |
465 | int32_t ret_hw0, ret_hw1; |
466 | |
467 | ret_hw0 = sextract32(r1, 0, 16) - sextract32(r2, 0, 16); |
468 | ret_hw1 = sextract32(r1, 16, 16) - sextract32(r2, 16, 16); |
469 | return ssov16(env, ret_hw0, ret_hw1); |
470 | } |
471 | |
472 | uint32_t helper_subr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, |
473 | uint32_t r2_h) |
474 | { |
475 | int64_t mul_res0 = sextract64(r1, 0, 32); |
476 | int64_t mul_res1 = sextract64(r1, 32, 32); |
477 | int64_t r2_low = sextract64(r2_l, 0, 32); |
478 | int64_t r2_high = sextract64(r2_h, 0, 32); |
479 | int64_t result0, result1; |
480 | uint32_t ovf0, ovf1; |
481 | uint32_t avf0, avf1; |
482 | |
483 | ovf0 = ovf1 = 0; |
484 | |
485 | result0 = r2_low - mul_res0 + 0x8000; |
486 | result1 = r2_high - mul_res1 + 0x8000; |
487 | |
488 | avf0 = result0 * 2u; |
489 | avf0 = result0 ^ avf0; |
490 | avf1 = result1 * 2u; |
491 | avf1 = result1 ^ avf1; |
492 | |
493 | if (result0 > INT32_MAX) { |
494 | ovf0 = (1 << 31); |
495 | result0 = INT32_MAX; |
496 | } else if (result0 < INT32_MIN) { |
497 | ovf0 = (1 << 31); |
498 | result0 = INT32_MIN; |
499 | } |
500 | |
501 | if (result1 > INT32_MAX) { |
502 | ovf1 = (1 << 31); |
503 | result1 = INT32_MAX; |
504 | } else if (result1 < INT32_MIN) { |
505 | ovf1 = (1 << 31); |
506 | result1 = INT32_MIN; |
507 | } |
508 | |
509 | env->PSW_USB_V = ovf0 | ovf1; |
510 | env->PSW_USB_SV |= env->PSW_USB_V; |
511 | |
512 | env->PSW_USB_AV = avf0 | avf1; |
513 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
514 | |
515 | return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); |
516 | } |
517 | |
518 | uint32_t helper_subadr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, |
519 | uint32_t r2_h) |
520 | { |
521 | int64_t mul_res0 = sextract64(r1, 0, 32); |
522 | int64_t mul_res1 = sextract64(r1, 32, 32); |
523 | int64_t r2_low = sextract64(r2_l, 0, 32); |
524 | int64_t r2_high = sextract64(r2_h, 0, 32); |
525 | int64_t result0, result1; |
526 | uint32_t ovf0, ovf1; |
527 | uint32_t avf0, avf1; |
528 | |
529 | ovf0 = ovf1 = 0; |
530 | |
531 | result0 = r2_low + mul_res0 + 0x8000; |
532 | result1 = r2_high - mul_res1 + 0x8000; |
533 | |
534 | avf0 = result0 * 2u; |
535 | avf0 = result0 ^ avf0; |
536 | avf1 = result1 * 2u; |
537 | avf1 = result1 ^ avf1; |
538 | |
539 | if (result0 > INT32_MAX) { |
540 | ovf0 = (1 << 31); |
541 | result0 = INT32_MAX; |
542 | } else if (result0 < INT32_MIN) { |
543 | ovf0 = (1 << 31); |
544 | result0 = INT32_MIN; |
545 | } |
546 | |
547 | if (result1 > INT32_MAX) { |
548 | ovf1 = (1 << 31); |
549 | result1 = INT32_MAX; |
550 | } else if (result1 < INT32_MIN) { |
551 | ovf1 = (1 << 31); |
552 | result1 = INT32_MIN; |
553 | } |
554 | |
555 | env->PSW_USB_V = ovf0 | ovf1; |
556 | env->PSW_USB_SV |= env->PSW_USB_V; |
557 | |
558 | env->PSW_USB_AV = avf0 | avf1; |
559 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
560 | |
561 | return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); |
562 | } |
563 | |
564 | target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, |
565 | target_ulong r2) |
566 | { |
567 | int64_t t1 = extract64(r1, 0, 32); |
568 | int64_t t2 = extract64(r2, 0, 32); |
569 | int64_t result = t1 - t2; |
570 | return suov32_neg(env, result); |
571 | } |
572 | |
573 | target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1, |
574 | target_ulong r2) |
575 | { |
576 | int32_t ret_hw0, ret_hw1; |
577 | |
578 | ret_hw0 = extract32(r1, 0, 16) - extract32(r2, 0, 16); |
579 | ret_hw1 = extract32(r1, 16, 16) - extract32(r2, 16, 16); |
580 | return suov16(env, ret_hw0, ret_hw1); |
581 | } |
582 | |
583 | target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1, |
584 | target_ulong r2) |
585 | { |
586 | int64_t t1 = sextract64(r1, 0, 32); |
587 | int64_t t2 = sextract64(r2, 0, 32); |
588 | int64_t result = t1 * t2; |
589 | return ssov32(env, result); |
590 | } |
591 | |
592 | target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1, |
593 | target_ulong r2) |
594 | { |
595 | int64_t t1 = extract64(r1, 0, 32); |
596 | int64_t t2 = extract64(r2, 0, 32); |
597 | int64_t result = t1 * t2; |
598 | |
599 | return suov32_pos(env, result); |
600 | } |
601 | |
602 | target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, |
603 | target_ulong r2) |
604 | { |
605 | int64_t t1 = sextract64(r1, 0, 32); |
606 | int32_t t2 = sextract64(r2, 0, 6); |
607 | int64_t result; |
608 | if (t2 == 0) { |
609 | result = t1; |
610 | } else if (t2 > 0) { |
611 | result = t1 << t2; |
612 | } else { |
613 | result = t1 >> -t2; |
614 | } |
615 | return ssov32(env, result); |
616 | } |
617 | |
618 | uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1) |
619 | { |
620 | target_ulong result; |
621 | result = ((int32_t)r1 >= 0) ? r1 : (0 - r1); |
622 | return ssov32(env, result); |
623 | } |
624 | |
625 | uint32_t helper_abs_h_ssov(CPUTriCoreState *env, target_ulong r1) |
626 | { |
627 | int32_t ret_h0, ret_h1; |
628 | |
629 | ret_h0 = sextract32(r1, 0, 16); |
630 | ret_h0 = (ret_h0 >= 0) ? ret_h0 : (0 - ret_h0); |
631 | |
632 | ret_h1 = sextract32(r1, 16, 16); |
633 | ret_h1 = (ret_h1 >= 0) ? ret_h1 : (0 - ret_h1); |
634 | |
635 | return ssov16(env, ret_h0, ret_h1); |
636 | } |
637 | |
638 | target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, |
639 | target_ulong r2) |
640 | { |
641 | int64_t t1 = sextract64(r1, 0, 32); |
642 | int64_t t2 = sextract64(r2, 0, 32); |
643 | int64_t result; |
644 | |
645 | if (t1 > t2) { |
646 | result = t1 - t2; |
647 | } else { |
648 | result = t2 - t1; |
649 | } |
650 | return ssov32(env, result); |
651 | } |
652 | |
653 | uint32_t helper_absdif_h_ssov(CPUTriCoreState *env, target_ulong r1, |
654 | target_ulong r2) |
655 | { |
656 | int32_t t1, t2; |
657 | int32_t ret_h0, ret_h1; |
658 | |
659 | t1 = sextract32(r1, 0, 16); |
660 | t2 = sextract32(r2, 0, 16); |
661 | if (t1 > t2) { |
662 | ret_h0 = t1 - t2; |
663 | } else { |
664 | ret_h0 = t2 - t1; |
665 | } |
666 | |
667 | t1 = sextract32(r1, 16, 16); |
668 | t2 = sextract32(r2, 16, 16); |
669 | if (t1 > t2) { |
670 | ret_h1 = t1 - t2; |
671 | } else { |
672 | ret_h1 = t2 - t1; |
673 | } |
674 | |
675 | return ssov16(env, ret_h0, ret_h1); |
676 | } |
677 | |
678 | target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1, |
679 | target_ulong r2, target_ulong r3) |
680 | { |
681 | int64_t t1 = sextract64(r1, 0, 32); |
682 | int64_t t2 = sextract64(r2, 0, 32); |
683 | int64_t t3 = sextract64(r3, 0, 32); |
684 | int64_t result; |
685 | |
686 | result = t2 + (t1 * t3); |
687 | return ssov32(env, result); |
688 | } |
689 | |
690 | target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1, |
691 | target_ulong r2, target_ulong r3) |
692 | { |
693 | uint64_t t1 = extract64(r1, 0, 32); |
694 | uint64_t t2 = extract64(r2, 0, 32); |
695 | uint64_t t3 = extract64(r3, 0, 32); |
696 | int64_t result; |
697 | |
698 | result = t2 + (t1 * t3); |
699 | return suov32_pos(env, result); |
700 | } |
701 | |
702 | uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1, |
703 | uint64_t r2, target_ulong r3) |
704 | { |
705 | uint64_t ret, ovf; |
706 | int64_t t1 = sextract64(r1, 0, 32); |
707 | int64_t t3 = sextract64(r3, 0, 32); |
708 | int64_t mul; |
709 | |
710 | mul = t1 * t3; |
711 | ret = mul + r2; |
712 | ovf = (ret ^ mul) & ~(mul ^ r2); |
713 | |
714 | t1 = ret >> 32; |
715 | env->PSW_USB_AV = t1 ^ t1 * 2u; |
716 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
717 | |
718 | if ((int64_t)ovf < 0) { |
719 | env->PSW_USB_V = (1 << 31); |
720 | env->PSW_USB_SV = (1 << 31); |
721 | /* ext_ret > MAX_INT */ |
722 | if (mul >= 0) { |
723 | ret = INT64_MAX; |
724 | /* ext_ret < MIN_INT */ |
725 | } else { |
726 | ret = INT64_MIN; |
727 | } |
728 | } else { |
729 | env->PSW_USB_V = 0; |
730 | } |
731 | |
732 | return ret; |
733 | } |
734 | |
735 | uint32_t |
736 | helper_madd32_q_add_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) |
737 | { |
738 | int64_t result; |
739 | |
740 | result = (r1 + r2); |
741 | |
742 | env->PSW_USB_AV = (result ^ result * 2u); |
743 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
744 | |
745 | /* we do the saturation by hand, since we produce an overflow on the host |
746 | if the mul before was (0x80000000 * 0x80000000) << 1). If this is the |
747 | case, we flip the saturated value. */ |
748 | if (r2 == 0x8000000000000000LL) { |
749 | if (result > 0x7fffffffLL) { |
750 | env->PSW_USB_V = (1 << 31); |
751 | env->PSW_USB_SV = (1 << 31); |
752 | result = INT32_MIN; |
753 | } else if (result < -0x80000000LL) { |
754 | env->PSW_USB_V = (1 << 31); |
755 | env->PSW_USB_SV = (1 << 31); |
756 | result = INT32_MAX; |
757 | } else { |
758 | env->PSW_USB_V = 0; |
759 | } |
760 | } else { |
761 | if (result > 0x7fffffffLL) { |
762 | env->PSW_USB_V = (1 << 31); |
763 | env->PSW_USB_SV = (1 << 31); |
764 | result = INT32_MAX; |
765 | } else if (result < -0x80000000LL) { |
766 | env->PSW_USB_V = (1 << 31); |
767 | env->PSW_USB_SV = (1 << 31); |
768 | result = INT32_MIN; |
769 | } else { |
770 | env->PSW_USB_V = 0; |
771 | } |
772 | } |
773 | return (uint32_t)result; |
774 | } |
775 | |
776 | uint64_t helper_madd64_q_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2, |
777 | uint32_t r3, uint32_t n) |
778 | { |
779 | int64_t t1 = (int64_t)r1; |
780 | int64_t t2 = sextract64(r2, 0, 32); |
781 | int64_t t3 = sextract64(r3, 0, 32); |
782 | int64_t result, mul; |
783 | int64_t ovf; |
784 | |
785 | mul = (t2 * t3) << n; |
786 | result = mul + t1; |
787 | |
788 | env->PSW_USB_AV = (result ^ result * 2u) >> 32; |
789 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
790 | |
791 | ovf = (result ^ mul) & ~(mul ^ t1); |
792 | /* we do the saturation by hand, since we produce an overflow on the host |
793 | if the mul was (0x80000000 * 0x80000000) << 1). If this is the |
794 | case, we flip the saturated value. */ |
795 | if ((r2 == 0x80000000) && (r3 == 0x80000000) && (n == 1)) { |
796 | if (ovf >= 0) { |
797 | env->PSW_USB_V = (1 << 31); |
798 | env->PSW_USB_SV = (1 << 31); |
799 | /* ext_ret > MAX_INT */ |
800 | if (mul < 0) { |
801 | result = INT64_MAX; |
802 | /* ext_ret < MIN_INT */ |
803 | } else { |
804 | result = INT64_MIN; |
805 | } |
806 | } else { |
807 | env->PSW_USB_V = 0; |
808 | } |
809 | } else { |
810 | if (ovf < 0) { |
811 | env->PSW_USB_V = (1 << 31); |
812 | env->PSW_USB_SV = (1 << 31); |
813 | /* ext_ret > MAX_INT */ |
814 | if (mul >= 0) { |
815 | result = INT64_MAX; |
816 | /* ext_ret < MIN_INT */ |
817 | } else { |
818 | result = INT64_MIN; |
819 | } |
820 | } else { |
821 | env->PSW_USB_V = 0; |
822 | } |
823 | } |
824 | return (uint64_t)result; |
825 | } |
826 | |
827 | uint32_t helper_maddr_q_ssov(CPUTriCoreState *env, uint32_t r1, uint32_t r2, |
828 | uint32_t r3, uint32_t n) |
829 | { |
830 | int64_t t1 = sextract64(r1, 0, 32); |
831 | int64_t t2 = sextract64(r2, 0, 32); |
832 | int64_t t3 = sextract64(r3, 0, 32); |
833 | int64_t mul, ret; |
834 | |
835 | if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { |
836 | mul = 0x7fffffff; |
837 | } else { |
838 | mul = (t2 * t3) << n; |
839 | } |
840 | |
841 | ret = t1 + mul + 0x8000; |
842 | |
843 | env->PSW_USB_AV = ret ^ ret * 2u; |
844 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
845 | |
846 | if (ret > 0x7fffffffll) { |
847 | env->PSW_USB_V = (1 << 31); |
848 | env->PSW_USB_SV |= env->PSW_USB_V; |
849 | ret = INT32_MAX; |
850 | } else if (ret < -0x80000000ll) { |
851 | env->PSW_USB_V = (1 << 31); |
852 | env->PSW_USB_SV |= env->PSW_USB_V; |
853 | ret = INT32_MIN; |
854 | } else { |
855 | env->PSW_USB_V = 0; |
856 | } |
857 | return ret & 0xffff0000ll; |
858 | } |
859 | |
860 | uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1, |
861 | uint64_t r2, target_ulong r3) |
862 | { |
863 | uint64_t ret, mul; |
864 | uint64_t t1 = extract64(r1, 0, 32); |
865 | uint64_t t3 = extract64(r3, 0, 32); |
866 | |
867 | mul = t1 * t3; |
868 | ret = mul + r2; |
869 | |
870 | t1 = ret >> 32; |
871 | env->PSW_USB_AV = t1 ^ t1 * 2u; |
872 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
873 | |
874 | if (ret < r2) { |
875 | env->PSW_USB_V = (1 << 31); |
876 | env->PSW_USB_SV = (1 << 31); |
877 | /* saturate */ |
878 | ret = UINT64_MAX; |
879 | } else { |
880 | env->PSW_USB_V = 0; |
881 | } |
882 | return ret; |
883 | } |
884 | |
885 | target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1, |
886 | target_ulong r2, target_ulong r3) |
887 | { |
888 | int64_t t1 = sextract64(r1, 0, 32); |
889 | int64_t t2 = sextract64(r2, 0, 32); |
890 | int64_t t3 = sextract64(r3, 0, 32); |
891 | int64_t result; |
892 | |
893 | result = t2 - (t1 * t3); |
894 | return ssov32(env, result); |
895 | } |
896 | |
897 | target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1, |
898 | target_ulong r2, target_ulong r3) |
899 | { |
900 | uint64_t t1 = extract64(r1, 0, 32); |
901 | uint64_t t2 = extract64(r2, 0, 32); |
902 | uint64_t t3 = extract64(r3, 0, 32); |
903 | uint64_t result; |
904 | uint64_t mul; |
905 | |
906 | mul = (t1 * t3); |
907 | result = t2 - mul; |
908 | |
909 | env->PSW_USB_AV = result ^ result * 2u; |
910 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
911 | /* we calculate ovf by hand here, because the multiplication can overflow on |
912 | the host, which would give false results if we compare to less than |
913 | zero */ |
914 | if (mul > t2) { |
915 | env->PSW_USB_V = (1 << 31); |
916 | env->PSW_USB_SV = (1 << 31); |
917 | result = 0; |
918 | } else { |
919 | env->PSW_USB_V = 0; |
920 | } |
921 | return result; |
922 | } |
923 | |
924 | uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1, |
925 | uint64_t r2, target_ulong r3) |
926 | { |
927 | uint64_t ret, ovf; |
928 | int64_t t1 = sextract64(r1, 0, 32); |
929 | int64_t t3 = sextract64(r3, 0, 32); |
930 | int64_t mul; |
931 | |
932 | mul = t1 * t3; |
933 | ret = r2 - mul; |
934 | ovf = (ret ^ r2) & (mul ^ r2); |
935 | |
936 | t1 = ret >> 32; |
937 | env->PSW_USB_AV = t1 ^ t1 * 2u; |
938 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
939 | |
940 | if ((int64_t)ovf < 0) { |
941 | env->PSW_USB_V = (1 << 31); |
942 | env->PSW_USB_SV = (1 << 31); |
943 | /* ext_ret > MAX_INT */ |
944 | if (mul < 0) { |
945 | ret = INT64_MAX; |
946 | /* ext_ret < MIN_INT */ |
947 | } else { |
948 | ret = INT64_MIN; |
949 | } |
950 | } else { |
951 | env->PSW_USB_V = 0; |
952 | } |
953 | return ret; |
954 | } |
955 | |
956 | uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1, |
957 | uint64_t r2, target_ulong r3) |
958 | { |
959 | uint64_t ret, mul; |
960 | uint64_t t1 = extract64(r1, 0, 32); |
961 | uint64_t t3 = extract64(r3, 0, 32); |
962 | |
963 | mul = t1 * t3; |
964 | ret = r2 - mul; |
965 | |
966 | t1 = ret >> 32; |
967 | env->PSW_USB_AV = t1 ^ t1 * 2u; |
968 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
969 | |
970 | if (ret > r2) { |
971 | env->PSW_USB_V = (1 << 31); |
972 | env->PSW_USB_SV = (1 << 31); |
973 | /* saturate */ |
974 | ret = 0; |
975 | } else { |
976 | env->PSW_USB_V = 0; |
977 | } |
978 | return ret; |
979 | } |
980 | |
981 | uint32_t |
982 | helper_msub32_q_sub_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) |
983 | { |
984 | int64_t result; |
985 | int64_t t1 = (int64_t)r1; |
986 | int64_t t2 = (int64_t)r2; |
987 | |
988 | result = t1 - t2; |
989 | |
990 | env->PSW_USB_AV = (result ^ result * 2u); |
991 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
992 | |
993 | /* we do the saturation by hand, since we produce an overflow on the host |
994 | if the mul before was (0x80000000 * 0x80000000) << 1). If this is the |
995 | case, we flip the saturated value. */ |
996 | if (r2 == 0x8000000000000000LL) { |
997 | if (result > 0x7fffffffLL) { |
998 | env->PSW_USB_V = (1 << 31); |
999 | env->PSW_USB_SV = (1 << 31); |
1000 | result = INT32_MIN; |
1001 | } else if (result < -0x80000000LL) { |
1002 | env->PSW_USB_V = (1 << 31); |
1003 | env->PSW_USB_SV = (1 << 31); |
1004 | result = INT32_MAX; |
1005 | } else { |
1006 | env->PSW_USB_V = 0; |
1007 | } |
1008 | } else { |
1009 | if (result > 0x7fffffffLL) { |
1010 | env->PSW_USB_V = (1 << 31); |
1011 | env->PSW_USB_SV = (1 << 31); |
1012 | result = INT32_MAX; |
1013 | } else if (result < -0x80000000LL) { |
1014 | env->PSW_USB_V = (1 << 31); |
1015 | env->PSW_USB_SV = (1 << 31); |
1016 | result = INT32_MIN; |
1017 | } else { |
1018 | env->PSW_USB_V = 0; |
1019 | } |
1020 | } |
1021 | return (uint32_t)result; |
1022 | } |
1023 | |
1024 | uint64_t helper_msub64_q_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2, |
1025 | uint32_t r3, uint32_t n) |
1026 | { |
1027 | int64_t t1 = (int64_t)r1; |
1028 | int64_t t2 = sextract64(r2, 0, 32); |
1029 | int64_t t3 = sextract64(r3, 0, 32); |
1030 | int64_t result, mul; |
1031 | int64_t ovf; |
1032 | |
1033 | mul = (t2 * t3) << n; |
1034 | result = t1 - mul; |
1035 | |
1036 | env->PSW_USB_AV = (result ^ result * 2u) >> 32; |
1037 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1038 | |
1039 | ovf = (result ^ t1) & (t1 ^ mul); |
1040 | /* we do the saturation by hand, since we produce an overflow on the host |
1041 | if the mul before was (0x80000000 * 0x80000000) << 1). If this is the |
1042 | case, we flip the saturated value. */ |
1043 | if (mul == 0x8000000000000000LL) { |
1044 | if (ovf >= 0) { |
1045 | env->PSW_USB_V = (1 << 31); |
1046 | env->PSW_USB_SV = (1 << 31); |
1047 | /* ext_ret > MAX_INT */ |
1048 | if (mul >= 0) { |
1049 | result = INT64_MAX; |
1050 | /* ext_ret < MIN_INT */ |
1051 | } else { |
1052 | result = INT64_MIN; |
1053 | } |
1054 | } else { |
1055 | env->PSW_USB_V = 0; |
1056 | } |
1057 | } else { |
1058 | if (ovf < 0) { |
1059 | env->PSW_USB_V = (1 << 31); |
1060 | env->PSW_USB_SV = (1 << 31); |
1061 | /* ext_ret > MAX_INT */ |
1062 | if (mul < 0) { |
1063 | result = INT64_MAX; |
1064 | /* ext_ret < MIN_INT */ |
1065 | } else { |
1066 | result = INT64_MIN; |
1067 | } |
1068 | } else { |
1069 | env->PSW_USB_V = 0; |
1070 | } |
1071 | } |
1072 | |
1073 | return (uint64_t)result; |
1074 | } |
1075 | |
1076 | uint32_t helper_msubr_q_ssov(CPUTriCoreState *env, uint32_t r1, uint32_t r2, |
1077 | uint32_t r3, uint32_t n) |
1078 | { |
1079 | int64_t t1 = sextract64(r1, 0, 32); |
1080 | int64_t t2 = sextract64(r2, 0, 32); |
1081 | int64_t t3 = sextract64(r3, 0, 32); |
1082 | int64_t mul, ret; |
1083 | |
1084 | if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { |
1085 | mul = 0x7fffffff; |
1086 | } else { |
1087 | mul = (t2 * t3) << n; |
1088 | } |
1089 | |
1090 | ret = t1 - mul + 0x8000; |
1091 | |
1092 | env->PSW_USB_AV = ret ^ ret * 2u; |
1093 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1094 | |
1095 | if (ret > 0x7fffffffll) { |
1096 | env->PSW_USB_V = (1 << 31); |
1097 | env->PSW_USB_SV |= env->PSW_USB_V; |
1098 | ret = INT32_MAX; |
1099 | } else if (ret < -0x80000000ll) { |
1100 | env->PSW_USB_V = (1 << 31); |
1101 | env->PSW_USB_SV |= env->PSW_USB_V; |
1102 | ret = INT32_MIN; |
1103 | } else { |
1104 | env->PSW_USB_V = 0; |
1105 | } |
1106 | return ret & 0xffff0000ll; |
1107 | } |
1108 | |
1109 | uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg) |
1110 | { |
1111 | int32_t b, i; |
1112 | int32_t ovf = 0; |
1113 | int32_t avf = 0; |
1114 | int32_t ret = 0; |
1115 | |
1116 | for (i = 0; i < 4; i++) { |
1117 | b = sextract32(arg, i * 8, 8); |
1118 | b = (b >= 0) ? b : (0 - b); |
1119 | ovf |= (b > 0x7F) || (b < -0x80); |
1120 | avf |= b ^ b * 2u; |
1121 | ret |= (b & 0xff) << (i * 8); |
1122 | } |
1123 | |
1124 | env->PSW_USB_V = ovf << 31; |
1125 | env->PSW_USB_SV |= env->PSW_USB_V; |
1126 | env->PSW_USB_AV = avf << 24; |
1127 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1128 | |
1129 | return ret; |
1130 | } |
1131 | |
1132 | uint32_t helper_abs_h(CPUTriCoreState *env, target_ulong arg) |
1133 | { |
1134 | int32_t h, i; |
1135 | int32_t ovf = 0; |
1136 | int32_t avf = 0; |
1137 | int32_t ret = 0; |
1138 | |
1139 | for (i = 0; i < 2; i++) { |
1140 | h = sextract32(arg, i * 16, 16); |
1141 | h = (h >= 0) ? h : (0 - h); |
1142 | ovf |= (h > 0x7FFF) || (h < -0x8000); |
1143 | avf |= h ^ h * 2u; |
1144 | ret |= (h & 0xffff) << (i * 16); |
1145 | } |
1146 | |
1147 | env->PSW_USB_V = ovf << 31; |
1148 | env->PSW_USB_SV |= env->PSW_USB_V; |
1149 | env->PSW_USB_AV = avf << 16; |
1150 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1151 | |
1152 | return ret; |
1153 | } |
1154 | |
1155 | uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) |
1156 | { |
1157 | int32_t b, i; |
1158 | int32_t extr_r2; |
1159 | int32_t ovf = 0; |
1160 | int32_t avf = 0; |
1161 | int32_t ret = 0; |
1162 | |
1163 | for (i = 0; i < 4; i++) { |
1164 | extr_r2 = sextract32(r2, i * 8, 8); |
1165 | b = sextract32(r1, i * 8, 8); |
1166 | b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b); |
1167 | ovf |= (b > 0x7F) || (b < -0x80); |
1168 | avf |= b ^ b * 2u; |
1169 | ret |= (b & 0xff) << (i * 8); |
1170 | } |
1171 | |
1172 | env->PSW_USB_V = ovf << 31; |
1173 | env->PSW_USB_SV |= env->PSW_USB_V; |
1174 | env->PSW_USB_AV = avf << 24; |
1175 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1176 | return ret; |
1177 | } |
1178 | |
1179 | uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) |
1180 | { |
1181 | int32_t h, i; |
1182 | int32_t extr_r2; |
1183 | int32_t ovf = 0; |
1184 | int32_t avf = 0; |
1185 | int32_t ret = 0; |
1186 | |
1187 | for (i = 0; i < 2; i++) { |
1188 | extr_r2 = sextract32(r2, i * 16, 16); |
1189 | h = sextract32(r1, i * 16, 16); |
1190 | h = (h > extr_r2) ? (h - extr_r2) : (extr_r2 - h); |
1191 | ovf |= (h > 0x7FFF) || (h < -0x8000); |
1192 | avf |= h ^ h * 2u; |
1193 | ret |= (h & 0xffff) << (i * 16); |
1194 | } |
1195 | |
1196 | env->PSW_USB_V = ovf << 31; |
1197 | env->PSW_USB_SV |= env->PSW_USB_V; |
1198 | env->PSW_USB_AV = avf << 16; |
1199 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1200 | |
1201 | return ret; |
1202 | } |
1203 | |
1204 | uint32_t helper_addr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, |
1205 | uint32_t r2_h) |
1206 | { |
1207 | int64_t mul_res0 = sextract64(r1, 0, 32); |
1208 | int64_t mul_res1 = sextract64(r1, 32, 32); |
1209 | int64_t r2_low = sextract64(r2_l, 0, 32); |
1210 | int64_t r2_high = sextract64(r2_h, 0, 32); |
1211 | int64_t result0, result1; |
1212 | uint32_t ovf0, ovf1; |
1213 | uint32_t avf0, avf1; |
1214 | |
1215 | ovf0 = ovf1 = 0; |
1216 | |
1217 | result0 = r2_low + mul_res0 + 0x8000; |
1218 | result1 = r2_high + mul_res1 + 0x8000; |
1219 | |
1220 | if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { |
1221 | ovf0 = (1 << 31); |
1222 | } |
1223 | |
1224 | if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { |
1225 | ovf1 = (1 << 31); |
1226 | } |
1227 | |
1228 | env->PSW_USB_V = ovf0 | ovf1; |
1229 | env->PSW_USB_SV |= env->PSW_USB_V; |
1230 | |
1231 | avf0 = result0 * 2u; |
1232 | avf0 = result0 ^ avf0; |
1233 | avf1 = result1 * 2u; |
1234 | avf1 = result1 ^ avf1; |
1235 | |
1236 | env->PSW_USB_AV = avf0 | avf1; |
1237 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1238 | |
1239 | return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); |
1240 | } |
1241 | |
1242 | uint32_t helper_addsur_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, |
1243 | uint32_t r2_h) |
1244 | { |
1245 | int64_t mul_res0 = sextract64(r1, 0, 32); |
1246 | int64_t mul_res1 = sextract64(r1, 32, 32); |
1247 | int64_t r2_low = sextract64(r2_l, 0, 32); |
1248 | int64_t r2_high = sextract64(r2_h, 0, 32); |
1249 | int64_t result0, result1; |
1250 | uint32_t ovf0, ovf1; |
1251 | uint32_t avf0, avf1; |
1252 | |
1253 | ovf0 = ovf1 = 0; |
1254 | |
1255 | result0 = r2_low - mul_res0 + 0x8000; |
1256 | result1 = r2_high + mul_res1 + 0x8000; |
1257 | |
1258 | if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { |
1259 | ovf0 = (1 << 31); |
1260 | } |
1261 | |
1262 | if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { |
1263 | ovf1 = (1 << 31); |
1264 | } |
1265 | |
1266 | env->PSW_USB_V = ovf0 | ovf1; |
1267 | env->PSW_USB_SV |= env->PSW_USB_V; |
1268 | |
1269 | avf0 = result0 * 2u; |
1270 | avf0 = result0 ^ avf0; |
1271 | avf1 = result1 * 2u; |
1272 | avf1 = result1 ^ avf1; |
1273 | |
1274 | env->PSW_USB_AV = avf0 | avf1; |
1275 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1276 | |
1277 | return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); |
1278 | } |
1279 | |
1280 | uint32_t helper_maddr_q(CPUTriCoreState *env, uint32_t r1, uint32_t r2, |
1281 | uint32_t r3, uint32_t n) |
1282 | { |
1283 | int64_t t1 = sextract64(r1, 0, 32); |
1284 | int64_t t2 = sextract64(r2, 0, 32); |
1285 | int64_t t3 = sextract64(r3, 0, 32); |
1286 | int64_t mul, ret; |
1287 | |
1288 | if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { |
1289 | mul = 0x7fffffff; |
1290 | } else { |
1291 | mul = (t2 * t3) << n; |
1292 | } |
1293 | |
1294 | ret = t1 + mul + 0x8000; |
1295 | |
1296 | if ((ret > 0x7fffffffll) || (ret < -0x80000000ll)) { |
1297 | env->PSW_USB_V = (1 << 31); |
1298 | env->PSW_USB_SV |= env->PSW_USB_V; |
1299 | } else { |
1300 | env->PSW_USB_V = 0; |
1301 | } |
1302 | env->PSW_USB_AV = ret ^ ret * 2u; |
1303 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1304 | |
1305 | return ret & 0xffff0000ll; |
1306 | } |
1307 | |
1308 | uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) |
1309 | { |
1310 | int32_t b, i; |
1311 | int32_t extr_r1, extr_r2; |
1312 | int32_t ovf = 0; |
1313 | int32_t avf = 0; |
1314 | uint32_t ret = 0; |
1315 | |
1316 | for (i = 0; i < 4; i++) { |
1317 | extr_r1 = sextract32(r1, i * 8, 8); |
1318 | extr_r2 = sextract32(r2, i * 8, 8); |
1319 | |
1320 | b = extr_r1 + extr_r2; |
1321 | ovf |= ((b > 0x7f) || (b < -0x80)); |
1322 | avf |= b ^ b * 2u; |
1323 | ret |= ((b & 0xff) << (i*8)); |
1324 | } |
1325 | |
1326 | env->PSW_USB_V = (ovf << 31); |
1327 | env->PSW_USB_SV |= env->PSW_USB_V; |
1328 | env->PSW_USB_AV = avf << 24; |
1329 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1330 | |
1331 | return ret; |
1332 | } |
1333 | |
1334 | uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) |
1335 | { |
1336 | int32_t h, i; |
1337 | int32_t extr_r1, extr_r2; |
1338 | int32_t ovf = 0; |
1339 | int32_t avf = 0; |
1340 | int32_t ret = 0; |
1341 | |
1342 | for (i = 0; i < 2; i++) { |
1343 | extr_r1 = sextract32(r1, i * 16, 16); |
1344 | extr_r2 = sextract32(r2, i * 16, 16); |
1345 | h = extr_r1 + extr_r2; |
1346 | ovf |= ((h > 0x7fff) || (h < -0x8000)); |
1347 | avf |= h ^ h * 2u; |
1348 | ret |= (h & 0xffff) << (i * 16); |
1349 | } |
1350 | |
1351 | env->PSW_USB_V = (ovf << 31); |
1352 | env->PSW_USB_SV |= env->PSW_USB_V; |
1353 | env->PSW_USB_AV = (avf << 16); |
1354 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1355 | |
1356 | return ret; |
1357 | } |
1358 | |
1359 | uint32_t helper_subr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, |
1360 | uint32_t r2_h) |
1361 | { |
1362 | int64_t mul_res0 = sextract64(r1, 0, 32); |
1363 | int64_t mul_res1 = sextract64(r1, 32, 32); |
1364 | int64_t r2_low = sextract64(r2_l, 0, 32); |
1365 | int64_t r2_high = sextract64(r2_h, 0, 32); |
1366 | int64_t result0, result1; |
1367 | uint32_t ovf0, ovf1; |
1368 | uint32_t avf0, avf1; |
1369 | |
1370 | ovf0 = ovf1 = 0; |
1371 | |
1372 | result0 = r2_low - mul_res0 + 0x8000; |
1373 | result1 = r2_high - mul_res1 + 0x8000; |
1374 | |
1375 | if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { |
1376 | ovf0 = (1 << 31); |
1377 | } |
1378 | |
1379 | if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { |
1380 | ovf1 = (1 << 31); |
1381 | } |
1382 | |
1383 | env->PSW_USB_V = ovf0 | ovf1; |
1384 | env->PSW_USB_SV |= env->PSW_USB_V; |
1385 | |
1386 | avf0 = result0 * 2u; |
1387 | avf0 = result0 ^ avf0; |
1388 | avf1 = result1 * 2u; |
1389 | avf1 = result1 ^ avf1; |
1390 | |
1391 | env->PSW_USB_AV = avf0 | avf1; |
1392 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1393 | |
1394 | return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); |
1395 | } |
1396 | |
1397 | uint32_t helper_subadr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, |
1398 | uint32_t r2_h) |
1399 | { |
1400 | int64_t mul_res0 = sextract64(r1, 0, 32); |
1401 | int64_t mul_res1 = sextract64(r1, 32, 32); |
1402 | int64_t r2_low = sextract64(r2_l, 0, 32); |
1403 | int64_t r2_high = sextract64(r2_h, 0, 32); |
1404 | int64_t result0, result1; |
1405 | uint32_t ovf0, ovf1; |
1406 | uint32_t avf0, avf1; |
1407 | |
1408 | ovf0 = ovf1 = 0; |
1409 | |
1410 | result0 = r2_low + mul_res0 + 0x8000; |
1411 | result1 = r2_high - mul_res1 + 0x8000; |
1412 | |
1413 | if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { |
1414 | ovf0 = (1 << 31); |
1415 | } |
1416 | |
1417 | if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { |
1418 | ovf1 = (1 << 31); |
1419 | } |
1420 | |
1421 | env->PSW_USB_V = ovf0 | ovf1; |
1422 | env->PSW_USB_SV |= env->PSW_USB_V; |
1423 | |
1424 | avf0 = result0 * 2u; |
1425 | avf0 = result0 ^ avf0; |
1426 | avf1 = result1 * 2u; |
1427 | avf1 = result1 ^ avf1; |
1428 | |
1429 | env->PSW_USB_AV = avf0 | avf1; |
1430 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1431 | |
1432 | return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); |
1433 | } |
1434 | |
1435 | uint32_t helper_msubr_q(CPUTriCoreState *env, uint32_t r1, uint32_t r2, |
1436 | uint32_t r3, uint32_t n) |
1437 | { |
1438 | int64_t t1 = sextract64(r1, 0, 32); |
1439 | int64_t t2 = sextract64(r2, 0, 32); |
1440 | int64_t t3 = sextract64(r3, 0, 32); |
1441 | int64_t mul, ret; |
1442 | |
1443 | if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { |
1444 | mul = 0x7fffffff; |
1445 | } else { |
1446 | mul = (t2 * t3) << n; |
1447 | } |
1448 | |
1449 | ret = t1 - mul + 0x8000; |
1450 | |
1451 | if ((ret > 0x7fffffffll) || (ret < -0x80000000ll)) { |
1452 | env->PSW_USB_V = (1 << 31); |
1453 | env->PSW_USB_SV |= env->PSW_USB_V; |
1454 | } else { |
1455 | env->PSW_USB_V = 0; |
1456 | } |
1457 | env->PSW_USB_AV = ret ^ ret * 2u; |
1458 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1459 | |
1460 | return ret & 0xffff0000ll; |
1461 | } |
1462 | |
1463 | uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) |
1464 | { |
1465 | int32_t b, i; |
1466 | int32_t extr_r1, extr_r2; |
1467 | int32_t ovf = 0; |
1468 | int32_t avf = 0; |
1469 | uint32_t ret = 0; |
1470 | |
1471 | for (i = 0; i < 4; i++) { |
1472 | extr_r1 = sextract32(r1, i * 8, 8); |
1473 | extr_r2 = sextract32(r2, i * 8, 8); |
1474 | |
1475 | b = extr_r1 - extr_r2; |
1476 | ovf |= ((b > 0x7f) || (b < -0x80)); |
1477 | avf |= b ^ b * 2u; |
1478 | ret |= ((b & 0xff) << (i*8)); |
1479 | } |
1480 | |
1481 | env->PSW_USB_V = (ovf << 31); |
1482 | env->PSW_USB_SV |= env->PSW_USB_V; |
1483 | env->PSW_USB_AV = avf << 24; |
1484 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1485 | |
1486 | return ret; |
1487 | } |
1488 | |
1489 | uint32_t helper_sub_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) |
1490 | { |
1491 | int32_t h, i; |
1492 | int32_t extr_r1, extr_r2; |
1493 | int32_t ovf = 0; |
1494 | int32_t avf = 0; |
1495 | int32_t ret = 0; |
1496 | |
1497 | for (i = 0; i < 2; i++) { |
1498 | extr_r1 = sextract32(r1, i * 16, 16); |
1499 | extr_r2 = sextract32(r2, i * 16, 16); |
1500 | h = extr_r1 - extr_r2; |
1501 | ovf |= ((h > 0x7fff) || (h < -0x8000)); |
1502 | avf |= h ^ h * 2u; |
1503 | ret |= (h & 0xffff) << (i * 16); |
1504 | } |
1505 | |
1506 | env->PSW_USB_V = (ovf << 31); |
1507 | env->PSW_USB_SV |= env->PSW_USB_V; |
1508 | env->PSW_USB_AV = avf << 16; |
1509 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1510 | |
1511 | return ret; |
1512 | } |
1513 | |
1514 | uint32_t helper_eq_b(target_ulong r1, target_ulong r2) |
1515 | { |
1516 | int32_t ret; |
1517 | int32_t i, msk; |
1518 | |
1519 | ret = 0; |
1520 | msk = 0xff; |
1521 | for (i = 0; i < 4; i++) { |
1522 | if ((r1 & msk) == (r2 & msk)) { |
1523 | ret |= msk; |
1524 | } |
1525 | msk = msk << 8; |
1526 | } |
1527 | |
1528 | return ret; |
1529 | } |
1530 | |
1531 | uint32_t helper_eq_h(target_ulong r1, target_ulong r2) |
1532 | { |
1533 | int32_t ret = 0; |
1534 | |
1535 | if ((r1 & 0xffff) == (r2 & 0xffff)) { |
1536 | ret = 0xffff; |
1537 | } |
1538 | |
1539 | if ((r1 & 0xffff0000) == (r2 & 0xffff0000)) { |
1540 | ret |= 0xffff0000; |
1541 | } |
1542 | |
1543 | return ret; |
1544 | } |
1545 | |
1546 | uint32_t helper_eqany_b(target_ulong r1, target_ulong r2) |
1547 | { |
1548 | int32_t i; |
1549 | uint32_t ret = 0; |
1550 | |
1551 | for (i = 0; i < 4; i++) { |
1552 | ret |= (sextract32(r1, i * 8, 8) == sextract32(r2, i * 8, 8)); |
1553 | } |
1554 | |
1555 | return ret; |
1556 | } |
1557 | |
1558 | uint32_t helper_eqany_h(target_ulong r1, target_ulong r2) |
1559 | { |
1560 | uint32_t ret; |
1561 | |
1562 | ret = (sextract32(r1, 0, 16) == sextract32(r2, 0, 16)); |
1563 | ret |= (sextract32(r1, 16, 16) == sextract32(r2, 16, 16)); |
1564 | |
1565 | return ret; |
1566 | } |
1567 | |
1568 | uint32_t helper_lt_b(target_ulong r1, target_ulong r2) |
1569 | { |
1570 | int32_t i; |
1571 | uint32_t ret = 0; |
1572 | |
1573 | for (i = 0; i < 4; i++) { |
1574 | if (sextract32(r1, i * 8, 8) < sextract32(r2, i * 8, 8)) { |
1575 | ret |= (0xff << (i * 8)); |
1576 | } |
1577 | } |
1578 | |
1579 | return ret; |
1580 | } |
1581 | |
1582 | uint32_t helper_lt_bu(target_ulong r1, target_ulong r2) |
1583 | { |
1584 | int32_t i; |
1585 | uint32_t ret = 0; |
1586 | |
1587 | for (i = 0; i < 4; i++) { |
1588 | if (extract32(r1, i * 8, 8) < extract32(r2, i * 8, 8)) { |
1589 | ret |= (0xff << (i * 8)); |
1590 | } |
1591 | } |
1592 | |
1593 | return ret; |
1594 | } |
1595 | |
1596 | uint32_t helper_lt_h(target_ulong r1, target_ulong r2) |
1597 | { |
1598 | uint32_t ret = 0; |
1599 | |
1600 | if (sextract32(r1, 0, 16) < sextract32(r2, 0, 16)) { |
1601 | ret |= 0xffff; |
1602 | } |
1603 | |
1604 | if (sextract32(r1, 16, 16) < sextract32(r2, 16, 16)) { |
1605 | ret |= 0xffff0000; |
1606 | } |
1607 | |
1608 | return ret; |
1609 | } |
1610 | |
1611 | uint32_t helper_lt_hu(target_ulong r1, target_ulong r2) |
1612 | { |
1613 | uint32_t ret = 0; |
1614 | |
1615 | if (extract32(r1, 0, 16) < extract32(r2, 0, 16)) { |
1616 | ret |= 0xffff; |
1617 | } |
1618 | |
1619 | if (extract32(r1, 16, 16) < extract32(r2, 16, 16)) { |
1620 | ret |= 0xffff0000; |
1621 | } |
1622 | |
1623 | return ret; |
1624 | } |
1625 | |
1626 | #define EXTREMA_H_B(name, op) \ |
1627 | uint32_t helper_##name ##_b(target_ulong r1, target_ulong r2) \ |
1628 | { \ |
1629 | int32_t i, extr_r1, extr_r2; \ |
1630 | uint32_t ret = 0; \ |
1631 | \ |
1632 | for (i = 0; i < 4; i++) { \ |
1633 | extr_r1 = sextract32(r1, i * 8, 8); \ |
1634 | extr_r2 = sextract32(r2, i * 8, 8); \ |
1635 | extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ |
1636 | ret |= (extr_r1 & 0xff) << (i * 8); \ |
1637 | } \ |
1638 | return ret; \ |
1639 | } \ |
1640 | \ |
1641 | uint32_t helper_##name ##_bu(target_ulong r1, target_ulong r2)\ |
1642 | { \ |
1643 | int32_t i; \ |
1644 | uint32_t extr_r1, extr_r2; \ |
1645 | uint32_t ret = 0; \ |
1646 | \ |
1647 | for (i = 0; i < 4; i++) { \ |
1648 | extr_r1 = extract32(r1, i * 8, 8); \ |
1649 | extr_r2 = extract32(r2, i * 8, 8); \ |
1650 | extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ |
1651 | ret |= (extr_r1 & 0xff) << (i * 8); \ |
1652 | } \ |
1653 | return ret; \ |
1654 | } \ |
1655 | \ |
1656 | uint32_t helper_##name ##_h(target_ulong r1, target_ulong r2) \ |
1657 | { \ |
1658 | int32_t extr_r1, extr_r2; \ |
1659 | uint32_t ret = 0; \ |
1660 | \ |
1661 | extr_r1 = sextract32(r1, 0, 16); \ |
1662 | extr_r2 = sextract32(r2, 0, 16); \ |
1663 | ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ |
1664 | ret = ret & 0xffff; \ |
1665 | \ |
1666 | extr_r1 = sextract32(r1, 16, 16); \ |
1667 | extr_r2 = sextract32(r2, 16, 16); \ |
1668 | extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ |
1669 | ret |= extr_r1 << 16; \ |
1670 | \ |
1671 | return ret; \ |
1672 | } \ |
1673 | \ |
1674 | uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\ |
1675 | { \ |
1676 | uint32_t extr_r1, extr_r2; \ |
1677 | uint32_t ret = 0; \ |
1678 | \ |
1679 | extr_r1 = extract32(r1, 0, 16); \ |
1680 | extr_r2 = extract32(r2, 0, 16); \ |
1681 | ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ |
1682 | ret = ret & 0xffff; \ |
1683 | \ |
1684 | extr_r1 = extract32(r1, 16, 16); \ |
1685 | extr_r2 = extract32(r2, 16, 16); \ |
1686 | extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ |
1687 | ret |= extr_r1 << (16); \ |
1688 | \ |
1689 | return ret; \ |
1690 | } \ |
1691 | \ |
1692 | uint64_t helper_ix##name(uint64_t r1, uint32_t r2) \ |
1693 | { \ |
1694 | int64_t r2l, r2h, r1hl; \ |
1695 | uint64_t ret = 0; \ |
1696 | \ |
1697 | ret = ((r1 + 2) & 0xffff); \ |
1698 | r2l = sextract64(r2, 0, 16); \ |
1699 | r2h = sextract64(r2, 16, 16); \ |
1700 | r1hl = sextract64(r1, 32, 16); \ |
1701 | \ |
1702 | if ((r2l op ## = r2h) && (r2l op r1hl)) { \ |
1703 | ret |= (r2l & 0xffff) << 32; \ |
1704 | ret |= extract64(r1, 0, 16) << 16; \ |
1705 | } else if ((r2h op r2l) && (r2h op r1hl)) { \ |
1706 | ret |= extract64(r2, 16, 16) << 32; \ |
1707 | ret |= extract64(r1 + 1, 0, 16) << 16; \ |
1708 | } else { \ |
1709 | ret |= r1 & 0xffffffff0000ull; \ |
1710 | } \ |
1711 | return ret; \ |
1712 | } \ |
1713 | \ |
1714 | uint64_t helper_ix##name ##_u(uint64_t r1, uint32_t r2) \ |
1715 | { \ |
1716 | int64_t r2l, r2h, r1hl; \ |
1717 | uint64_t ret = 0; \ |
1718 | \ |
1719 | ret = ((r1 + 2) & 0xffff); \ |
1720 | r2l = extract64(r2, 0, 16); \ |
1721 | r2h = extract64(r2, 16, 16); \ |
1722 | r1hl = extract64(r1, 32, 16); \ |
1723 | \ |
1724 | if ((r2l op ## = r2h) && (r2l op r1hl)) { \ |
1725 | ret |= (r2l & 0xffff) << 32; \ |
1726 | ret |= extract64(r1, 0, 16) << 16; \ |
1727 | } else if ((r2h op r2l) && (r2h op r1hl)) { \ |
1728 | ret |= extract64(r2, 16, 16) << 32; \ |
1729 | ret |= extract64(r1 + 1, 0, 16) << 16; \ |
1730 | } else { \ |
1731 | ret |= r1 & 0xffffffff0000ull; \ |
1732 | } \ |
1733 | return ret; \ |
1734 | } |
1735 | |
1736 | EXTREMA_H_B(max, >) |
1737 | EXTREMA_H_B(min, <) |
1738 | |
1739 | #undef EXTREMA_H_B |
1740 | |
1741 | uint32_t helper_clo_h(target_ulong r1) |
1742 | { |
1743 | uint32_t ret_hw0 = extract32(r1, 0, 16); |
1744 | uint32_t ret_hw1 = extract32(r1, 16, 16); |
1745 | |
1746 | ret_hw0 = clo32(ret_hw0 << 16); |
1747 | ret_hw1 = clo32(ret_hw1 << 16); |
1748 | |
1749 | if (ret_hw0 > 16) { |
1750 | ret_hw0 = 16; |
1751 | } |
1752 | if (ret_hw1 > 16) { |
1753 | ret_hw1 = 16; |
1754 | } |
1755 | |
1756 | return ret_hw0 | (ret_hw1 << 16); |
1757 | } |
1758 | |
1759 | uint32_t helper_clz_h(target_ulong r1) |
1760 | { |
1761 | uint32_t ret_hw0 = extract32(r1, 0, 16); |
1762 | uint32_t ret_hw1 = extract32(r1, 16, 16); |
1763 | |
1764 | ret_hw0 = clz32(ret_hw0 << 16); |
1765 | ret_hw1 = clz32(ret_hw1 << 16); |
1766 | |
1767 | if (ret_hw0 > 16) { |
1768 | ret_hw0 = 16; |
1769 | } |
1770 | if (ret_hw1 > 16) { |
1771 | ret_hw1 = 16; |
1772 | } |
1773 | |
1774 | return ret_hw0 | (ret_hw1 << 16); |
1775 | } |
1776 | |
1777 | uint32_t helper_cls_h(target_ulong r1) |
1778 | { |
1779 | uint32_t ret_hw0 = extract32(r1, 0, 16); |
1780 | uint32_t ret_hw1 = extract32(r1, 16, 16); |
1781 | |
1782 | ret_hw0 = clrsb32(ret_hw0 << 16); |
1783 | ret_hw1 = clrsb32(ret_hw1 << 16); |
1784 | |
1785 | if (ret_hw0 > 15) { |
1786 | ret_hw0 = 15; |
1787 | } |
1788 | if (ret_hw1 > 15) { |
1789 | ret_hw1 = 15; |
1790 | } |
1791 | |
1792 | return ret_hw0 | (ret_hw1 << 16); |
1793 | } |
1794 | |
1795 | uint32_t helper_sh(target_ulong r1, target_ulong r2) |
1796 | { |
1797 | int32_t shift_count = sextract32(r2, 0, 6); |
1798 | |
1799 | if (shift_count == -32) { |
1800 | return 0; |
1801 | } else if (shift_count < 0) { |
1802 | return r1 >> -shift_count; |
1803 | } else { |
1804 | return r1 << shift_count; |
1805 | } |
1806 | } |
1807 | |
1808 | uint32_t helper_sh_h(target_ulong r1, target_ulong r2) |
1809 | { |
1810 | int32_t ret_hw0, ret_hw1; |
1811 | int32_t shift_count; |
1812 | |
1813 | shift_count = sextract32(r2, 0, 5); |
1814 | |
1815 | if (shift_count == -16) { |
1816 | return 0; |
1817 | } else if (shift_count < 0) { |
1818 | ret_hw0 = extract32(r1, 0, 16) >> -shift_count; |
1819 | ret_hw1 = extract32(r1, 16, 16) >> -shift_count; |
1820 | return (ret_hw0 & 0xffff) | (ret_hw1 << 16); |
1821 | } else { |
1822 | ret_hw0 = extract32(r1, 0, 16) << shift_count; |
1823 | ret_hw1 = extract32(r1, 16, 16) << shift_count; |
1824 | return (ret_hw0 & 0xffff) | (ret_hw1 << 16); |
1825 | } |
1826 | } |
1827 | |
1828 | uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2) |
1829 | { |
1830 | int32_t shift_count; |
1831 | int64_t result, t1; |
1832 | uint32_t ret; |
1833 | |
1834 | shift_count = sextract32(r2, 0, 6); |
1835 | t1 = sextract32(r1, 0, 32); |
1836 | |
1837 | if (shift_count == 0) { |
1838 | env->PSW_USB_C = env->PSW_USB_V = 0; |
1839 | ret = r1; |
1840 | } else if (shift_count == -32) { |
1841 | env->PSW_USB_C = r1; |
1842 | env->PSW_USB_V = 0; |
1843 | ret = t1 >> 31; |
1844 | } else if (shift_count > 0) { |
1845 | result = t1 << shift_count; |
1846 | /* calc carry */ |
1847 | env->PSW_USB_C = ((result & 0xffffffff00000000ULL) != 0); |
1848 | /* calc v */ |
1849 | env->PSW_USB_V = (((result > 0x7fffffffLL) || |
1850 | (result < -0x80000000LL)) << 31); |
1851 | /* calc sv */ |
1852 | env->PSW_USB_SV |= env->PSW_USB_V; |
1853 | ret = (uint32_t)result; |
1854 | } else { |
1855 | env->PSW_USB_V = 0; |
1856 | env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1)); |
1857 | ret = t1 >> -shift_count; |
1858 | } |
1859 | |
1860 | env->PSW_USB_AV = ret ^ ret * 2u; |
1861 | env->PSW_USB_SAV |= env->PSW_USB_AV; |
1862 | |
1863 | return ret; |
1864 | } |
1865 | |
1866 | uint32_t helper_sha_h(target_ulong r1, target_ulong r2) |
1867 | { |
1868 | int32_t shift_count; |
1869 | int32_t ret_hw0, ret_hw1; |
1870 | |
1871 | shift_count = sextract32(r2, 0, 5); |
1872 | |
1873 | if (shift_count == 0) { |
1874 | return r1; |
1875 | } else if (shift_count < 0) { |
1876 | ret_hw0 = sextract32(r1, 0, 16) >> -shift_count; |
1877 | ret_hw1 = sextract32(r1, 16, 16) >> -shift_count; |
1878 | return (ret_hw0 & 0xffff) | (ret_hw1 << 16); |
1879 | } else { |
1880 | ret_hw0 = sextract32(r1, 0, 16) << shift_count; |
1881 | ret_hw1 = sextract32(r1, 16, 16) << shift_count; |
1882 | return (ret_hw0 & 0xffff) | (ret_hw1 << 16); |
1883 | } |
1884 | } |
1885 | |
1886 | uint32_t helper_bmerge(target_ulong r1, target_ulong r2) |
1887 | { |
1888 | uint32_t i, ret; |
1889 | |
1890 | ret = 0; |
1891 | for (i = 0; i < 16; i++) { |
1892 | ret |= (r1 & 1) << (2 * i + 1); |
1893 | ret |= (r2 & 1) << (2 * i); |
1894 | r1 = r1 >> 1; |
1895 | r2 = r2 >> 1; |
1896 | } |
1897 | return ret; |
1898 | } |
1899 | |
1900 | uint64_t helper_bsplit(uint32_t r1) |
1901 | { |
1902 | int32_t i; |
1903 | uint64_t ret; |
1904 | |
1905 | ret = 0; |
1906 | for (i = 0; i < 32; i = i + 2) { |
1907 | /* even */ |
1908 | ret |= (r1 & 1) << (i/2); |
1909 | r1 = r1 >> 1; |
1910 | /* odd */ |
1911 | ret |= (uint64_t)(r1 & 1) << (i/2 + 32); |
1912 | r1 = r1 >> 1; |
1913 | } |
1914 | return ret; |
1915 | } |
1916 | |
1917 | uint32_t helper_parity(target_ulong r1) |
1918 | { |
1919 | uint32_t ret; |
1920 | uint32_t nOnes, i; |
1921 | |
1922 | ret = 0; |
1923 | nOnes = 0; |
1924 | for (i = 0; i < 8; i++) { |
1925 | ret ^= (r1 & 1); |
1926 | r1 = r1 >> 1; |
1927 | } |
1928 | /* second byte */ |
1929 | nOnes = 0; |
1930 | for (i = 0; i < 8; i++) { |
1931 | nOnes ^= (r1 & 1); |
1932 | r1 = r1 >> 1; |
1933 | } |
1934 | ret |= nOnes << 8; |
1935 | /* third byte */ |
1936 | nOnes = 0; |
1937 | for (i = 0; i < 8; i++) { |
1938 | nOnes ^= (r1 & 1); |
1939 | r1 = r1 >> 1; |
1940 | } |
1941 | ret |= nOnes << 16; |
1942 | /* fourth byte */ |
1943 | nOnes = 0; |
1944 | for (i = 0; i < 8; i++) { |
1945 | nOnes ^= (r1 & 1); |
1946 | r1 = r1 >> 1; |
1947 | } |
1948 | ret |= nOnes << 24; |
1949 | |
1950 | return ret; |
1951 | } |
1952 | |
1953 | uint32_t helper_pack(uint32_t carry, uint32_t r1_low, uint32_t r1_high, |
1954 | target_ulong r2) |
1955 | { |
1956 | uint32_t ret; |
1957 | int32_t fp_exp, fp_frac, temp_exp, fp_exp_frac; |
1958 | int32_t int_exp = r1_high; |
1959 | int32_t int_mant = r1_low; |
1960 | uint32_t flag_rnd = (int_mant & (1 << 7)) && ( |
1961 | (int_mant & (1 << 8)) || |
1962 | (int_mant & 0x7f) || |
1963 | (carry != 0)); |
1964 | if (((int_mant & (1<<31)) == 0) && (int_exp == 255)) { |
1965 | fp_exp = 255; |
1966 | fp_frac = extract32(int_mant, 8, 23); |
1967 | } else if ((int_mant & (1<<31)) && (int_exp >= 127)) { |
1968 | fp_exp = 255; |
1969 | fp_frac = 0; |
1970 | } else if ((int_mant & (1<<31)) && (int_exp <= -128)) { |
1971 | fp_exp = 0; |
1972 | fp_frac = 0; |
1973 | } else if (int_mant == 0) { |
1974 | fp_exp = 0; |
1975 | fp_frac = 0; |
1976 | } else { |
1977 | if (((int_mant & (1 << 31)) == 0)) { |
1978 | temp_exp = 0; |
1979 | } else { |
1980 | temp_exp = int_exp + 128; |
1981 | } |
1982 | fp_exp_frac = (((temp_exp & 0xff) << 23) | |
1983 | extract32(int_mant, 8, 23)) |
1984 | + flag_rnd; |
1985 | fp_exp = extract32(fp_exp_frac, 23, 8); |
1986 | fp_frac = extract32(fp_exp_frac, 0, 23); |
1987 | } |
1988 | ret = r2 & (1 << 31); |
1989 | ret = ret + (fp_exp << 23); |
1990 | ret = ret + (fp_frac & 0x7fffff); |
1991 | |
1992 | return ret; |
1993 | } |
1994 | |
1995 | uint64_t helper_unpack(target_ulong arg1) |
1996 | { |
1997 | int32_t fp_exp = extract32(arg1, 23, 8); |
1998 | int32_t fp_frac = extract32(arg1, 0, 23); |
1999 | uint64_t ret; |
2000 | int32_t int_exp, int_mant; |
2001 | |
2002 | if (fp_exp == 255) { |
2003 | int_exp = 255; |
2004 | int_mant = (fp_frac << 7); |
2005 | } else if ((fp_exp == 0) && (fp_frac == 0)) { |
2006 | int_exp = -127; |
2007 | int_mant = 0; |
2008 | } else if ((fp_exp == 0) && (fp_frac != 0)) { |
2009 | int_exp = -126; |
2010 | int_mant = (fp_frac << 7); |
2011 | } else { |
2012 | int_exp = fp_exp - 127; |
2013 | int_mant = (fp_frac << 7); |
2014 | int_mant |= (1 << 30); |
2015 | } |
2016 | ret = int_exp; |
2017 | ret = ret << 32; |
2018 | ret |= int_mant; |
2019 | |
2020 | return ret; |
2021 | } |
2022 | |
2023 | uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) |
2024 | { |
2025 | uint64_t ret; |
2026 | int32_t abs_sig_dividend, abs_divisor; |
2027 | |
2028 | ret = sextract32(r1, 0, 32); |
2029 | ret = ret << 24; |
2030 | if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { |
2031 | ret |= 0xffffff; |
2032 | } |
2033 | |
2034 | abs_sig_dividend = abs((int32_t)r1) >> 8; |
2035 | abs_divisor = abs((int32_t)r2); |
2036 | /* calc overflow |
2037 | ofv if (a/b >= 255) <=> (a/255 >= b) */ |
2038 | env->PSW_USB_V = (abs_sig_dividend >= abs_divisor) << 31; |
2039 | env->PSW_USB_V = env->PSW_USB_V << 31; |
2040 | env->PSW_USB_SV |= env->PSW_USB_V; |
2041 | env->PSW_USB_AV = 0; |
2042 | |
2043 | return ret; |
2044 | } |
2045 | |
2046 | uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) |
2047 | { |
2048 | uint64_t ret = sextract32(r1, 0, 32); |
2049 | |
2050 | ret = ret << 24; |
2051 | if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { |
2052 | ret |= 0xffffff; |
2053 | } |
2054 | /* calc overflow */ |
2055 | env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffffff80))); |
2056 | env->PSW_USB_V = env->PSW_USB_V << 31; |
2057 | env->PSW_USB_SV |= env->PSW_USB_V; |
2058 | env->PSW_USB_AV = 0; |
2059 | |
2060 | return ret; |
2061 | } |
2062 | |
2063 | uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) |
2064 | { |
2065 | uint64_t ret; |
2066 | int32_t abs_sig_dividend, abs_divisor; |
2067 | |
2068 | ret = sextract32(r1, 0, 32); |
2069 | ret = ret << 16; |
2070 | if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { |
2071 | ret |= 0xffff; |
2072 | } |
2073 | |
2074 | abs_sig_dividend = abs((int32_t)r1) >> 16; |
2075 | abs_divisor = abs((int32_t)r2); |
2076 | /* calc overflow |
2077 | ofv if (a/b >= 0xffff) <=> (a/0xffff >= b) */ |
2078 | env->PSW_USB_V = (abs_sig_dividend >= abs_divisor) << 31; |
2079 | env->PSW_USB_V = env->PSW_USB_V << 31; |
2080 | env->PSW_USB_SV |= env->PSW_USB_V; |
2081 | env->PSW_USB_AV = 0; |
2082 | |
2083 | return ret; |
2084 | } |
2085 | |
2086 | uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) |
2087 | { |
2088 | uint64_t ret = sextract32(r1, 0, 32); |
2089 | |
2090 | ret = ret << 16; |
2091 | if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { |
2092 | ret |= 0xffff; |
2093 | } |
2094 | /* calc overflow */ |
2095 | env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffff8000))); |
2096 | env->PSW_USB_V = env->PSW_USB_V << 31; |
2097 | env->PSW_USB_SV |= env->PSW_USB_V; |
2098 | env->PSW_USB_AV = 0; |
2099 | |
2100 | return ret; |
2101 | } |
2102 | |
2103 | uint64_t helper_dvadj(uint64_t r1, uint32_t r2) |
2104 | { |
2105 | int32_t x_sign = (r1 >> 63); |
2106 | int32_t q_sign = x_sign ^ (r2 >> 31); |
2107 | int32_t eq_pos = x_sign & ((r1 >> 32) == r2); |
2108 | int32_t eq_neg = x_sign & ((r1 >> 32) == -r2); |
2109 | uint32_t quotient; |
2110 | uint64_t remainder; |
2111 | |
2112 | if ((q_sign & ~eq_neg) | eq_pos) { |
2113 | quotient = (r1 + 1) & 0xffffffff; |
2114 | } else { |
2115 | quotient = r1 & 0xffffffff; |
2116 | } |
2117 | |
2118 | if (eq_pos | eq_neg) { |
2119 | remainder = 0; |
2120 | } else { |
2121 | remainder = (r1 & 0xffffffff00000000ull); |
2122 | } |
2123 | return remainder | quotient; |
2124 | } |
2125 | |
2126 | uint64_t helper_dvstep(uint64_t r1, uint32_t r2) |
2127 | { |
2128 | int32_t dividend_sign = extract64(r1, 63, 1); |
2129 | int32_t divisor_sign = extract32(r2, 31, 1); |
2130 | int32_t quotient_sign = (dividend_sign != divisor_sign); |
2131 | int32_t addend, dividend_quotient, remainder; |
2132 | int32_t i, temp; |
2133 | |
2134 | if (quotient_sign) { |
2135 | addend = r2; |
2136 | } else { |
2137 | addend = -r2; |
2138 | } |
2139 | dividend_quotient = (int32_t)r1; |
2140 | remainder = (int32_t)(r1 >> 32); |
2141 | |
2142 | for (i = 0; i < 8; i++) { |
2143 | remainder = (remainder << 1) | extract32(dividend_quotient, 31, 1); |
2144 | dividend_quotient <<= 1; |
2145 | temp = remainder + addend; |
2146 | if ((temp < 0) == dividend_sign) { |
2147 | remainder = temp; |
2148 | } |
2149 | if (((temp < 0) == dividend_sign)) { |
2150 | dividend_quotient = dividend_quotient | !quotient_sign; |
2151 | } else { |
2152 | dividend_quotient = dividend_quotient | quotient_sign; |
2153 | } |
2154 | } |
2155 | return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; |
2156 | } |
2157 | |
2158 | uint64_t helper_dvstep_u(uint64_t r1, uint32_t r2) |
2159 | { |
2160 | int32_t dividend_quotient = extract64(r1, 0, 32); |
2161 | int64_t remainder = extract64(r1, 32, 32); |
2162 | int32_t i; |
2163 | int64_t temp; |
2164 | for (i = 0; i < 8; i++) { |
2165 | remainder = (remainder << 1) | extract32(dividend_quotient, 31, 1); |
2166 | dividend_quotient <<= 1; |
2167 | temp = (remainder & 0xffffffff) - r2; |
2168 | if (temp >= 0) { |
2169 | remainder = temp; |
2170 | } |
2171 | dividend_quotient = dividend_quotient | !(temp < 0); |
2172 | } |
2173 | return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; |
2174 | } |
2175 | |
2176 | uint64_t helper_divide(CPUTriCoreState *env, uint32_t r1, uint32_t r2) |
2177 | { |
2178 | int32_t quotient, remainder; |
2179 | int32_t dividend = (int32_t)r1; |
2180 | int32_t divisor = (int32_t)r2; |
2181 | |
2182 | if (divisor == 0) { |
2183 | if (dividend >= 0) { |
2184 | quotient = 0x7fffffff; |
2185 | remainder = 0; |
2186 | } else { |
2187 | quotient = 0x80000000; |
2188 | remainder = 0; |
2189 | } |
2190 | env->PSW_USB_V = (1 << 31); |
2191 | } else if ((divisor == 0xffffffff) && (dividend == 0x80000000)) { |
2192 | quotient = 0x7fffffff; |
2193 | remainder = 0; |
2194 | env->PSW_USB_V = (1 << 31); |
2195 | } else { |
2196 | remainder = dividend % divisor; |
2197 | quotient = (dividend - remainder)/divisor; |
2198 | env->PSW_USB_V = 0; |
2199 | } |
2200 | env->PSW_USB_SV |= env->PSW_USB_V; |
2201 | env->PSW_USB_AV = 0; |
2202 | return ((uint64_t)remainder << 32) | (uint32_t)quotient; |
2203 | } |
2204 | |
2205 | uint64_t helper_divide_u(CPUTriCoreState *env, uint32_t r1, uint32_t r2) |
2206 | { |
2207 | uint32_t quotient, remainder; |
2208 | uint32_t dividend = r1; |
2209 | uint32_t divisor = r2; |
2210 | |
2211 | if (divisor == 0) { |
2212 | quotient = 0xffffffff; |
2213 | remainder = 0; |
2214 | env->PSW_USB_V = (1 << 31); |
2215 | } else { |
2216 | remainder = dividend % divisor; |
2217 | quotient = (dividend - remainder)/divisor; |
2218 | env->PSW_USB_V = 0; |
2219 | } |
2220 | env->PSW_USB_SV |= env->PSW_USB_V; |
2221 | env->PSW_USB_AV = 0; |
2222 | return ((uint64_t)remainder << 32) | quotient; |
2223 | } |
2224 | |
2225 | uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01, |
2226 | uint32_t arg10, uint32_t arg11, uint32_t n) |
2227 | { |
2228 | uint32_t result0, result1; |
2229 | |
2230 | int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && |
2231 | ((arg10 & 0xffff) == 0x8000) && (n == 1); |
2232 | int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && |
2233 | ((arg11 & 0xffff) == 0x8000) && (n == 1); |
2234 | if (sc1) { |
2235 | result1 = 0x7fffffff; |
2236 | } else { |
2237 | result1 = (((uint32_t)(arg00 * arg10)) << n); |
2238 | } |
2239 | if (sc0) { |
2240 | result0 = 0x7fffffff; |
2241 | } else { |
2242 | result0 = (((uint32_t)(arg01 * arg11)) << n); |
2243 | } |
2244 | return (((uint64_t)result1 << 32)) | result0; |
2245 | } |
2246 | |
2247 | uint64_t helper_mulm_h(uint32_t arg00, uint32_t arg01, |
2248 | uint32_t arg10, uint32_t arg11, uint32_t n) |
2249 | { |
2250 | uint64_t ret; |
2251 | int64_t result0, result1; |
2252 | |
2253 | int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && |
2254 | ((arg10 & 0xffff) == 0x8000) && (n == 1); |
2255 | int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && |
2256 | ((arg11 & 0xffff) == 0x8000) && (n == 1); |
2257 | |
2258 | if (sc1) { |
2259 | result1 = 0x7fffffff; |
2260 | } else { |
2261 | result1 = (((int32_t)arg00 * (int32_t)arg10) << n); |
2262 | } |
2263 | if (sc0) { |
2264 | result0 = 0x7fffffff; |
2265 | } else { |
2266 | result0 = (((int32_t)arg01 * (int32_t)arg11) << n); |
2267 | } |
2268 | ret = (result1 + result0); |
2269 | ret = ret << 16; |
2270 | return ret; |
2271 | } |
2272 | uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01, |
2273 | uint32_t arg10, uint32_t arg11, uint32_t n) |
2274 | { |
2275 | uint32_t result0, result1; |
2276 | |
2277 | int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && |
2278 | ((arg10 & 0xffff) == 0x8000) && (n == 1); |
2279 | int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && |
2280 | ((arg11 & 0xffff) == 0x8000) && (n == 1); |
2281 | |
2282 | if (sc1) { |
2283 | result1 = 0x7fffffff; |
2284 | } else { |
2285 | result1 = ((arg00 * arg10) << n) + 0x8000; |
2286 | } |
2287 | if (sc0) { |
2288 | result0 = 0x7fffffff; |
2289 | } else { |
2290 | result0 = ((arg01 * arg11) << n) + 0x8000; |
2291 | } |
2292 | return (result1 & 0xffff0000) | (result0 >> 16); |
2293 | } |
2294 | |
2295 | uint32_t helper_crc32(uint32_t arg0, uint32_t arg1) |
2296 | { |
2297 | uint8_t buf[4]; |
2298 | stl_be_p(buf, arg0); |
2299 | |
2300 | return crc32(arg1, buf, 4); |
2301 | } |
2302 | |
2303 | /* context save area (CSA) related helpers */ |
2304 | |
2305 | static int cdc_increment(target_ulong *psw) |
2306 | { |
2307 | if ((*psw & MASK_PSW_CDC) == 0x7f) { |
2308 | return 0; |
2309 | } |
2310 | |
2311 | (*psw)++; |
2312 | /* check for overflow */ |
2313 | int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); |
2314 | int mask = (1u << (7 - lo)) - 1; |
2315 | int count = *psw & mask; |
2316 | if (count == 0) { |
2317 | (*psw)--; |
2318 | return 1; |
2319 | } |
2320 | return 0; |
2321 | } |
2322 | |
2323 | static int cdc_decrement(target_ulong *psw) |
2324 | { |
2325 | if ((*psw & MASK_PSW_CDC) == 0x7f) { |
2326 | return 0; |
2327 | } |
2328 | /* check for underflow */ |
2329 | int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); |
2330 | int mask = (1u << (7 - lo)) - 1; |
2331 | int count = *psw & mask; |
2332 | if (count == 0) { |
2333 | return 1; |
2334 | } |
2335 | (*psw)--; |
2336 | return 0; |
2337 | } |
2338 | |
2339 | static bool cdc_zero(target_ulong *psw) |
2340 | { |
2341 | int cdc = *psw & MASK_PSW_CDC; |
2342 | /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC == |
2343 | 7'b1111111, otherwise returns FALSE. */ |
2344 | if (cdc == 0x7f) { |
2345 | return true; |
2346 | } |
2347 | /* find CDC.COUNT */ |
2348 | int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); |
2349 | int mask = (1u << (7 - lo)) - 1; |
2350 | int count = *psw & mask; |
2351 | return count == 0; |
2352 | } |
2353 | |
2354 | static void save_context_upper(CPUTriCoreState *env, int ea) |
2355 | { |
2356 | cpu_stl_data(env, ea, env->PCXI); |
2357 | cpu_stl_data(env, ea+4, psw_read(env)); |
2358 | cpu_stl_data(env, ea+8, env->gpr_a[10]); |
2359 | cpu_stl_data(env, ea+12, env->gpr_a[11]); |
2360 | cpu_stl_data(env, ea+16, env->gpr_d[8]); |
2361 | cpu_stl_data(env, ea+20, env->gpr_d[9]); |
2362 | cpu_stl_data(env, ea+24, env->gpr_d[10]); |
2363 | cpu_stl_data(env, ea+28, env->gpr_d[11]); |
2364 | cpu_stl_data(env, ea+32, env->gpr_a[12]); |
2365 | cpu_stl_data(env, ea+36, env->gpr_a[13]); |
2366 | cpu_stl_data(env, ea+40, env->gpr_a[14]); |
2367 | cpu_stl_data(env, ea+44, env->gpr_a[15]); |
2368 | cpu_stl_data(env, ea+48, env->gpr_d[12]); |
2369 | cpu_stl_data(env, ea+52, env->gpr_d[13]); |
2370 | cpu_stl_data(env, ea+56, env->gpr_d[14]); |
2371 | cpu_stl_data(env, ea+60, env->gpr_d[15]); |
2372 | } |
2373 | |
2374 | static void save_context_lower(CPUTriCoreState *env, int ea) |
2375 | { |
2376 | cpu_stl_data(env, ea, env->PCXI); |
2377 | cpu_stl_data(env, ea+4, env->gpr_a[11]); |
2378 | cpu_stl_data(env, ea+8, env->gpr_a[2]); |
2379 | cpu_stl_data(env, ea+12, env->gpr_a[3]); |
2380 | cpu_stl_data(env, ea+16, env->gpr_d[0]); |
2381 | cpu_stl_data(env, ea+20, env->gpr_d[1]); |
2382 | cpu_stl_data(env, ea+24, env->gpr_d[2]); |
2383 | cpu_stl_data(env, ea+28, env->gpr_d[3]); |
2384 | cpu_stl_data(env, ea+32, env->gpr_a[4]); |
2385 | cpu_stl_data(env, ea+36, env->gpr_a[5]); |
2386 | cpu_stl_data(env, ea+40, env->gpr_a[6]); |
2387 | cpu_stl_data(env, ea+44, env->gpr_a[7]); |
2388 | cpu_stl_data(env, ea+48, env->gpr_d[4]); |
2389 | cpu_stl_data(env, ea+52, env->gpr_d[5]); |
2390 | cpu_stl_data(env, ea+56, env->gpr_d[6]); |
2391 | cpu_stl_data(env, ea+60, env->gpr_d[7]); |
2392 | } |
2393 | |
2394 | static void restore_context_upper(CPUTriCoreState *env, int ea, |
2395 | target_ulong *new_PCXI, target_ulong *new_PSW) |
2396 | { |
2397 | *new_PCXI = cpu_ldl_data(env, ea); |
2398 | *new_PSW = cpu_ldl_data(env, ea+4); |
2399 | env->gpr_a[10] = cpu_ldl_data(env, ea+8); |
2400 | env->gpr_a[11] = cpu_ldl_data(env, ea+12); |
2401 | env->gpr_d[8] = cpu_ldl_data(env, ea+16); |
2402 | env->gpr_d[9] = cpu_ldl_data(env, ea+20); |
2403 | env->gpr_d[10] = cpu_ldl_data(env, ea+24); |
2404 | env->gpr_d[11] = cpu_ldl_data(env, ea+28); |
2405 | env->gpr_a[12] = cpu_ldl_data(env, ea+32); |
2406 | env->gpr_a[13] = cpu_ldl_data(env, ea+36); |
2407 | env->gpr_a[14] = cpu_ldl_data(env, ea+40); |
2408 | env->gpr_a[15] = cpu_ldl_data(env, ea+44); |
2409 | env->gpr_d[12] = cpu_ldl_data(env, ea+48); |
2410 | env->gpr_d[13] = cpu_ldl_data(env, ea+52); |
2411 | env->gpr_d[14] = cpu_ldl_data(env, ea+56); |
2412 | env->gpr_d[15] = cpu_ldl_data(env, ea+60); |
2413 | } |
2414 | |
2415 | static void restore_context_lower(CPUTriCoreState *env, int ea, |
2416 | target_ulong *ra, target_ulong *pcxi) |
2417 | { |
2418 | *pcxi = cpu_ldl_data(env, ea); |
2419 | *ra = cpu_ldl_data(env, ea+4); |
2420 | env->gpr_a[2] = cpu_ldl_data(env, ea+8); |
2421 | env->gpr_a[3] = cpu_ldl_data(env, ea+12); |
2422 | env->gpr_d[0] = cpu_ldl_data(env, ea+16); |
2423 | env->gpr_d[1] = cpu_ldl_data(env, ea+20); |
2424 | env->gpr_d[2] = cpu_ldl_data(env, ea+24); |
2425 | env->gpr_d[3] = cpu_ldl_data(env, ea+28); |
2426 | env->gpr_a[4] = cpu_ldl_data(env, ea+32); |
2427 | env->gpr_a[5] = cpu_ldl_data(env, ea+36); |
2428 | env->gpr_a[6] = cpu_ldl_data(env, ea+40); |
2429 | env->gpr_a[7] = cpu_ldl_data(env, ea+44); |
2430 | env->gpr_d[4] = cpu_ldl_data(env, ea+48); |
2431 | env->gpr_d[5] = cpu_ldl_data(env, ea+52); |
2432 | env->gpr_d[6] = cpu_ldl_data(env, ea+56); |
2433 | env->gpr_d[7] = cpu_ldl_data(env, ea+60); |
2434 | } |
2435 | |
2436 | void helper_call(CPUTriCoreState *env, uint32_t next_pc) |
2437 | { |
2438 | target_ulong tmp_FCX; |
2439 | target_ulong ea; |
2440 | target_ulong new_FCX; |
2441 | target_ulong psw; |
2442 | |
2443 | psw = psw_read(env); |
2444 | /* if (FCX == 0) trap(FCU); */ |
2445 | if (env->FCX == 0) { |
2446 | /* FCU trap */ |
2447 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC()); |
2448 | } |
2449 | /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */ |
2450 | if (psw & MASK_PSW_CDE) { |
2451 | if (cdc_increment(&psw)) { |
2452 | /* CDO trap */ |
2453 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CDO, GETPC()); |
2454 | } |
2455 | } |
2456 | /* PSW.CDE = 1;*/ |
2457 | psw |= MASK_PSW_CDE; |
2458 | /* tmp_FCX = FCX; */ |
2459 | tmp_FCX = env->FCX; |
2460 | /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ |
2461 | ea = ((env->FCX & MASK_FCX_FCXS) << 12) + |
2462 | ((env->FCX & MASK_FCX_FCXO) << 6); |
2463 | /* new_FCX = M(EA, word); */ |
2464 | new_FCX = cpu_ldl_data(env, ea); |
2465 | /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], |
2466 | A[12], A[13], A[14], A[15], D[12], D[13], D[14], |
2467 | D[15]}; */ |
2468 | save_context_upper(env, ea); |
2469 | |
2470 | /* PCXI.PCPN = ICR.CCPN; */ |
2471 | env->PCXI = (env->PCXI & 0xffffff) + |
2472 | ((env->ICR & MASK_ICR_CCPN) << 24); |
2473 | /* PCXI.PIE = ICR.IE; */ |
2474 | env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) + |
2475 | ((env->ICR & MASK_ICR_IE_1_3) << 15)); |
2476 | /* PCXI.UL = 1; */ |
2477 | env->PCXI |= MASK_PCXI_UL; |
2478 | |
2479 | /* PCXI[19: 0] = FCX[19: 0]; */ |
2480 | env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); |
2481 | /* FCX[19: 0] = new_FCX[19: 0]; */ |
2482 | env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); |
2483 | /* A[11] = next_pc[31: 0]; */ |
2484 | env->gpr_a[11] = next_pc; |
2485 | |
2486 | /* if (tmp_FCX == LCX) trap(FCD);*/ |
2487 | if (tmp_FCX == env->LCX) { |
2488 | /* FCD trap */ |
2489 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC()); |
2490 | } |
2491 | psw_write(env, psw); |
2492 | } |
2493 | |
2494 | void helper_ret(CPUTriCoreState *env) |
2495 | { |
2496 | target_ulong ea; |
2497 | target_ulong new_PCXI; |
2498 | target_ulong new_PSW, psw; |
2499 | |
2500 | psw = psw_read(env); |
2501 | /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/ |
2502 | if (psw & MASK_PSW_CDE) { |
2503 | if (cdc_decrement(&psw)) { |
2504 | /* CDU trap */ |
2505 | psw_write(env, psw); |
2506 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CDU, GETPC()); |
2507 | } |
2508 | } |
2509 | /* if (PCXI[19: 0] == 0) then trap(CSU); */ |
2510 | if ((env->PCXI & 0xfffff) == 0) { |
2511 | /* CSU trap */ |
2512 | psw_write(env, psw); |
2513 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC()); |
2514 | } |
2515 | /* if (PCXI.UL == 0) then trap(CTYP); */ |
2516 | if ((env->PCXI & MASK_PCXI_UL) == 0) { |
2517 | /* CTYP trap */ |
2518 | cdc_increment(&psw); /* restore to the start of helper */ |
2519 | psw_write(env, psw); |
2520 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC()); |
2521 | } |
2522 | /* PC = {A11 [31: 1], 1’b0}; */ |
2523 | env->PC = env->gpr_a[11] & 0xfffffffe; |
2524 | |
2525 | /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ |
2526 | ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + |
2527 | ((env->PCXI & MASK_PCXI_PCXO) << 6); |
2528 | /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], |
2529 | A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ |
2530 | restore_context_upper(env, ea, &new_PCXI, &new_PSW); |
2531 | /* M(EA, word) = FCX; */ |
2532 | cpu_stl_data(env, ea, env->FCX); |
2533 | /* FCX[19: 0] = PCXI[19: 0]; */ |
2534 | env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); |
2535 | /* PCXI = new_PCXI; */ |
2536 | env->PCXI = new_PCXI; |
2537 | |
2538 | if (tricore_feature(env, TRICORE_FEATURE_13)) { |
2539 | /* PSW = new_PSW */ |
2540 | psw_write(env, new_PSW); |
2541 | } else { |
2542 | /* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */ |
2543 | psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000))); |
2544 | } |
2545 | } |
2546 | |
2547 | void helper_bisr(CPUTriCoreState *env, uint32_t const9) |
2548 | { |
2549 | target_ulong tmp_FCX; |
2550 | target_ulong ea; |
2551 | target_ulong new_FCX; |
2552 | |
2553 | if (env->FCX == 0) { |
2554 | /* FCU trap */ |
2555 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC()); |
2556 | } |
2557 | |
2558 | tmp_FCX = env->FCX; |
2559 | ea = ((env->FCX & 0xf0000) << 12) + ((env->FCX & 0xffff) << 6); |
2560 | |
2561 | /* new_FCX = M(EA, word); */ |
2562 | new_FCX = cpu_ldl_data(env, ea); |
2563 | /* M(EA, 16 * word) = {PCXI, A[11], A[2], A[3], D[0], D[1], D[2], D[3], A[4] |
2564 | , A[5], A[6], A[7], D[4], D[5], D[6], D[7]}; */ |
2565 | save_context_lower(env, ea); |
2566 | |
2567 | |
2568 | /* PCXI.PCPN = ICR.CCPN */ |
2569 | env->PCXI = (env->PCXI & 0xffffff) + |
2570 | ((env->ICR & MASK_ICR_CCPN) << 24); |
2571 | /* PCXI.PIE = ICR.IE */ |
2572 | env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) + |
2573 | ((env->ICR & MASK_ICR_IE_1_3) << 15)); |
2574 | /* PCXI.UL = 0 */ |
2575 | env->PCXI &= ~(MASK_PCXI_UL); |
2576 | /* PCXI[19: 0] = FCX[19: 0] */ |
2577 | env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); |
2578 | /* FXC[19: 0] = new_FCX[19: 0] */ |
2579 | env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); |
2580 | /* ICR.IE = 1 */ |
2581 | env->ICR |= MASK_ICR_IE_1_3; |
2582 | |
2583 | env->ICR |= const9; /* ICR.CCPN = const9[7: 0];*/ |
2584 | |
2585 | if (tmp_FCX == env->LCX) { |
2586 | /* FCD trap */ |
2587 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC()); |
2588 | } |
2589 | } |
2590 | |
2591 | void helper_rfe(CPUTriCoreState *env) |
2592 | { |
2593 | target_ulong ea; |
2594 | target_ulong new_PCXI; |
2595 | target_ulong new_PSW; |
2596 | /* if (PCXI[19: 0] == 0) then trap(CSU); */ |
2597 | if ((env->PCXI & 0xfffff) == 0) { |
2598 | /* raise csu trap */ |
2599 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC()); |
2600 | } |
2601 | /* if (PCXI.UL == 0) then trap(CTYP); */ |
2602 | if ((env->PCXI & MASK_PCXI_UL) == 0) { |
2603 | /* raise CTYP trap */ |
2604 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC()); |
2605 | } |
2606 | /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */ |
2607 | if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) { |
2608 | /* raise NEST trap */ |
2609 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_NEST, GETPC()); |
2610 | } |
2611 | env->PC = env->gpr_a[11] & ~0x1; |
2612 | /* ICR.IE = PCXI.PIE; */ |
2613 | env->ICR = (env->ICR & ~MASK_ICR_IE_1_3) |
2614 | + ((env->PCXI & MASK_PCXI_PIE_1_3) >> 15); |
2615 | /* ICR.CCPN = PCXI.PCPN; */ |
2616 | env->ICR = (env->ICR & ~MASK_ICR_CCPN) + |
2617 | ((env->PCXI & MASK_PCXI_PCPN) >> 24); |
2618 | /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/ |
2619 | ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + |
2620 | ((env->PCXI & MASK_PCXI_PCXO) << 6); |
2621 | /*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], |
2622 | A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ |
2623 | restore_context_upper(env, ea, &new_PCXI, &new_PSW); |
2624 | /* M(EA, word) = FCX;*/ |
2625 | cpu_stl_data(env, ea, env->FCX); |
2626 | /* FCX[19: 0] = PCXI[19: 0]; */ |
2627 | env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); |
2628 | /* PCXI = new_PCXI; */ |
2629 | env->PCXI = new_PCXI; |
2630 | /* write psw */ |
2631 | psw_write(env, new_PSW); |
2632 | } |
2633 | |
2634 | void helper_rfm(CPUTriCoreState *env) |
2635 | { |
2636 | env->PC = (env->gpr_a[11] & ~0x1); |
2637 | /* ICR.IE = PCXI.PIE; */ |
2638 | env->ICR = (env->ICR & ~MASK_ICR_IE_1_3) |
2639 | | ((env->PCXI & MASK_PCXI_PIE_1_3) >> 15); |
2640 | /* ICR.CCPN = PCXI.PCPN; */ |
2641 | env->ICR = (env->ICR & ~MASK_ICR_CCPN) | |
2642 | ((env->PCXI & MASK_PCXI_PCPN) >> 24); |
2643 | /* {PCXI, PSW, A[10], A[11]} = M(DCX, 4 * word); */ |
2644 | env->PCXI = cpu_ldl_data(env, env->DCX); |
2645 | psw_write(env, cpu_ldl_data(env, env->DCX+4)); |
2646 | env->gpr_a[10] = cpu_ldl_data(env, env->DCX+8); |
2647 | env->gpr_a[11] = cpu_ldl_data(env, env->DCX+12); |
2648 | |
2649 | if (tricore_feature(env, TRICORE_FEATURE_131)) { |
2650 | env->DBGTCR = 0; |
2651 | } |
2652 | } |
2653 | |
2654 | void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) |
2655 | { |
2656 | uint32_t dummy; |
2657 | /* insn doesn't load PCXI and RA */ |
2658 | restore_context_lower(env, ea, &dummy, &dummy); |
2659 | } |
2660 | |
2661 | void helper_lducx(CPUTriCoreState *env, uint32_t ea) |
2662 | { |
2663 | uint32_t dummy; |
2664 | /* insn doesn't load PCXI and PSW */ |
2665 | restore_context_upper(env, ea, &dummy, &dummy); |
2666 | } |
2667 | |
2668 | void helper_stlcx(CPUTriCoreState *env, uint32_t ea) |
2669 | { |
2670 | save_context_lower(env, ea); |
2671 | } |
2672 | |
2673 | void helper_stucx(CPUTriCoreState *env, uint32_t ea) |
2674 | { |
2675 | save_context_upper(env, ea); |
2676 | } |
2677 | |
2678 | void helper_svlcx(CPUTriCoreState *env) |
2679 | { |
2680 | target_ulong tmp_FCX; |
2681 | target_ulong ea; |
2682 | target_ulong new_FCX; |
2683 | |
2684 | if (env->FCX == 0) { |
2685 | /* FCU trap */ |
2686 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC()); |
2687 | } |
2688 | /* tmp_FCX = FCX; */ |
2689 | tmp_FCX = env->FCX; |
2690 | /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ |
2691 | ea = ((env->FCX & MASK_FCX_FCXS) << 12) + |
2692 | ((env->FCX & MASK_FCX_FCXO) << 6); |
2693 | /* new_FCX = M(EA, word); */ |
2694 | new_FCX = cpu_ldl_data(env, ea); |
2695 | /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], |
2696 | A[12], A[13], A[14], A[15], D[12], D[13], D[14], |
2697 | D[15]}; */ |
2698 | save_context_lower(env, ea); |
2699 | |
2700 | /* PCXI.PCPN = ICR.CCPN; */ |
2701 | env->PCXI = (env->PCXI & 0xffffff) + |
2702 | ((env->ICR & MASK_ICR_CCPN) << 24); |
2703 | /* PCXI.PIE = ICR.IE; */ |
2704 | env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) + |
2705 | ((env->ICR & MASK_ICR_IE_1_3) << 15)); |
2706 | /* PCXI.UL = 0; */ |
2707 | env->PCXI &= ~MASK_PCXI_UL; |
2708 | |
2709 | /* PCXI[19: 0] = FCX[19: 0]; */ |
2710 | env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); |
2711 | /* FCX[19: 0] = new_FCX[19: 0]; */ |
2712 | env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); |
2713 | |
2714 | /* if (tmp_FCX == LCX) trap(FCD);*/ |
2715 | if (tmp_FCX == env->LCX) { |
2716 | /* FCD trap */ |
2717 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC()); |
2718 | } |
2719 | } |
2720 | |
2721 | void helper_svucx(CPUTriCoreState *env) |
2722 | { |
2723 | target_ulong tmp_FCX; |
2724 | target_ulong ea; |
2725 | target_ulong new_FCX; |
2726 | |
2727 | if (env->FCX == 0) { |
2728 | /* FCU trap */ |
2729 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC()); |
2730 | } |
2731 | /* tmp_FCX = FCX; */ |
2732 | tmp_FCX = env->FCX; |
2733 | /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ |
2734 | ea = ((env->FCX & MASK_FCX_FCXS) << 12) + |
2735 | ((env->FCX & MASK_FCX_FCXO) << 6); |
2736 | /* new_FCX = M(EA, word); */ |
2737 | new_FCX = cpu_ldl_data(env, ea); |
2738 | /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], |
2739 | A[12], A[13], A[14], A[15], D[12], D[13], D[14], |
2740 | D[15]}; */ |
2741 | save_context_upper(env, ea); |
2742 | |
2743 | /* PCXI.PCPN = ICR.CCPN; */ |
2744 | env->PCXI = (env->PCXI & 0xffffff) + |
2745 | ((env->ICR & MASK_ICR_CCPN) << 24); |
2746 | /* PCXI.PIE = ICR.IE; */ |
2747 | env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) + |
2748 | ((env->ICR & MASK_ICR_IE_1_3) << 15)); |
2749 | /* PCXI.UL = 1; */ |
2750 | env->PCXI |= MASK_PCXI_UL; |
2751 | |
2752 | /* PCXI[19: 0] = FCX[19: 0]; */ |
2753 | env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); |
2754 | /* FCX[19: 0] = new_FCX[19: 0]; */ |
2755 | env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); |
2756 | |
2757 | /* if (tmp_FCX == LCX) trap(FCD);*/ |
2758 | if (tmp_FCX == env->LCX) { |
2759 | /* FCD trap */ |
2760 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC()); |
2761 | } |
2762 | } |
2763 | |
2764 | void helper_rslcx(CPUTriCoreState *env) |
2765 | { |
2766 | target_ulong ea; |
2767 | target_ulong new_PCXI; |
2768 | /* if (PCXI[19: 0] == 0) then trap(CSU); */ |
2769 | if ((env->PCXI & 0xfffff) == 0) { |
2770 | /* CSU trap */ |
2771 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC()); |
2772 | } |
2773 | /* if (PCXI.UL == 1) then trap(CTYP); */ |
2774 | if ((env->PCXI & MASK_PCXI_UL) != 0) { |
2775 | /* CTYP trap */ |
2776 | raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC()); |
2777 | } |
2778 | /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ |
2779 | ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + |
2780 | ((env->PCXI & MASK_PCXI_PCXO) << 6); |
2781 | /* {new_PCXI, A[11], A[10], A[11], D[8], D[9], D[10], D[11], A[12], |
2782 | A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ |
2783 | restore_context_lower(env, ea, &env->gpr_a[11], &new_PCXI); |
2784 | /* M(EA, word) = FCX; */ |
2785 | cpu_stl_data(env, ea, env->FCX); |
2786 | /* M(EA, word) = FCX; */ |
2787 | cpu_stl_data(env, ea, env->FCX); |
2788 | /* FCX[19: 0] = PCXI[19: 0]; */ |
2789 | env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); |
2790 | /* PCXI = new_PCXI; */ |
2791 | env->PCXI = new_PCXI; |
2792 | } |
2793 | |
2794 | void helper_psw_write(CPUTriCoreState *env, uint32_t arg) |
2795 | { |
2796 | psw_write(env, arg); |
2797 | } |
2798 | |
2799 | uint32_t helper_psw_read(CPUTriCoreState *env) |
2800 | { |
2801 | return psw_read(env); |
2802 | } |
2803 | |