File:  [Qemu by Fabrice Bellard] / qemu / target-sh4 / op_helper.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:51:06 2018 UTC (3 years, 9 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    1: /*
    2:  *  SH4 emulation
    3:  *
    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
   17:  * 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
   19:  */
   20: #include <assert.h>
   21: #include "exec.h"
   22: #include "helper.h"
   23: 
   24: #ifndef CONFIG_USER_ONLY
   25: 
   26: #define MMUSUFFIX _mmu
   27: 
   28: #define SHIFT 0
   29: #include "softmmu_template.h"
   30: 
   31: #define SHIFT 1
   32: #include "softmmu_template.h"
   33: 
   34: #define SHIFT 2
   35: #include "softmmu_template.h"
   36: 
   37: #define SHIFT 3
   38: #include "softmmu_template.h"
   39: 
   40: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
   41: {
   42:     TranslationBlock *tb;
   43:     CPUState *saved_env;
   44:     unsigned long pc;
   45:     int ret;
   46: 
   47:     /* XXX: hack to restore env in all cases, even if not called from
   48:        generated code */
   49:     saved_env = env;
   50:     env = cpu_single_env;
   51:     ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
   52:     if (ret) {
   53: 	if (retaddr) {
   54: 	    /* now we have a real cpu fault */
   55: 	    pc = (unsigned long) retaddr;
   56: 	    tb = tb_find_pc(pc);
   57: 	    if (tb) {
   58: 		/* the PC is inside the translated code. It means that we have
   59: 		   a virtual CPU fault */
   60: 		cpu_restore_state(tb, env, pc, NULL);
   61: 	    }
   62: 	}
   63: 	cpu_loop_exit();
   64:     }
   65:     env = saved_env;
   66: }
   67: 
   68: #endif
   69: 
   70: void helper_ldtlb(void)
   71: {
   72: #ifdef CONFIG_USER_ONLY
   73:     /* XXXXX */
   74:     assert(0);
   75: #else
   76:     cpu_load_tlb(env);
   77: #endif
   78: }
   79: 
   80: void helper_raise_illegal_instruction(void)
   81: {
   82:     env->exception_index = 0x180;
   83:     cpu_loop_exit();
   84: }
   85: 
   86: void helper_raise_slot_illegal_instruction(void)
   87: {
   88:     env->exception_index = 0x1a0;
   89:     cpu_loop_exit();
   90: }
   91: 
   92: void helper_raise_fpu_disable(void)
   93: {
   94:   env->exception_index = 0x800;
   95:   cpu_loop_exit();
   96: }
   97: 
   98: void helper_raise_slot_fpu_disable(void)
   99: {
  100:   env->exception_index = 0x820;
  101:   cpu_loop_exit();
  102: }
  103: 
  104: void helper_debug(void)
  105: {
  106:     env->exception_index = EXCP_DEBUG;
  107:     cpu_loop_exit();
  108: }
  109: 
  110: void helper_sleep(uint32_t next_pc)
  111: {
  112:     env->halted = 1;
  113:     env->exception_index = EXCP_HLT;
  114:     env->pc = next_pc;
  115:     cpu_loop_exit();
  116: }
  117: 
  118: void helper_trapa(uint32_t tra)
  119: {
  120:     env->tra = tra << 2;
  121:     env->exception_index = 0x160;
  122:     cpu_loop_exit();
  123: }
  124: 
  125: uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
  126: {
  127:     uint32_t tmp0, tmp1;
  128: 
  129:     tmp1 = arg0 + arg1;
  130:     tmp0 = arg1;
  131:     arg1 = tmp1 + (env->sr & 1);
  132:     if (tmp0 > tmp1)
  133: 	env->sr |= SR_T;
  134:     else
  135: 	env->sr &= ~SR_T;
  136:     if (tmp1 > arg1)
  137: 	env->sr |= SR_T;
  138:     return arg1;
  139: }
  140: 
  141: uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
  142: {
  143:     uint32_t dest, src, ans;
  144: 
  145:     if ((int32_t) arg1 >= 0)
  146: 	dest = 0;
  147:     else
  148: 	dest = 1;
  149:     if ((int32_t) arg0 >= 0)
  150: 	src = 0;
  151:     else
  152: 	src = 1;
  153:     src += dest;
  154:     arg1 += arg0;
  155:     if ((int32_t) arg1 >= 0)
  156: 	ans = 0;
  157:     else
  158: 	ans = 1;
  159:     ans += dest;
  160:     if (src == 0 || src == 2) {
  161: 	if (ans == 1)
  162: 	    env->sr |= SR_T;
  163: 	else
  164: 	    env->sr &= ~SR_T;
  165:     } else
  166: 	env->sr &= ~SR_T;
  167:     return arg1;
  168: }
  169: 
  170: #define T (env->sr & SR_T)
  171: #define Q (env->sr & SR_Q ? 1 : 0)
  172: #define M (env->sr & SR_M ? 1 : 0)
  173: #define SETT env->sr |= SR_T
  174: #define CLRT env->sr &= ~SR_T
  175: #define SETQ env->sr |= SR_Q
  176: #define CLRQ env->sr &= ~SR_Q
  177: #define SETM env->sr |= SR_M
  178: #define CLRM env->sr &= ~SR_M
  179: 
  180: uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
  181: {
  182:     uint32_t tmp0, tmp2;
  183:     uint8_t old_q, tmp1 = 0xff;
  184: 
  185:     //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
  186:     old_q = Q;
  187:     if ((0x80000000 & arg1) != 0)
  188: 	SETQ;
  189:     else
  190: 	CLRQ;
  191:     tmp2 = arg0;
  192:     arg1 <<= 1;
  193:     arg1 |= T;
  194:     switch (old_q) {
  195:     case 0:
  196: 	switch (M) {
  197: 	case 0:
  198: 	    tmp0 = arg1;
  199: 	    arg1 -= tmp2;
  200: 	    tmp1 = arg1 > tmp0;
  201: 	    switch (Q) {
  202: 	    case 0:
  203: 		if (tmp1)
  204: 		    SETQ;
  205: 		else
  206: 		    CLRQ;
  207: 		break;
  208: 	    case 1:
  209: 		if (tmp1 == 0)
  210: 		    SETQ;
  211: 		else
  212: 		    CLRQ;
  213: 		break;
  214: 	    }
  215: 	    break;
  216: 	case 1:
  217: 	    tmp0 = arg1;
  218: 	    arg1 += tmp2;
  219: 	    tmp1 = arg1 < tmp0;
  220: 	    switch (Q) {
  221: 	    case 0:
  222: 		if (tmp1 == 0)
  223: 		    SETQ;
  224: 		else
  225: 		    CLRQ;
  226: 		break;
  227: 	    case 1:
  228: 		if (tmp1)
  229: 		    SETQ;
  230: 		else
  231: 		    CLRQ;
  232: 		break;
  233: 	    }
  234: 	    break;
  235: 	}
  236: 	break;
  237:     case 1:
  238: 	switch (M) {
  239: 	case 0:
  240: 	    tmp0 = arg1;
  241: 	    arg1 += tmp2;
  242: 	    tmp1 = arg1 < tmp0;
  243: 	    switch (Q) {
  244: 	    case 0:
  245: 		if (tmp1)
  246: 		    SETQ;
  247: 		else
  248: 		    CLRQ;
  249: 		break;
  250: 	    case 1:
  251: 		if (tmp1 == 0)
  252: 		    SETQ;
  253: 		else
  254: 		    CLRQ;
  255: 		break;
  256: 	    }
  257: 	    break;
  258: 	case 1:
  259: 	    tmp0 = arg1;
  260: 	    arg1 -= tmp2;
  261: 	    tmp1 = arg1 > tmp0;
  262: 	    switch (Q) {
  263: 	    case 0:
  264: 		if (tmp1 == 0)
  265: 		    SETQ;
  266: 		else
  267: 		    CLRQ;
  268: 		break;
  269: 	    case 1:
  270: 		if (tmp1)
  271: 		    SETQ;
  272: 		else
  273: 		    CLRQ;
  274: 		break;
  275: 	    }
  276: 	    break;
  277: 	}
  278: 	break;
  279:     }
  280:     if (Q == M)
  281: 	SETT;
  282:     else
  283: 	CLRT;
  284:     //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
  285:     return arg1;
  286: }
  287: 
  288: void helper_macl(uint32_t arg0, uint32_t arg1)
  289: {
  290:     int64_t res;
  291: 
  292:     res = ((uint64_t) env->mach << 32) | env->macl;
  293:     res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
  294:     env->mach = (res >> 32) & 0xffffffff;
  295:     env->macl = res & 0xffffffff;
  296:     if (env->sr & SR_S) {
  297: 	if (res < 0)
  298: 	    env->mach |= 0xffff0000;
  299: 	else
  300: 	    env->mach &= 0x00007fff;
  301:     }
  302: }
  303: 
  304: void helper_macw(uint32_t arg0, uint32_t arg1)
  305: {
  306:     int64_t res;
  307: 
  308:     res = ((uint64_t) env->mach << 32) | env->macl;
  309:     res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
  310:     env->mach = (res >> 32) & 0xffffffff;
  311:     env->macl = res & 0xffffffff;
  312:     if (env->sr & SR_S) {
  313: 	if (res < -0x80000000) {
  314: 	    env->mach = 1;
  315: 	    env->macl = 0x80000000;
  316: 	} else if (res > 0x000000007fffffff) {
  317: 	    env->mach = 1;
  318: 	    env->macl = 0x7fffffff;
  319: 	}
  320:     }
  321: }
  322: 
  323: uint32_t helper_negc(uint32_t arg)
  324: {
  325:     uint32_t temp;
  326: 
  327:     temp = -arg;
  328:     arg = temp - (env->sr & SR_T);
  329:     if (0 < temp)
  330: 	env->sr |= SR_T;
  331:     else
  332: 	env->sr &= ~SR_T;
  333:     if (temp < arg)
  334: 	env->sr |= SR_T;
  335:     return arg;
  336: }
  337: 
  338: uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
  339: {
  340:     uint32_t tmp0, tmp1;
  341: 
  342:     tmp1 = arg1 - arg0;
  343:     tmp0 = arg1;
  344:     arg1 = tmp1 - (env->sr & SR_T);
  345:     if (tmp0 < tmp1)
  346: 	env->sr |= SR_T;
  347:     else
  348: 	env->sr &= ~SR_T;
  349:     if (tmp1 < arg1)
  350: 	env->sr |= SR_T;
  351:     return arg1;
  352: }
  353: 
  354: uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
  355: {
  356:     int32_t dest, src, ans;
  357: 
  358:     if ((int32_t) arg1 >= 0)
  359: 	dest = 0;
  360:     else
  361: 	dest = 1;
  362:     if ((int32_t) arg0 >= 0)
  363: 	src = 0;
  364:     else
  365: 	src = 1;
  366:     src += dest;
  367:     arg1 -= arg0;
  368:     if ((int32_t) arg1 >= 0)
  369: 	ans = 0;
  370:     else
  371: 	ans = 1;
  372:     ans += dest;
  373:     if (src == 1) {
  374: 	if (ans == 1)
  375: 	    env->sr |= SR_T;
  376: 	else
  377: 	    env->sr &= ~SR_T;
  378:     } else
  379: 	env->sr &= ~SR_T;
  380:     return arg1;
  381: }
  382: 
  383: static inline void set_t(void)
  384: {
  385:     env->sr |= SR_T;
  386: }
  387: 
  388: static inline void clr_t(void)
  389: {
  390:     env->sr &= ~SR_T;
  391: }
  392: 
  393: void helper_ld_fpscr(uint32_t val)
  394: {
  395:     env->fpscr = val & 0x003fffff;
  396:     if (val & 0x01)
  397: 	set_float_rounding_mode(float_round_to_zero, &env->fp_status);
  398:     else
  399: 	set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
  400: }
  401: 
  402: uint32_t helper_fabs_FT(uint32_t t0)
  403: {
  404:     CPU_FloatU f;
  405:     f.l = t0;
  406:     f.f = float32_abs(f.f);
  407:     return f.l;
  408: }
  409: 
  410: uint64_t helper_fabs_DT(uint64_t t0)
  411: {
  412:     CPU_DoubleU d;
  413:     d.ll = t0;
  414:     d.d = float64_abs(d.d);
  415:     return d.ll;
  416: }
  417: 
  418: uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
  419: {
  420:     CPU_FloatU f0, f1;
  421:     f0.l = t0;
  422:     f1.l = t1;
  423:     f0.f = float32_add(f0.f, f1.f, &env->fp_status);
  424:     return f0.l;
  425: }
  426: 
  427: uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
  428: {
  429:     CPU_DoubleU d0, d1;
  430:     d0.ll = t0;
  431:     d1.ll = t1;
  432:     d0.d = float64_add(d0.d, d1.d, &env->fp_status);
  433:     return d0.ll;
  434: }
  435: 
  436: void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
  437: {
  438:     CPU_FloatU f0, f1;
  439:     f0.l = t0;
  440:     f1.l = t1;
  441: 
  442:     if (float32_compare(f0.f, f1.f, &env->fp_status) == 0)
  443: 	set_t();
  444:     else
  445: 	clr_t();
  446: }
  447: 
  448: void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
  449: {
  450:     CPU_DoubleU d0, d1;
  451:     d0.ll = t0;
  452:     d1.ll = t1;
  453: 
  454:     if (float64_compare(d0.d, d1.d, &env->fp_status) == 0)
  455: 	set_t();
  456:     else
  457: 	clr_t();
  458: }
  459: 
  460: void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
  461: {
  462:     CPU_FloatU f0, f1;
  463:     f0.l = t0;
  464:     f1.l = t1;
  465: 
  466:     if (float32_compare(f0.f, f1.f, &env->fp_status) == 1)
  467: 	set_t();
  468:     else
  469: 	clr_t();
  470: }
  471: 
  472: void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
  473: {
  474:     CPU_DoubleU d0, d1;
  475:     d0.ll = t0;
  476:     d1.ll = t1;
  477: 
  478:     if (float64_compare(d0.d, d1.d, &env->fp_status) == 1)
  479: 	set_t();
  480:     else
  481: 	clr_t();
  482: }
  483: 
  484: uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
  485: {
  486:     CPU_DoubleU d;
  487:     CPU_FloatU f;
  488:     f.l = t0;
  489:     d.d = float32_to_float64(f.f, &env->fp_status);
  490:     return d.ll;
  491: }
  492: 
  493: uint32_t helper_fcnvds_DT_FT(uint64_t t0)
  494: {
  495:     CPU_DoubleU d;
  496:     CPU_FloatU f;
  497:     d.ll = t0;
  498:     f.f = float64_to_float32(d.d, &env->fp_status);
  499:     return f.l;
  500: }
  501: 
  502: uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
  503: {
  504:     CPU_FloatU f0, f1;
  505:     f0.l = t0;
  506:     f1.l = t1;
  507:     f0.f = float32_div(f0.f, f1.f, &env->fp_status);
  508:     return f0.l;
  509: }
  510: 
  511: uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
  512: {
  513:     CPU_DoubleU d0, d1;
  514:     d0.ll = t0;
  515:     d1.ll = t1;
  516:     d0.d = float64_div(d0.d, d1.d, &env->fp_status);
  517:     return d0.ll;
  518: }
  519: 
  520: uint32_t helper_float_FT(uint32_t t0)
  521: {
  522:     CPU_FloatU f;
  523:     f.f = int32_to_float32(t0, &env->fp_status);
  524:     return f.l;
  525: }
  526: 
  527: uint64_t helper_float_DT(uint32_t t0)
  528: {
  529:     CPU_DoubleU d;
  530:     d.d = int32_to_float64(t0, &env->fp_status);
  531:     return d.ll;
  532: }
  533: 
  534: uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
  535: {
  536:     CPU_FloatU f0, f1, f2;
  537:     f0.l = t0;
  538:     f1.l = t1;
  539:     f2.l = t2;
  540:     f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
  541:     f0.f = float32_add(f0.f, f2.f, &env->fp_status);
  542:     return f0.l;
  543: }
  544: 
  545: uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
  546: {
  547:     CPU_FloatU f0, f1;
  548:     f0.l = t0;
  549:     f1.l = t1;
  550:     f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
  551:     return f0.l;
  552: }
  553: 
  554: uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
  555: {
  556:     CPU_DoubleU d0, d1;
  557:     d0.ll = t0;
  558:     d1.ll = t1;
  559:     d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
  560:     return d0.ll;
  561: }
  562: 
  563: uint32_t helper_fneg_T(uint32_t t0)
  564: {
  565:     CPU_FloatU f;
  566:     f.l = t0;
  567:     f.f = float32_chs(f.f);
  568:     return f.l;
  569: }
  570: 
  571: uint32_t helper_fsqrt_FT(uint32_t t0)
  572: {
  573:     CPU_FloatU f;
  574:     f.l = t0;
  575:     f.f = float32_sqrt(f.f, &env->fp_status);
  576:     return f.l;
  577: }
  578: 
  579: uint64_t helper_fsqrt_DT(uint64_t t0)
  580: {
  581:     CPU_DoubleU d;
  582:     d.ll = t0;
  583:     d.d = float64_sqrt(d.d, &env->fp_status);
  584:     return d.ll;
  585: }
  586: 
  587: uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
  588: {
  589:     CPU_FloatU f0, f1;
  590:     f0.l = t0;
  591:     f1.l = t1;
  592:     f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
  593:     return f0.l;
  594: }
  595: 
  596: uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
  597: {
  598:     CPU_DoubleU d0, d1;
  599:     d0.ll = t0;
  600:     d1.ll = t1;
  601:     d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
  602:     return d0.ll;
  603: }
  604: 
  605: uint32_t helper_ftrc_FT(uint32_t t0)
  606: {
  607:     CPU_FloatU f;
  608:     f.l = t0;
  609:     return float32_to_int32_round_to_zero(f.f, &env->fp_status);
  610: }
  611: 
  612: uint32_t helper_ftrc_DT(uint64_t t0)
  613: {
  614:     CPU_DoubleU d;
  615:     d.ll = t0;
  616:     return float64_to_int32_round_to_zero(d.d, &env->fp_status);
  617: }

unix.superglobalmegacorp.com