25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_sh_instr.c,v 1.51 2007/03/08 19:04:09 debug Exp $ |
* $Id: cpu_sh_instr.c,v 1.56 2007/04/19 15:49:39 debug Exp $ |
29 |
* |
* |
30 |
* SH instructions. |
* SH instructions. |
31 |
* |
* |
818 |
else |
else |
819 |
data = BE32_TO_HOST(data); |
data = BE32_TO_HOST(data); |
820 |
reg(ic->arg[1]) = addr + sizeof(data); |
reg(ic->arg[1]) = addr + sizeof(data); |
821 |
reg(ic->arg[0]) = data; |
|
822 |
|
/* Special case when loading into the SR register: */ |
823 |
|
if (ic->arg[0] == (size_t)&cpu->cd.sh.sr) |
824 |
|
sh_update_sr(cpu, data); |
825 |
|
else |
826 |
|
reg(ic->arg[0]) = data; |
827 |
} |
} |
828 |
X(mov_l_arg1_postinc_to_arg0_fp) |
X(mov_l_arg1_postinc_to_arg0_fp) |
829 |
{ |
{ |
850 |
data = BE32_TO_HOST(data); |
data = BE32_TO_HOST(data); |
851 |
reg(ic->arg[1]) = addr + sizeof(data); |
reg(ic->arg[1]) = addr + sizeof(data); |
852 |
|
|
853 |
if (ic->arg[0] == (size_t)cpu->cd.sh.fpscr) |
/* Ugly special case for FPSCR: */ |
854 |
|
if (ic->arg[0] == (size_t)&cpu->cd.sh.fpscr) |
855 |
sh_update_fpscr(cpu, data); |
sh_update_fpscr(cpu, data); |
856 |
else |
else |
857 |
reg(ic->arg[0]) = data; |
reg(ic->arg[0]) = data; |
1990 |
|
|
1991 |
|
|
1992 |
/* |
/* |
|
* sts_mach_rn: Store MACH into Rn |
|
|
* sts_macl_rn: Store MACL into Rn |
|
|
* sts_pr_rn: Store PR into Rn |
|
|
* |
|
|
* arg[1] = ptr to rn |
|
|
*/ |
|
|
X(sts_mach_rn) { reg(ic->arg[1]) = cpu->cd.sh.mach; } |
|
|
X(sts_macl_rn) { reg(ic->arg[1]) = cpu->cd.sh.macl; } |
|
|
X(sts_pr_rn) { reg(ic->arg[1]) = cpu->cd.sh.pr; } |
|
|
|
|
|
|
|
|
/* |
|
1993 |
* rte: Return from exception. |
* rte: Return from exception. |
1994 |
*/ |
*/ |
1995 |
X(rte) |
X(rte) |
2034 |
old_hi & 0xfffff000, INVALIDATE_VADDR); |
old_hi & 0xfffff000, INVALIDATE_VADDR); |
2035 |
else |
else |
2036 |
cpu->invalidate_translation_caches(cpu, |
cpu->invalidate_translation_caches(cpu, |
2037 |
old_hi & 0xfffff000, INVALIDATE_ALL); |
0, INVALIDATE_ALL); |
2038 |
} |
} |
2039 |
} |
} |
2040 |
|
|
2062 |
{ |
{ |
2063 |
RES_INST_IF_NOT_MD; |
RES_INST_IF_NOT_MD; |
2064 |
sh_update_sr(cpu, reg(ic->arg[1])); |
sh_update_sr(cpu, reg(ic->arg[1])); |
2065 |
|
|
2066 |
|
#if 0 |
2067 |
|
/* NOTE: This code causes NetBSD/landisk to get past a point where it |
2068 |
|
otherwise hangs, but it causes Linux/Dreamcast to bug out instead. :/ */ |
2069 |
|
|
2070 |
|
if (!(cpu->cd.sh.sr & SH_SR_BL) && cpu->cd.sh.int_to_assert > 0 && |
2071 |
|
( (cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT) |
2072 |
|
< cpu->cd.sh.int_level) { |
2073 |
|
/* Cause interrupt immediately, by dropping out of the |
2074 |
|
main dyntrans loop: */ |
2075 |
|
cpu->cd.sh.next_ic = ¬hing_call; |
2076 |
|
} |
2077 |
|
#endif |
2078 |
} |
} |
2079 |
|
|
2080 |
|
|
2199 |
|
|
2200 |
|
|
2201 |
/* |
/* |
2202 |
|
* fcnvsd_fpul_drn: Convert single-precision to double-precision. |
2203 |
|
* fcnvds_drm_fpul: Convert double-precision to single-precision. |
2204 |
|
* |
2205 |
|
* arg[0] = ptr to destination (double- or single-precision float) |
2206 |
|
*/ |
2207 |
|
X(fcnvsd_fpul_drn) |
2208 |
|
{ |
2209 |
|
struct ieee_float_value op1; |
2210 |
|
int64_t ieee; |
2211 |
|
|
2212 |
|
FLOATING_POINT_AVAILABLE_CHECK; |
2213 |
|
|
2214 |
|
ieee_interpret_float_value(cpu->cd.sh.fpul, &op1, IEEE_FMT_S); |
2215 |
|
cpu->cd.sh.fpul = (int32_t) op1.f; |
2216 |
|
|
2217 |
|
/* Store double-precision result: */ |
2218 |
|
ieee = ieee_store_float_value(op1.f, IEEE_FMT_D, 0); |
2219 |
|
reg(ic->arg[0]) = (uint32_t) (ieee >> 32); |
2220 |
|
reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee; |
2221 |
|
} |
2222 |
|
X(fcnvds_drm_fpul) |
2223 |
|
{ |
2224 |
|
struct ieee_float_value op1; |
2225 |
|
int64_t r1; |
2226 |
|
|
2227 |
|
FLOATING_POINT_AVAILABLE_CHECK; |
2228 |
|
|
2229 |
|
r1 = reg(ic->arg[0] + sizeof(uint32_t)) + |
2230 |
|
((uint64_t)reg(ic->arg[0]) << 32); |
2231 |
|
ieee_interpret_float_value(r1, &op1, IEEE_FMT_D); |
2232 |
|
|
2233 |
|
cpu->cd.sh.fpul = ieee_store_float_value(op1.f, IEEE_FMT_S, 0); |
2234 |
|
} |
2235 |
|
|
2236 |
|
|
2237 |
|
/* |
2238 |
* fsca_fpul_drn: Sinus/cosinus approximation. |
* fsca_fpul_drn: Sinus/cosinus approximation. |
2239 |
* |
* |
2240 |
* Note: This is an interesting instruction. It is not included in the SH4 |
* Note: This is an interesting instruction. It is not included in the SH4 |
2967 |
} |
} |
2968 |
break; |
break; |
2969 |
case 0x0a: /* STS MACH,Rn */ |
case 0x0a: /* STS MACH,Rn */ |
2970 |
ic->f = instr(sts_mach_rn); |
ic->f = instr(mov_rm_rn); |
2971 |
|
ic->arg[0] = (size_t)&cpu->cd.sh.mach; |
2972 |
break; |
break; |
2973 |
case 0x12: /* STC GBR,Rn */ |
case 0x12: /* STC GBR,Rn */ |
2974 |
ic->f = instr(mov_rm_rn); |
ic->f = instr(mov_rm_rn); |
2975 |
ic->arg[0] = (size_t)&cpu->cd.sh.gbr; |
ic->arg[0] = (size_t)&cpu->cd.sh.gbr; |
2976 |
break; |
break; |
2977 |
case 0x1a: /* STS MACL,Rn */ |
case 0x1a: /* STS MACL,Rn */ |
2978 |
ic->f = instr(sts_macl_rn); |
ic->f = instr(mov_rm_rn); |
2979 |
|
ic->arg[0] = (size_t)&cpu->cd.sh.macl; |
2980 |
break; |
break; |
2981 |
case 0x22: /* STC VBR,Rn */ |
case 0x22: /* STC VBR,Rn */ |
2982 |
ic->f = instr(copy_privileged_register); |
ic->f = instr(copy_privileged_register); |
2993 |
ic->f = instr(movt_rn); |
ic->f = instr(movt_rn); |
2994 |
break; |
break; |
2995 |
case 0x2a: /* STS PR,Rn */ |
case 0x2a: /* STS PR,Rn */ |
2996 |
ic->f = instr(sts_pr_rn); |
ic->f = instr(mov_rm_rn); |
2997 |
|
ic->arg[0] = (size_t)&cpu->cd.sh.pr; |
2998 |
break; |
break; |
2999 |
case 0x32: /* STC SSR,Rn */ |
case 0x32: /* STC SSR,Rn */ |
3000 |
ic->f = instr(copy_privileged_register); |
ic->f = instr(copy_privileged_register); |
3355 |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */ |
ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */ |
3356 |
break; |
break; |
3357 |
case 0x66: /* LDS.L @Rm+,FPSCR */ |
case 0x66: /* LDS.L @Rm+,FPSCR */ |
3358 |
|
/* Note: Loading into FPSCR is a specia |
3359 |
|
case (need to call sh_update_fpsrc()). */ |
3360 |
ic->f = instr(mov_l_arg1_postinc_to_arg0_fp); |
ic->f = instr(mov_l_arg1_postinc_to_arg0_fp); |
3361 |
ic->arg[0] = (size_t)&cpu->cd.sh.fpscr; |
ic->arg[0] = (size_t)&cpu->cd.sh.fpscr; |
3362 |
break; |
break; |
3703 |
ic->f = instr(fldi_frn); |
ic->f = instr(fldi_frn); |
3704 |
ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8]; |
ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8]; |
3705 |
ic->arg[1] = 0x3f800000; |
ic->arg[1] = 0x3f800000; |
3706 |
|
} else if ((iword & 0x01ff) == 0x00ad) { |
3707 |
|
/* FCNVSD FPUL,DRn */ |
3708 |
|
ic->f = instr(fcnvsd_fpul_drn); |
3709 |
|
ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8]; |
3710 |
|
} else if ((iword & 0x01ff) == 0x00bd) { |
3711 |
|
/* FCNVDS DRm,FPUL */ |
3712 |
|
ic->f = instr(fcnvds_drm_fpul); |
3713 |
|
ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8]; |
3714 |
} else if ((iword & 0x01ff) == 0x00fd) { |
} else if ((iword & 0x01ff) == 0x00fd) { |
3715 |
/* FSCA FPUL,DRn */ |
/* FSCA FPUL,DRn */ |
3716 |
ic->f = instr(fsca_fpul_drn); |
ic->f = instr(fsca_fpul_drn); |