op_helper.c 15.6 KB
Newer Older
B
bellard 已提交
1 2
/*
 *  SH4 emulation
3
 *
B
bellard 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16
 *  Copyright (c) 2005 Samuel Tardieu
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
18 19
 */
#include <assert.h>
E
edgar_igl 已提交
20
#include <stdlib.h>
B
Blue Swirl 已提交
21 22
#include "cpu.h"
#include "dyngen-exec.h"
P
pbrook 已提交
23
#include "helper.h"
B
bellard 已提交
24

25 26 27 28 29 30 31 32 33 34 35
static void cpu_restore_state_from_retaddr(void *retaddr)
{
    TranslationBlock *tb;
    unsigned long pc;

    if (retaddr) {
        pc = (unsigned long) retaddr;
        tb = tb_find_pc(pc);
        if (tb) {
            /* the PC is inside the translated code. It means that we have
               a virtual CPU fault */
36
            cpu_restore_state(tb, env, pc);
37 38 39 40
        }
    }
}

B
bellard 已提交
41
#ifndef CONFIG_USER_ONLY
B
Blue Swirl 已提交
42
#include "softmmu_exec.h"
B
bellard 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

#define MMUSUFFIX _mmu

#define SHIFT 0
#include "softmmu_template.h"

#define SHIFT 1
#include "softmmu_template.h"

#define SHIFT 2
#include "softmmu_template.h"

#define SHIFT 3
#include "softmmu_template.h"

58
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
B
bellard 已提交
59 60 61 62 63 64 65 66
{
    CPUState *saved_env;
    int ret;

    /* XXX: hack to restore env in all cases, even if not called from
       generated code */
    saved_env = env;
    env = cpu_single_env;
67
    ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx);
B
bellard 已提交
68
    if (ret) {
69 70
        /* now we have a real cpu fault */
        cpu_restore_state_from_retaddr(retaddr);
B
Blue Swirl 已提交
71
        cpu_loop_exit(env);
B
bellard 已提交
72 73 74 75 76 77
    }
    env = saved_env;
}

#endif

A
aurel32 已提交
78 79 80 81
void helper_ldtlb(void)
{
#ifdef CONFIG_USER_ONLY
    /* XXXXX */
82
    cpu_abort(env, "Unhandled ldtlb");
A
aurel32 已提交
83 84 85 86 87
#else
    cpu_load_tlb(env);
#endif
}

A
Aurelien Jarno 已提交
88
static inline void raise_exception(int index, void *retaddr)
A
aurel32 已提交
89
{
A
Aurelien Jarno 已提交
90 91
    env->exception_index = index;
    cpu_restore_state_from_retaddr(retaddr);
B
Blue Swirl 已提交
92
    cpu_loop_exit(env);
A
aurel32 已提交
93 94
}

A
Aurelien Jarno 已提交
95 96 97 98 99
void helper_raise_illegal_instruction(void)
{
    raise_exception(0x180, GETPC());
}

A
aurel32 已提交
100 101
void helper_raise_slot_illegal_instruction(void)
{
A
Aurelien Jarno 已提交
102
    raise_exception(0x1a0, GETPC());
A
aurel32 已提交
103 104
}

A
aurel32 已提交
105 106
void helper_raise_fpu_disable(void)
{
A
Aurelien Jarno 已提交
107
    raise_exception(0x800, GETPC());
A
aurel32 已提交
108 109 110 111
}

void helper_raise_slot_fpu_disable(void)
{
A
Aurelien Jarno 已提交
112
    raise_exception(0x820, GETPC());
A
aurel32 已提交
113 114
}

A
aurel32 已提交
115 116 117
void helper_debug(void)
{
    env->exception_index = EXCP_DEBUG;
B
Blue Swirl 已提交
118
    cpu_loop_exit(env);
A
aurel32 已提交
119 120
}

A
aurel32 已提交
121
void helper_sleep(uint32_t next_pc)
A
aurel32 已提交
122 123
{
    env->halted = 1;
124
    env->in_sleep = 1;
A
aurel32 已提交
125
    env->exception_index = EXCP_HLT;
A
aurel32 已提交
126
    env->pc = next_pc;
B
Blue Swirl 已提交
127
    cpu_loop_exit(env);
A
aurel32 已提交
128 129 130 131 132
}

