op_helper.c 12.1 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 17
 *  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
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
B
bellard 已提交
19 20
 */
#include <assert.h>
E
edgar_igl 已提交
21
#include <stdlib.h>
B
bellard 已提交
22
#include "exec.h"
P
pbrook 已提交
23
#include "helper.h"
B
bellard 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

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

41
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
B
bellard 已提交
42 43 44 45 46 47 48 49 50 51
{
    TranslationBlock *tb;
    CPUState *saved_env;
    unsigned long pc;
    int ret;

    /* XXX: hack to restore env in all cases, even if not called from
       generated code */
    saved_env = env;
    env = cpu_single_env;
52
    ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
B
bellard 已提交
53 54 55 56 57 58 59 60 61 62 63
    if (ret) {
	if (retaddr) {
	    /* now we have a real cpu fault */
	    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);
	    }
	}
A
aurel32 已提交
64
	cpu_loop_exit();
B
bellard 已提交
65 66 67 68 69 70
    }
    env = saved_env;
}

#endif

A
aurel32 已提交
71 72 73 74 75 76 77 78 79 80
void helper_ldtlb(void)
{
#ifdef CONFIG_USER_ONLY
    /* XXXXX */
    assert(0);
#else
    cpu_load_tlb(env);
#endif
}

A
aurel32 已提交
81 82 83 84 85 86 87 88 89 90 91 92
void helper_raise_illegal_instruction(void)
{
    env->exception_index = 0x180;
    cpu_loop_exit();
}

void helper_raise_slot_illegal_instruction(void)
{
    env->exception_index = 0x1a0;
    cpu_loop_exit();
}

A
aurel32 已提交
93 94 95 96 97 98 99 100 101 102 103 104
void helper_raise_fpu_disable(void)
{
  env->exception_index = 0x800;
  cpu_loop_exit();
}

void helper_raise_slot_fpu_disable(void)
{
  env->exception_index = 0x820;
  cpu_loop_exit();
}

A
aurel32 已提交
105 106 107 108 109 110
void helper_debug(void)
{
    env->exception_index = EXCP_DEBUG;
    cpu_loop_exit();
}

A
aurel32 已提交
111
void helper_sleep(uint32_t next_pc)
A
aurel32 已提交
112 113 114
{
    env->halted = 1;
    env->exception_index = EXCP_HLT;
A
aurel32 已提交
115
    env->pc = next_pc;
A
aurel32 已提交
116 117 118 119 120 121 122 123 124 125
    cpu_loop_exit();
}

void helper_trapa(uint32_t tra)
{
    env->tra = tra << 2;
    env->exception_index = 0x160;
    cpu_loop_exit();
}

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

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

177
uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
178 179 180
{
    uint32_t tmp0, tmp1;

181 182 183
    tmp1 = arg0 + arg1;
    tmp0 = arg1;
    arg1 = tmp1 + (env->sr & 1);
B
bellard 已提交
184 185 186 187
    if (tmp0 > tmp1)
	env->sr |= SR_T;
    else
	env->sr &= ~SR_T;
188
    if (tmp1 > arg1)
B
bellard 已提交
189
	env->sr |= SR_T;
190
    return arg1;
B
bellard 已提交
191 192
}

