summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp75
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h117
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp35
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp30
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/hle/kernel/thread.cpp48
-rw-r--r--src/core/hle/kernel/thread.h17
7 files changed, 189 insertions, 137 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index c2973fb39..315b4cc91 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -992,6 +992,14 @@ typedef struct _mcr_inst {
992 unsigned int inst; 992 unsigned int inst;
993} mcr_inst; 993} mcr_inst;
994 994
995typedef struct mcrr_inst {
996 unsigned int opcode_1;
997 unsigned int cp_num;
998 unsigned int crm;
999 unsigned int rt;
1000 unsigned int rt2;
1001} mcrr_inst;
1002
995typedef struct _mrs_inst { 1003typedef struct _mrs_inst {
996 unsigned int R; 1004 unsigned int R;
997 unsigned int Rd; 1005 unsigned int Rd;
@@ -1261,11 +1269,6 @@ static get_addr_fp_t get_calc_addr_op(unsigned int inst) {
1261#define CHECK_RM (inst_cream->Rm == 15) 1269#define CHECK_RM (inst_cream->Rm == 15)
1262#define CHECK_RS (inst_cream->Rs == 15) 1270#define CHECK_RS (inst_cream->Rs == 15)
1263 1271
1264#define UNIMPLEMENTED_INSTRUCTION(mnemonic) \
1265 LOG_ERROR(Core_ARM11, "unimplemented instruction: %s", mnemonic); \
1266 CITRA_IGNORE_EXIT(-1); \
1267 return nullptr;
1268
1269static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) 1272static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index)
1270{ 1273{
1271 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); 1274 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst));
@@ -1871,7 +1874,26 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index)
1871 inst_cream->inst = inst; 1874 inst_cream->inst = inst;
1872 return inst_base; 1875 return inst_base;
1873} 1876}
1874static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("MCRR"); } 1877
1878static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index)
1879{
1880 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst));
1881 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
1882
1883 inst_base->cond = BITS(inst, 28, 31);
1884 inst_base->idx = index;
1885 inst_base->br = NON_BRANCH;
1886 inst_base->load_r15 = 0;
1887
1888 inst_cream->crm = BITS(inst, 0, 3);
1889 inst_cream->opcode_1 = BITS(inst, 4, 7);
1890 inst_cream->cp_num = BITS(inst, 8, 11);
1891 inst_cream->rt = BITS(inst, 12, 15);
1892 inst_cream->rt2 = BITS(inst, 16, 19);
1893
1894 return inst_base;
1895}
1896
1875static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) 1897static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index)
1876{ 1898{
1877 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); 1899 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst));
@@ -1930,7 +1952,12 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index)
1930 inst_cream->inst = inst; 1952 inst_cream->inst = inst;
1931 return inst_base; 1953 return inst_base;
1932} 1954}
1933static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("MRRC"); } 1955
1956static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index)
1957{
1958 return INTERPRETER_TRANSLATE(mcrr)(inst, index);
1959}
1960
1934static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) 1961static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index)
1935{ 1962{
1936 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); 1963 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst));
@@ -4754,7 +4781,24 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4754 FETCH_INST; 4781 FETCH_INST;
4755 GOTO_NEXT_INST; 4782 GOTO_NEXT_INST;
4756 } 4783 }
4784
4757 MCRR_INST: 4785 MCRR_INST:
4786 {
4787 // Stubbed, as the MPCore doesn't have any registers that are accessible
4788 // through this instruction.
4789 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4790 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
4791
4792 LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
4793 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2);
4794 }
4795
4796 cpu->Reg[15] += GET_INST_SIZE(cpu);
4797 INC_PC(sizeof(mcrr_inst));
4798 FETCH_INST;
4799 GOTO_NEXT_INST;
4800 }
4801
4758 MLA_INST: 4802 MLA_INST:
4759 { 4803 {
4760 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { 4804 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
@@ -4830,7 +4874,24 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4830 FETCH_INST; 4874 FETCH_INST;
4831 GOTO_NEXT_INST; 4875 GOTO_NEXT_INST;
4832 } 4876 }
4877
4833 MRRC_INST: 4878 MRRC_INST:
4879 {
4880 // Stubbed, as the MPCore doesn't have any registers that are accessible
4881 // through this instruction.
4882 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4883 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
4884
4885 LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
4886 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2);
4887 }
4888
4889 cpu->Reg[15] += GET_INST_SIZE(cpu);
4890 INC_PC(sizeof(mcrr_inst));
4891 FETCH_INST;
4892 GOTO_NEXT_INST;
4893 }
4894
4834 MRS_INST: 4895 MRS_INST:
4835 { 4896 {
4836 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { 4897 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index 6b3dae280..ccc0212ab 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -35,6 +35,7 @@
35#include <cstdio> 35#include <cstdio>
36#include "common/common_types.h" 36#include "common/common_types.h"
37#include "core/arm/skyeye_common/armdefs.h" 37#include "core/arm/skyeye_common/armdefs.h"
38#include "core/arm/skyeye_common/vfp/asm_vfp.h"
38 39
39#define do_div(n, base) {n/=base;} 40#define do_div(n, base) {n/=base;}
40 41
@@ -236,33 +237,6 @@ struct vfp_single {
236#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) 237#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
237#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) 238#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
238 239
239// Unpack a single-precision float. Note that this returns the magnitude
240// of the single-precision float mantissa with the 1. if necessary,
241// aligned to bit 30.
242static inline void vfp_single_unpack(vfp_single* s, s32 val)
243{
244 u32 significand;
245
246 s->sign = vfp_single_packed_sign(val) >> 16,
247 s->exponent = vfp_single_packed_exponent(val);
248
249 significand = (u32) val;
250 significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
251 if (s->exponent && s->exponent != 255)
252 significand |= 0x40000000;
253 s->significand = significand;
254}
255
256// Re-pack a single-precision float. This assumes that the float is
257// already normalised such that the MSB is bit 30, _not_ bit 31.
258static inline s32 vfp_single_pack(vfp_single* s)
259{
260 u32 val = (s->sign << 16) +
261 (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
262 (s->significand >> VFP_SINGLE_LOW_BITS);
263 return (s32)val;
264}
265
266enum : u32 { 240enum : u32 {
267 VFP_NUMBER = (1 << 0), 241 VFP_NUMBER = (1 << 0),
268 VFP_ZERO = (1 << 1), 242 VFP_ZERO = (1 << 1),
@@ -294,6 +268,39 @@ static inline int vfp_single_type(vfp_single* s)
294 return type; 268 return type;
295} 269}
296 270
271// Unpack a single-precision float. Note that this returns the magnitude
272// of the single-precision float mantissa with the 1. if necessary,
273// aligned to bit 30.
274static inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr)
275{
276 s->sign = vfp_single_packed_sign(val) >> 16,
277 s->exponent = vfp_single_packed_exponent(val);
278
279 u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
280 if (s->exponent && s->exponent != 255)
281 significand |= 0x40000000;
282 s->significand = significand;
283
284 // If flush-to-zero mode is enabled, turn the denormal into zero.
285 // On a VFPv2 architecture, the sign of the zero is always positive.
286 if ((*fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_single_type(s) & VFP_DENORMAL) != 0) {
287 s->sign = 0;
288 s->exponent = 0;
289 s->significand = 0;
290 *fpscr |= FPSCR_IDC;
291 }
292}
293
294// Re-pack a single-precision float. This assumes that the float is
295// already normalised such that the MSB is bit 30, _not_ bit 31.
296static inline s32 vfp_single_pack(vfp_single* s)
297{
298 u32 val = (s->sign << 16) +
299 (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
300 (s->significand >> VFP_SINGLE_LOW_BITS);
301 return (s32)val;
302}
303
297 304
298u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, u32 exceptions, const char* func); 305u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, u32 exceptions, const char* func);
299 306
@@ -328,24 +335,49 @@ struct vfp_double {
328#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) 335#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
329#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) 336#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
330 337
338static inline int vfp_double_type(vfp_double* s)
339{
340 int type = VFP_NUMBER;
341 if (s->exponent == 2047) {
342 if (s->significand == 0)
343 type = VFP_INFINITY;
344 else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
345 type = VFP_QNAN;
346 else
347 type = VFP_SNAN;
348 } else if (s->exponent == 0) {
349 if (s->significand == 0)
350 type |= VFP_ZERO;
351 else
352 type |= VFP_DENORMAL;
353 }
354 return type;
355}
356
331// Unpack a double-precision float. Note that this returns the magnitude 357// Unpack a double-precision float. Note that this returns the magnitude
332// of the double-precision float mantissa with the 1. if necessary, 358// of the double-precision float mantissa with the 1. if necessary,
333// aligned to bit 62. 359// aligned to bit 62.
334static inline void vfp_double_unpack(vfp_double* s, s64 val) 360static inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr)
335{ 361{
336 u64 significand;
337
338 s->sign = vfp_double_packed_sign(val) >> 48; 362 s->sign = vfp_double_packed_sign(val) >> 48;
339 s->exponent = vfp_double_packed_exponent(val); 363 s->exponent = vfp_double_packed_exponent(val);
340 364
341 significand = (u64) val; 365 u64 significand = ((u64)val << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
342 significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
343 if (s->exponent && s->exponent != 2047) 366 if (s->exponent && s->exponent != 2047)
344 significand |= (1ULL << 62); 367 significand |= (1ULL << 62);
345 s->significand = significand; 368 s->significand = significand;
369
370 // If flush-to-zero mode is enabled, turn the denormal into zero.
371 // On a VFPv2 architecture, the sign of the zero is always positive.
372 if ((*fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_double_type(s) & VFP_DENORMAL) != 0) {
373 s->sign = 0;
374 s->exponent = 0;
375 s->significand = 0;
376 *fpscr |= FPSCR_IDC;
377 }
346} 378}
347 379
348// Re-pack a double-precision float. This assumes that the float is 380// Re-pack a double-precision float. This assumes that the float is
349// already normalised such that the MSB is bit 30, _not_ bit 31. 381// already normalised such that the MSB is bit 30, _not_ bit 31.
350static inline s64 vfp_double_pack(vfp_double* s) 382static inline s64 vfp_double_pack(vfp_double* s)
351{ 383{
@@ -355,25 +387,6 @@ static inline s64 vfp_double_pack(vfp_double* s)
355 return (s64)val; 387 return (s64)val;
356} 388}
357 389
358static inline int vfp_double_type(vfp_double* s)
359{
360 int type = VFP_NUMBER;
361 if (s->exponent == 2047) {
362 if (s->significand == 0)
363 type = VFP_INFINITY;
364 else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
365 type = VFP_QNAN;
366 else
367 type = VFP_SNAN;
368 } else if (s->exponent == 0) {
369 if (s->significand == 0)
370 type |= VFP_ZERO;
371 else
372 type |= VFP_DENORMAL;
373 }
374 return type;
375}
376
377u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); 390u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
378 391
379// A special flag to tell the normalisation code not to normalise. 392// A special flag to tell the normalisation code not to normalise.
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index d76d37fd4..ab9fec39d 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -291,7 +291,8 @@ static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32
291 vfp_double vdm, vdd, *vdp; 291 vfp_double vdm, vdd, *vdp;
292 int ret, tm; 292 int ret, tm;
293 293
294 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 294 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
295
295 tm = vfp_double_type(&vdm); 296 tm = vfp_double_type(&vdm);
296 if (tm & (VFP_NAN|VFP_INFINITY)) { 297 if (tm & (VFP_NAN|VFP_INFINITY)) {
297 vdp = &vdd; 298 vdp = &vdd;
@@ -473,7 +474,7 @@ static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32
473 u32 exceptions = 0; 474 u32 exceptions = 0;
474 475
475 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__); 476 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
476 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 477 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
477 478
478 tm = vfp_double_type(&vdm); 479 tm = vfp_double_type(&vdm);
479 480
@@ -543,7 +544,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32
543 int tm; 544 int tm;
544 545
545 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__); 546 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
546 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 547 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
547 548
548 /* 549 /*
549 * Do we have a denormalised number? 550 * Do we have a denormalised number?
@@ -624,7 +625,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
624 int tm; 625 int tm;
625 626
626 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__); 627 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
627 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 628 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
628 vfp_double_dump("VDM", &vdm); 629 vfp_double_dump("VDM", &vdm);
629 630
630 /* 631 /*
@@ -896,11 +897,11 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f
896 struct vfp_double vdd, vdp, vdn, vdm; 897 struct vfp_double vdd, vdp, vdn, vdm;
897 u32 exceptions; 898 u32 exceptions;
898 899
899 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 900 vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
900 if (vdn.exponent == 0 && vdn.significand) 901 if (vdn.exponent == 0 && vdn.significand)
901 vfp_double_normalise_denormal(&vdn); 902 vfp_double_normalise_denormal(&vdn);
902 903
903 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 904 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
904 if (vdm.exponent == 0 && vdm.significand) 905 if (vdm.exponent == 0 && vdm.significand)
905 vfp_double_normalise_denormal(&vdm); 906 vfp_double_normalise_denormal(&vdm);
906 907
@@ -908,7 +909,7 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f
908 if (negate & NEG_MULTIPLY) 909 if (negate & NEG_MULTIPLY)
909 vdp.sign = vfp_sign_negate(vdp.sign); 910 vdp.sign = vfp_sign_negate(vdp.sign);
910 911
911 vfp_double_unpack(&vdn, vfp_get_double(state, dd)); 912 vfp_double_unpack(&vdn, vfp_get_double(state, dd), &fpscr);
912 if (vdn.exponent == 0 && vdn.significand != 0) 913 if (vdn.exponent == 0 && vdn.significand != 0)
913 vfp_double_normalise_denormal(&vdn); 914 vfp_double_normalise_denormal(&vdn);
914 915
@@ -969,11 +970,11 @@ static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
969 u32 exceptions; 970 u32 exceptions;
970 971
971 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__); 972 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
972 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 973 vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
973 if (vdn.exponent == 0 && vdn.significand) 974 if (vdn.exponent == 0 && vdn.significand)
974 vfp_double_normalise_denormal(&vdn); 975 vfp_double_normalise_denormal(&vdn);
975 976
976 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 977 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
977 if (vdm.exponent == 0 && vdm.significand) 978 if (vdm.exponent == 0 && vdm.significand)
978 vfp_double_normalise_denormal(&vdm); 979 vfp_double_normalise_denormal(&vdm);
979 980
@@ -990,11 +991,11 @@ static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
990 u32 exceptions; 991 u32 exceptions;
991 992
992 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__); 993 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
993 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 994 vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
994 if (vdn.exponent == 0 && vdn.significand) 995 if (vdn.exponent == 0 && vdn.significand)
995 vfp_double_normalise_denormal(&vdn); 996 vfp_double_normalise_denormal(&vdn);
996 997
997 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 998 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
998 if (vdm.exponent == 0 && vdm.significand) 999 if (vdm.exponent == 0 && vdm.significand)
999 vfp_double_normalise_denormal(&vdm); 1000 vfp_double_normalise_denormal(&vdm);
1000 1001
@@ -1013,11 +1014,11 @@ static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1013 u32 exceptions; 1014 u32 exceptions;
1014 1015
1015 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__); 1016 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
1016 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1017 vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
1017 if (vdn.exponent == 0 && vdn.significand) 1018 if (vdn.exponent == 0 && vdn.significand)
1018 vfp_double_normalise_denormal(&vdn); 1019 vfp_double_normalise_denormal(&vdn);
1019 1020
1020 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1021 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
1021 if (vdm.exponent == 0 && vdm.significand) 1022 if (vdm.exponent == 0 && vdm.significand)
1022 vfp_double_normalise_denormal(&vdm); 1023 vfp_double_normalise_denormal(&vdm);
1023 1024
@@ -1035,11 +1036,11 @@ static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1035 u32 exceptions; 1036 u32 exceptions;
1036 1037
1037 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__); 1038 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
1038 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1039 vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
1039 if (vdn.exponent == 0 && vdn.significand) 1040 if (vdn.exponent == 0 && vdn.significand)
1040 vfp_double_normalise_denormal(&vdn); 1041 vfp_double_normalise_denormal(&vdn);
1041 1042
1042 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1043 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
1043 if (vdm.exponent == 0 && vdm.significand) 1044 if (vdm.exponent == 0 && vdm.significand)
1044 vfp_double_normalise_denormal(&vdm); 1045 vfp_double_normalise_denormal(&vdm);
1045 1046
@@ -1063,8 +1064,8 @@ static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1063 int tm, tn; 1064 int tm, tn;
1064 1065
1065 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__); 1066 LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
1066 vfp_double_unpack(&vdn, vfp_get_double(state, dn)); 1067 vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
1067 vfp_double_unpack(&vdm, vfp_get_double(state, dm)); 1068 vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
1068 1069
1069 vdd.sign = vdn.sign ^ vdm.sign; 1070 vdd.sign = vdn.sign ^ vdm.sign;
1070 1071
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index a78bdc430..4dfe0254d 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -330,7 +330,7 @@ static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 f
330 struct vfp_single vsm, vsd, *vsp; 330 struct vfp_single vsm, vsd, *vsp;
331 int ret, tm; 331 int ret, tm;
332 332
333 vfp_single_unpack(&vsm, m); 333 vfp_single_unpack(&vsm, m, &fpscr);
334 tm = vfp_single_type(&vsm); 334 tm = vfp_single_type(&vsm);
335 if (tm & (VFP_NAN|VFP_INFINITY)) { 335 if (tm & (VFP_NAN|VFP_INFINITY)) {
336 vsp = &vsd; 336 vsp = &vsd;
@@ -498,7 +498,7 @@ static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 f
498 int tm; 498 int tm;
499 u32 exceptions = 0; 499 u32 exceptions = 0;
500 500
501 vfp_single_unpack(&vsm, m); 501 vfp_single_unpack(&vsm, m, &fpscr);
502 502
503 tm = vfp_single_type(&vsm); 503 tm = vfp_single_type(&vsm);
504 504
@@ -563,7 +563,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
563 int rmode = fpscr & FPSCR_RMODE_MASK; 563 int rmode = fpscr & FPSCR_RMODE_MASK;
564 int tm; 564 int tm;
565 565
566 vfp_single_unpack(&vsm, m); 566 vfp_single_unpack(&vsm, m, &fpscr);
567 vfp_single_dump("VSM", &vsm); 567 vfp_single_dump("VSM", &vsm);
568 568
569 /* 569 /*
@@ -643,7 +643,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
643 int rmode = fpscr & FPSCR_RMODE_MASK; 643 int rmode = fpscr & FPSCR_RMODE_MASK;
644 int tm; 644 int tm;
645 645
646 vfp_single_unpack(&vsm, m); 646 vfp_single_unpack(&vsm, m, &fpscr);
647 vfp_single_dump("VSM", &vsm); 647 vfp_single_dump("VSM", &vsm);
648 648
649 /* 649 /*
@@ -925,11 +925,11 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
925 925
926 v = vfp_get_float(state, sn); 926 v = vfp_get_float(state, sn);
927 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, v); 927 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, v);
928 vfp_single_unpack(&vsn, v); 928 vfp_single_unpack(&vsn, v, &fpscr);
929 if (vsn.exponent == 0 && vsn.significand) 929 if (vsn.exponent == 0 && vsn.significand)
930 vfp_single_normalise_denormal(&vsn); 930 vfp_single_normalise_denormal(&vsn);
931 931
932 vfp_single_unpack(&vsm, m); 932 vfp_single_unpack(&vsm, m, &fpscr);
933 if (vsm.exponent == 0 && vsm.significand) 933 if (vsm.exponent == 0 && vsm.significand)
934 vfp_single_normalise_denormal(&vsm); 934 vfp_single_normalise_denormal(&vsm);
935 935
@@ -940,7 +940,7 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
940 940
941 v = vfp_get_float(state, sd); 941 v = vfp_get_float(state, sd);
942 LOG_DEBUG(Core_ARM11, "s%u = %08x", sd, v); 942 LOG_DEBUG(Core_ARM11, "s%u = %08x", sd, v);
943 vfp_single_unpack(&vsn, v); 943 vfp_single_unpack(&vsn, v, &fpscr);
944 if (vsn.exponent == 0 && vsn.significand != 0) 944 if (vsn.exponent == 0 && vsn.significand != 0)
945 vfp_single_normalise_denormal(&vsn); 945 vfp_single_normalise_denormal(&vsn);
946 946
@@ -1004,11 +1004,11 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1004 1004
1005 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n); 1005 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
1006 1006
1007 vfp_single_unpack(&vsn, n); 1007 vfp_single_unpack(&vsn, n, &fpscr);
1008 if (vsn.exponent == 0 && vsn.significand) 1008 if (vsn.exponent == 0 && vsn.significand)
1009 vfp_single_normalise_denormal(&vsn); 1009 vfp_single_normalise_denormal(&vsn);
1010 1010
1011 vfp_single_unpack(&vsm, m); 1011 vfp_single_unpack(&vsm, m, &fpscr);
1012 if (vsm.exponent == 0 && vsm.significand) 1012 if (vsm.exponent == 0 && vsm.significand)
1013 vfp_single_normalise_denormal(&vsm); 1013 vfp_single_normalise_denormal(&vsm);
1014 1014
@@ -1027,11 +1027,11 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
1027 1027
1028 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n); 1028 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
1029 1029
1030 vfp_single_unpack(&vsn, n); 1030 vfp_single_unpack(&vsn, n, &fpscr);
1031 if (vsn.exponent == 0 && vsn.significand) 1031 if (vsn.exponent == 0 && vsn.significand)
1032 vfp_single_normalise_denormal(&vsn); 1032 vfp_single_normalise_denormal(&vsn);
1033 1033
1034 vfp_single_unpack(&vsm, m); 1034 vfp_single_unpack(&vsm, m, &fpscr);
1035 if (vsm.exponent == 0 && vsm.significand) 1035 if (vsm.exponent == 0 && vsm.significand)
1036 vfp_single_normalise_denormal(&vsm); 1036 vfp_single_normalise_denormal(&vsm);
1037 1037
@@ -1054,11 +1054,11 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1054 /* 1054 /*
1055 * Unpack and normalise denormals. 1055 * Unpack and normalise denormals.
1056 */ 1056 */
1057 vfp_single_unpack(&vsn, n); 1057 vfp_single_unpack(&vsn, n, &fpscr);
1058 if (vsn.exponent == 0 && vsn.significand) 1058 if (vsn.exponent == 0 && vsn.significand)
1059 vfp_single_normalise_denormal(&vsn); 1059 vfp_single_normalise_denormal(&vsn);
1060 1060
1061 vfp_single_unpack(&vsm, m); 1061 vfp_single_unpack(&vsm, m, &fpscr);
1062 if (vsm.exponent == 0 && vsm.significand) 1062 if (vsm.exponent == 0 && vsm.significand)
1063 vfp_single_normalise_denormal(&vsm); 1063 vfp_single_normalise_denormal(&vsm);
1064 1064
@@ -1094,8 +1094,8 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1094 1094
1095 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n); 1095 LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
1096 1096
1097 vfp_single_unpack(&vsn, n); 1097 vfp_single_unpack(&vsn, n, &fpscr);
1098 vfp_single_unpack(&vsm, m); 1098 vfp_single_unpack(&vsm, m, &fpscr);
1099 1099
1100 vsd.sign = vsn.sign ^ vsm.sign; 1100 vsd.sign = vsn.sign ^ vsm.sign;
1101 1101
diff --git a/src/core/core.cpp b/src/core/core.cpp
index b5c258230..53aae8c2f 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -24,9 +24,9 @@ ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core
24 24
25/// Run the core CPU loop 25/// Run the core CPU loop
26void RunLoop(int tight_loop) { 26void RunLoop(int tight_loop) {
27 // If the current thread is an idle thread, then don't execute instructions, 27 // If we don't have a currently active thread then don't execute instructions,
28 // instead advance to the next event and try to yield to the next thread 28 // instead advance to the next event and try to yield to the next thread
29 if (Kernel::GetCurrentThread()->IsIdle()) { 29 if (Kernel::GetCurrentThread() == nullptr) {
30 LOG_TRACE(Core_ARM11, "Idling"); 30 LOG_TRACE(Core_ARM11, "Idling");
31 CoreTiming::Idle(); 31 CoreTiming::Idle();
32 CoreTiming::Advance(); 32 CoreTiming::Advance();
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 34dc257aa..afaf0cd5d 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -160,7 +160,7 @@ static void PriorityBoostStarvedThreads() {
160 160
161 u64 delta = current_ticks - thread->last_running_ticks; 161 u64 delta = current_ticks - thread->last_running_ticks;
162 162
163 if (thread->status == THREADSTATUS_READY && delta > boost_timeout && !thread->idle) { 163 if (thread->status == THREADSTATUS_READY && delta > boost_timeout) {
164 const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0); 164 const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0);
165 thread->BoostPriority(priority); 165 thread->BoostPriority(priority);
166 } 166 }
@@ -172,8 +172,6 @@ static void PriorityBoostStarvedThreads() {
172 * @param new_thread The thread to switch to 172 * @param new_thread The thread to switch to
173 */ 173 */
174static void SwitchContext(Thread* new_thread) { 174static void SwitchContext(Thread* new_thread) {
175 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running.");
176
177 Thread* previous_thread = GetCurrentThread(); 175 Thread* previous_thread = GetCurrentThread();
178 176
179 // Save context for previous thread 177 // Save context for previous thread
@@ -191,6 +189,8 @@ static void SwitchContext(Thread* new_thread) {
191 189
192 // Load context of new thread 190 // Load context of new thread
193 if (new_thread) { 191 if (new_thread) {
192 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running.");
193
194 current_thread = new_thread; 194 current_thread = new_thread;
195 195
196 ready_queue.remove(new_thread->current_priority, new_thread); 196 ready_queue.remove(new_thread->current_priority, new_thread);
@@ -218,6 +218,10 @@ static Thread* PopNextReadyThread() {
218 // We have to do better than the current thread. 218 // We have to do better than the current thread.
219 // This call returns null when that's not possible. 219 // This call returns null when that's not possible.
220 next = ready_queue.pop_first_better(thread->current_priority); 220 next = ready_queue.pop_first_better(thread->current_priority);
221 if (!next) {
222 // Otherwise just keep going with the current thread
223 next = thread;
224 }
221 } else { 225 } else {
222 next = ready_queue.pop_first(); 226 next = ready_queue.pop_first();
223 } 227 }
@@ -450,6 +454,8 @@ void Thread::SetPriority(s32 priority) {
450 // If thread was ready, adjust queues 454 // If thread was ready, adjust queues
451 if (status == THREADSTATUS_READY) 455 if (status == THREADSTATUS_READY)
452 ready_queue.move(this, current_priority, priority); 456 ready_queue.move(this, current_priority, priority);
457 else
458 ready_queue.prepare(priority);
453 459
454 nominal_priority = current_priority = priority; 460 nominal_priority = current_priority = priority;
455} 461}
@@ -459,16 +465,6 @@ void Thread::BoostPriority(s32 priority) {
459 current_priority = priority; 465 current_priority = priority;
460} 466}
461 467
462SharedPtr<Thread> SetupIdleThread() {
463 // We need to pass a few valid values to get around parameter checking in Thread::Create.
464 // TODO(yuriks): Figure out a way to avoid passing the bogus VAddr parameter
465 auto thread = Thread::Create("idle", Memory::TLS_AREA_VADDR, THREADPRIO_LOWEST, 0,
466 THREADPROCESSORID_0, 0).MoveFrom();
467
468 thread->idle = true;
469 return thread;
470}
471
472SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { 468SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
473 DEBUG_ASSERT(!GetCurrentThread()); 469 DEBUG_ASSERT(!GetCurrentThread());
474 470
@@ -485,24 +481,25 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
485} 481}
486 482
487void Reschedule() { 483void Reschedule() {
488 Thread* prev = GetCurrentThread();
489
490 PriorityBoostStarvedThreads(); 484 PriorityBoostStarvedThreads();
491 485
486 Thread* cur = GetCurrentThread();
492 Thread* next = PopNextReadyThread(); 487 Thread* next = PopNextReadyThread();
493 HLE::g_reschedule = false; 488 HLE::g_reschedule = false;
494 489
495 if (next != nullptr) { 490 // Don't bother switching to the same thread
496 LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId()); 491 if (next == cur)
497 SwitchContext(next); 492 return;
498 } else {
499 LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId());
500 493
501 for (auto& thread : thread_list) { 494 if (cur && next) {
502 LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(), 495 LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId());
503 thread->current_priority, thread->status); 496 } else if (cur) {
504 } 497 LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId());
498 } else {
499 LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId());
505 } 500 }
501
502 SwitchContext(next);
506} 503}
507 504
508void Thread::SetWaitSynchronizationResult(ResultCode result) { 505void Thread::SetWaitSynchronizationResult(ResultCode result) {
@@ -527,9 +524,6 @@ void ThreadingInit() {
527 524
528 thread_list.clear(); 525 thread_list.clear();
529 ready_queue.clear(); 526 ready_queue.clear();
530
531 // Setup the idle thread
532 SetupIdleThread();
533} 527}
534 528
535void ThreadingShutdown() { 529void ThreadingShutdown() {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index cfbebab08..6b329c12a 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -73,12 +73,6 @@ public:
73 void Acquire() override; 73 void Acquire() override;
74 74
75 /** 75 /**
76 * Checks if the thread is an idle (stub) thread
77 * @return True if the thread is an idle (stub) thread, false otherwise
78 */
79 inline bool IsIdle() const { return idle; }
80
81 /**
82 * Gets the thread's current priority 76 * Gets the thread's current priority
83 * @return The current thread's priority 77 * @return The current thread's priority
84 */ 78 */
@@ -170,9 +164,6 @@ public:
170 164
171 std::string name; 165 std::string name;
172 166
173 /// Whether this thread is intended to never actually be executed, i.e. always idle
174 bool idle = false;
175
176private: 167private:
177 Thread(); 168 Thread();
178 ~Thread() override; 169 ~Thread() override;
@@ -231,14 +222,6 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa
231void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); 222void WaitCurrentThread_ArbitrateAddress(VAddr wait_address);
232 223
233/** 224/**
234 * Sets up the idle thread, this is a thread that is intended to never execute instructions,
235 * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue
236 * and will try to yield on every call.
237 * @return The handle of the idle thread
238 */
239SharedPtr<Thread> SetupIdleThread();
240
241/**
242 * Initialize threading 225 * Initialize threading
243 */ 226 */
244void ThreadingInit(); 227void ThreadingInit();