void helper_trapa(uint32_t tra)
{
    env->tra = tra << 2;
A
Aurelien Jarno 已提交
133
    raise_exception(0x160, GETPC());
A
aurel32 已提交
134 135
}

E
edgar_igl 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
void helper_movcal(uint32_t address, uint32_t value)
{
    if (cpu_sh4_is_cached (env, address))
    {
	memory_content *r = malloc (sizeof(memory_content));
	r->address = address;
	r->value = value;
	r->next = NULL;

	*(env->movcal_backup_tail) = r;
	env->movcal_backup_tail = &(r->next);
    }
}

void helper_discard_movcal_backup(void)
{
    memory_content *current = env->movcal_backup;

    while(current)
    {
	memory_content *next = current->next;
	free (current);
	env->movcal_backup = current = next;
159
	if (current == NULL)
E
edgar_igl 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
	    env->movcal_backup_tail = &(env->movcal_backup);
    } 
}

void helper_ocbi(uint32_t address)
{
    memory_content **current = &(env->movcal_backup);
    while (*current)
    {
	uint32_t a = (*current)->address;
	if ((a & ~0x1F) == (address & ~0x1F))
	{
	    memory_content *next = (*current)->next;
	    stl(a, (*current)->value);
	    
175
	    if (next == NULL)
E
edgar_igl 已提交
176 177 178 179 180 181 182 183 184 185 186
	    {
		env->movcal_backup_tail = current;
	    }

	    free (*current);
	    *current = next;
	    break;
	}
    }
}

187
uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
188 189 190
{
    uint32_t tmp0, tmp1;

191 192 193
    tmp1 = arg0 + arg1;
    tmp0 = arg1;
    arg1 = tmp1 + (env->sr & 1);
B
bellard 已提交
194 195 196 197
    if (tmp0 > tmp1)
	env->sr |= SR_T;
    else
	env->sr &= ~SR_T;
198
    if (tmp1 > arg1)
B
bellard 已提交
199
	env->sr |= SR_T;
200
    return arg1;
B
bellard 已提交
201 202
}

203
uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
204 205 206
{
    uint32_t dest, src, ans;

207
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
208 209 210
	dest = 0;
    else
	dest = 1;
211
    if ((int32_t) arg0 >= 0)
B
bellard 已提交
212 213 214 215
	src = 0;
    else
	src = 1;
    src += dest;
216 217
    arg1 += arg0;
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
218 219 220 221 222 223 224 225 226 227 228
	ans = 0;
    else
	ans = 1;
    ans += dest;
    if (src == 0 || src == 2) {
	if (ans == 1)
	    env->sr |= SR_T;
	else
	    env->sr &= ~SR_T;
    } else
	env->sr &= ~SR_T;
229
    return arg1;
B
bellard 已提交
230 231 232 233 234 235 236 237 238 239 240 241
}

#define T (env->sr & SR_T)
#define Q (env->sr & SR_Q ? 1 : 0)
#define M (env->sr & SR_M ? 1 : 0)
#define SETT env->sr |= SR_T
#define CLRT env->sr &= ~SR_T
#define SETQ env->sr |= SR_Q
#define CLRQ env->sr &= ~SR_Q
#define SETM env->sr |= SR_M
#define CLRM env->sr &= ~SR_M

