op_helper.c 16.8 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
bellard 已提交
21
#include "exec.h"
P
pbrook 已提交
22
#include "helper.h"
B
bellard 已提交
23

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
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 */
            cpu_restore_state(tb, env, pc, NULL);
        }
    }
}

B
bellard 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#ifndef CONFIG_USER_ONLY

#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"

56
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
B
bellard 已提交
57 58 59 60 61 62 63 64
{
    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;
65
    ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
B
bellard 已提交
66
    if (ret) {
67 68
        /* now we have a real cpu fault */
        cpu_restore_state_from_retaddr(retaddr);
A
aurel32 已提交
69
	cpu_loop_exit();
B
bellard 已提交
70 71 72 73 74 75
    }
    env = saved_env;
}

#endif

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

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

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

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

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

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

A
aurel32 已提交
113 114 115 116 117 118
void helper_debug(void)
{
    env->exception_index = EXCP_DEBUG;
    cpu_loop_exit();
}

A
aurel32 已提交
119
void helper_sleep(uint32_t next_pc)
A
aurel32 已提交
120 121 122
{
    env->halted = 1;
    env->exception_index = EXCP_HLT;
A
aurel32 已提交
123
    env->pc = next_pc;
A
aurel32 已提交
124 125 126 127 128 129
    cpu_loop_exit();
}

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

E
edgar_igl 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
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;
156
	if (current == NULL)
E
edgar_igl 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
	    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);
	    
172
	    if (next == NULL)
E
edgar_igl 已提交
173 174 175 176 177 178 179 180 181 182 183
	    {
		env->movcal_backup_tail = current;
	    }

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

184
uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
185 186 187
{
    uint32_t tmp0, tmp1;

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

200
uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
201 202 203
{
    uint32_t dest, src, ans;

204
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
205 206 207
	dest = 0;
    else
	dest = 1;
208
    if ((int32_t) arg0 >= 0)
B
bellard 已提交
209 210 211 212
	src = 0;
    else
	src = 1;
    src += dest;
213 214
    arg1 += arg0;
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
215 216 217 218 219 220 221 222 223 224 225
	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;
226
    return arg1;
B
bellard 已提交
227 228 229 230 231 232 233 234 235 236 237 238
}

#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

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

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

347
void helper_macl(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
348 349 350 351
{
    int64_t res;

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

363
void helper_macw(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
364 365 366 367
{
    int64_t res;

    res = ((uint64_t) env->mach << 32) | env->macl;
368
    res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
B
bellard 已提交
369 370 371 372 373 374 375 376 377 378 379 380 381
    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;
	}
    }
}

382
uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
383 384 385
{
    uint32_t tmp0, tmp1;

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

398
uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
399 400 401
{
    int32_t dest, src, ans;

402
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
403 404 405
	dest = 0;
    else
	dest = 1;
406
    if ((int32_t) arg0 >= 0)
B
bellard 已提交
407 408 409 410
	src = 0;
    else
	src = 1;
    src += dest;
411 412
    arg1 -= arg0;
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
413 414 415 416 417 418 419 420 421 422 423
	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;
424
    return arg1;
B
bellard 已提交
425 426
}

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

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

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

448 449 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 487 488
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;
            cpu_loop_exit();
        }
    }
}

A
aurel32 已提交
489 490
uint32_t helper_fabs_FT(uint32_t t0)
{
491 492 493 494
    CPU_FloatU f;
    f.l = t0;
    f.f = float32_abs(f.f);
    return f.l;
A
aurel32 已提交
495 496 497 498
}

uint64_t helper_fabs_DT(uint64_t t0)
{
499 500 501 502
    CPU_DoubleU d;
    d.ll = t0;
    d.d = float64_abs(d.d);
    return d.ll;
A
aurel32 已提交
503 504 505 506
}

uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
{
507 508 509
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;
510
    set_float_exception_flags(0, &env->fp_status);
511
    f0.f = float32_add(f0.f, f1.f, &env->fp_status);
512
    update_fpscr(GETPC());
513
    return f0.l;
A
aurel32 已提交
514 515 516 517
}

uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
{
518 519 520
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;
521
    set_float_exception_flags(0, &env->fp_status);
522
    d0.d = float64_add(d0.d, d1.d, &env->fp_status);
523
    update_fpscr(GETPC());
524
    return d0.ll;
A
aurel32 已提交
525 526 527 528
}

void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
{
529
    CPU_FloatU f0, f1;
530
    int relation;
531 532 533
    f0.l = t0;
    f1.l = t1;

534 535 536 537 538
    set_float_exception_flags(0, &env->fp_status);
    relation = float32_compare(f0.f, f1.f, &env->fp_status);
    if (unlikely(relation == float_relation_unordered)) {
        update_fpscr(GETPC());
    } else if (relation == float_relation_equal) {
A
aurel32 已提交
539
	set_t();
540
    } else {
A
aurel32 已提交
541
	clr_t();
542
    }
A
aurel32 已提交
543 544 545 546
}

void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
{
547
    CPU_DoubleU d0, d1;
548
    int relation;
549 550 551
    d0.ll = t0;
    d1.ll = t1;

552 553 554 555 556
    set_float_exception_flags(0, &env->fp_status);
    relation = float64_compare(d0.d, d1.d, &env->fp_status);
    if (unlikely(relation == float_relation_unordered)) {
        update_fpscr(GETPC());
    } else if (relation == float_relation_equal) {
A
aurel32 已提交
557
	set_t();
558
    } else {
A
aurel32 已提交
559
	clr_t();
560
    }
A
aurel32 已提交
561 562 563 564
}

void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
{
565
    CPU_FloatU f0, f1;
566
    int relation;
567 568 569
    f0.l = t0;
    f1.l = t1;

570 571 572 573 574
    set_float_exception_flags(0, &env->fp_status);
    relation = float32_compare(f0.f, f1.f, &env->fp_status);
    if (unlikely(relation == float_relation_unordered)) {
        update_fpscr(GETPC());
    } else if (relation == float_relation_greater) {
A
aurel32 已提交
575
	set_t();
576
    } else {
A
aurel32 已提交
577
	clr_t();
578
    }
A
aurel32 已提交
579 580 581 582
}

void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
{
583
    CPU_DoubleU d0, d1;
584
    int relation;
585 586 587
    d0.ll = t0;
    d1.ll = t1;

588 589 590 591 592
    set_float_exception_flags(0, &env->fp_status);
    relation = float64_compare(d0.d, d1.d, &env->fp_status);
    if (unlikely(relation == float_relation_unordered)) {
        update_fpscr(GETPC());
    } else if (relation == float_relation_greater) {
A
aurel32 已提交
593
	set_t();
594
    } else {
A
aurel32 已提交
595
	clr_t();
596
    }
A
aurel32 已提交
597 598 599 600
}

uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
{
601 602 603
    CPU_DoubleU d;
    CPU_FloatU f;
    f.l = t0;
604
    set_float_exception_flags(0, &env->fp_status);
605
    d.d = float32_to_float64(f.f, &env->fp_status);
606
    update_fpscr(GETPC());
607
    return d.ll;
A
aurel32 已提交
608 609 610 611
}

uint32_t helper_fcnvds_DT_FT(uint64_t t0)
{
612 613 614
    CPU_DoubleU d;
    CPU_FloatU f;
    d.ll = t0;
615
    set_float_exception_flags(0, &env->fp_status);
616
    f.f = float64_to_float32(d.d, &env->fp_status);
617
    update_fpscr(GETPC());
618
    return f.l;
A
aurel32 已提交
619 620 621 622
}

uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
{
623 624 625
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;
626
    set_float_exception_flags(0, &env->fp_status);
627
    f0.f = float32_div(f0.f, f1.f, &env->fp_status);
628
    update_fpscr(GETPC());
629
    return f0.l;
A
aurel32 已提交
630 631 632 633
}

uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
{
634 635 636
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;
637
    set_float_exception_flags(0, &env->fp_status);
638
    d0.d = float64_div(d0.d, d1.d, &env->fp_status);
639
    update_fpscr(GETPC());
640
    return d0.ll;
A
aurel32 已提交
641 642 643 644
}

