]> git.proxmox.com Git - mirror_qemu.git/blame - target-sh4/op_helper.c
exec: move include files to include/exec/
[mirror_qemu.git] / target-sh4 / op_helper.c
CommitLineData
fdf9b3e8
FB
1/*
2 * SH4 emulation
5fafdf24 3 *
fdf9b3e8
FB
4 * Copyright (c) 2005 Samuel Tardieu
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
fdf9b3e8
FB
18 */
19#include <assert.h>
852d481f 20#include <stdlib.h>
3e457172 21#include "cpu.h"
a7812ae4 22#include "helper.h"
fdf9b3e8 23
fdf9b3e8 24#ifndef CONFIG_USER_ONLY
022c62cb 25#include "exec/softmmu_exec.h"
fdf9b3e8
FB
26
27#define MMUSUFFIX _mmu
fdf9b3e8
FB
28
29#define SHIFT 0
022c62cb 30#include "exec/softmmu_template.h"
fdf9b3e8
FB
31
32#define SHIFT 1
022c62cb 33#include "exec/softmmu_template.h"
fdf9b3e8
FB
34
35#define SHIFT 2
022c62cb 36#include "exec/softmmu_template.h"
fdf9b3e8
FB
37
38#define SHIFT 3
022c62cb 39#include "exec/softmmu_template.h"
fdf9b3e8 40
485d0035 41void tlb_fill(CPUSH4State *env, target_ulong addr, int is_write, int mmu_idx,
20503968 42 uintptr_t retaddr)
fdf9b3e8 43{
fdf9b3e8
FB
44 int ret;
45
97b348e7 46 ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx);
fdf9b3e8 47 if (ret) {
21829e9b 48 /* now we have a real cpu fault */
a8a826a3
BS
49 if (retaddr) {
50 cpu_restore_state(env, retaddr);
51 }
1162c041 52 cpu_loop_exit(env);
fdf9b3e8 53 }
fdf9b3e8
FB
54}
55
56#endif
57
485d0035 58void helper_ldtlb(CPUSH4State *env)
ea2b542a
AJ
59{
60#ifdef CONFIG_USER_ONLY
61 /* XXXXX */
43dc2a64 62 cpu_abort(env, "Unhandled ldtlb");
ea2b542a
AJ
63#else
64 cpu_load_tlb(env);
65#endif
66}
67
10127400
AJ
68static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index,
69 uintptr_t retaddr)
e6afc2f4 70{
fd4bab10 71 env->exception_index = index;
a8a826a3
BS
72 if (retaddr) {
73 cpu_restore_state(env, retaddr);
74 }
1162c041 75 cpu_loop_exit(env);
e6afc2f4
AJ
76}
77
485d0035 78void helper_raise_illegal_instruction(CPUSH4State *env)
fd4bab10 79{
10127400 80 raise_exception(env, 0x180, 0);
fd4bab10
AJ
81}
82
485d0035 83void helper_raise_slot_illegal_instruction(CPUSH4State *env)
e6afc2f4 84{
10127400 85 raise_exception(env, 0x1a0, 0);
e6afc2f4
AJ
86}
87
485d0035 88void helper_raise_fpu_disable(CPUSH4State *env)
d8299bcc 89{
10127400 90 raise_exception(env, 0x800, 0);
d8299bcc
AJ
91}
92
485d0035 93void helper_raise_slot_fpu_disable(CPUSH4State *env)
d8299bcc 94{
10127400 95 raise_exception(env, 0x820, 0);
d8299bcc
AJ
96}
97
485d0035 98void helper_debug(CPUSH4State *env)
e6afc2f4 99{
10127400 100 raise_exception(env, EXCP_DEBUG, 0);
e6afc2f4
AJ
101}
102
10127400 103void helper_sleep(CPUSH4State *env)
e6afc2f4
AJ
104{
105 env->halted = 1;
efac4154 106 env->in_sleep = 1;
10127400 107 raise_exception(env, EXCP_HLT, 0);
e6afc2f4
AJ
108}
109
485d0035 110void helper_trapa(CPUSH4State *env, uint32_t tra)
e6afc2f4
AJ
111{
112 env->tra = tra << 2;
10127400 113 raise_exception(env, 0x160, 0);
e6afc2f4
AJ
114}
115
485d0035 116void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value)
852d481f
EI
117{
118 if (cpu_sh4_is_cached (env, address))
119 {
120 memory_content *r = malloc (sizeof(memory_content));
121 r->address = address;
122 r->value = value;
123 r->next = NULL;
124
125 *(env->movcal_backup_tail) = r;
126 env->movcal_backup_tail = &(r->next);
127 }
128}
129
485d0035 130void helper_discard_movcal_backup(CPUSH4State *env)
852d481f
EI
131{
132 memory_content *current = env->movcal_backup;
133
134 while(current)
135 {
136 memory_content *next = current->next;
137 free (current);
138 env->movcal_backup = current = next;
b9d38e95 139 if (current == NULL)
852d481f
EI
140 env->movcal_backup_tail = &(env->movcal_backup);
141 }
142}
143
485d0035 144void helper_ocbi(CPUSH4State *env, uint32_t address)
852d481f
EI
145{
146 memory_content **current = &(env->movcal_backup);
147 while (*current)
148 {
149 uint32_t a = (*current)->address;
150 if ((a & ~0x1F) == (address & ~0x1F))
151 {
152 memory_content *next = (*current)->next;
485d0035 153 cpu_stl_data(env, a, (*current)->value);
852d481f 154
b9d38e95 155 if (next == NULL)
852d481f
EI
156 {
157 env->movcal_backup_tail = current;
158 }
159
160 free (*current);
161 *current = next;
162 break;
163 }
164 }
165}
166
fdf9b3e8
FB
167#define T (env->sr & SR_T)
168#define Q (env->sr & SR_Q ? 1 : 0)
169#define M (env->sr & SR_M ? 1 : 0)
170#define SETT env->sr |= SR_T
171#define CLRT env->sr &= ~SR_T
172#define SETQ env->sr |= SR_Q
173#define CLRQ env->sr &= ~SR_Q
174#define SETM env->sr |= SR_M
175#define CLRM env->sr &= ~SR_M
176
485d0035 177uint32_t helper_div1(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
178{
179 uint32_t tmp0, tmp2;
180 uint8_t old_q, tmp1 = 0xff;
181
69d6275b 182 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
fdf9b3e8 183 old_q = Q;
69d6275b 184 if ((0x80000000 & arg1) != 0)
fdf9b3e8
FB
185 SETQ;
186 else
187 CLRQ;
69d6275b
AJ
188 tmp2 = arg0;
189 arg1 <<= 1;
190 arg1 |= T;
fdf9b3e8
FB
191 switch (old_q) {
192 case 0:
193 switch (M) {
194 case 0:
69d6275b
AJ
195 tmp0 = arg1;
196 arg1 -= tmp2;
197 tmp1 = arg1 > tmp0;
fdf9b3e8
FB
198 switch (Q) {
199 case 0:
200 if (tmp1)
201 SETQ;
202 else
203 CLRQ;
204 break;
205 case 1:
206 if (tmp1 == 0)
207 SETQ;
208 else
209 CLRQ;
210 break;
211 }
212 break;
213 case 1:
69d6275b
AJ
214 tmp0 = arg1;
215 arg1 += tmp2;
216 tmp1 = arg1 < tmp0;
fdf9b3e8
FB
217 switch (Q) {
218 case 0:
219 if (tmp1 == 0)
220 SETQ;
221 else
222 CLRQ;
223 break;
224 case 1:
225 if (tmp1)
226 SETQ;
227 else
228 CLRQ;
229 break;
230 }
231 break;
232 }
233 break;
234 case 1:
235 switch (M) {
236 case 0:
69d6275b
AJ
237 tmp0 = arg1;
238 arg1 += tmp2;
239 tmp1 = arg1 < tmp0;
fdf9b3e8
FB
240 switch (Q) {
241 case 0:
242 if (tmp1)
243 SETQ;
244 else
245 CLRQ;
246 break;
247 case 1:
248 if (tmp1 == 0)
249 SETQ;
250 else
251 CLRQ;
252 break;
253 }
254 break;
255 case 1:
69d6275b
AJ
256 tmp0 = arg1;
257 arg1 -= tmp2;
258 tmp1 = arg1 > tmp0;
fdf9b3e8
FB
259 switch (Q) {
260 case 0:
261 if (tmp1 == 0)
262 SETQ;
263 else
264 CLRQ;
265 break;
266 case 1:
267 if (tmp1)
268 SETQ;
269 else
270 CLRQ;
271 break;
272 }
273 break;
274 }
275 break;
276 }
277 if (Q == M)
278 SETT;
279 else
280 CLRT;
69d6275b
AJ
281 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
282 return arg1;
fdf9b3e8
FB
283}
284
485d0035 285void helper_macl(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
286{
287 int64_t res;
288
289 res = ((uint64_t) env->mach << 32) | env->macl;
6f06939b 290 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
fdf9b3e8
FB
291 env->mach = (res >> 32) & 0xffffffff;
292 env->macl = res & 0xffffffff;
293 if (env->sr & SR_S) {
294 if (res < 0)
295 env->mach |= 0xffff0000;
296 else
297 env->mach &= 0x00007fff;
298 }
299}
300
485d0035 301void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
302{
303 int64_t res;
304
305 res = ((uint64_t) env->mach << 32) | env->macl;
6f06939b 306 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
fdf9b3e8
FB
307 env->mach = (res >> 32) & 0xffffffff;
308 env->macl = res & 0xffffffff;
309 if (env->sr & SR_S) {
310 if (res < -0x80000000) {
311 env->mach = 1;
312 env->macl = 0x80000000;
313 } else if (res > 0x000000007fffffff) {
314 env->mach = 1;
315 env->macl = 0x7fffffff;
316 }
317 }
318}
319
485d0035 320static inline void set_t(CPUSH4State *env)
cc4ba6a9
AJ
321{
322 env->sr |= SR_T;
323}
324
485d0035 325static inline void clr_t(CPUSH4State *env)
cc4ba6a9
AJ
326{
327 env->sr &= ~SR_T;
328}
329
485d0035 330void helper_ld_fpscr(CPUSH4State *env, uint32_t val)
390af821 331{
26ac1ea5
AJ
332 env->fpscr = val & FPSCR_MASK;
333 if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
390af821 334 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
26ac1ea5 335 } else {
390af821 336 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
26ac1ea5 337 }
a0d4ac33 338 set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
390af821 339}
cc4ba6a9 340
485d0035 341static void update_fpscr(CPUSH4State *env, uintptr_t retaddr)
21829e9b
AJ
342{
343 int xcpt, cause, enable;
344
345 xcpt = get_float_exception_flags(&env->fp_status);
346
347 /* Clear the flag entries */
348 env->fpscr &= ~FPSCR_FLAG_MASK;
349
350 if (unlikely(xcpt)) {
351 if (xcpt & float_flag_invalid) {
352 env->fpscr |= FPSCR_FLAG_V;
353 }
354 if (xcpt & float_flag_divbyzero) {
355 env->fpscr |= FPSCR_FLAG_Z;
356 }
357 if (xcpt & float_flag_overflow) {
358 env->fpscr |= FPSCR_FLAG_O;
359 }
360 if (xcpt & float_flag_underflow) {
361 env->fpscr |= FPSCR_FLAG_U;
362 }
363 if (xcpt & float_flag_inexact) {
364 env->fpscr |= FPSCR_FLAG_I;
365 }
366
367 /* Accumulate in cause entries */
368 env->fpscr |= (env->fpscr & FPSCR_FLAG_MASK)
369 << (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT);
370
371 /* Generate an exception if enabled */
372 cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
373 enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
374 if (cause & enable) {
10127400 375 raise_exception(env, 0x120, retaddr);
21829e9b
AJ
376 }
377 }
378}
379
d6c424c5 380float32 helper_fabs_FT(float32 t0)
cc4ba6a9 381{
d6c424c5 382 return float32_abs(t0);
cc4ba6a9
AJ
383}
384
d6c424c5 385float64 helper_fabs_DT(float64 t0)
cc4ba6a9 386{
d6c424c5 387 return float64_abs(t0);
cc4ba6a9
AJ
388}
389
485d0035 390float32 helper_fadd_FT(CPUSH4State *env, float32 t0, float32 t1)
cc4ba6a9 391{
21829e9b 392 set_float_exception_flags(0, &env->fp_status);
d6c424c5 393 t0 = float32_add(t0, t1, &env->fp_status);
485d0035 394 update_fpscr(env, GETPC());
d6c424c5 395 return t0;
cc4ba6a9
AJ
396}
397
485d0035 398float64 helper_fadd_DT(CPUSH4State *env, float64 t0, float64 t1)
cc4ba6a9 399{
21829e9b 400 set_float_exception_flags(0, &env->fp_status);
d6c424c5 401 t0 = float64_add(t0, t1, &env->fp_status);
485d0035 402 update_fpscr(env, GETPC());
d6c424c5 403 return t0;
cc4ba6a9
AJ
404}
405
485d0035 406void helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1)
cc4ba6a9 407{
21829e9b 408 int relation;
9850d1e8 409
21829e9b 410 set_float_exception_flags(0, &env->fp_status);
d6c424c5 411 relation = float32_compare(t0, t1, &env->fp_status);
21829e9b 412 if (unlikely(relation == float_relation_unordered)) {
485d0035 413 update_fpscr(env, GETPC());
21829e9b 414 } else if (relation == float_relation_equal) {
485d0035 415 set_t(env);
21829e9b 416 } else {
485d0035 417 clr_t(env);
21829e9b 418 }
cc4ba6a9
AJ
419}
420
485d0035 421void helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1)
cc4ba6a9 422{
21829e9b 423 int relation;
9850d1e8 424
21829e9b 425 set_float_exception_flags(0, &env->fp_status);
d6c424c5 426 relation = float64_compare(t0, t1, &env->fp_status);
21829e9b 427 if (unlikely(relation == float_relation_unordered)) {
485d0035 428 update_fpscr(env, GETPC());
21829e9b 429 } else if (relation == float_relation_equal) {
485d0035 430 set_t(env);
21829e9b 431 } else {
485d0035 432 clr_t(env);
21829e9b 433 }
cc4ba6a9
AJ
434}
435
485d0035 436void helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1)
cc4ba6a9 437{
21829e9b 438 int relation;
9850d1e8 439
21829e9b 440 set_float_exception_flags(0, &env->fp_status);
d6c424c5 441 relation = float32_compare(t0, t1, &env->fp_status);
21829e9b 442 if (unlikely(relation == float_relation_unordered)) {
485d0035 443 update_fpscr(env, GETPC());
21829e9b 444 } else if (relation == float_relation_greater) {
485d0035 445 set_t(env);
21829e9b 446 } else {
485d0035 447 clr_t(env);
21829e9b 448 }
cc4ba6a9
AJ
449}
450
485d0035 451void helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1)
cc4ba6a9 452{
21829e9b 453 int relation;
9850d1e8 454
21829e9b 455 set_float_exception_flags(0, &env->fp_status);
d6c424c5 456 relation = float64_compare(t0, t1, &env->fp_status);
21829e9b 457 if (unlikely(relation == float_relation_unordered)) {
485d0035 458 update_fpscr(env, GETPC());
21829e9b 459 } else if (relation == float_relation_greater) {
485d0035 460 set_t(env);
21829e9b 461 } else {
485d0035 462 clr_t(env);
21829e9b 463 }
cc4ba6a9
AJ
464}
465
485d0035 466float64 helper_fcnvsd_FT_DT(CPUSH4State *env, float32 t0)
cc4ba6a9 467{
d6c424c5 468 float64 ret;
21829e9b 469 set_float_exception_flags(0, &env->fp_status);
d6c424c5 470 ret = float32_to_float64(t0, &env->fp_status);
485d0035 471 update_fpscr(env, GETPC());
d6c424c5 472 return ret;
cc4ba6a9
AJ
473}
474
485d0035 475float32 helper_fcnvds_DT_FT(CPUSH4State *env, float64 t0)
cc4ba6a9 476{
d6c424c5 477 float32 ret;
21829e9b 478 set_float_exception_flags(0, &env->fp_status);
d6c424c5 479 ret = float64_to_float32(t0, &env->fp_status);
485d0035 480 update_fpscr(env, GETPC());
d6c424c5 481 return ret;
cc4ba6a9
AJ
482}
483
485d0035 484float32 helper_fdiv_FT(CPUSH4State *env, float32 t0, float32 t1)
cc4ba6a9 485{
21829e9b 486 set_float_exception_flags(0, &env->fp_status);
d6c424c5 487 t0 = float32_div(t0, t1, &env->fp_status);
485d0035 488 update_fpscr(env, GETPC());
d6c424c5 489 return t0;
cc4ba6a9
AJ
490}
491
485d0035 492float64 helper_fdiv_DT(CPUSH4State *env, float64 t0, float64 t1)
cc4ba6a9 493{
21829e9b 494 set_float_exception_flags(0, &env->fp_status);
d6c424c5 495 t0 = float64_div(t0, t1, &env->fp_status);
485d0035 496 update_fpscr(env, GETPC());
d6c424c5 497 return t0;
cc4ba6a9
AJ
498}
499
485d0035 500float32 helper_float_FT(CPUSH4State *env, uint32_t t0)
cc4ba6a9 501{
d6c424c5 502 float32 ret;
21829e9b 503 set_float_exception_flags(0, &env->fp_status);
d6c424c5 504 ret = int32_to_float32(t0, &env->fp_status);
485d0035 505 update_fpscr(env, GETPC());
d6c424c5 506 return ret;
cc4ba6a9
AJ
507}
508
485d0035 509float64 helper_float_DT(CPUSH4State *env, uint32_t t0)
cc4ba6a9 510{
d6c424c5 511 float64 ret;
21829e9b 512 set_float_exception_flags(0, &env->fp_status);
d6c424c5 513 ret = int32_to_float64(t0, &env->fp_status);
485d0035 514 update_fpscr(env, GETPC());
d6c424c5 515 return ret;
cc4ba6a9
AJ
516}
517
485d0035 518float32 helper_fmac_FT(CPUSH4State *env, float32 t0, float32 t1, float32 t2)
5b7141a1 519{
21829e9b 520 set_float_exception_flags(0, &env->fp_status);
ff2086fe 521 t0 = float32_muladd(t0, t1, t2, 0, &env->fp_status);
485d0035 522 update_fpscr(env, GETPC());
d6c424c5 523 return t0;
5b7141a1
AJ
524}
525
485d0035 526float32 helper_fmul_FT(CPUSH4State *env, float32 t0, float32 t1)
cc4ba6a9 527{
21829e9b 528 set_float_exception_flags(0, &env->fp_status);
d6c424c5 529 t0 = float32_mul(t0, t1, &env->fp_status);
485d0035 530 update_fpscr(env, GETPC());
d6c424c5 531 return t0;
cc4ba6a9
AJ
532}
533
485d0035 534float64 helper_fmul_DT(CPUSH4State *env, float64 t0, float64 t1)
cc4ba6a9 535{
21829e9b 536 set_float_exception_flags(0, &env->fp_status);
d6c424c5 537 t0 = float64_mul(t0, t1, &env->fp_status);
485d0035 538 update_fpscr(env, GETPC());
d6c424c5 539 return t0;
cc4ba6a9
AJ
540}
541
d6c424c5 542float32 helper_fneg_T(float32 t0)
7fdf924f 543{
d6c424c5 544 return float32_chs(t0);
7fdf924f
AJ
545}
546
485d0035 547float32 helper_fsqrt_FT(CPUSH4State *env, float32 t0)
cc4ba6a9 548{
21829e9b 549 set_float_exception_flags(0, &env->fp_status);
d6c424c5 550 t0 = float32_sqrt(t0, &env->fp_status);
485d0035 551 update_fpscr(env, GETPC());
d6c424c5 552 return t0;
cc4ba6a9
AJ
553}
554
485d0035 555float64 helper_fsqrt_DT(CPUSH4State *env, float64 t0)
cc4ba6a9 556{
21829e9b 557 set_float_exception_flags(0, &env->fp_status);
d6c424c5 558 t0 = float64_sqrt(t0, &env->fp_status);
485d0035 559 update_fpscr(env, GETPC());
d6c424c5 560 return t0;
cc4ba6a9
AJ
561}
562
485d0035 563float32 helper_fsub_FT(CPUSH4State *env, float32 t0, float32 t1)
cc4ba6a9 564{
21829e9b 565 set_float_exception_flags(0, &env->fp_status);
d6c424c5 566 t0 = float32_sub(t0, t1, &env->fp_status);
485d0035 567 update_fpscr(env, GETPC());
d6c424c5 568 return t0;
cc4ba6a9
AJ
569}
570
485d0035 571float64 helper_fsub_DT(CPUSH4State *env, float64 t0, float64 t1)
cc4ba6a9 572{
21829e9b 573 set_float_exception_flags(0, &env->fp_status);
d6c424c5 574 t0 = float64_sub(t0, t1, &env->fp_status);
485d0035 575 update_fpscr(env, GETPC());
d6c424c5 576 return t0;
cc4ba6a9
AJ
577}
578
485d0035 579uint32_t helper_ftrc_FT(CPUSH4State *env, float32 t0)
cc4ba6a9 580{
21829e9b 581 uint32_t ret;
21829e9b 582 set_float_exception_flags(0, &env->fp_status);
d6c424c5 583 ret = float32_to_int32_round_to_zero(t0, &env->fp_status);
485d0035 584 update_fpscr(env, GETPC());
21829e9b 585 return ret;
cc4ba6a9
AJ
586}
587
485d0035 588uint32_t helper_ftrc_DT(CPUSH4State *env, float64 t0)
cc4ba6a9 589{
21829e9b 590 uint32_t ret;
21829e9b 591 set_float_exception_flags(0, &env->fp_status);
d6c424c5 592 ret = float64_to_int32_round_to_zero(t0, &env->fp_status);
485d0035 593 update_fpscr(env, GETPC());
21829e9b 594 return ret;
cc4ba6a9 595}
af8c2bde 596
485d0035 597void helper_fipr(CPUSH4State *env, uint32_t m, uint32_t n)
af8c2bde
AJ
598{
599 int bank, i;
600 float32 r, p;
601
602 bank = (env->sr & FPSCR_FR) ? 16 : 0;
603 r = float32_zero;
604 set_float_exception_flags(0, &env->fp_status);
605
606 for (i = 0 ; i < 4 ; i++) {
607 p = float32_mul(env->fregs[bank + m + i],
608 env->fregs[bank + n + i],
609 &env->fp_status);
610 r = float32_add(r, p, &env->fp_status);
611 }
485d0035 612 update_fpscr(env, GETPC());
af8c2bde
AJ
613
614 env->fregs[bank + n + 3] = r;
615}
17075f10 616
485d0035 617void helper_ftrv(CPUSH4State *env, uint32_t n)
17075f10
AJ
618{
619 int bank_matrix, bank_vector;
620 int i, j;
621 float32 r[4];
622 float32 p;
623
624 bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
625 bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
626 set_float_exception_flags(0, &env->fp_status);
627 for (i = 0 ; i < 4 ; i++) {
628 r[i] = float32_zero;
629 for (j = 0 ; j < 4 ; j++) {
630 p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
631 env->fregs[bank_vector + j],
632 &env->fp_status);
633 r[i] = float32_add(r[i], p, &env->fp_status);
634 }
635 }
485d0035 636 update_fpscr(env, GETPC());
17075f10
AJ
637
638 for (i = 0 ; i < 4 ; i++) {
639 env->fregs[bank_vector + i] = r[i];
640 }
641}