242
uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
243 244 245 246
{
    uint32_t tmp0, tmp2;
    uint8_t old_q, tmp1 = 0xff;

247
    //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
B
bellard 已提交
248
    old_q = Q;
249
    if ((0x80000000 & arg1) != 0)
B
bellard 已提交
250 251 252
	SETQ;
    else
	CLRQ;
253 254 255
    tmp2 = arg0;
    arg1 <<= 1;
    arg1 |= T;
B
bellard 已提交
256 257 258 259
    switch (old_q) {
    case 0:
	switch (M) {
	case 0:
260 261 262
	    tmp0 = arg1;
	    arg1 -= tmp2;
	    tmp1 = arg1 > tmp0;
B
bellard 已提交
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
	    switch (Q) {
	    case 0:
		if (tmp1)
		    SETQ;
		else
		    CLRQ;
		break;
	    case 1:
		if (tmp1 == 0)
		    SETQ;
		else
		    CLRQ;
		break;
	    }
	    break;
	case 1:
279 280 281
	    tmp0 = arg1;
	    arg1 += tmp2;
	    tmp1 = arg1 < tmp0;
B
bellard 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
	    switch (Q) {
	    case 0:
		if (tmp1 == 0)
		    SETQ;
		else
		    CLRQ;
		break;
	    case 1:
		if (tmp1)
		    SETQ;
		else
		    CLRQ;
		break;
	    }
	    break;
	}
	break;
    case 1:
	switch (M) {
	case 0:
302 303 304
	    tmp0 = arg1;
	    arg1 += tmp2;
	    tmp1 = arg1 < tmp0;
B
bellard 已提交
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
	    switch (Q) {
	    case 0:
		if (tmp1)
		    SETQ;
		else
		    CLRQ;
		break;
	    case 1:
		if (tmp1 == 0)
		    SETQ;
		else
		    CLRQ;
		break;
	    }
	    break;
	case 1:
321 322 323
	    tmp0 = arg1;
	    arg1 -= tmp2;
	    tmp1 = arg1 > tmp0;
B
bellard 已提交
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
	    switch (Q) {
	    case 0:
		if (tmp1 == 0)
		    SETQ;
		else
		    CLRQ;
		break;
	    case 1:
		if (tmp1)
		    SETQ;
		else
		    CLRQ;
		break;
	    }
	    break;
	}
	break;
    }
    if (Q == M)
	SETT;
    else
	CLRT;
346 347
    //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
    return arg1;
B
bellard 已提交
348 349
}

