summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp48
-rw-r--r--src/core/arm/interpreter/armemu.cpp102
-rw-r--r--src/core/file_sys/archive_backend.h11
-rw-r--r--src/core/hle/kernel/kernel.h12
-rw-r--r--src/core/hle/kernel/semaphore.cpp8
-rw-r--r--src/core/hle/kernel/semaphore.h2
-rw-r--r--src/core/hle/kernel/thread.cpp3
-rw-r--r--src/core/hle/kernel/thread.h3
-rw-r--r--src/core/loader/3dsx.cpp4
9 files changed, 153 insertions, 40 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 68012bffd..84b4a38f0 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -1266,6 +1266,13 @@ typedef struct _smla_inst {
1266 unsigned int Rn; 1266 unsigned int Rn;
1267} smla_inst; 1267} smla_inst;
1268 1268
1269typedef struct umaal_inst {
1270 unsigned int Rn;
1271 unsigned int Rm;
1272 unsigned int RdHi;
1273 unsigned int RdLo;
1274} umaal_inst;
1275
1269typedef struct _umlal_inst { 1276typedef struct _umlal_inst {
1270 unsigned int S; 1277 unsigned int S;
1271 unsigned int Rm; 1278 unsigned int Rm;
@@ -3010,7 +3017,26 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) { UN
3010ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB16"); } 3017ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB16"); }
3011ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB8"); } 3018ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB8"); }
3012ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUBADDX"); } 3019ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUBADDX"); }
3013ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UMAAL"); } 3020ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index)
3021{
3022 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
3023 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
3024
3025 inst_base->cond = BITS(inst, 28, 31);
3026 inst_base->idx = index;
3027 inst_base->br = NON_BRANCH;
3028 inst_base->load_r15 = 0;
3029
3030 inst_cream->Rm = BITS(inst, 8, 11);
3031 inst_cream->Rn = BITS(inst, 0, 3);
3032 inst_cream->RdLo = BITS(inst, 12, 15);
3033 inst_cream->RdHi = BITS(inst, 16, 19);
3034
3035 if (CHECK_RM || CHECK_RN)
3036 inst_base->load_r15 = 1;
3037
3038 return inst_base;
3039}
3014ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) 3040ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index)
3015{ 3041{
3016 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); 3042 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
@@ -6374,6 +6400,26 @@ unsigned InterpreterMainLoop(ARMul_State* state)
6374 UHSUB8_INST: 6400 UHSUB8_INST:
6375 UHSUBADDX_INST: 6401 UHSUBADDX_INST:
6376 UMAAL_INST: 6402 UMAAL_INST:
6403 {
6404 INC_ICOUNTER;
6405 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6406 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
6407
6408 const u32 rm = RM;
6409 const u32 rn = RN;
6410 const u32 rd_lo = RDLO;
6411 const u32 rd_hi = RDHI;
6412
6413 const u64 result = (rm * rn) + rd_lo + rd_hi;
6414
6415 RDLO = (result & 0xFFFFFFFF);
6416 RDHI = ((result >> 32) & 0xFFFFFFFF);
6417 }
6418 cpu->Reg[15] += GET_INST_SIZE(cpu);
6419 INC_PC(sizeof(umaal_inst));
6420 FETCH_INST;
6421 GOTO_NEXT_INST;
6422 }
6377 UMLAL_INST: 6423 UMLAL_INST:
6378 { 6424 {
6379 INC_ICOUNTER; 6425 INC_ICOUNTER;
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 63cfd03c6..7a319b635 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -5882,8 +5882,10 @@ L_stm_s_takeabort:
5882 printf("Unhandled v6 insn: %08x", BITS(20, 27)); 5882 printf("Unhandled v6 insn: %08x", BITS(20, 27));
5883 } 5883 }
5884 break; 5884 break;
5885 case 0x62: // QSUB16 and QADD16 5885 case 0x62: // QADD16, QASX, QSAX, and QSUB16
5886 if ((instr & 0xFF0) == 0xf70 || (instr & 0xFF0) == 0xf10) { 5886 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
5887 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
5888 {
5887 const u8 rd_idx = BITS(12, 15); 5889 const u8 rd_idx = BITS(12, 15);
5888 const u8 rn_idx = BITS(16, 19); 5890 const u8 rn_idx = BITS(16, 19);
5889 const u8 rm_idx = BITS(0, 3); 5891 const u8 rm_idx = BITS(0, 3);
@@ -5895,15 +5897,26 @@ L_stm_s_takeabort:
5895 s32 lo_result; 5897 s32 lo_result;
5896 s32 hi_result; 5898 s32 hi_result;
5897 5899
5900 // QADD16
5901 if ((instr & 0xFF0) == 0xf10) {
5902 lo_result = (rn_lo + rm_lo);
5903 hi_result = (rn_hi + rm_hi);
5904 }
5905 // QASX
5906 else if ((instr & 0xFF0) == 0xf30) {
5907 lo_result = (rn_lo - rm_hi);
5908 hi_result = (rn_hi + rm_lo);
5909 }
5910 // QSAX
5911 else if ((instr & 0xFF0) == 0xf50) {
5912 lo_result = (rn_lo + rm_hi);
5913 hi_result = (rn_hi - rm_lo);
5914 }
5898 // QSUB16 5915 // QSUB16
5899 if ((instr & 0xFF0) == 0xf70) { 5916 else {
5900 lo_result = (rn_lo - rm_lo); 5917 lo_result = (rn_lo - rm_lo);
5901 hi_result = (rn_hi - rm_hi); 5918 hi_result = (rn_hi - rm_hi);
5902 } 5919 }
5903 else { // QADD16
5904 lo_result = (rn_lo + rm_lo);
5905 hi_result = (rn_hi + rm_hi);
5906 }
5907 5920
5908 if (lo_result > 0x7FFF) 5921 if (lo_result > 0x7FFF)
5909 lo_result = 0x7FFF; 5922 lo_result = 0x7FFF;
@@ -6078,22 +6091,28 @@ L_stm_s_takeabort:
6078 //ichfly 6091 //ichfly
6079 //SSAT16 6092 //SSAT16
6080 { 6093 {
6081 u8 tar = BITS(12, 15); 6094 const u8 rd_idx = BITS(12, 15);
6082 u8 src = BITS(0, 3); 6095 const u8 rn_idx = BITS(0, 3);
6083 u8 val = BITS(16, 19) + 1; 6096 const u8 num_bits = BITS(16, 19) + 1;
6084 s16 a1 = (state->Reg[src]); 6097 const s16 min = -(0x8000 >> (16 - num_bits));
6085 s16 a2 = (state->Reg[src] >> 0x10); 6098 const s16 max = (0x7FFF >> (16 - num_bits));
6086 s16 min = (s16)(0x8000 >> (16 - val)); 6099 s16 rn_lo = (state->Reg[rn_idx]);
6087 s16 max = 0x7FFF >> (16 - val); 6100 s16 rn_hi = (state->Reg[rn_idx] >> 16);
6088 if (min > a1) a1 = min; 6101
6089 if (max < a1) a1 = max; 6102 if (rn_lo > max)
6090 if (min > a2) a2 = min; 6103 rn_lo = max;
6091 if (max < a2) a2 = max; 6104 else if (rn_lo < min)
6092 u32 temp2 = ((u32)(a2)) << 0x10; 6105 rn_lo = min;
6093 state->Reg[tar] = (a1 & 0xFFFF) | (temp2); 6106
6107 if (rn_hi > max)
6108 rn_hi = max;
6109 else if (rn_hi < min)
6110 rn_hi = min;
6111
6112 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
6113 return 1;
6094 } 6114 }
6095 6115
6096 return 1;
6097 default: 6116 default:
6098 break; 6117 break;
6099 } 6118 }
@@ -6314,11 +6333,14 @@ L_stm_s_takeabort:
6314 } 6333 }
6315 case 0x70: 6334 case 0x70:
6316 // ichfly 6335 // ichfly
6317 // SMUAD, SMUSD, SMLAD 6336 // SMUAD, SMUSD, SMLAD, and SMLSD
6318 if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 || (instr & 0xd0) == 0x10) { 6337 if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 ||
6338 (instr & 0xd0) == 0x10 || (instr & 0xd0) == 0x50)
6339 {
6319 const u8 rd_idx = BITS(16, 19); 6340 const u8 rd_idx = BITS(16, 19);
6320 const u8 rn_idx = BITS(0, 3); 6341 const u8 rn_idx = BITS(0, 3);
6321 const u8 rm_idx = BITS(8, 11); 6342 const u8 rm_idx = BITS(8, 11);
6343 const u8 ra_idx = BITS(12, 15);
6322 const bool do_swap = (BIT(5) == 1); 6344 const bool do_swap = (BIT(5) == 1);
6323 6345
6324 u32 rm_val = state->Reg[rm_idx]; 6346 u32 rm_val = state->Reg[rm_idx];
@@ -6341,13 +6363,14 @@ L_stm_s_takeabort:
6341 state->Reg[rd_idx] = (rn_lo * rm_lo) - (rn_hi * rm_hi); 6363 state->Reg[rd_idx] = (rn_lo * rm_lo) - (rn_hi * rm_hi);
6342 } 6364 }
6343 // SMLAD 6365 // SMLAD
6344 else { 6366 else if ((instr & 0xd0) == 0x10) {
6345 const u8 ra_idx = BITS(12, 15);
6346 state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi) + (s32)state->Reg[ra_idx]; 6367 state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi) + (s32)state->Reg[ra_idx];
6347 } 6368 }
6369 // SMLSD
6370 else {
6371 state->Reg[rd_idx] = ((rn_lo * rm_lo) - (rn_hi * rm_hi)) + (s32)state->Reg[ra_idx];
6372 }
6348 return 1; 6373 return 1;
6349 } else {
6350 printf ("Unhandled v6 insn: smlsd\n");
6351 } 6374 }
6352 break; 6375 break;
6353 case 0x74: 6376 case 0x74:
@@ -6357,7 +6380,30 @@ L_stm_s_takeabort:
6357 printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); 6380 printf ("Unhandled v6 insn: smmla/smmls/smmul\n");
6358 break; 6381 break;
6359 case 0x78: 6382 case 0x78:
6360 printf ("Unhandled v6 insn: usad/usada8\n"); 6383 if (BITS(20, 24) == 0x18)
6384 {
6385 const u8 rm_idx = BITS(8, 11);
6386 const u8 rn_idx = BITS(0, 3);
6387 const u8 rd_idx = BITS(16, 19);
6388
6389 const u32 rm_val = state->Reg[rm_idx];
6390 const u32 rn_val = state->Reg[rn_idx];
6391
6392 const u8 diff1 = (u8)std::labs((rn_val & 0xFF) - (rm_val & 0xFF));
6393 const u8 diff2 = (u8)std::labs(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF));
6394 const u8 diff3 = (u8)std::labs(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF));
6395 const u8 diff4 = (u8)std::labs(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF));
6396
6397 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
6398
6399 // Op is USADA8 if true.
6400 const u8 ra_idx = BITS(12, 15);
6401 if (ra_idx != 15)
6402 finalDif += state->Reg[ra_idx];
6403
6404 state->Reg[rd_idx] = finalDif;
6405 return 1;
6406 }
6361 break; 6407 break;
6362 case 0x7a: 6408 case 0x7a:
6363 printf ("Unhandled v6 insn: usbfx\n"); 6409 printf ("Unhandled v6 insn: usbfx\n");
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index 18c314884..d7959b2ca 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -143,7 +143,16 @@ public:
143 case Char: 143 case Char:
144 return std::vector<u8>(string.begin(), string.end()); 144 return std::vector<u8>(string.begin(), string.end());
145 case Wchar: 145 case Wchar:
146 return std::vector<u8>(u16str.begin(), u16str.end()); 146 {
147 // use two u8 for each character of u16str
148 std::vector<u8> to_return(u16str.size() * 2);
149 for (size_t i = 0; i < u16str.size(); ++i) {
150 u16 tmp_char = u16str.at(i);
151 to_return[i*2] = (tmp_char & 0xFF00) >> 8;
152 to_return[i*2 + 1] = (tmp_char & 0x00FF);
153 }
154 return to_return;
155 }
147 case Empty: 156 case Empty:
148 return {}; 157 return {};
149 default: 158 default:
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7123485be..683fffeee 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -14,6 +14,10 @@ typedef s32 Result;
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17// From kernel.h. Declarations duplicated here to avoid a circular header dependency.
18class Thread;
19Thread* GetCurrentThread();
20
17enum KernelHandle { 21enum KernelHandle {
18 CurrentThread = 0xFFFF8000, 22 CurrentThread = 0xFFFF8000,
19 CurrentProcess = 0xFFFF8001, 23 CurrentProcess = 0xFFFF8001,
@@ -81,6 +85,10 @@ public:
81 85
82 template <class T> 86 template <class T>
83 T* Get(Handle handle) { 87 T* Get(Handle handle) {
88 if (handle == CurrentThread) {
89 return reinterpret_cast<T*>(GetCurrentThread());
90 }
91
84 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { 92 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) {
85 if (handle != 0) { 93 if (handle != 0) {
86 LOG_ERROR(Kernel, "Bad object handle %08x", handle); 94 LOG_ERROR(Kernel, "Bad object handle %08x", handle);
@@ -99,6 +107,10 @@ public:
99 // ONLY use this when you know the handle is valid. 107 // ONLY use this when you know the handle is valid.
100 template <class T> 108 template <class T>
101 T *GetFast(Handle handle) { 109 T *GetFast(Handle handle) {
110 if (handle == CurrentThread) {
111 return reinterpret_cast<T*>(GetCurrentThread());
112 }
113
102 const Handle realHandle = handle - HANDLE_OFFSET; 114 const Handle realHandle = handle - HANDLE_OFFSET;
103 _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]); 115 _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]);
104 return static_cast<T*>(pool[realHandle]); 116 return static_cast<T*>(pool[realHandle]);
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 6f56da8a9..f955d1957 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -20,8 +20,8 @@ public:
20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; } 20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; }
21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; } 21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; }
22 22
23 u32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
24 u32 available_count; ///< Number of free slots left in the semaphore 24 s32 available_count; ///< Number of free slots left in the semaphore
25 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore 25 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore
26 std::string name; ///< Name of semaphore (optional) 26 std::string name; ///< Name of semaphore (optional)
27 27
@@ -49,8 +49,8 @@ public:
49 49
50//////////////////////////////////////////////////////////////////////////////////////////////////// 50////////////////////////////////////////////////////////////////////////////////////////////////////
51 51
52ResultCode CreateSemaphore(Handle* handle, u32 initial_count, 52ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
53 u32 max_count, const std::string& name) { 53 s32 max_count, const std::string& name) {
54 54
55 if (initial_count > max_count) 55 if (initial_count > max_count)
56 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 56 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index f0075fdb8..ad474b875 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -18,7 +18,7 @@ namespace Kernel {
18 * @param name Optional name of semaphore 18 * @param name Optional name of semaphore
19 * @return ResultCode of the error 19 * @return ResultCode of the error
20 */ 20 */
21ResultCode CreateSemaphore(Handle* handle, u32 initial_count, u32 max_count, const std::string& name = "Unknown"); 21ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown");
22 22
23/** 23/**
24 * Releases a certain number of slots from a semaphore. 24 * Releases a certain number of slots from a semaphore.
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1c04701de..47be22653 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -83,8 +83,7 @@ static Thread* current_thread;
83static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup 83static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
84static u32 next_thread_id; ///< The next available thread id 84static u32 next_thread_id; ///< The next available thread id
85 85
86/// Gets the current thread 86Thread* GetCurrentThread() {
87inline Thread* GetCurrentThread() {
88 return current_thread; 87 return current_thread;
89} 88}
90 89
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index be7adface..ec3b887d4 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -78,6 +78,9 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address);
78/// Arbitrate all threads currently waiting... 78/// Arbitrate all threads currently waiting...
79void ArbitrateAllThreads(u32 arbiter, u32 address); 79void ArbitrateAllThreads(u32 arbiter, u32 address);
80 80
81/// Gets the current thread
82Thread* GetCurrentThread();
83
81/// Gets the current thread handle 84/// Gets the current thread handle
82Handle GetCurrentThreadHandle(); 85Handle GetCurrentThreadHandle();
83 86
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index 0437e5374..3d84fc5da 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -223,9 +223,7 @@ int THREEDSXReader::Load3DSXFile(const std::string& filename, u32 base_addr)
223 LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); 223 LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str());
224 FileUtil::IOFile file(filename, "rb"); 224 FileUtil::IOFile file(filename, "rb");
225 if (file.IsOpen()) { 225 if (file.IsOpen()) {
226 226 THREEDSXReader::Load3DSXFile(filename, 0x00100000);
227 THREEDSXReader reader;
228 reader.Load3DSXFile(filename, 0x00100000);
229 Kernel::LoadExec(0x00100000); 227 Kernel::LoadExec(0x00100000);
230 } else { 228 } else {
231 return ResultStatus::Error; 229 return ResultStatus::Error;