uint32_t helper_float_FT(uint32_t t0)
{
645
    CPU_FloatU f;
646 647

    set_float_exception_flags(0, &env->fp_status);
648
    f.f = int32_to_float32(t0, &env->fp_status);
649 650
    update_fpscr(GETPC());

651
    return f.l;
A
aurel32 已提交
652 653 654 655
}

uint64_t helper_float_DT(uint32_t t0)
{
656
    CPU_DoubleU d;
657
    set_float_exception_flags(0, &env->fp_status);
658
    d.d = int32_to_float64(t0, &env->fp_status);
659
    update_fpscr(GETPC());
660
    return d.ll;
A
aurel32 已提交
661 662
}

A
aurel32 已提交
663 664 665 666 667 668
uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
{
    CPU_FloatU f0, f1, f2;
    f0.l = t0;
    f1.l = t1;
    f2.l = t2;
669
    set_float_exception_flags(0, &env->fp_status);
A
aurel32 已提交
670 671
    f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
    f0.f = float32_add(f0.f, f2.f, &env->fp_status);
672 673
    update_fpscr(GETPC());

A
aurel32 已提交
674 675 676
    return f0.l;
}

A
aurel32 已提交
677 678
uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
{
679 680 681
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;
682
    set_float_exception_flags(0, &env->fp_status);
683
    f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
684
    update_fpscr(GETPC());
685
    return f0.l;
A
aurel32 已提交
686 687 688 689
}

uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
{
690 691 692
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;
693
    set_float_exception_flags(0, &env->fp_status);
694
    d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
695 696
    update_fpscr(GETPC());

697
    return d0.ll;
A
aurel32 已提交
698 699
}

A
aurel32 已提交
700 701
uint32_t helper_fneg_T(uint32_t t0)
{
702 703 704 705
    CPU_FloatU f;
    f.l = t0;
    f.f = float32_chs(f.f);
    return f.l;
A
aurel32 已提交
706 707
}

A
aurel32 已提交
708 709
uint32_t helper_fsqrt_FT(uint32_t t0)
{
710 711
    CPU_FloatU f;
    f.l = t0;
712
    set_float_exception_flags(0, &env->fp_status);
713
    f.f = float32_sqrt(f.f, &env->fp_status);
714
    update_fpscr(GETPC());
715
    return f.l;
A
aurel32 已提交
716 717 718 719
}

uint64_t helper_fsqrt_DT(uint64_t t0)
{
720 721
    CPU_DoubleU d;
    d.ll = t0;
722
    set_float_exception_flags(0, &env->fp_status);
723
    d.d = float64_sqrt(d.d, &env->fp_status);
724
    update_fpscr(GETPC());
725
    return d.ll;
A
aurel32 已提交
726 727 728 729
}

uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
{
730 731 732
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;
733
    set_float_exception_flags(0, &env->fp_status);
734
    f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
735
    update_fpscr(GETPC());
736
    return f0.l;
A
aurel32 已提交
737 738 739 740
}

uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
{
741
    CPU_DoubleU d0, d1;
742

743 744
    d0.ll = t0;
    d1.ll = t1;
745
    set_float_exception_flags(0, &env->fp_status);
746
    d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
747
    update_fpscr(GETPC());
748
    return d0.ll;
A
aurel32 已提交
749 750 751 752
}

uint32_t helper_ftrc_FT(uint32_t t0)
{
753
    CPU_FloatU f;
754
    uint32_t ret;
755
    f.l = t0;
756 757 758 759
    set_float_exception_flags(0, &env->fp_status);
    ret = float32_to_int32_round_to_zero(f.f, &env->fp_status);
    update_fpscr(GETPC());
    return ret;
A
aurel32 已提交
760 761 762 763
}

uint32_t helper_ftrc_DT(uint64_t t0)
{
764
    CPU_DoubleU d;
765
    uint32_t ret;
766
    d.ll = t0;
767 768 769 770
    set_float_exception_flags(0, &env->fp_status);
    ret = float64_to_int32_round_to_zero(d.d, &env->fp_status);
    update_fpscr(GETPC());
    return ret;
A
aurel32 已提交
771
}
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791

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;
}
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817

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];
    }
}