350
void helper_macl(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
351 352 353 354
{
    int64_t res;

    res = ((uint64_t) env->mach << 32) | env->macl;
355
    res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
B
bellard 已提交
356 357 358 359 360 361 362 363 364 365
    env->mach = (res >> 32) & 0xffffffff;
    env->macl = res & 0xffffffff;
    if (env->sr & SR_S) {
	if (res < 0)
	    env->mach |= 0xffff0000;
	else
	    env->mach &= 0x00007fff;
    }
}

366
void helper_macw(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
367 368 369 370
{
    int64_t res;

    res = ((uint64_t) env->mach << 32) | env->macl;
371
    res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
B
bellard 已提交
372 373 374 375 376 377 378 379 380 381 382 383 384
    env->mach = (res >> 32) & 0xffffffff;
    env->macl = res & 0xffffffff;
    if (env->sr & SR_S) {
	if (res < -0x80000000) {
	    env->mach = 1;
	    env->macl = 0x80000000;
	} else if (res > 0x000000007fffffff) {
	    env->mach = 1;
	    env->macl = 0x7fffffff;
	}
    }
}

385
uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
386 387 388
{
    uint32_t tmp0, tmp1;

389 390 391
    tmp1 = arg1 - arg0;
    tmp0 = arg1;
    arg1 = tmp1 - (env->sr & SR_T);
B
bellard 已提交
392 393 394 395
    if (tmp0 < tmp1)
	env->sr |= SR_T;
    else
	env->sr &= ~SR_T;
396
    if (tmp1 < arg1)
B
bellard 已提交
397
	env->sr |= SR_T;
398
    return arg1;
B
bellard 已提交
399 400
}

401
uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
402 403 404
{
    int32_t dest, src, ans;

405
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
406 407 408
	dest = 0;
    else
	dest = 1;
409
    if ((int32_t) arg0 >= 0)
B
bellard 已提交
410 411 412 413
	src = 0;
    else
	src = 1;
    src += dest;
414 415
    arg1 -= arg0;
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
416 417 418 419 420 421 422 423 424 425 426
	ans = 0;
    else
	ans = 1;
    ans += dest;
    if (src == 1) {
	if (ans == 1)
	    env->sr |= SR_T;
	else
	    env->sr &= ~SR_T;
    } else
	env->sr &= ~SR_T;
427
    return arg1;
B
bellard 已提交
428 429
}

A
aurel32 已提交
430 431 432 433 434 435 436 437 438 439
static inline void set_t(void)
{
    env->sr |= SR_T;
}

static inline void clr_t(void)
{
    env->sr &= ~SR_T;
}

440 441
void helper_ld_fpscr(uint32_t val)
{
442 443
    env->fpscr = val & FPSCR_MASK;
    if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
444
	set_float_rounding_mode(float_round_to_zero, &env->fp_status);
445
    } else {
446
	set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
447
    }
448
    set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
449
}
A
aurel32 已提交
450

451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
static void update_fpscr(void *retaddr)
{
    int xcpt, cause, enable;

    xcpt = get_float_exception_flags(&env->fp_status);

    /* Clear the flag entries */
    env->fpscr &= ~FPSCR_FLAG_MASK;

    if (unlikely(xcpt)) {
        if (xcpt & float_flag_invalid) {
            env->fpscr |= FPSCR_FLAG_V;
        }
        if (xcpt & float_flag_divbyzero) {
            env->fpscr |= FPSCR_FLAG_Z;
        }
        if (xcpt & float_flag_overflow) {
            env->fpscr |= FPSCR_FLAG_O;
        }
        if (xcpt & float_flag_underflow) {
            env->fpscr |= FPSCR_FLAG_U;
        }
        if (xcpt & float_flag_inexact) {
            env->fpscr |= FPSCR_FLAG_I;
        }

        /* Accumulate in cause entries */
        env->fpscr |= (env->fpscr & FPSCR_FLAG_MASK)
                      << (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT);

        /* Generate an exception if enabled */
        cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
        enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
        if (cause & enable) {
            cpu_restore_state_from_retaddr(retaddr);
            env->exception_index = 0x120;
B
Blue Swirl 已提交
487
            cpu_loop_exit(env);
488 489 490 491
        }
    }
}

492
float32 helper_fabs_FT(float32 t0)
A
aurel32 已提交
493
{
494
    return float32_abs(t0);
A
aurel32 已提交
495 496
}

497
float64 helper_fabs_DT(float64 t0)
A
aurel32 已提交
498
{
499
    return float64_abs(t0);
A
aurel32 已提交
500 501
}

502
float32 helper_fadd_FT(float32 t0, float32 t1)
A
aurel32 已提交
503
{
504
    set_float_exception_flags(0, &env->fp_status);
505
    t0 = float32_add(t0, t1, &env->fp_status);
506
    update_fpscr(GETPC());
507
    return t0;
A
aurel32 已提交
508 509
}

510
float64 helper_fadd_DT(float64 t0, float64 t1)
A
aurel32 已提交
511
{
512
    set_float_exception_flags(0, &env->fp_status);
513
    t0 = float64_add(t0, t1, &env->fp_status);
514
    update_fpscr(GETPC());
515
    return t0;
A
aurel32 已提交
516 517
}

518
void helper_fcmp_eq_FT(float32 t0, float32 t1)
A
aurel32 已提交
519
{
520
    int relation;
521

522
    set_float_exception_flags(0, &env->fp_status);
523
    relation = float32_compare(t0, t1, &env->fp_status);
524 525 526
    if (unlikely(relation == float_relation_unordered)) {
        update_fpscr(GETPC());
    } else if (relation == float_relation_equal) {
A
aurel32 已提交
527
	set_t();
528
    } else {
A
aurel32 已提交
529
	clr_t();
530
    }
A
aurel32 已提交
531 532
}

533
void helper_fcmp_eq_DT(float64 t0, float64 t1)
A
aurel32 已提交
534
{
535
    int relation;
536

537
    set_float_exception_flags(0, &env->fp_status);
538
    relation = float64_compare(t0, t1, &env->fp_status);
539 540 541
    if (unlikely(relation == float_relation_unordered)) {
        update_fpscr(GETPC());
    } else if (relation == float_relation_equal) {
A
aurel32 已提交
542
	set_t();
543
    } else {
A
aurel32 已提交
544
	clr_t();
545
    }
A
aurel32 已提交
546 547
}

548
void helper_fcmp_gt_FT(float32 t0, float32 t1)
A
aurel32 已提交
549
{
550
    int relation;
551

552
    set_float_exception_flags(0, &env->fp_status);
553
    relation = float32_compare(t0, t1, &env->fp_status);
554 555 556
    if (unlikely(relation == float_relation_unordered)) {
        update_fpscr(GETPC());
    } else if (relation == float_relation_greater) {
A
aurel32 已提交
557
	set_t();
558
    } else {
A
aurel32 已提交
559
	clr_t();
560
    }
A
aurel32 已提交
561 562
}

563
void helper_fcmp_gt_DT(float64 t0, float64 t1)
A
aurel32 已提交
564
{
565
    int relation;
566

567
    set_float_exception_flags(0, &env->fp_status);
568
    relation = float64_compare(t0, t1, &env->fp_status);
569 570 571
    if (unlikely(relation == float_relation_unordered)) {
        update_fpscr(GETPC());
    } else if (relation == float_relation_greater) {
A
aurel32 已提交
572
	set_t();
573
    } else {
A
aurel32 已提交
574
	clr_t();
575
    }
A
aurel32 已提交
576 577
}

578
float64 helper_fcnvsd_FT_DT(float32 t0)
A
aurel32 已提交
579
{
580
    float64 ret;
581
    set_float_exception_flags(0, &env->fp_status);
582
    ret = float32_to_float64(t0, &env->fp_status);
583
    update_fpscr(GETPC());
584
    return ret;
A
aurel32 已提交
585 586
}

587
float32 helper_fcnvds_DT_FT(float64 t0)
A
aurel32 已提交
588
{
589
    float32 ret;
590
    set_float_exception_flags(0, &env->fp_status);
591
    ret = float64_to_float32(t0, &env->fp_status);
592
    update_fpscr(GETPC());
593
    return ret;
A
aurel32 已提交
594 595
}

596
float32 helper_fdiv_FT(float32 t0, float32 t1)
A
aurel32 已提交
597
{
598
    set_float_exception_flags(0, &env->fp_status);
599
    t0 = float32_div(t0, t1, &env->fp_status);
600
    update_fpscr(GETPC());
601
    return t0;
A
aurel32 已提交
602 603
}

604
float64 helper_fdiv_DT(float64 t0, float64 t1)
A
aurel32 已提交
605
{
606
    set_float_exception_flags(0, &env->fp_status);
607
    t0 = float64_div(t0, t1, &env->fp_status);
608
    update_fpscr(GETPC());
609
    return t0;
A
aurel32 已提交
610 611
}

612
float32 helper_float_FT(uint32_t t0)
A
aurel32 已提交
613
{
614
    float32 ret;
615
    set_float_exception_flags(0, &env->fp_status);
616
    ret = int32_to_float32(t0, &env->fp_status);
617
    update_fpscr(GETPC());
618
    return ret;
A
aurel32 已提交
619 620
}

621
float64 helper_float_DT(uint32_t t0)
A
aurel32 已提交
622
{
623
    float64 ret;
624
    set_float_exception_flags(0, &env->fp_status);
625
    ret = int32_to_float64(t0, &env->fp_status);
626
    update_fpscr(GETPC());
627
    return ret;
A
aurel32 已提交
628 629
}

630
float32 helper_fmac_FT(float32 t0, float32 t1, float32 t2)
A
aurel32 已提交
631
{
632
    set_float_exception_flags(0, &env->fp_status);
633 634
    t0 = float32_mul(t0, t1, &env->fp_status);
    t0 = float32_add(t0, t2, &env->fp_status);
635
    update_fpscr(GETPC());
636
    return t0;
A
aurel32 已提交
637 638
}

639
float32 helper_fmul_FT(float32 t0, float32 t1)
A
aurel32 已提交
640
{
641
    set_float_exception_flags(0, &env->fp_status);
642
    t0 = float32_mul(t0, t1, &env->fp_status);
643
    update_fpscr(GETPC());
644
    return t0;
A
aurel32 已提交
645 646
}

647
float64 helper_fmul_DT(float64 t0, float64 t1)
A
aurel32 已提交
648
{
649
    set_float_exception_flags(0, &env->fp_status);
650
    t0 = float64_mul(t0, t1, &env->fp_status);
651
    update_fpscr(GETPC());
652
    return t0;
A
aurel32 已提交
653 654
}

655
float32 helper_fneg_T(float32 t0)
A
aurel32 已提交
656
{
657
    return float32_chs(t0);
A
aurel32 已提交
658 659
}

660
float32 helper_fsqrt_FT(float32 t0)
A
aurel32 已提交
661
{
662
    set_float_exception_flags(0, &env->fp_status);
663
    t0 = float32_sqrt(t0, &env->fp_status);
664
    update_fpscr(GETPC());
665
    return t0;
A
aurel32 已提交
666 667
}

668
float64 helper_fsqrt_DT(float64 t0)
A
aurel32 已提交
669
{
670
    set_float_exception_flags(0, &env->fp_status);
671
    t0 = float64_sqrt(t0, &env->fp_status);
672
    update_fpscr(GETPC());
673
    return t0;
A
aurel32 已提交
674 675
}

676
float32 helper_fsub_FT(float32 t0, float32 t1)
A
aurel32 已提交
677
{
678
    set_float_exception_flags(0, &env->fp_status);
679
    t0 = float32_sub(t0, t1, &env->fp_status);
680
    update_fpscr(GETPC());
681
    return t0;
A
aurel32 已提交
682 683
}

684
float64 helper_fsub_DT(float64 t0, float64 t1)
A
aurel32 已提交
685
{
686
    set_float_exception_flags(0, &env->fp_status);
687
    t0 = float64_sub(t0, t1, &env->fp_status);
688
    update_fpscr(GETPC());
689
    return t0;
A
aurel32 已提交
690 691
}

692
uint32_t helper_ftrc_FT(float32 t0)
A
aurel32 已提交
693
{
694 695
    uint32_t ret;
    set_float_exception_flags(0, &env->fp_status);
696
    ret = float32_to_int32_round_to_zero(t0, &env->fp_status);
697 698
    update_fpscr(GETPC());
    return ret;
A
aurel32 已提交
699 700
}

701
uint32_t helper_ftrc_DT(float64 t0)
A
aurel32 已提交
702
{
703 704
    uint32_t ret;
    set_float_exception_flags(0, &env->fp_status);
705
    ret = float64_to_int32_round_to_zero(t0, &env->fp_status);
706 707
    update_fpscr(GETPC());
    return ret;
A
aurel32 已提交
708
}
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728

void helper_fipr(uint32_t m, uint32_t n)
{
    int bank, i;
    float32 r, p;

    bank = (env->sr & FPSCR_FR) ? 16 : 0;
    r = float32_zero;
    set_float_exception_flags(0, &env->fp_status);

    for (i = 0 ; i < 4 ; i++) {
        p = float32_mul(env->fregs[bank + m + i],
                        env->fregs[bank + n + i],
                        &env->fp_status);
        r = float32_add(r, p, &env->fp_status);
    }
    update_fpscr(GETPC());

    env->fregs[bank + n + 3] = r;
}
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754

void helper_ftrv(uint32_t n)
{
    int bank_matrix, bank_vector;
    int i, j;
    float32 r[4];
    float32 p;

    bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
    bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
    set_float_exception_flags(0, &env->fp_status);
    for (i = 0 ; i < 4 ; i++) {
        r[i] = float32_zero;
        for (j = 0 ; j < 4 ; j++) {
            p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
                            env->fregs[bank_vector + j],
                            &env->fp_status);
            r[i] = float32_add(r[i], p, &env->fp_status);
        }
    }
    update_fpscr(GETPC());

    for (i = 0 ; i < 4 ; i++) {
        env->fregs[bank_vector + i] = r[i];
    }
}