symbian-qemu-0.9.1-12/qemu-symbian-svp/target-sh4/op_helper.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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_fmul_FT(uint32_t t0, uint32_t t1)
       
   535 {
       
   536     CPU_FloatU f0, f1;
       
   537     f0.l = t0;
       
   538     f1.l = t1;
       
   539     f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
       
   540     return f0.l;
       
   541 }
       
   542 
       
   543 uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
       
   544 {
       
   545     CPU_DoubleU d0, d1;
       
   546     d0.ll = t0;
       
   547     d1.ll = t1;
       
   548     d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
       
   549     return d0.ll;
       
   550 }
       
   551 
       
   552 uint32_t helper_fneg_T(uint32_t t0)
       
   553 {
       
   554     CPU_FloatU f;
       
   555     f.l = t0;
       
   556     f.f = float32_chs(f.f);
       
   557     return f.l;
       
   558 }
       
   559 
       
   560 uint32_t helper_fsqrt_FT(uint32_t t0)
       
   561 {
       
   562     CPU_FloatU f;
       
   563     f.l = t0;
       
   564     f.f = float32_sqrt(f.f, &env->fp_status);
       
   565     return f.l;
       
   566 }
       
   567 
       
   568 uint64_t helper_fsqrt_DT(uint64_t t0)
       
   569 {
       
   570     CPU_DoubleU d;
       
   571     d.ll = t0;
       
   572     d.d = float64_sqrt(d.d, &env->fp_status);
       
   573     return d.ll;
       
   574 }
       
   575 
       
   576 uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
       
   577 {
       
   578     CPU_FloatU f0, f1;
       
   579     f0.l = t0;
       
   580     f1.l = t1;
       
   581     f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
       
   582     return f0.l;
       
   583 }
       
   584 
       
   585 uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
       
   586 {
       
   587     CPU_DoubleU d0, d1;
       
   588     d0.ll = t0;
       
   589     d1.ll = t1;
       
   590     d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
       
   591     return d0.ll;
       
   592 }
       
   593 
       
   594 uint32_t helper_ftrc_FT(uint32_t t0)
       
   595 {
       
   596     CPU_FloatU f;
       
   597     f.l = t0;
       
   598     return float32_to_int32_round_to_zero(f.f, &env->fp_status);
       
   599 }
       
   600 
       
   601 uint32_t helper_ftrc_DT(uint64_t t0)
       
   602 {
       
   603     CPU_DoubleU d;
       
   604     d.ll = t0;
       
   605     return float64_to_int32_round_to_zero(d.d, &env->fp_status);
       
   606 }