diff options
| -rw-r--r-- | .travis-deps.sh | 6 | ||||
| -rw-r--r-- | CMakeLists.txt | 30 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | src/citra/CMakeLists.txt | 14 | ||||
| -rw-r--r-- | src/citra_qt/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/common/bit_field.h | 6 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.h | 2 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 106 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_run.cpp | 1 | ||||
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 262 | ||||
| -rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 13 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 2 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armemu.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/apt_u.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/fs/fs_user.cpp | 19 | ||||
| -rw-r--r-- | src/video_core/command_processor.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/pica.h | 10 | 
17 files changed, 369 insertions, 124 deletions
diff --git a/.travis-deps.sh b/.travis-deps.sh index b978e552e..2a0f6b284 100644 --- a/.travis-deps.sh +++ b/.travis-deps.sh @@ -12,7 +12,11 @@ if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then      (          git clone https://github.com/glfw/glfw.git --branch 3.0.4 --depth 1          mkdir glfw/build && cd glfw/build -        cmake .. && make -j2 && sudo make install +        cmake -DBUILD_SHARED_LIBS=ON \ +              -DGLFW_BUILD_EXAMPLES=OFF \ +              -DGLFW_BUILD_TESTS=OFF \ +              .. +        make -j4 && sudo make install      )      sudo apt-get install lib32stdc++6 diff --git a/CMakeLists.txt b/CMakeLists.txt index 638b468a6..5bb87d50d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,18 +6,40 @@ project(citra)  if (NOT MSVC)      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-attributes") +    add_definitions(-pthread)  else()      # Silence deprecation warnings      add_definitions(/D_CRT_SECURE_NO_WARNINGS)      # set up output paths for executable binaries (.exe-files, and .dll-files on DLL-capable platforms)      set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +    # Tweak optimization settings +    # As far as I can tell, there's no way to override the CMake defaults while leaving user +    # changes intact, so we'll just clobber everything and say sorry. +    message(STATUS "Cache compiler flags ignored, please edit CMakeFiles.txt to change the flags.") +    # /MD - Multi-threaded runtime +    # /Ox - Full optimization +    # /Oi - Use intrinsic functions +    # /Oy- - Don't omit frame pointer +    # /GR- - Disable RTTI +    # /GS- - No stack buffer overflow checks +    # /EHsc - C++-only exception handling semantics +    set(optimization_flags "/MD /Ox /Oi /Oy- /DNDEBUG /GR- /GS- /EHsc") +    # /Zi - Output debugging information +    # /Zo - enahnced debug info for optimized builds +    set(CMAKE_C_FLAGS_RELEASE   "${optimization_flags} /Zi" CACHE STRING "" FORCE) +    set(CMAKE_CXX_FLAGS_RELEASE "${optimization_flags} /Zi" CACHE STRING "" FORCE) +    set(CMAKE_C_FLAGS_RELWITHDEBINFO   "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE) +    set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE)  endif()  add_definitions(-DSINGLETHREADED) -find_package(PNG) +find_package(PNG QUIET)  if (PNG_FOUND)      add_definitions(-DHAVE_PNG) -endif () +else() +    message(STATUS "libpng not found. Some debugging features have been disabled.") +endif()  find_package(Boost)  if (Boost_FOUND) @@ -75,10 +97,6 @@ if (ENABLE_GLFW)          set(GLFW_LIBRARIES glfw3)      else() -        if (NOT APPLE) -            find_package(X11 REQUIRED) -        endif() -          find_package(PkgConfig REQUIRED)          pkg_search_module(GLFW REQUIRED glfw3)      endif() @@ -10,7 +10,7 @@ For development discussion, please join us @ #citra on [freenode](http://webchat  ### Development -If you want to contribute please take a took at the [Contributor's Guide](CONTRIBUTING.md), [Roadmap](https://github.com/citra-emu/citra/wiki/Roadmap) and [Developer Information](https://github.com/citra-emu/citra/wiki/Developer-Information) pages. You should as well contact any of the developers in the forum in order to know about the current state of the emulator. +If you want to contribute please take a look at the [Contributor's Guide](CONTRIBUTING.md), [Roadmap](https://github.com/citra-emu/citra/wiki/Roadmap) and [Developer Information](https://github.com/citra-emu/citra/wiki/Developer-Information) pages. You should as well contact any of the developers in the forum in order to know about the current state of the emulator.  ### Building diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt index f2add394f..b06259f5e 100644 --- a/src/citra/CMakeLists.txt +++ b/src/citra/CMakeLists.txt @@ -12,22 +12,20 @@ set(HEADERS  create_directory_groups(${SRCS} ${HEADERS}) -# NOTE: This is a workaround for CMake bug 0006976 (missing X11_xf86vmode_LIB variable) -if (NOT X11_xf86vmode_LIB) -    set(X11_xv86vmode_LIB Xxf86vm) -endif() -  add_executable(citra ${SRCS} ${HEADERS})  target_link_libraries(citra core common video_core)  target_link_libraries(citra ${OPENGL_gl_LIBRARY} ${GLFW_LIBRARIES} inih) +if (UNIX) +    target_link_libraries(citra -pthread) +endif() +  if (APPLE) -    target_link_libraries(citra iconv pthread ${COREFOUNDATION_LIBRARY}) +    target_link_libraries(citra iconv ${COREFOUNDATION_LIBRARY})  elseif (WIN32)      target_link_libraries(citra winmm)  else() # Unix -    target_link_libraries(citra pthread rt) -    target_link_libraries(citra ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_Xcursor_LIB} ${X11_Xrandr_LIB} ${X11_xv86vmode_LIB}) +    target_link_libraries(citra rt)  endif()  #install(TARGETS citra RUNTIME DESTINATION ${bindir}) diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 90e5c6aa6..54d0a1271 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -60,6 +60,10 @@ add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS})  target_link_libraries(citra-qt core common video_core qhexedit)  target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS}) +if (UNIX) +    target_link_libraries(citra-qt -pthread) +endif() +  if (APPLE)      target_link_libraries(citra-qt iconv ${COREFOUNDATION_LIBRARY})  elseif (WIN32) diff --git a/src/common/bit_field.h b/src/common/bit_field.h index c38a3fb08..8eab054b8 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -168,6 +168,12 @@ public:          }      } +    // TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015 +    __forceinline bool ToBool() const +    { +        return Value() != 0; +    } +  private:      // StorageType is T for non-enum types and the underlying type of T if      // T is an enumeration. Note that T is wrapped within an enable_if in the diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h index 19d94f369..70eb96e93 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.h +++ b/src/core/arm/dyncom/arm_dyncom_dec.h @@ -56,8 +56,6 @@  #define RN ((instr >> 16) & 0xF)  /*xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 */  #define RM (instr & 0xF) -#define BIT(n) ((instr >> (n)) & 1) -#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))  /* CP15 registers */  #define OPCODE_1        BITS(21, 23) diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index df698e8f1..460001b1a 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -2390,15 +2390,41 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)  	return inst_base;  }  ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index)     { UNIMPLEMENTED_INSTRUCTION("QADD"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)   { UNIMPLEMENTED_INSTRUCTION("QADD16"); }  ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("QADD8"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADDSUBX"); } +ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) +{ +	arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); +	generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + +	inst_base->cond     = BITS(inst, 28, 31); +	inst_base->idx      = index; +	inst_base->br       = NON_BRANCH; +	inst_base->load_r15 = 0; + +	inst_cream->Rm  = BITS(inst, 0, 3); +	inst_cream->Rn  = BITS(inst, 16, 19); +	inst_cream->Rd  = BITS(inst, 12, 15); +	inst_cream->op1 = BITS(inst, 20, 21); +	inst_cream->op2 = BITS(inst, 5, 7); + +	return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) +{ +	return INTERPRETER_TRANSLATE(qadd16)(inst, index); +}  ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("QDADD"); }  ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("QDSUB"); }  ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index)     { UNIMPLEMENTED_INSTRUCTION("QSUB"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index)   { UNIMPLEMENTED_INSTRUCTION("QSUB16"); }  ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("QSUB8"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUBADDX"); } +ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) +{ +	return INTERPRETER_TRANSLATE(qadd16)(inst, index); +} +ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) +{ +	return INTERPRETER_TRANSLATE(qadd16)(inst, index); +}  ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index)  {  	arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); @@ -3798,9 +3824,9 @@ unsigned InterpreterMainLoop(ARMul_State* state)  	#define INC_ICOUNTER			cpu->icounter++;                                                   \  						if(cpu->Reg[15] > 0xc0000000) 					\  							cpu->kernel_icounter++; -						//if (debug_function(core))                                          \ +						/*if (debug_function(core))                                          \  							if (core->check_int_flag)                                  \ -								goto END +								goto END*/  						//LOG_TRACE(Core_ARM11, "icounter is %llx pc is %x\n", cpu->icounter, cpu->Reg[15])  	#else  	#define INC_ICOUNTER			;                                                    @@ -4021,18 +4047,18 @@ unsigned InterpreterMainLoop(ARMul_State* state)  	#define UPDATE_NFLAG(dst)		(cpu->NFlag = BIT(dst, 31) ? 1 : 0)  	#define UPDATE_ZFLAG(dst)		(cpu->ZFlag = dst ? 0 : 1) -//	#define UPDATE_CFLAG(dst, lop, rop)	(cpu->CFlag = ((ISNEG(lop) && ISPOS(rop)) ||                        \ +/*	#define UPDATE_CFLAG(dst, lop, rop)	(cpu->CFlag = ((ISNEG(lop) && ISPOS(rop)) ||                        \  								(ISNEG(lop) && ISPOS(dst)) ||                       \ -								(ISPOS(rop) && ISPOS(dst)))) +								(ISPOS(rop) && ISPOS(dst)))) */  	#define UPDATE_CFLAG(dst, lop, rop)	(cpu->CFlag = ((dst < lop) || (dst < rop)))  	#define UPDATE_CFLAG_CARRY_FROM_ADD(lop, rop, flag)	(cpu->CFlag = (((uint64_t) lop + (uint64_t) rop + (uint64_t) flag) > 0xffffffff) )  	#define UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(lop, rop, flag) (cpu->CFlag = ((uint64_t) lop >= ((uint64_t) rop + (uint64_t) flag)))  	#define UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop)	(cpu->CFlag = (lop >= rop))  	#define UPDATE_CFLAG_WITH_NOT(dst, lop, rop)	(cpu->CFlag = !(dst < lop))  	#define UPDATE_CFLAG_WITH_SC		cpu->CFlag = cpu->shifter_carry_out -//	#define UPDATE_CFLAG_WITH_NOT(dst, lop, rop)	cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) ||                        \ +/*	#define UPDATE_CFLAG_WITH_NOT(dst, lop, rop)	cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) ||                        \  								(ISNEG(lop) && ISPOS(dst)) ||                       \ -								(ISPOS(rop) && ISPOS(dst))) +								(ISPOS(rop) && ISPOS(dst))) */  	#define UPDATE_VFLAG(dst, lop, rop)	(cpu->VFlag = (((lop < 0) && (rop < 0) && (dst >= 0)) ||            \  								((lop >= 0) && (rop) >= 0 && (dst < 0))))  	#define UPDATE_VFLAG_WITH_NOT(dst, lop, rop)	(cpu->VFlag = !(((lop < 0) && (rop < 0) && (dst >= 0)) ||            \ @@ -5561,15 +5587,69 @@ unsigned InterpreterMainLoop(ARMul_State* state)  		GOTO_NEXT_INST;  	}  	QADD_INST: -	QADD16_INST:  	QADD8_INST: + +	QADD16_INST:  	QADDSUBX_INST: +	QSUB16_INST: +	QSUBADDX_INST: +	{ +		INC_ICOUNTER; +		if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { +			generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; +			const s16 rm_lo = (RM & 0xFFFF); +			const s16 rm_hi = ((RM >> 16) & 0xFFFF); +			const s16 rn_lo = (RN & 0xFFFF); +			const s16 rn_hi = ((RN >> 16) & 0xFFFF); +			const u8 op2    = inst_cream->op2; + +			s32 lo_result = 0; +			s32 hi_result = 0; + +			// QADD16 +			if (op2 == 0x00) { +				lo_result = (rn_lo + rm_lo); +				hi_result = (rn_hi + rm_hi); +			} +			// QASX +			else if (op2 == 0x01) { +				lo_result = (rn_lo - rm_hi); +				hi_result = (rn_hi + rm_lo); +			} +			// QSAX +			else if (op2 == 0x02) { +				lo_result = (rn_lo + rm_hi); +				hi_result = (rn_hi - rm_lo); +			} +			// QSUB16 +			else if (op2 == 0x03) { +				lo_result = (rn_lo - rm_lo); +				hi_result = (rn_hi - rm_hi); +			} + +			if (lo_result > 0x7FFF) +				lo_result = 0x7FFF; +			else if (lo_result < -0x8000) +				lo_result = -0x8000; + +			if (hi_result > 0x7FFF) +				hi_result = 0x7FFF; +			else if (hi_result < -0x8000) +				hi_result = -0x8000; + +			RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); +		} + +		cpu->Reg[15] += GET_INST_SIZE(cpu); +		INC_PC(sizeof(generic_arm_inst)); +		FETCH_INST; +		GOTO_NEXT_INST; +	} +  	QDADD_INST:  	QDSUB_INST:  	QSUB_INST: -	QSUB16_INST:  	QSUB8_INST: -	QSUBADDX_INST:  	REV_INST:  	{  		INC_ICOUNTER; diff --git a/src/core/arm/dyncom/arm_dyncom_run.cpp b/src/core/arm/dyncom/arm_dyncom_run.cpp index a2026cbf3..b66b92cf5 100644 --- a/src/core/arm/dyncom/arm_dyncom_run.cpp +++ b/src/core/arm/dyncom/arm_dyncom_run.cpp @@ -29,7 +29,6 @@  void switch_mode(arm_core_t *core, uint32_t mode)  { -    uint32_t tmp1, tmp2;      if (core->Mode == mode) {          //Mode not changed.          //printf("mode not changed\n"); diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index 610e04f10..d54dbeac5 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -1670,7 +1670,7 @@ mainswitch:                              op1 *= op2;                              //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn);                              if (AddOverflow(op1, Rn, op1 + Rn)) -                                SETS; +                                SETQ;                              state->Reg[BITS (16, 19)] = op1 + Rn;                              break;                          } @@ -1682,7 +1682,7 @@ mainswitch:                              ARMword result = op1 + op2;                              if (AddOverflow(op1, op2, result)) {                                  result = POS (result) ? 0x80000000 : 0x7fffffff; -                                SETS; +                                SETQ;                              }                              state->Reg[BITS (12, 15)] = result;                              break; @@ -1724,7 +1724,7 @@ mainswitch:                              TAKEABORT;                      } else if ((BITS (0, 11) == 0) && (LHSReg == 15)) {	/* MRS CPSR */                          UNDEF_MRSPC; -                        DEST = ECC | EINT | EMODE; +                        DEST = ARMul_GetCPSR(state);                      } else {                          UNDEF_Test;                      } @@ -1795,7 +1795,7 @@ mainswitch:                                  ARMword Rn = state->Reg[BITS(12, 15)];                                  if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn))) -                                    SETS; +                                    SETQ;                                  result += Rn;                              }                              state->Reg[BITS (16, 19)] = (ARMword)result; @@ -1811,7 +1811,7 @@ mainswitch:                              if (SubOverflow                                      (op1, op2, result)) {                                  result = POS (result) ? 0x80000000 : 0x7fffffff; -                                SETS; +                                SETQ;                              }                              state->Reg[BITS (12, 15)] = result; @@ -1934,13 +1934,13 @@ mainswitch:                              if (AddOverflow                                      (op2, op2, op2d)) { -                                SETS; +                                SETQ;                                  op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;                              }                              result = op1 + op2d;                              if (AddOverflow(op1, op2d, result)) { -                                SETS; +                                SETQ;                                  result = POS (result) ? 0x80000000 : 0x7fffffff;                              } @@ -2053,13 +2053,13 @@ mainswitch:                              ARMword result;                              if (AddOverflow(op2, op2, op2d)) { -                                SETS; +                                SETQ;                                  op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;                              }                              result = op1 - op2d;                              if (SubOverflow(op1, op2d, result)) { -                                SETS; +                                SETQ;                                  result = POS (result) ? 0x80000000 : 0x7fffffff;                              } @@ -5863,20 +5863,21 @@ L_stm_s_takeabort:                  state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);                  if (lo_result >= 0) { -                    state->Cpsr |= (1 << 16); -                    state->Cpsr |= (1 << 17); +                    state->GEFlag |= (1 << 16); +                    state->GEFlag |= (1 << 17);                  } else { -                    state->Cpsr &= ~(1 << 16); -                    state->Cpsr &= ~(1 << 17); +                    state->GEFlag &= ~(1 << 16); +                    state->GEFlag &= ~(1 << 17);                  }                  if (hi_result >= 0) { -                    state->Cpsr |= (1 << 18); -                    state->Cpsr |= (1 << 19); +                    state->GEFlag |= (1 << 18); +                    state->GEFlag |= (1 << 19);                  } else { -                    state->Cpsr &= ~(1 << 18); -                    state->Cpsr &= ~(1 << 19); +                    state->GEFlag &= ~(1 << 18); +                    state->GEFlag &= ~(1 << 19);                  } +                  return 1;              }              // SADD8/SSUB8 @@ -5901,24 +5902,24 @@ L_stm_s_takeabort:                      hi_val2 = (u8)(((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF));                      if (lo_val1 & 0x80) -                        state->Cpsr |= (1 << 16); +                        state->GEFlag |= (1 << 16);                      else -                        state->Cpsr &= ~(1 << 16); +                        state->GEFlag &= ~(1 << 16);                      if (lo_val2 & 0x80) -                        state->Cpsr |= (1 << 17); +                        state->GEFlag |= (1 << 17);                      else -                        state->Cpsr &= ~(1 << 17); +                        state->GEFlag &= ~(1 << 17);                      if (hi_val1 & 0x80) -                        state->Cpsr |= (1 << 18); +                        state->GEFlag |= (1 << 18);                      else -                        state->Cpsr &= ~(1 << 18); +                        state->GEFlag &= ~(1 << 18);                      if (hi_val2 & 0x80) -                        state->Cpsr |= (1 << 19); +                        state->GEFlag |= (1 << 19);                      else -                        state->Cpsr &= ~(1 << 19); +                        state->GEFlag &= ~(1 << 19);                  }                  // SSUB8                  else { @@ -5928,24 +5929,24 @@ L_stm_s_takeabort:                      hi_val2 = (u8)(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF));                      if (!(lo_val1 & 0x80)) -                        state->Cpsr |= (1 << 16); +                        state->GEFlag |= (1 << 16);                      else -                        state->Cpsr &= ~(1 << 16); +                        state->GEFlag &= ~(1 << 16);                      if (!(lo_val2 & 0x80)) -                        state->Cpsr |= (1 << 17); +                        state->GEFlag |= (1 << 17);                      else -                        state->Cpsr &= ~(1 << 17); +                        state->GEFlag &= ~(1 << 17);                      if (!(hi_val1 & 0x80)) -                        state->Cpsr |= (1 << 18); +                        state->GEFlag |= (1 << 18);                      else -                        state->Cpsr &= ~(1 << 18); +                        state->GEFlag &= ~(1 << 18);                      if (!(hi_val2 & 0x80)) -                        state->Cpsr |= (1 << 19); +                        state->GEFlag |= (1 << 19);                      else -                        state->Cpsr &= ~(1 << 19); +                        state->GEFlag &= ~(1 << 19);                  }                  state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24); @@ -6024,15 +6025,32 @@ L_stm_s_takeabort:                  if ((instr & 0x0F0) == 0x070) { // USUB16                      h1 = ((u16)from - (u16)to);                      h2 = ((u16)(from >> 16) - (u16)(to >> 16)); -                    if (!(h1 & 0xffff0000)) state->Cpsr |= (3 << 16); -                    if (!(h2 & 0xffff0000)) state->Cpsr |= (3 << 18); + +                    if (!(h1 & 0xffff0000)) +                        state->GEFlag |= (3 << 16); +                    else +                        state->GEFlag &= ~(3 << 16); + +                    if (!(h2 & 0xffff0000)) +                        state->GEFlag |= (3 << 18); +                    else +                        state->GEFlag &= ~(3 << 18);                  }                  else { // UADD16                      h1 = ((u16)from + (u16)to);                      h2 = ((u16)(from >> 16) + (u16)(to >> 16)); -                    if (h1 & 0xffff0000) state->Cpsr |= (3 << 16); -                    if (h2 & 0xffff0000) state->Cpsr |= (3 << 18); + +                    if (h1 & 0xffff0000) +                        state->GEFlag |= (3 << 16); +                    else +                        state->GEFlag &= ~(3 << 16); + +                    if (h2 & 0xffff0000) +                        state->GEFlag |= (3 << 18); +                    else +                        state->GEFlag &= ~(3 << 18);                  } +                  state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16));                  return 1;              } @@ -6045,10 +6063,26 @@ L_stm_s_takeabort:                          b2 = ((u8)(from >> 8) - (u8)(to >> 8));                          b3 = ((u8)(from >> 16) - (u8)(to >> 16));                          b4 = ((u8)(from >> 24) - (u8)(to >> 24)); -                        if (!(b1 & 0xffffff00)) state->Cpsr |= (1 << 16); -                        if (!(b2 & 0xffffff00)) state->Cpsr |= (1 << 17); -                        if (!(b3 & 0xffffff00)) state->Cpsr |= (1 << 18); -                        if (!(b4 & 0xffffff00)) state->Cpsr |= (1 << 19); + +                        if (!(b1 & 0xffffff00)) +                            state->GEFlag |= (1 << 16); +                        else +                            state->GEFlag &= ~(1 << 16); + +                        if (!(b2 & 0xffffff00)) +                            state->GEFlag |= (1 << 17); +                        else +                            state->GEFlag &= ~(1 << 17); + +                        if (!(b3 & 0xffffff00)) +                            state->GEFlag |= (1 << 18); +                        else +                            state->GEFlag &= ~(1 << 18); + +                        if (!(b4 & 0xffffff00)) +                            state->GEFlag |= (1 << 19); +                        else +                            state->GEFlag &= ~(1 << 19);                      }                      else { // UADD8                          b1 = ((u8)from + (u8)to); @@ -6057,25 +6091,24 @@ L_stm_s_takeabort:                          b4 = ((u8)(from >> 24) + (u8)(to >> 24));                          if (b1 & 0xffffff00) -                            state->Cpsr |= (1 << 16); +                            state->GEFlag |= (1 << 16);                          else -                            state->Cpsr &= ~(1 << 16); +                            state->GEFlag &= ~(1 << 16);                          if (b2 & 0xffffff00) -                            state->Cpsr |= (1 << 17); +                            state->GEFlag |= (1 << 17);                          else -                            state->Cpsr &= ~(1 << 17); +                            state->GEFlag &= ~(1 << 17);                          if (b3 & 0xffffff00) -                            state->Cpsr |= (1 << 18); +                            state->GEFlag |= (1 << 18);                          else -                            state->Cpsr &= ~(1 << 18); - +                            state->GEFlag &= ~(1 << 18);                          if (b4 & 0xffffff00) -                            state->Cpsr |= (1 << 19); +                            state->GEFlag |= (1 << 19);                          else -                            state->Cpsr &= ~(1 << 19); +                            state->GEFlag &= ~(1 << 19);                      }                      state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); @@ -6116,7 +6149,7 @@ L_stm_s_takeabort:              u32 rm = (instr >> 0) & 0xF;              u32 from = state->Reg[rn];              u32 to = state->Reg[rm]; -            u32 cpsr = state->Cpsr; +            u32 cpsr = ARMul_GetCPSR(state);              if ((instr & 0xFF0) == 0xFB0) { // SEL                  u32 result;                  if (cpsr & (1 << 16)) @@ -6172,15 +6205,21 @@ L_stm_s_takeabort:  					s16 rn_lo = (state->Reg[rn_idx]);  					s16 rn_hi = (state->Reg[rn_idx] >> 16); -					if (rn_lo > max) +					if (rn_lo > max) {  						rn_lo = max; -					else if (rn_lo < min) +						SETQ; +					} else if (rn_lo < min) {  						rn_lo = min; +						SETQ; +					} -					if (rn_hi > max) +					if (rn_hi > max) {  						rn_hi = max; -					else if (rn_hi < min) +						SETQ; +					} else if (rn_hi < min) {  						rn_hi = min; +						SETQ; +					}  					state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);  					return 1; @@ -6313,16 +6352,22 @@ L_stm_s_takeabort:  					s16 rn_lo = (state->Reg[rn_idx]);  					s16 rn_hi = (state->Reg[rn_idx] >> 16); -					if (max < rn_lo) +					if (max < rn_lo) {  						rn_lo = max; -					else if (rn_lo < 0) +						SETQ; +					} else if (rn_lo < 0) {  						rn_lo = 0; +						SETQ; +					} -					if (max < rn_hi) +					if (max < rn_hi) {  						rn_hi = max; -					else if (rn_hi < 0) +						SETQ; +					} else if (rn_hi < 0) {  						rn_hi = 0; -					 +						SETQ; +					} +  					state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF);  					return 1;  				} @@ -6427,30 +6472,95 @@ L_stm_s_takeabort:                  const s16 rn_lo = (rn_val & 0xFFFF);                  const s16 rn_hi = ((rn_val >> 16) & 0xFFFF); -                // SMUAD -                if ((instr & 0xf0d0) == 0xf010) { -                    state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi); +                const u32 product1 = (rn_lo * rm_lo); +                const u32 product2 = (rn_hi * rm_hi); + +                // SMUAD and SMLAD +                if (BIT(6) == 0) { +                    state->Reg[rd_idx] = product1 + product2; + +                    if (BITS(12, 15) != 15) { +                        state->Reg[rd_idx] += state->Reg[ra_idx]; +                        ARMul_AddOverflowQ(state, product1 + product2, state->Reg[ra_idx]); +                    } + +                    ARMul_AddOverflowQ(state, product1, product2);                  } -                // SMUSD -                else if ((instr & 0xf0d0) == 0xf050) { -                    state->Reg[rd_idx] = (rn_lo * rm_lo) - (rn_hi * rm_hi); +                // SMUSD and SMLSD +                else { +                    state->Reg[rd_idx] = product1 - product2; +                     +                    if (BITS(12, 15) != 15) +                        state->Reg[rd_idx] += state->Reg[ra_idx];                  } -                // SMLAD -                else if ((instr & 0xd0) == 0x10) { -                    state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi) + (s32)state->Reg[ra_idx]; + +                return 1; +            } +            break; +        case 0x74: // SMLALD and SMLSLD +            { +                const u8 rm_idx = BITS(8, 11); +                const u8 rn_idx = BITS(0, 3); +                const u8 rdlo_idx = BITS(12, 15); +                const u8 rdhi_idx = BITS(16, 19); +                const bool do_swap = (BIT(5) == 1); + +                const u32 rdlo_val = state->Reg[rdlo_idx]; +                const u32 rdhi_val = state->Reg[rdhi_idx]; +                const u32 rn_val   = state->Reg[rn_idx]; +                u32 rm_val         = state->Reg[rm_idx]; + +                if (do_swap) +                    rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); + +                const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); +                const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); +                s64 result; + +                // SMLALD +                if (BIT(6) == 0) { +                    result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));                  } -                // SMLSD +                // SMLSLD                  else { -                    state->Reg[rd_idx] = ((rn_lo * rm_lo) - (rn_hi * rm_hi)) + (s32)state->Reg[ra_idx]; +                    result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));                  } + +                state->Reg[rdlo_idx] = (result & 0xFFFFFFFF); +                state->Reg[rdhi_idx] = ((result >> 32) & 0xFFFFFFFF);                  return 1;              }              break; -        case 0x74: -            printf ("Unhandled v6 insn: smlald/smlsld\n"); -            break; -        case 0x75: -            printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); +        case 0x75: // SMMLA, SMMUL, and SMMLS +            { +                const u8 rm_idx = BITS(8, 11); +                const u8 rn_idx = BITS(0, 3); +                const u8 ra_idx = BITS(12, 15); +                const u8 rd_idx = BITS(16, 19); +                const bool do_round = (BIT(5) == 1); + +                const u32 rm_val = state->Reg[rm_idx]; +                const u32 rn_val = state->Reg[rn_idx]; + +                // Assume SMMUL by default. +                s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; + +                if (ra_idx != 15) { +                    const u32 ra_val = state->Reg[ra_idx]; + +                    // SMMLA, otherwise SMMLS +                    if (BIT(6) == 0) +                        result += ((s64)ra_val << 32); +                    else +                        result = ((s64)ra_val << 32) - result; +                } + +                if (do_round) +                    result += 0x80000000; + +                state->Reg[rd_idx] = ((result >> 32) & 0xFFFFFFFF); +                return 1; +            }              break;          case 0x78:              if (BITS(20, 24) == 0x18) diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index 30519f216..6774f8a74 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp @@ -227,8 +227,9 @@ ARMul_CPSRAltered (ARMul_State * state)      //state->Cpsr &= ~CBIT;      ASSIGNV ((state->Cpsr & VBIT) != 0);      //state->Cpsr &= ~VBIT; -    ASSIGNS ((state->Cpsr & SBIT) != 0); -    //state->Cpsr &= ~SBIT; +    ASSIGNQ ((state->Cpsr & QBIT) != 0); +    //state->Cpsr &= ~QBIT; +    state->GEFlag = (state->Cpsr & 0x000F0000);  #ifdef MODET      ASSIGNT ((state->Cpsr & TBIT) != 0);      //state->Cpsr &= ~TBIT; @@ -443,6 +444,14 @@ ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)      ASSIGNV (AddOverflow (a, b, result));  } +/* Assigns the Q flag if the given result is considered an overflow from the addition of a and b  */ +void ARMul_AddOverflowQ(ARMul_State* state, ARMword a, ARMword b) +{ +    u32 result = a + b; +    if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) +        SETQ; +} +  /* Assigns the C flag after an subtraction of a and b to give result.  */  void diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index 28a4a0db4..34eb5aaf7 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h @@ -198,7 +198,7 @@ struct ARMul_State          //ARMword translate_pc;      /* add armv6 flags dyf:2010-08-09 */ -    ARMword GEFlag, EFlag, AFlag, QFlags; +    ARMword GEFlag, EFlag, AFlag, QFlag;      //chy:2003-08-19, used in arm v5e|xscale      ARMword SFlag;  #ifdef MODET diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h index 7f7c0e682..3ea14b5a3 100644 --- a/src/core/arm/skyeye_common/armemu.h +++ b/src/core/arm/skyeye_common/armemu.h @@ -34,7 +34,7 @@  #define ZBIT (1L << 30)  #define CBIT (1L << 29)  #define VBIT (1L << 28) -#define SBIT (1L << 27) +#define QBIT (1L << 27)  #define IBIT (1L << 7)  #define FBIT (1L << 6)  #define IFBITS (3L << 6) @@ -156,13 +156,14 @@  #define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))  #define R15MODE (state->Reg[15] & R15MODEBITS) -#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (SFLAG << 27)) +#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (QFLAG << 27))  #define EINT (IFFLAGS << 6)  #define ER15INT (IFFLAGS << 26)  #define EMODE (state->Mode) +#define EGEBITS (state->GEFlag & 0x000F0000)  #ifdef MODET -#define CPSR (ECC | EINT | EMODE | (TFLAG << 5)) +#define CPSR (ECC | EGEBITS | (EFLAG << 9) | (AFLAG << 8) | EINT | (TFLAG << 5) | EMODE)  #else  #define CPSR (ECC | EINT | EMODE)  #endif @@ -601,6 +602,7 @@ extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);  extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);  extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);  extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword); +extern void ARMul_AddOverflowQ(ARMul_State*, ARMword, ARMword);  extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword);  extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword);  extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *); diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index e7df72ed7..d8b261ba7 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp @@ -315,8 +315,8 @@ Interface::Interface() {      if (file.IsOpen()) {          // Read shared font data -        shared_font.resize(file.GetSize()); -        file.ReadBytes(shared_font.data(), file.GetSize()); +        shared_font.resize((size_t)file.GetSize()); +        file.ReadBytes(shared_font.data(), (size_t)file.GetSize());          // Create shared font memory object          shared_font_mem = Kernel::CreateSharedMemory("APT_U:shared_font_mem"); diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 027c68d01..b1a465274 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -426,6 +426,23 @@ static void IsSdmcDetected(Service::Interface* self) {  }  /** + * FS_User::IsSdmcWriteable service function + *  Outputs: + *      0 : Command header 0x08180000 + *      1 : Result of function, 0 on success, otherwise error code + *      2 : Whether the Sdmc is currently writeable + */ +static void IsSdmcWriteable(Service::Interface* self) { +    u32* cmd_buff = Kernel::GetCommandBuffer(); + +    cmd_buff[1] = RESULT_SUCCESS.raw; +    // If the SD isn't enabled, it can't be writeable...else, stubbed true +    cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0; +     +    LOG_DEBUG(Service_FS, " (STUBBED)"); +} + +/**   * FS_User::FormatSaveData service function,    * formats the SaveData specified by the input path.   *  Inputs: @@ -510,7 +527,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = {      {0x08150000, nullptr,               "GetNandArchiveResource"},      {0x08160000, nullptr,               "GetSdmcFatfsErro"},      {0x08170000, IsSdmcDetected,        "IsSdmcDetected"}, -    {0x08180000, nullptr,               "IsSdmcWritable"}, +    {0x08180000, IsSdmcWriteable,       "IsSdmcWritable"},      {0x08190042, nullptr,               "GetSdmcCid"},      {0x081A0042, nullptr,               "GetNandCid"},      {0x081B0000, nullptr,               "GetSdmcSpeedInfo"}, diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index ea29e5027..2083357fe 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -90,7 +90,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {              const auto& index_info = registers.index_array;              const u8* index_address_8 = Memory::GetPointer(PAddrToVAddr(base_address + index_info.offset));              const u16* index_address_16 = (u16*)index_address_8; -            bool index_u16 = (bool)index_info.format; +            bool index_u16 = index_info.format != 0;              DebugUtils::GeometryDumper geometry_dumper;              PrimitiveAssembler<VertexShader::OutputVertex> clipper_primitive_assembler(registers.triangle_topology.Value()); @@ -164,7 +164,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {          case PICA_REG_INDEX(vs_bool_uniforms):              for (unsigned i = 0; i < 16; ++i) -                VertexShader::GetBoolUniform(i) = (registers.vs_bool_uniforms.Value() & (1 << i)); +                VertexShader::GetBoolUniform(i) = (registers.vs_bool_uniforms.Value() & (1 << i)) != 0;              break; diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 1fac9ff36..89d97e4e9 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -201,9 +201,9 @@ struct Regs {      };      const std::array<FullTextureConfig, 3> GetTextures() const {          return {{ -                   { static_cast<bool>(texture0_enable), texture0, texture0_format }, -                   { static_cast<bool>(texture1_enable), texture1, texture1_format }, -                   { static_cast<bool>(texture2_enable), texture2, texture2_format } +                   { texture0_enable.ToBool(), texture0, texture0_format }, +                   { texture1_enable.ToBool(), texture1, texture1_format }, +                   { texture2_enable.ToBool(), texture2, texture2_format }                 }};      } @@ -590,11 +590,11 @@ struct Regs {      static std::string GetCommandName(int index) {          std::map<u32, std::string> map; -        Regs regs;          #define ADD_FIELD(name)                                                                               \              do {                                                                                              \                  map.insert({PICA_REG_INDEX(name), #name});                                                    \ -                for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(regs.name) / 4; ++i) \ +                /* TODO: change to Regs::name when VS2015 and other compilers support it  */                   \ +                for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \                      map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))});       \              } while(false)  | 