193
uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
194 195 196
{
    uint32_t dest, src, ans;

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

#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

232
uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
233 234 235 236
{
    uint32_t tmp0, tmp2;
    uint8_t old_q, tmp1 = 0xff;

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

340
void helper_macl(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
341 342 343 344
{
    int64_t res;

    res = ((uint64_t) env->mach << 32) | env->macl;
345
    res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
B
bellard 已提交
346 347 348 349 350 351 352 353 354 355
    env->mach = (res >> 32) & 0xffffffff;
    env->macl = res & 0xffffffff;
    if (env->sr & SR_S) {
	if (res < 0)
	    env->mach |= 0xffff0000;
	else
	    env->mach &= 0x00007fff;
    }
}

356
void helper_macw(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
357 358 359 360
{
    int64_t res;

    res = ((uint64_t) env->mach << 32) | env->macl;
361
    res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
B
bellard 已提交
362 363 364 365 366 367 368 369 370 371 372 373 374
    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;
	}
    }
}

375
uint32_t helper_negc(uint32_t arg)
B
bellard 已提交
376 377 378
{
    uint32_t temp;

379 380
    temp = -arg;
    arg = temp - (env->sr & SR_T);
B
bellard 已提交
381 382 383 384
    if (0 < temp)
	env->sr |= SR_T;
    else
	env->sr &= ~SR_T;
385
    if (temp < arg)
B
bellard 已提交
386
	env->sr |= SR_T;
387
    return arg;
B
bellard 已提交
388 389
}

390
uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
391 392 393
{
    uint32_t tmp0, tmp1;

394 395 396
    tmp1 = arg1 - arg0;
    tmp0 = arg1;
    arg1 = tmp1 - (env->sr & SR_T);
B
bellard 已提交
397 398 399 400
    if (tmp0 < tmp1)
	env->sr |= SR_T;
    else
	env->sr &= ~SR_T;
401
    if (tmp1 < arg1)
B
bellard 已提交
402
	env->sr |= SR_T;
403
    return arg1;
B
bellard 已提交
404 405
}

406
uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
B
bellard 已提交
407 408 409
{
    int32_t dest, src, ans;

410
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
411 412 413
	dest = 0;
    else
	dest = 1;
414
    if ((int32_t) arg0 >= 0)
B
bellard 已提交
415 416 417 418
	src = 0;
    else
	src = 1;
    src += dest;
419 420
    arg1 -= arg0;
    if ((int32_t) arg1 >= 0)
B
bellard 已提交
421 422 423 424 425 426 427 428 429 430 431
	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;
432
    return arg1;
B
bellard 已提交
433 434
}

A
aurel32 已提交
435 436 437 438 439 440 441 442 443 444
static inline void set_t(void)
{
    env->sr |= SR_T;
}

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

445 446 447 448 449 450 451 452
void helper_ld_fpscr(uint32_t val)
{
    env->fpscr = val & 0x003fffff;
    if (val & 0x01)
	set_float_rounding_mode(float_round_to_zero, &env->fp_status);
    else
	set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
}
A
aurel32 已提交
453 454 455

uint32_t helper_fabs_FT(uint32_t t0)
{
456 457 458 459
    CPU_FloatU f;
    f.l = t0;
    f.f = float32_abs(f.f);
    return f.l;
A
aurel32 已提交
460 461 462 463
}

uint64_t helper_fabs_DT(uint64_t t0)
{
464 465 466 467
    CPU_DoubleU d;
    d.ll = t0;
    d.d = float64_abs(d.d);
    return d.ll;
A
aurel32 已提交
468 469 470 471
}

uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
{
472 473 474 475 476
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;
    f0.f = float32_add(f0.f, f1.f, &env->fp_status);
    return f0.l;
A
aurel32 已提交
477 478 479 480
}

uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
{
481 482 483 484 485
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;
    d0.d = float64_add(d0.d, d1.d, &env->fp_status);
    return d0.ll;
A
aurel32 已提交
486 487 488 489
}

void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
{
490 491 492 493 494
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;

    if (float32_compare(f0.f, f1.f, &env->fp_status) == 0)
A
aurel32 已提交
495 496 497 498 499 500 501
	set_t();
    else
	clr_t();
}

void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
{
502 503 504 505 506
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;

    if (float64_compare(d0.d, d1.d, &env->fp_status) == 0)
A
aurel32 已提交
507 508 509 510 511 512 513
	set_t();
    else
	clr_t();
}

void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
{
514 515 516 517 518
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;

    if (float32_compare(f0.f, f1.f, &env->fp_status) == 1)
A
aurel32 已提交
519 520 521 522 523 524 525
	set_t();
    else
	clr_t();
}

void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
{
526 527 528 529 530
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;

    if (float64_compare(d0.d, d1.d, &env->fp_status) == 1)
A
aurel32 已提交
531 532 533 534 535 536 537
	set_t();
    else
	clr_t();
}

uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
{
538 539 540 541 542
    CPU_DoubleU d;
    CPU_FloatU f;
    f.l = t0;
    d.d = float32_to_float64(f.f, &env->fp_status);
    return d.ll;
A
aurel32 已提交
543 544 545 546
}

uint32_t helper_fcnvds_DT_FT(uint64_t t0)
{
547 548 549 550 551
    CPU_DoubleU d;
    CPU_FloatU f;
    d.ll = t0;
    f.f = float64_to_float32(d.d, &env->fp_status);
    return f.l;
A
aurel32 已提交
552 553 554 555
}

uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
{
556 557 558 559 560
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;
    f0.f = float32_div(f0.f, f1.f, &env->fp_status);
    return f0.l;
A
aurel32 已提交
561 562 563 564
}

uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
{
565 566 567 568 569
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;
    d0.d = float64_div(d0.d, d1.d, &env->fp_status);
    return d0.ll;
A
aurel32 已提交
570 571 572 573
}

uint32_t helper_float_FT(uint32_t t0)
{
574 575 576
    CPU_FloatU f;
    f.f = int32_to_float32(t0, &env->fp_status);
    return f.l;
A
aurel32 已提交
577 578 579 580
}

uint64_t helper_float_DT(uint32_t t0)
{
581 582 583
    CPU_DoubleU d;
    d.d = int32_to_float64(t0, &env->fp_status);
    return d.ll;
A
aurel32 已提交
584 585
}

A
aurel32 已提交
586 587 588 589 590 591 592 593 594 595 596
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;
    f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
    f0.f = float32_add(f0.f, f2.f, &env->fp_status);
    return f0.l;
}

A
aurel32 已提交
597 598
uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
{
599 600 601 602 603
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;
    f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
    return f0.l;
A
aurel32 已提交
604 605 606 607
}

uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
{
608 609 610 611 612
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;
    d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
    return d0.ll;
A
aurel32 已提交
613 614
}

A
aurel32 已提交
615 616
uint32_t helper_fneg_T(uint32_t t0)
{
617 618 619 620
    CPU_FloatU f;
    f.l = t0;
    f.f = float32_chs(f.f);
    return f.l;
A
aurel32 已提交
621 622
}

A
aurel32 已提交
623 624
uint32_t helper_fsqrt_FT(uint32_t t0)
{
625 626 627 628
    CPU_FloatU f;
    f.l = t0;
    f.f = float32_sqrt(f.f, &env->fp_status);
    return f.l;
A
aurel32 已提交
629 630 631 632
}

uint64_t helper_fsqrt_DT(uint64_t t0)
{
633 634 635 636
    CPU_DoubleU d;
    d.ll = t0;
    d.d = float64_sqrt(d.d, &env->fp_status);
    return d.ll;
A
aurel32 已提交
637 638 639 640
}

uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
{
641 642 643 644 645
    CPU_FloatU f0, f1;
    f0.l = t0;
    f1.l = t1;
    f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
    return f0.l;
A
aurel32 已提交
646 647 648 649
}

uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
{
650 651 652 653 654
    CPU_DoubleU d0, d1;
    d0.ll = t0;
    d1.ll = t1;
    d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
    return d0.ll;
A
aurel32 已提交
655 656 657 658
}

uint32_t helper_ftrc_FT(uint32_t t0)
{
659 660 661
    CPU_FloatU f;
    f.l = t0;
    return float32_to_int32_round_to_zero(f.f, &env->fp_status);
A
aurel32 已提交
662 663 664 665
}

uint32_t helper_ftrc_DT(uint64_t t0)
{
666 667 668
    CPU_DoubleU d;
    d.ll = t0;
    return float64_to_int32_round_to_zero(d.d, &env->fp_status);
A
aurel32 已提交
669
}