Revision 5a5012ec target-mips/op.c
b/target-mips/op.c | ||
---|---|---|
23 | 23 |
#include "exec.h" |
24 | 24 |
|
25 | 25 |
#ifndef CALL_FROM_TB0 |
26 |
#define CALL_FROM_TB0(func) func();
|
|
26 |
#define CALL_FROM_TB0(func) func() |
|
27 | 27 |
#endif |
28 | 28 |
#ifndef CALL_FROM_TB1 |
29 |
#define CALL_FROM_TB1(func, arg0) func(arg0);
|
|
29 |
#define CALL_FROM_TB1(func, arg0) func(arg0) |
|
30 | 30 |
#endif |
31 | 31 |
#ifndef CALL_FROM_TB1_CONST16 |
32 |
#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0);
|
|
32 |
#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0) |
|
33 | 33 |
#endif |
34 | 34 |
#ifndef CALL_FROM_TB2 |
35 |
#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1);
|
|
35 |
#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1) |
|
36 | 36 |
#endif |
37 | 37 |
#ifndef CALL_FROM_TB2_CONST16 |
38 | 38 |
#define CALL_FROM_TB2_CONST16(func, arg0, arg1) \ |
39 |
CALL_FROM_TB2(func, arg0, arg1);
|
|
39 |
CALL_FROM_TB2(func, arg0, arg1)
|
|
40 | 40 |
#endif |
41 | 41 |
#ifndef CALL_FROM_TB3 |
42 |
#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2);
|
|
42 |
#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2) |
|
43 | 43 |
#endif |
44 | 44 |
#ifndef CALL_FROM_TB4 |
45 | 45 |
#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \ |
46 |
func(arg0, arg1, arg2, arg3);
|
|
46 |
func(arg0, arg1, arg2, arg3) |
|
47 | 47 |
#endif |
48 | 48 |
|
49 | 49 |
#define REG 1 |
... | ... | |
144 | 144 |
#include "op_template.c" |
145 | 145 |
#undef TN |
146 | 146 |
|
147 |
#define SFREG 0 |
|
148 |
#define DFREG 0 |
|
147 |
#define FREG 0 |
|
149 | 148 |
#include "fop_template.c" |
150 |
#undef SFREG |
|
151 |
#undef DFREG |
|
152 |
#define SFREG 1 |
|
149 |
#undef FREG |
|
150 |
#define FREG 1 |
|
153 | 151 |
#include "fop_template.c" |
154 |
#undef SFREG |
|
155 |
#define SFREG 2 |
|
156 |
#define DFREG 2 |
|
152 |
#undef FREG |
|
153 |
#define FREG 2 |
|
157 | 154 |
#include "fop_template.c" |
158 |
#undef SFREG |
|
159 |
#undef DFREG |
|
160 |
#define SFREG 3 |
|
155 |
#undef FREG |
|
156 |
#define FREG 3 |
|
161 | 157 |
#include "fop_template.c" |
162 |
#undef SFREG |
|
163 |
#define SFREG 4 |
|
164 |
#define DFREG 4 |
|
158 |
#undef FREG |
|
159 |
#define FREG 4 |
|
165 | 160 |
#include "fop_template.c" |
166 |
#undef SFREG |
|
167 |
#undef DFREG |
|
168 |
#define SFREG 5 |
|
161 |
#undef FREG |
|
162 |
#define FREG 5 |
|
169 | 163 |
#include "fop_template.c" |
170 |
#undef SFREG |
|
171 |
#define SFREG 6 |
|
172 |
#define DFREG 6 |
|
164 |
#undef FREG |
|
165 |
#define FREG 6 |
|
173 | 166 |
#include "fop_template.c" |
174 |
#undef SFREG |
|
175 |
#undef DFREG |
|
176 |
#define SFREG 7 |
|
167 |
#undef FREG |
|
168 |
#define FREG 7 |
|
177 | 169 |
#include "fop_template.c" |
178 |
#undef SFREG |
|
179 |
#define SFREG 8 |
|
180 |
#define DFREG 8 |
|
170 |
#undef FREG |
|
171 |
#define FREG 8 |
|
181 | 172 |
#include "fop_template.c" |
182 |
#undef SFREG |
|
183 |
#undef DFREG |
|
184 |
#define SFREG 9 |
|
173 |
#undef FREG |
|
174 |
#define FREG 9 |
|
185 | 175 |
#include "fop_template.c" |
186 |
#undef SFREG |
|
187 |
#define SFREG 10 |
|
188 |
#define DFREG 10 |
|
176 |
#undef FREG |
|
177 |
#define FREG 10 |
|
189 | 178 |
#include "fop_template.c" |
190 |
#undef SFREG |
|
191 |
#undef DFREG |
|
192 |
#define SFREG 11 |
|
179 |
#undef FREG |
|
180 |
#define FREG 11 |
|
193 | 181 |
#include "fop_template.c" |
194 |
#undef SFREG |
|
195 |
#define SFREG 12 |
|
196 |
#define DFREG 12 |
|
182 |
#undef FREG |
|
183 |
#define FREG 12 |
|
197 | 184 |
#include "fop_template.c" |
198 |
#undef SFREG |
|
199 |
#undef DFREG |
|
200 |
#define SFREG 13 |
|
185 |
#undef FREG |
|
186 |
#define FREG 13 |
|
201 | 187 |
#include "fop_template.c" |
202 |
#undef SFREG |
|
203 |
#define SFREG 14 |
|
204 |
#define DFREG 14 |
|
188 |
#undef FREG |
|
189 |
#define FREG 14 |
|
205 | 190 |
#include "fop_template.c" |
206 |
#undef SFREG |
|
207 |
#undef DFREG |
|
208 |
#define SFREG 15 |
|
191 |
#undef FREG |
|
192 |
#define FREG 15 |
|
209 | 193 |
#include "fop_template.c" |
210 |
#undef SFREG |
|
211 |
#define SFREG 16 |
|
212 |
#define DFREG 16 |
|
194 |
#undef FREG |
|
195 |
#define FREG 16 |
|
213 | 196 |
#include "fop_template.c" |
214 |
#undef SFREG |
|
215 |
#undef DFREG |
|
216 |
#define SFREG 17 |
|
197 |
#undef FREG |
|
198 |
#define FREG 17 |
|
217 | 199 |
#include "fop_template.c" |
218 |
#undef SFREG |
|
219 |
#define SFREG 18 |
|
220 |
#define DFREG 18 |
|
200 |
#undef FREG |
|
201 |
#define FREG 18 |
|
221 | 202 |
#include "fop_template.c" |
222 |
#undef SFREG |
|
223 |
#undef DFREG |
|
224 |
#define SFREG 19 |
|
203 |
#undef FREG |
|
204 |
#define FREG 19 |
|
225 | 205 |
#include "fop_template.c" |
226 |
#undef SFREG |
|
227 |
#define SFREG 20 |
|
228 |
#define DFREG 20 |
|
206 |
#undef FREG |
|
207 |
#define FREG 20 |
|
229 | 208 |
#include "fop_template.c" |
230 |
#undef SFREG |
|
231 |
#undef DFREG |
|
232 |
#define SFREG 21 |
|
209 |
#undef FREG |
|
210 |
#define FREG 21 |
|
233 | 211 |
#include "fop_template.c" |
234 |
#undef SFREG |
|
235 |
#define SFREG 22 |
|
236 |
#define DFREG 22 |
|
212 |
#undef FREG |
|
213 |
#define FREG 22 |
|
237 | 214 |
#include "fop_template.c" |
238 |
#undef SFREG |
|
239 |
#undef DFREG |
|
240 |
#define SFREG 23 |
|
215 |
#undef FREG |
|
216 |
#define FREG 23 |
|
241 | 217 |
#include "fop_template.c" |
242 |
#undef SFREG |
|
243 |
#define SFREG 24 |
|
244 |
#define DFREG 24 |
|
218 |
#undef FREG |
|
219 |
#define FREG 24 |
|
245 | 220 |
#include "fop_template.c" |
246 |
#undef SFREG |
|
247 |
#undef DFREG |
|
248 |
#define SFREG 25 |
|
221 |
#undef FREG |
|
222 |
#define FREG 25 |
|
249 | 223 |
#include "fop_template.c" |
250 |
#undef SFREG |
|
251 |
#define SFREG 26 |
|
252 |
#define DFREG 26 |
|
224 |
#undef FREG |
|
225 |
#define FREG 26 |
|
253 | 226 |
#include "fop_template.c" |
254 |
#undef SFREG |
|
255 |
#undef DFREG |
|
256 |
#define SFREG 27 |
|
227 |
#undef FREG |
|
228 |
#define FREG 27 |
|
257 | 229 |
#include "fop_template.c" |
258 |
#undef SFREG |
|
259 |
#define SFREG 28 |
|
260 |
#define DFREG 28 |
|
230 |
#undef FREG |
|
231 |
#define FREG 28 |
|
261 | 232 |
#include "fop_template.c" |
262 |
#undef SFREG |
|
263 |
#undef DFREG |
|
264 |
#define SFREG 29 |
|
233 |
#undef FREG |
|
234 |
#define FREG 29 |
|
265 | 235 |
#include "fop_template.c" |
266 |
#undef SFREG |
|
267 |
#define SFREG 30 |
|
268 |
#define DFREG 30 |
|
236 |
#undef FREG |
|
237 |
#define FREG 30 |
|
269 | 238 |
#include "fop_template.c" |
270 |
#undef SFREG |
|
271 |
#undef DFREG |
|
272 |
#define SFREG 31 |
|
239 |
#undef FREG |
|
240 |
#define FREG 31 |
|
273 | 241 |
#include "fop_template.c" |
274 |
#undef SFREG
|
|
242 |
#undef FREG |
|
275 | 243 |
|
276 | 244 |
#define FTN |
277 | 245 |
#include "fop_template.c" |
... | ... | |
919 | 887 |
void op_movf (void) |
920 | 888 |
{ |
921 | 889 |
if (!(env->fcr31 & PARAM1)) |
922 |
env->gpr[PARAM2] = env->gpr[PARAM3];
|
|
890 |
T0 = T1;
|
|
923 | 891 |
RETURN(); |
924 | 892 |
} |
925 | 893 |
|
926 | 894 |
void op_movt (void) |
927 | 895 |
{ |
928 | 896 |
if (env->fcr31 & PARAM1) |
929 |
env->gpr[PARAM2] = env->gpr[PARAM3];
|
|
897 |
T0 = T1;
|
|
930 | 898 |
RETURN(); |
931 | 899 |
} |
932 | 900 |
|
... | ... | |
1354 | 1322 |
void op_mtc0_status (void) |
1355 | 1323 |
{ |
1356 | 1324 |
uint32_t val, old; |
1325 |
uint32_t mask = env->Status_rw_bitmask; |
|
1357 | 1326 |
|
1358 |
/* No 64bit FPU, no reverse endianness, no MDMX/DSP, no 64bit ops,
|
|
1327 |
/* No reverse endianness, no MDMX/DSP, no 64bit ops, |
|
1359 | 1328 |
no 64bit addressing implemented. */ |
1360 |
val = (int32_t)T0 & 0xF878FF17;
|
|
1329 |
val = (int32_t)T0 & mask;
|
|
1361 | 1330 |
old = env->CP0_Status; |
1362 | 1331 |
if (!(val & (1 << CP0St_EXL)) && |
1363 | 1332 |
!(val & (1 << CP0St_ERL)) && |
1364 | 1333 |
!(env->hflags & MIPS_HFLAG_DM) && |
1365 | 1334 |
(val & (1 << CP0St_UM))) |
1366 | 1335 |
env->hflags |= MIPS_HFLAG_UM; |
1367 |
env->CP0_Status = (env->CP0_Status & ~0xF878FF17) | val;
|
|
1336 |
env->CP0_Status = (env->CP0_Status & ~mask) | val;
|
|
1368 | 1337 |
if (loglevel & CPU_LOG_EXEC) |
1369 | 1338 |
CALL_FROM_TB2(do_mtc0_status_debug, old, val); |
1370 | 1339 |
CALL_FROM_TB1(cpu_mips_update_irq, env); |
... | ... | |
1643 | 1612 |
} |
1644 | 1613 |
#endif /* TARGET_MIPS64 */ |
1645 | 1614 |
|
1615 |
/* CP1 functions */ |
|
1646 | 1616 |
#if 0 |
1647 | 1617 |
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env) |
1648 | 1618 |
#else |
... | ... | |
1666 | 1636 |
RETURN(); |
1667 | 1637 |
} |
1668 | 1638 |
|
1669 |
/* CP1 functions */ |
|
1670 |
void op_cfc1 (void) |
|
1671 |
{ |
|
1672 |
if (T1 == 0) { |
|
1673 |
T0 = env->fcr0; |
|
1674 |
} |
|
1675 |
else { |
|
1676 |
/* fetch fcr31, masking unused bits */ |
|
1677 |
T0 = env->fcr31 & 0x0183FFFF; |
|
1678 |
} |
|
1679 |
DEBUG_FPU_STATE(); |
|
1680 |
RETURN(); |
|
1681 |
} |
|
1682 |
|
|
1683 | 1639 |
/* convert MIPS rounding mode in FCR31 to IEEE library */ |
1684 | 1640 |
unsigned int ieee_rm[] = { |
1685 | 1641 |
float_round_nearest_even, |
... | ... | |
1691 | 1647 |
#define RESTORE_ROUNDING_MODE \ |
1692 | 1648 |
set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status) |
1693 | 1649 |
|
1694 |
void op_ctc1 (void)
|
|
1650 |
inline char ieee_ex_to_mips(char ieee)
|
|
1695 | 1651 |
{ |
1696 |
if (T1 == 0) { |
|
1697 |
/* XXX should this throw an exception? |
|
1698 |
* don't write to FCR0. |
|
1699 |
* env->fcr0 = T0; |
|
1700 |
*/ |
|
1701 |
} |
|
1702 |
else { |
|
1703 |
/* store new fcr31, masking unused bits */ |
|
1704 |
env->fcr31 = T0 & 0x0183FFFF; |
|
1652 |
return (ieee & float_flag_inexact) >> 5 | |
|
1653 |
(ieee & float_flag_underflow) >> 3 | |
|
1654 |
(ieee & float_flag_overflow) >> 1 | |
|
1655 |
(ieee & float_flag_divbyzero) << 1 | |
|
1656 |
(ieee & float_flag_invalid) << 4; |
|
1657 |
} |
|
1705 | 1658 |
|
1706 |
/* set rounding mode */ |
|
1707 |
RESTORE_ROUNDING_MODE; |
|
1659 |
inline char mips_ex_to_ieee(char mips) |
|
1660 |
{ |
|
1661 |
return (mips & FP_INEXACT) << 5 | |
|
1662 |
(mips & FP_UNDERFLOW) << 3 | |
|
1663 |
(mips & FP_OVERFLOW) << 1 | |
|
1664 |
(mips & FP_DIV0) >> 1 | |
|
1665 |
(mips & FP_INVALID) >> 4; |
|
1666 |
} |
|
1708 | 1667 |
|
1709 |
#ifndef CONFIG_SOFTFLOAT |
|
1710 |
/* no floating point exception for native float */ |
|
1711 |
SET_FP_ENABLE(env->fcr31, 0); |
|
1712 |
#endif |
|
1668 |
inline void update_fcr31(void) |
|
1669 |
{ |
|
1670 |
int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status)); |
|
1671 |
|
|
1672 |
SET_FP_CAUSE(env->fcr31, tmp); |
|
1673 |
if (GET_FP_ENABLE(env->fcr31) & tmp) |
|
1674 |
CALL_FROM_TB1(do_raise_exception, EXCP_FPE); |
|
1675 |
else |
|
1676 |
UPDATE_FP_FLAGS(env->fcr31, tmp); |
|
1677 |
} |
|
1678 |
|
|
1679 |
|
|
1680 |
void op_cfc1 (void) |
|
1681 |
{ |
|
1682 |
switch (T1) { |
|
1683 |
case 0: |
|
1684 |
T0 = (int32_t)env->fcr0; |
|
1685 |
break; |
|
1686 |
case 25: |
|
1687 |
T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1); |
|
1688 |
break; |
|
1689 |
case 26: |
|
1690 |
T0 = env->fcr31 & 0x0003f07c; |
|
1691 |
break; |
|
1692 |
case 28: |
|
1693 |
T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4); |
|
1694 |
break; |
|
1695 |
default: |
|
1696 |
T0 = (int32_t)env->fcr31; |
|
1697 |
break; |
|
1698 |
} |
|
1699 |
DEBUG_FPU_STATE(); |
|
1700 |
RETURN(); |
|
1701 |
} |
|
1702 |
|
|
1703 |
void op_ctc1 (void) |
|
1704 |
{ |
|
1705 |
switch(T1) { |
|
1706 |
case 25: |
|
1707 |
if (T0 & 0xffffff00) |
|
1708 |
goto leave; |
|
1709 |
env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) | |
|
1710 |
((T0 & 0x1) << 23); |
|
1711 |
break; |
|
1712 |
case 26: |
|
1713 |
if (T0 & 0x007c0000) |
|
1714 |
goto leave; |
|
1715 |
env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c); |
|
1716 |
break; |
|
1717 |
case 28: |
|
1718 |
if (T0 & 0x007c0000) |
|
1719 |
goto leave; |
|
1720 |
env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) | |
|
1721 |
((T0 & 0x4) << 22); |
|
1722 |
break; |
|
1723 |
case 31: |
|
1724 |
if (T0 & 0x007c0000) |
|
1725 |
goto leave; |
|
1726 |
env->fcr31 = T0; |
|
1727 |
break; |
|
1728 |
default: |
|
1729 |
goto leave; |
|
1713 | 1730 |
} |
1731 |
/* set rounding mode */ |
|
1732 |
RESTORE_ROUNDING_MODE; |
|
1733 |
set_float_exception_flags(0, &env->fp_status); |
|
1734 |
if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31)) |
|
1735 |
CALL_FROM_TB1(do_raise_exception, EXCP_FPE); |
|
1736 |
leave: |
|
1714 | 1737 |
DEBUG_FPU_STATE(); |
1715 | 1738 |
RETURN(); |
1716 | 1739 |
} |
... | ... | |
1729 | 1752 |
RETURN(); |
1730 | 1753 |
} |
1731 | 1754 |
|
1755 |
void op_dmfc1 (void) |
|
1756 |
{ |
|
1757 |
T0 = DT0; |
|
1758 |
DEBUG_FPU_STATE(); |
|
1759 |
RETURN(); |
|
1760 |
} |
|
1761 |
|
|
1762 |
void op_dmtc1 (void) |
|
1763 |
{ |
|
1764 |
DT0 = T0; |
|
1765 |
DEBUG_FPU_STATE(); |
|
1766 |
RETURN(); |
|
1767 |
} |
|
1768 |
|
|
1769 |
void op_mfhc1 (void) |
|
1770 |
{ |
|
1771 |
T0 = WTH0; |
|
1772 |
DEBUG_FPU_STATE(); |
|
1773 |
RETURN(); |
|
1774 |
} |
|
1775 |
|
|
1776 |
void op_mthc1 (void) |
|
1777 |
{ |
|
1778 |
WTH0 = T0; |
|
1779 |
DEBUG_FPU_STATE(); |
|
1780 |
RETURN(); |
|
1781 |
} |
|
1782 |
|
|
1732 | 1783 |
/* Float support. |
1733 | 1784 |
Single precition routines have a "s" suffix, double precision a |
1734 |
"d" suffix. */ |
|
1785 |
"d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps", |
|
1786 |
paired single lowwer "pl", paired single upper "pu". */ |
|
1735 | 1787 |
|
1736 | 1788 |
#define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void) |
1737 | 1789 |
|
1738 | 1790 |
FLOAT_OP(cvtd, s) |
1739 | 1791 |
{ |
1792 |
set_float_exception_flags(0, &env->fp_status); |
|
1740 | 1793 |
FDT2 = float32_to_float64(FST0, &env->fp_status); |
1794 |
update_fcr31(); |
|
1741 | 1795 |
DEBUG_FPU_STATE(); |
1742 | 1796 |
RETURN(); |
1743 | 1797 |
} |
1744 | 1798 |
FLOAT_OP(cvtd, w) |
1745 | 1799 |
{ |
1800 |
set_float_exception_flags(0, &env->fp_status); |
|
1746 | 1801 |
FDT2 = int32_to_float64(WT0, &env->fp_status); |
1802 |
update_fcr31(); |
|
1803 |
DEBUG_FPU_STATE(); |
|
1804 |
RETURN(); |
|
1805 |
} |
|
1806 |
FLOAT_OP(cvtd, l) |
|
1807 |
{ |
|
1808 |
set_float_exception_flags(0, &env->fp_status); |
|
1809 |
FDT2 = int64_to_float64(DT0, &env->fp_status); |
|
1810 |
update_fcr31(); |
|
1811 |
DEBUG_FPU_STATE(); |
|
1812 |
RETURN(); |
|
1813 |
} |
|
1814 |
FLOAT_OP(cvtl, d) |
|
1815 |
{ |
|
1816 |
set_float_exception_flags(0, &env->fp_status); |
|
1817 |
DT2 = float64_to_int64(FDT0, &env->fp_status); |
|
1818 |
update_fcr31(); |
|
1819 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1820 |
DT2 = 0x7fffffffffffffffULL; |
|
1821 |
DEBUG_FPU_STATE(); |
|
1822 |
RETURN(); |
|
1823 |
} |
|
1824 |
FLOAT_OP(cvtl, s) |
|
1825 |
{ |
|
1826 |
set_float_exception_flags(0, &env->fp_status); |
|
1827 |
DT2 = float32_to_int64(FST0, &env->fp_status); |
|
1828 |
update_fcr31(); |
|
1829 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1830 |
DT2 = 0x7fffffffffffffffULL; |
|
1831 |
DEBUG_FPU_STATE(); |
|
1832 |
RETURN(); |
|
1833 |
} |
|
1834 |
FLOAT_OP(cvtps, s) |
|
1835 |
{ |
|
1836 |
WT2 = WT0; |
|
1837 |
WTH2 = WT1; |
|
1838 |
DEBUG_FPU_STATE(); |
|
1839 |
RETURN(); |
|
1840 |
} |
|
1841 |
FLOAT_OP(cvtps, pw) |
|
1842 |
{ |
|
1843 |
set_float_exception_flags(0, &env->fp_status); |
|
1844 |
FST2 = int32_to_float32(WT0, &env->fp_status); |
|
1845 |
FSTH2 = int32_to_float32(WTH0, &env->fp_status); |
|
1846 |
update_fcr31(); |
|
1847 |
DEBUG_FPU_STATE(); |
|
1848 |
RETURN(); |
|
1849 |
} |
|
1850 |
FLOAT_OP(cvtpw, ps) |
|
1851 |
{ |
|
1852 |
set_float_exception_flags(0, &env->fp_status); |
|
1853 |
WT2 = float32_to_int32(FST0, &env->fp_status); |
|
1854 |
WTH2 = float32_to_int32(FSTH0, &env->fp_status); |
|
1855 |
update_fcr31(); |
|
1856 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1857 |
WT2 = 0x7fffffff; |
|
1747 | 1858 |
DEBUG_FPU_STATE(); |
1748 | 1859 |
RETURN(); |
1749 | 1860 |
} |
1750 | 1861 |
FLOAT_OP(cvts, d) |
1751 | 1862 |
{ |
1863 |
set_float_exception_flags(0, &env->fp_status); |
|
1752 | 1864 |
FST2 = float64_to_float32(FDT0, &env->fp_status); |
1865 |
update_fcr31(); |
|
1753 | 1866 |
DEBUG_FPU_STATE(); |
1754 | 1867 |
RETURN(); |
1755 | 1868 |
} |
1756 | 1869 |
FLOAT_OP(cvts, w) |
1757 | 1870 |
{ |
1871 |
set_float_exception_flags(0, &env->fp_status); |
|
1758 | 1872 |
FST2 = int32_to_float32(WT0, &env->fp_status); |
1873 |
update_fcr31(); |
|
1874 |
DEBUG_FPU_STATE(); |
|
1875 |
RETURN(); |
|
1876 |
} |
|
1877 |
FLOAT_OP(cvts, l) |
|
1878 |
{ |
|
1879 |
set_float_exception_flags(0, &env->fp_status); |
|
1880 |
FST2 = int64_to_float32(DT0, &env->fp_status); |
|
1881 |
update_fcr31(); |
|
1882 |
DEBUG_FPU_STATE(); |
|
1883 |
RETURN(); |
|
1884 |
} |
|
1885 |
FLOAT_OP(cvts, pl) |
|
1886 |
{ |
|
1887 |
set_float_exception_flags(0, &env->fp_status); |
|
1888 |
WT2 = WT0; |
|
1889 |
update_fcr31(); |
|
1890 |
DEBUG_FPU_STATE(); |
|
1891 |
RETURN(); |
|
1892 |
} |
|
1893 |
FLOAT_OP(cvts, pu) |
|
1894 |
{ |
|
1895 |
set_float_exception_flags(0, &env->fp_status); |
|
1896 |
WT2 = WTH0; |
|
1897 |
update_fcr31(); |
|
1759 | 1898 |
DEBUG_FPU_STATE(); |
1760 | 1899 |
RETURN(); |
1761 | 1900 |
} |
1762 | 1901 |
FLOAT_OP(cvtw, s) |
1763 | 1902 |
{ |
1903 |
set_float_exception_flags(0, &env->fp_status); |
|
1764 | 1904 |
WT2 = float32_to_int32(FST0, &env->fp_status); |
1905 |
update_fcr31(); |
|
1906 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1907 |
WT2 = 0x7fffffff; |
|
1765 | 1908 |
DEBUG_FPU_STATE(); |
1766 | 1909 |
RETURN(); |
1767 | 1910 |
} |
1768 | 1911 |
FLOAT_OP(cvtw, d) |
1769 | 1912 |
{ |
1913 |
set_float_exception_flags(0, &env->fp_status); |
|
1770 | 1914 |
WT2 = float64_to_int32(FDT0, &env->fp_status); |
1915 |
update_fcr31(); |
|
1916 |
if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) |
|
1917 |
WT2 = 0x7fffffff; |
|
1918 |
DEBUG_FPU_STATE(); |
|
1919 |
RETURN(); |
|
1920 |
} |
|
1921 |
|
|
1922 |
FLOAT_OP(pll, ps) |
|
1923 |
{ |
|
1924 |
DT2 = ((uint64_t)WT0 << 32) | WT1; |
|
1925 |
DEBUG_FPU_STATE(); |
|
1926 |
RETURN(); |
|
1927 |
} |
|
1928 |
FLOAT_OP(plu, ps) |
|
1929 |
{ |
|
1930 |
DT2 = ((uint64_t)WT0 << 32) | WTH1; |
|
1931 |
DEBUG_FPU_STATE(); |
|
1932 |
RETURN(); |
|
1933 |
} |
|
1934 |
FLOAT_OP(pul, ps) |
|
1935 |
{ |
|
1936 |
DT2 = ((uint64_t)WTH0 << 32) | WT1; |
|
1937 |
DEBUG_FPU_STATE(); |
|
1938 |
RETURN(); |
|
1939 |
} |
|
1940 |
FLOAT_OP(puu, ps) |
|
1941 |
{ |
|
1942 |
DT2 = ((uint64_t)WTH0 << 32) | WTH1; |
|
1771 | 1943 |
DEBUG_FPU_STATE(); |
1772 | 1944 |
RETURN(); |
1773 | 1945 |
} |
1774 | 1946 |
|
1947 |
FLOAT_OP(roundl, d) |
|
1948 |
{ |
|
1949 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
1950 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
1951 |
RESTORE_ROUNDING_MODE; |
|
1952 |
DEBUG_FPU_STATE(); |
|
1953 |
RETURN(); |
|
1954 |
} |
|
1955 |
FLOAT_OP(roundl, s) |
|
1956 |
{ |
|
1957 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
|
1958 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
1959 |
RESTORE_ROUNDING_MODE; |
|
1960 |
DEBUG_FPU_STATE(); |
|
1961 |
RETURN(); |
|
1962 |
} |
|
1775 | 1963 |
FLOAT_OP(roundw, d) |
1776 | 1964 |
{ |
1777 | 1965 |
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
1778 | 1966 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
1779 | 1967 |
RESTORE_ROUNDING_MODE; |
1780 |
|
|
1781 | 1968 |
DEBUG_FPU_STATE(); |
1782 | 1969 |
RETURN(); |
1783 | 1970 |
} |
... | ... | |
1790 | 1977 |
RETURN(); |
1791 | 1978 |
} |
1792 | 1979 |
|
1980 |
FLOAT_OP(truncl, d) |
|
1981 |
{ |
|
1982 |
DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status); |
|
1983 |
DEBUG_FPU_STATE(); |
|
1984 |
RETURN(); |
|
1985 |
} |
|
1986 |
FLOAT_OP(truncl, s) |
|
1987 |
{ |
|
1988 |
DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status); |
|
1989 |
DEBUG_FPU_STATE(); |
|
1990 |
RETURN(); |
|
1991 |
} |
|
1793 | 1992 |
FLOAT_OP(truncw, d) |
1794 | 1993 |
{ |
1795 | 1994 |
WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); |
... | ... | |
1803 | 2002 |
RETURN(); |
1804 | 2003 |
} |
1805 | 2004 |
|
2005 |
FLOAT_OP(ceill, d) |
|
2006 |
{ |
|
2007 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
2008 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
2009 |
RESTORE_ROUNDING_MODE; |
|
2010 |
DEBUG_FPU_STATE(); |
|
2011 |
RETURN(); |
|
2012 |
} |
|
2013 |
FLOAT_OP(ceill, s) |
|
2014 |
{ |
|
2015 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
|
2016 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
2017 |
RESTORE_ROUNDING_MODE; |
|
2018 |
DEBUG_FPU_STATE(); |
|
2019 |
RETURN(); |
|
2020 |
} |
|
1806 | 2021 |
FLOAT_OP(ceilw, d) |
1807 | 2022 |
{ |
1808 | 2023 |
set_float_rounding_mode(float_round_up, &env->fp_status); |
1809 | 2024 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
1810 | 2025 |
RESTORE_ROUNDING_MODE; |
1811 |
|
|
1812 | 2026 |
DEBUG_FPU_STATE(); |
1813 | 2027 |
RETURN(); |
1814 | 2028 |
} |
... | ... | |
1821 | 2035 |
RETURN(); |
1822 | 2036 |
} |
1823 | 2037 |
|
2038 |
FLOAT_OP(floorl, d) |
|
2039 |
{ |
|
2040 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
2041 |
DT2 = float64_round_to_int(FDT0, &env->fp_status); |
|
2042 |
RESTORE_ROUNDING_MODE; |
|
2043 |
DEBUG_FPU_STATE(); |
|
2044 |
RETURN(); |
|
2045 |
} |
|
2046 |
FLOAT_OP(floorl, s) |
|
2047 |
{ |
|
2048 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
|
2049 |
DT2 = float32_round_to_int(FST0, &env->fp_status); |
|
2050 |
RESTORE_ROUNDING_MODE; |
|
2051 |
DEBUG_FPU_STATE(); |
|
2052 |
RETURN(); |
|
2053 |
} |
|
1824 | 2054 |
FLOAT_OP(floorw, d) |
1825 | 2055 |
{ |
1826 | 2056 |
set_float_rounding_mode(float_round_down, &env->fp_status); |
1827 | 2057 |
WT2 = float64_round_to_int(FDT0, &env->fp_status); |
1828 | 2058 |
RESTORE_ROUNDING_MODE; |
1829 |
|
|
1830 | 2059 |
DEBUG_FPU_STATE(); |
1831 | 2060 |
RETURN(); |
1832 | 2061 |
} |
... | ... | |
1839 | 2068 |
RETURN(); |
1840 | 2069 |
} |
1841 | 2070 |
|
2071 |
FLOAT_OP(movf, d) |
|
2072 |
{ |
|
2073 |
if (!(env->fcr31 & PARAM1)) |
|
2074 |
DT2 = DT0; |
|
2075 |
DEBUG_FPU_STATE(); |
|
2076 |
RETURN(); |
|
2077 |
} |
|
2078 |
FLOAT_OP(movf, s) |
|
2079 |
{ |
|
2080 |
if (!(env->fcr31 & PARAM1)) |
|
2081 |
WT2 = WT0; |
|
2082 |
DEBUG_FPU_STATE(); |
|
2083 |
RETURN(); |
|
2084 |
} |
|
2085 |
FLOAT_OP(movf, ps) |
|
2086 |
{ |
|
2087 |
if (!(env->fcr31 & PARAM1)) { |
|
2088 |
WT2 = WT0; |
|
2089 |
WTH2 = WTH0; |
|
2090 |
} |
|
2091 |
DEBUG_FPU_STATE(); |
|
2092 |
RETURN(); |
|
2093 |
} |
|
2094 |
FLOAT_OP(movt, d) |
|
2095 |
{ |
|
2096 |
if (env->fcr31 & PARAM1) |
|
2097 |
DT2 = DT0; |
|
2098 |
DEBUG_FPU_STATE(); |
|
2099 |
RETURN(); |
|
2100 |
} |
|
2101 |
FLOAT_OP(movt, s) |
|
2102 |
{ |
|
2103 |
if (env->fcr31 & PARAM1) |
|
2104 |
WT2 = WT0; |
|
2105 |
DEBUG_FPU_STATE(); |
|
2106 |
RETURN(); |
|
2107 |
} |
|
2108 |
FLOAT_OP(movt, ps) |
|
2109 |
{ |
|
2110 |
if (env->fcr31 & PARAM1) { |
|
2111 |
WT2 = WT0; |
|
2112 |
WTH2 = WTH0; |
|
2113 |
} |
|
2114 |
DEBUG_FPU_STATE(); |
|
2115 |
RETURN(); |
|
2116 |
} |
|
2117 |
FLOAT_OP(movz, d) |
|
2118 |
{ |
|
2119 |
if (!T0) |
|
2120 |
DT2 = DT0; |
|
2121 |
DEBUG_FPU_STATE(); |
|
2122 |
RETURN(); |
|
2123 |
} |
|
2124 |
FLOAT_OP(movz, s) |
|
2125 |
{ |
|
2126 |
if (!T0) |
|
2127 |
WT2 = WT0; |
|
2128 |
DEBUG_FPU_STATE(); |
|
2129 |
RETURN(); |
|
2130 |
} |
|
2131 |
FLOAT_OP(movz, ps) |
|
2132 |
{ |
|
2133 |
if (!T0) { |
|
2134 |
WT2 = WT0; |
|
2135 |
WTH2 = WTH0; |
|
2136 |
} |
|
2137 |
DEBUG_FPU_STATE(); |
|
2138 |
RETURN(); |
|
2139 |
} |
|
2140 |
FLOAT_OP(movn, d) |
|
2141 |
{ |
|
2142 |
if (T0) |
|
2143 |
DT2 = DT0; |
|
2144 |
DEBUG_FPU_STATE(); |
|
2145 |
RETURN(); |
|
2146 |
} |
|
2147 |
FLOAT_OP(movn, s) |
|
2148 |
{ |
|
2149 |
if (T0) |
|
2150 |
WT2 = WT0; |
|
2151 |
DEBUG_FPU_STATE(); |
|
2152 |
RETURN(); |
|
2153 |
} |
|
2154 |
FLOAT_OP(movn, ps) |
|
2155 |
{ |
|
2156 |
if (T0) { |
|
2157 |
WT2 = WT0; |
|
2158 |
WTH2 = WTH0; |
|
2159 |
} |
|
2160 |
DEBUG_FPU_STATE(); |
|
2161 |
RETURN(); |
|
2162 |
} |
|
2163 |
|
|
1842 | 2164 |
/* binary operations */ |
1843 | 2165 |
#define FLOAT_BINOP(name) \ |
1844 | 2166 |
FLOAT_OP(name, d) \ |
1845 | 2167 |
{ \ |
2168 |
set_float_exception_flags(0, &env->fp_status); \ |
|
1846 | 2169 |
FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ |
2170 |
update_fcr31(); \ |
|
1847 | 2171 |
DEBUG_FPU_STATE(); \ |
1848 | 2172 |
} \ |
1849 | 2173 |
FLOAT_OP(name, s) \ |
1850 | 2174 |
{ \ |
2175 |
set_float_exception_flags(0, &env->fp_status); \ |
|
1851 | 2176 |
FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
2177 |
update_fcr31(); \ |
|
2178 |
DEBUG_FPU_STATE(); \ |
|
2179 |
} \ |
|
2180 |
FLOAT_OP(name, ps) \ |
|
2181 |
{ \ |
|
2182 |
set_float_exception_flags(0, &env->fp_status); \ |
|
2183 |
FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
|
2184 |
FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ |
|
2185 |
update_fcr31(); \ |
|
1852 | 2186 |
DEBUG_FPU_STATE(); \ |
1853 | 2187 |
} |
1854 | 2188 |
FLOAT_BINOP(add) |
... | ... | |
1857 | 2191 |
FLOAT_BINOP(div) |
1858 | 2192 |
#undef FLOAT_BINOP |
1859 | 2193 |
|
2194 |
/* ternary operations */ |
|
2195 |
#define FLOAT_TERNOP(name1, name2) \ |
|
2196 |
FLOAT_OP(name1 ## name2, d) \ |
|
2197 |
{ \ |
|
2198 |
FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \ |
|
2199 |
FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \ |
|
2200 |
DEBUG_FPU_STATE(); \ |
|
2201 |
} \ |
|
2202 |
FLOAT_OP(name1 ## name2, s) \ |
|
2203 |
{ \ |
|
2204 |
FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ |
|
2205 |
FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ |
|
2206 |
DEBUG_FPU_STATE(); \ |
|
2207 |
} \ |
|
2208 |
FLOAT_OP(name1 ## name2, ps) \ |
|
2209 |
{ \ |
|
2210 |
FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ |
|
2211 |
FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \ |
|
2212 |
FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ |
|
2213 |
FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \ |
|
2214 |
DEBUG_FPU_STATE(); \ |
|
2215 |
} |
|
2216 |
FLOAT_TERNOP(mul, add) |
|
2217 |
FLOAT_TERNOP(mul, sub) |
|
2218 |
#undef FLOAT_TERNOP |
|
2219 |
|
|
1860 | 2220 |
/* unary operations, modifying fp status */ |
1861 | 2221 |
#define FLOAT_UNOP(name) \ |
1862 | 2222 |
FLOAT_OP(name, d) \ |
... | ... | |
1868 | 2228 |
{ \ |
1869 | 2229 |
FST2 = float32_ ## name(FST0, &env->fp_status); \ |
1870 | 2230 |
DEBUG_FPU_STATE(); \ |
2231 |
} \ |
|
2232 |
FLOAT_OP(name, ps) \ |
|
2233 |
{ \ |
|
2234 |
FST2 = float32_ ## name(FST0, &env->fp_status); \ |
|
2235 |
FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \ |
|
2236 |
DEBUG_FPU_STATE(); \ |
|
1871 | 2237 |
} |
1872 | 2238 |
FLOAT_UNOP(sqrt) |
1873 | 2239 |
#undef FLOAT_UNOP |
... | ... | |
1883 | 2249 |
{ \ |
1884 | 2250 |
FST2 = float32_ ## name(FST0); \ |
1885 | 2251 |
DEBUG_FPU_STATE(); \ |
2252 |
} \ |
|
2253 |
FLOAT_OP(name, ps) \ |
|
2254 |
{ \ |
|
2255 |
FST2 = float32_ ## name(FST0); \ |
|
2256 |
FSTH2 = float32_ ## name(FSTH0); \ |
|
2257 |
DEBUG_FPU_STATE(); \ |
|
1886 | 2258 |
} |
1887 | 2259 |
FLOAT_UNOP(abs) |
1888 | 2260 |
FLOAT_UNOP(chs) |
... | ... | |
1900 | 2272 |
DEBUG_FPU_STATE(); |
1901 | 2273 |
RETURN(); |
1902 | 2274 |
} |
2275 |
FLOAT_OP(mov, ps) |
|
2276 |
{ |
|
2277 |
FST2 = FST0; |
|
2278 |
FSTH2 = FSTH0; |
|
2279 |
DEBUG_FPU_STATE(); |
|
2280 |
RETURN(); |
|
2281 |
} |
|
2282 |
FLOAT_OP(alnv, ps) |
|
2283 |
{ |
|
2284 |
switch (T0 & 0x7) { |
|
2285 |
case 0: |
|
2286 |
FST2 = FST0; |
|
2287 |
FSTH2 = FSTH0; |
|
2288 |
break; |
|
2289 |
case 4: |
|
2290 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
2291 |
FSTH2 = FST0; |
|
2292 |
FST2 = FSTH1; |
|
2293 |
#else |
|
2294 |
FSTH2 = FST1; |
|
2295 |
FST2 = FSTH0; |
|
2296 |
#endif |
|
2297 |
break; |
|
2298 |
default: /* unpredictable */ |
|
2299 |
break; |
|
2300 |
} |
|
2301 |
DEBUG_FPU_STATE(); |
|
2302 |
RETURN(); |
|
2303 |
} |
|
1903 | 2304 |
|
1904 | 2305 |
#ifdef CONFIG_SOFTFLOAT |
1905 | 2306 |
#define clear_invalid() do { \ |
... | ... | |
1913 | 2314 |
|
1914 | 2315 |
extern void dump_fpu_s(CPUState *env); |
1915 | 2316 |
|
1916 |
#define FOP_COND(fmt, op, sig, cond) \
|
|
1917 |
void op_cmp_ ## fmt ## _ ## op (void) \
|
|
2317 |
#define FOP_COND_D(op, cond) \
|
|
2318 |
void op_cmp_d_ ## op (void) \
|
|
1918 | 2319 |
{ \ |
1919 |
if (cond) \ |
|
1920 |
SET_FP_COND(env->fcr31); \ |
|
2320 |
int c = cond; \ |
|
2321 |
update_fcr31(); \ |
|
2322 |
if (c) \ |
|
2323 |
SET_FP_COND(PARAM1, env); \ |
|
1921 | 2324 |
else \ |
1922 |
CLEAR_FP_COND(env->fcr31); \ |
|
1923 |
if (!sig) \ |
|
1924 |
clear_invalid(); \ |
|
1925 |
/*CALL_FROM_TB1(dump_fpu_s, env);*/ \ |
|
2325 |
CLEAR_FP_COND(PARAM1, env); \ |
|
1926 | 2326 |
DEBUG_FPU_STATE(); \ |
1927 | 2327 |
RETURN(); \ |
1928 | 2328 |
} |
1929 | 2329 |
|
1930 |
int float64_is_unordered(float64 a, float64 b STATUS_PARAM) |
|
2330 |
int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
|
|
1931 | 2331 |
{ |
1932 |
if (float64_is_nan(a) || float64_is_nan(b)) { |
|
2332 |
if (float64_is_signaling_nan(a) || |
|
2333 |
float64_is_signaling_nan(b) || |
|
2334 |
(sig && (float64_is_nan(a) || float64_is_nan(b)))) { |
|
1933 | 2335 |
float_raise(float_flag_invalid, status); |
1934 | 2336 |
return 1; |
1935 |
} |
|
1936 |
else { |
|
2337 |
} else if (float64_is_nan(a) || float64_is_nan(b)) { |
|
2338 |
return 1; |
|
2339 |
} else { |
|
1937 | 2340 |
return 0; |
1938 | 2341 |
} |
1939 | 2342 |
} |
1940 | 2343 |
|
1941 |
FOP_COND(d, f, 0, 0) |
|
1942 |
FOP_COND(d, un, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status)) |
|
1943 |
FOP_COND(d, eq, 0, float64_eq(FDT0, FDT1, &env->fp_status)) |
|
1944 |
FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) |
|
1945 |
FOP_COND(d, olt, 0, float64_lt(FDT0, FDT1, &env->fp_status)) |
|
1946 |
FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) |
|
1947 |
FOP_COND(d, ole, 0, float64_le(FDT0, FDT1, &env->fp_status)) |
|
1948 |
FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) |
|
1949 | 2344 |
/* NOTE: the comma operator will make "cond" to eval to false, |
1950 |
* but float*_is_unordered() is still called |
|
1951 |
*/ |
|
1952 |
FOP_COND(d, sf, 1, (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0)) |
|
1953 |
FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status)) |
|
1954 |
FOP_COND(d, seq, 1, float64_eq(FDT0, FDT1, &env->fp_status)) |
|
1955 |
FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) |
|
1956 |
FOP_COND(d, lt, 1, float64_lt(FDT0, FDT1, &env->fp_status)) |
|
1957 |
FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) |
|
1958 |
FOP_COND(d, le, 1, float64_le(FDT0, FDT1, &env->fp_status)) |
|
1959 |
FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) |
|
1960 |
|
|
1961 |
flag float32_is_unordered(float32 a, float32 b STATUS_PARAM) |
|
1962 |
{ |
|
1963 |
extern flag float32_is_nan( float32 a ); |
|
1964 |
if (float32_is_nan(a) || float32_is_nan(b)) { |
|
2345 |
* but float*_is_unordered() is still called. */ |
|
2346 |
FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0)) |
|
2347 |
FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)) |
|
2348 |
FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status)) |
|
2349 |
FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) |
|
2350 |
FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status)) |
|
2351 |
FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) |
|
2352 |
FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status)) |
|
2353 |
FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) |
|
2354 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2355 |
* but float*_is_unordered() is still called. */ |
|
2356 |
FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0)) |
|
2357 |
FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status)) |
|
2358 |
FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status)) |
|
2359 |
FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status)) |
|
2360 |
FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status)) |
|
2361 |
FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status)) |
|
2362 |
FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status)) |
|
2363 |
FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status)) |
|
2364 |
|
|
2365 |
#define FOP_COND_S(op, cond) \ |
|
2366 |
void op_cmp_s_ ## op (void) \ |
|
2367 |
{ \ |
|
2368 |
int c = cond; \ |
|
2369 |
update_fcr31(); \ |
|
2370 |
if (c) \ |
|
2371 |
SET_FP_COND(PARAM1, env); \ |
|
2372 |
else \ |
|
2373 |
CLEAR_FP_COND(PARAM1, env); \ |
|
2374 |
DEBUG_FPU_STATE(); \ |
|
2375 |
RETURN(); \ |
|
2376 |
} |
|
2377 |
|
|
2378 |
flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) |
|
2379 |
{ |
|
2380 |
extern flag float32_is_nan(float32 a); |
|
2381 |
if (float32_is_signaling_nan(a) || |
|
2382 |
float32_is_signaling_nan(b) || |
|
2383 |
(sig && (float32_is_nan(a) || float32_is_nan(b)))) { |
|
1965 | 2384 |
float_raise(float_flag_invalid, status); |
1966 | 2385 |
return 1; |
1967 |
} |
|
1968 |
else { |
|
2386 |
} else if (float32_is_nan(a) || float32_is_nan(b)) { |
|
2387 |
return 1; |
|
2388 |
} else { |
|
1969 | 2389 |
return 0; |
1970 | 2390 |
} |
1971 | 2391 |
} |
1972 | 2392 |
|
1973 | 2393 |
/* NOTE: the comma operator will make "cond" to eval to false, |
1974 |
* but float*_is_unordered() is still called |
|
1975 |
*/ |
|
1976 |
FOP_COND(s, f, 0, 0) |
|
1977 |
FOP_COND(s, un, 0, float32_is_unordered(FST1, FST0, &env->fp_status)) |
|
1978 |
FOP_COND(s, eq, 0, float32_eq(FST0, FST1, &env->fp_status)) |
|
1979 |
FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) |
|
1980 |
FOP_COND(s, olt, 0, float32_lt(FST0, FST1, &env->fp_status)) |
|
1981 |
FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) |
|
1982 |
FOP_COND(s, ole, 0, float32_le(FST0, FST1, &env->fp_status)) |
|
1983 |
FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) |
|
2394 |
* but float*_is_unordered() is still called. */ |
|
2395 |
FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0)) |
|
2396 |
FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fp_status)) |
|
2397 |
FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status)) |
|
2398 |
FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) |
|
2399 |
FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status)) |
|
2400 |
FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) |
|
2401 |
FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status)) |
|
2402 |
FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) |
|
1984 | 2403 |
/* NOTE: the comma operator will make "cond" to eval to false, |
1985 |
* but float*_is_unordered() is still called |
|
1986 |
*/ |
|
1987 |
FOP_COND(s, sf, 1, (float32_is_unordered(FST0, FST1, &env->fp_status), 0)) |
|
1988 |
FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status)) |
|
1989 |
FOP_COND(s, seq, 1, float32_eq(FST0, FST1, &env->fp_status)) |
|
1990 |
FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) |
|
1991 |
FOP_COND(s, lt, 1, float32_lt(FST0, FST1, &env->fp_status)) |
|
1992 |
FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) |
|
1993 |
FOP_COND(s, le, 1, float32_le(FST0, FST1, &env->fp_status)) |
|
1994 |
FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) |
|
2404 |
* but float*_is_unordered() is still called. */ |
|
2405 |
FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0)) |
|
2406 |
FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status)) |
|
2407 |
FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status)) |
|
2408 |
FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status)) |
|
2409 |
FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status)) |
|
2410 |
FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status)) |
|
2411 |
FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status)) |
|
2412 |
FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) |
|
2413 |
|
|
2414 |
#define FOP_COND_PS(op, condl, condh) \ |
|
2415 |
void op_cmp_ps_ ## op (void) \ |
|
2416 |
{ \ |
|
2417 |
int cl = condl; \ |
|
2418 |
int ch = condh; \ |
|
2419 |
update_fcr31(); \ |
|
2420 |
if (cl) \ |
|
2421 |
SET_FP_COND(PARAM1, env); \ |
|
2422 |
else \ |
|
2423 |
CLEAR_FP_COND(PARAM1, env); \ |
|
2424 |
if (ch) \ |
|
2425 |
SET_FP_COND(PARAM1 + 1, env); \ |
|
2426 |
else \ |
|
2427 |
CLEAR_FP_COND(PARAM1 + 1, env); \ |
|
2428 |
DEBUG_FPU_STATE(); \ |
|
2429 |
RETURN(); \ |
|
2430 |
} |
|
2431 |
|
|
2432 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2433 |
* but float*_is_unordered() is still called. */ |
|
2434 |
FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0), |
|
2435 |
(float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0)) |
|
2436 |
FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fp_status), |
|
2437 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)) |
|
2438 |
FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status), |
|
2439 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
2440 |
FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status), |
|
2441 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
2442 |
FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status), |
|
2443 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
2444 |
FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status), |
|
2445 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
2446 |
FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status), |
|
2447 |
!float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
2448 |
FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status), |
|
2449 |
float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
2450 |
/* NOTE: the comma operator will make "cond" to eval to false, |
|
2451 |
* but float*_is_unordered() is still called. */ |
|
2452 |
FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0), |
|
2453 |
(float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0)) |
|
2454 |
FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status), |
|
2455 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)) |
|
2456 |
FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status), |
|
2457 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
2458 |
FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status), |
|
2459 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status)) |
|
2460 |
FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status), |
|
2461 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
2462 |
FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status), |
|
2463 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status)) |
|
2464 |
FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status), |
|
2465 |
!float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
2466 |
FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status), |
|
2467 |
float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status)) |
|
1995 | 2468 |
|
1996 | 2469 |
void op_bc1f (void) |
1997 | 2470 |
{ |
1998 |
T0 = ! IS_FP_COND_SET(env->fcr31); |
|
2471 |
T0 = !IS_FP_COND_SET(PARAM1, env); |
|
2472 |
DEBUG_FPU_STATE(); |
|
2473 |
RETURN(); |
|
2474 |
} |
|
2475 |
void op_bc1fany2 (void) |
|
2476 |
{ |
|
2477 |
T0 = (!IS_FP_COND_SET(PARAM1, env) || |
|
2478 |
!IS_FP_COND_SET(PARAM1 + 1, env)); |
|
2479 |
DEBUG_FPU_STATE(); |
|
2480 |
RETURN(); |
|
2481 |
} |
|
2482 |
void op_bc1fany4 (void) |
|
2483 |
{ |
|
2484 |
T0 = (!IS_FP_COND_SET(PARAM1, env) || |
|
2485 |
!IS_FP_COND_SET(PARAM1 + 1, env) || |
|
2486 |
!IS_FP_COND_SET(PARAM1 + 2, env) || |
|
2487 |
!IS_FP_COND_SET(PARAM1 + 3, env)); |
|
1999 | 2488 |
DEBUG_FPU_STATE(); |
2000 | 2489 |
RETURN(); |
2001 | 2490 |
} |
2002 | 2491 |
|
2003 | 2492 |
void op_bc1t (void) |
2004 | 2493 |
{ |
2005 |
T0 = IS_FP_COND_SET(env->fcr31); |
|
2494 |
T0 = IS_FP_COND_SET(PARAM1, env); |
|
2495 |
DEBUG_FPU_STATE(); |
|
2496 |
RETURN(); |
|
2497 |
} |
|
2498 |
void op_bc1tany2 (void) |
|
2499 |
{ |
|
2500 |
T0 = (IS_FP_COND_SET(PARAM1, env) || |
|
2501 |
IS_FP_COND_SET(PARAM1 + 1, env)); |
|
2502 |
DEBUG_FPU_STATE(); |
|
2503 |
RETURN(); |
|
2504 |
} |
|
2505 |
void op_bc1tany4 (void) |
|
2506 |
{ |
|
2507 |
T0 = (IS_FP_COND_SET(PARAM1, env) || |
|
2508 |
IS_FP_COND_SET(PARAM1 + 1, env) || |
|
2509 |
IS_FP_COND_SET(PARAM1 + 2, env) || |
|
2510 |
IS_FP_COND_SET(PARAM1 + 3, env)); |
|
2006 | 2511 |
DEBUG_FPU_STATE(); |
2007 | 2512 |
RETURN(); |
2008 | 2513 |
} |
... | ... | |
2037 | 2542 |
#if defined (CONFIG_USER_ONLY) |
2038 | 2543 |
void op_tls_value (void) |
2039 | 2544 |
{ |
2040 |
T0 = env->tls_value; |
|
2545 |
T0 = env->tls_value;
|
|
2041 | 2546 |
} |
2042 | 2547 |
#endif |
2043 | 2548 |
|
... | ... | |
2180 | 2685 |
RETURN(); |
2181 | 2686 |
} |
2182 | 2687 |
|
2688 |
void op_save_fp_status (void) |
|
2689 |
{ |
|
2690 |
union fps { |
|
2691 |
uint32_t i; |
|
2692 |
float_status f; |
|
2693 |
} fps; |
|
2694 |
fps.i = PARAM1; |
|
2695 |
env->fp_status = fps.f; |
|
2696 |
RETURN(); |
|
2697 |
} |
|
2698 |
|
|
2183 | 2699 |
void op_interrupt_restart (void) |
2184 | 2700 |
{ |
2185 | 2701 |
if (!(env->CP0_Status & (1 << CP0St_EXL)) && |
Also available in: Unified diff