diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp index 8fa8fdd7..a68c94e6 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp @@ -177,15 +177,11 @@ #undef PPC_NO_STATIC_II_INDEX_TABLE #endif -#if defined(PPC_EXECUTE_DUMP_STATE) && !defined(PPC_NO_DECODE_CACHE) -#define PPC_NO_DECODE_CACHE -#endif - #ifdef PPC_NO_DECODE_CACHE #undef PPC_LAZY_PC_UPDATE #endif -#if PPC_FLIGHT_RECORDER +#if PPC_FLIGHT_RECORDER || PPC_EXECUTE_DUMP_STATE #undef PPC_LAZY_PC_UPDATE #endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp index 1a06c930..5cec1cff 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp @@ -113,7 +113,6 @@ void powerpc_cpu::init_flight_recorder() #endif } -#if PPC_FLIGHT_RECORDER void powerpc_cpu::record_step(uint32 opcode) { #if PPC_FLIGHT_RECORDER @@ -141,6 +140,7 @@ void powerpc_cpu::record_step(uint32 opcode) #endif } +#if PPC_FLIGHT_RECORDER void powerpc_cpu::start_log() { logging = true; @@ -264,6 +264,16 @@ void powerpc_cpu::dump_registers() fflush(stderr); } +void powerpc_cpu::dump_instruction(uint32 opcode) +{ + fprintf(stderr, "[%08x]-> %08x\n", pc(), opcode); +} + +void powerpc_cpu::fake_dump_registers(uint32) +{ + dump_registers(); +} + struct execute_nothing { static inline void execute(powerpc_cpu *) { } }; @@ -289,6 +299,10 @@ void powerpc_cpu::init_decode_cache() // Leave enough room to last call to record_step() decode_cache_end_p -= 2; #endif +#ifdef PPC_EXECUTE_DUMP_STATE + // Leave enough room to last calls to dump state functions + decode_cache_end_p -= 2; +#endif block_cache.initialize(); #endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp index 5eeed0ff..b8c536f4 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp @@ -203,12 +203,12 @@ public: // Handle flight recorder #if PPC_FLIGHT_RECORDER - bool is_logging() { return logging; } + bool is_logging() const { return logging; } void start_log(); void stop_log(); void dump_log(const char *filename = NULL); #else - bool is_logging() { return false; } + bool is_logging() const { return false; } void start_log() { } void stop_log() { } void dump_log(const char *filename = NULL) { } @@ -216,6 +216,8 @@ public: // Dump registers void dump_registers(); + void dump_instruction(uint32 opcode); + void fake_dump_registers(uint32); // Start emulation loop template< class prologue, class epilogue > @@ -260,7 +262,7 @@ private: typedef powerpc_block_info block_info; block_cache< block_info, lazy_allocator > block_cache; - static const uint32 DECODE_CACHE_MAX_ENTRIES = 20000; + static const uint32 DECODE_CACHE_MAX_ENTRIES = 32768; static const uint32 DECODE_CACHE_SIZE = DECODE_CACHE_MAX_ENTRIES * sizeof(block_info::decode_info); block_info::decode_info * decode_cache; block_info::decode_info * decode_cache_p; @@ -338,13 +340,17 @@ private: template< class prologue, class epilogue > inline void powerpc_cpu::do_execute() { +#ifdef PPC_EXECUTE_DUMP_STATE + const bool dump_state = true; +#endif #ifdef PPC_NO_DECODE_CACHE for (;;) { prologue::execute(this); uint32 opcode = vm_read_memory_4(pc()); const instr_info_t *ii = decode(opcode); #ifdef PPC_EXECUTE_DUMP_STATE - fprintf(stderr, "[%08x]-> %08x\n", pc(), opcode); + if (dump_state) + dump_instruction(opcode); #endif #if PPC_FLIGHT_RECORDER if (is_logging()) @@ -353,7 +359,8 @@ inline void powerpc_cpu::do_execute() assert(ii->execute != 0); (this->*(ii->execute))(opcode); #ifdef PPC_EXECUTE_DUMP_STATE - dump_registers(); + if (dump_state) + dump_registers(); #endif epilogue::execute(this); } @@ -369,6 +376,12 @@ inline void powerpc_cpu::do_execute() do { uint32 opcode = vm_read_memory_4(dpc += 4); ii = decode(opcode); +#ifdef PPC_EXECUTE_DUMP_STATE + if (dump_state) { + di->opcode = opcode; + di->execute = &powerpc_cpu::dump_instruction; + } +#endif #if PPC_FLIGHT_RECORDER if (is_logging()) { di->opcode = opcode; @@ -378,7 +391,15 @@ inline void powerpc_cpu::do_execute() #endif di->opcode = opcode; di->execute = ii->execute; - if (++di >= decode_cache_end_p) { + di++; +#ifdef PPC_EXECUTE_DUMP_STATE + if (dump_state) { + di->opcode = 0; + di->execute = &powerpc_cpu::fake_dump_registers; + di++; + } +#endif + if (di >= decode_cache_end_p) { // Invalidate cache and move current code to start invalidate_cache(); const int blocklen = di - bi->di; diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp index ac7820d1..f83506be 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp @@ -122,12 +122,12 @@ const powerpc_cpu::instr_info_t powerpc_cpu::powerpc_ii_table[] = { D_form, 15, 0, CFLOW_NORMAL }, { "addme", - EXECUTE_ADDITION(RA_or_0, MINUS_ONE, XER_CA, CA_BIT_1, OE_BIT_G, RC_BIT_G), + EXECUTE_ADDITION(RA, MINUS_ONE, XER_CA, CA_BIT_1, OE_BIT_G, RC_BIT_G), NULL, XO_form, 31, 234, CFLOW_NORMAL }, { "addze", - EXECUTE_ADDITION(RA_or_0, ZERO, XER_CA, CA_BIT_1, OE_BIT_G, RC_BIT_G), + EXECUTE_ADDITION(RA, ZERO, XER_CA, CA_BIT_1, OE_BIT_G, RC_BIT_G), NULL, XO_form, 31, 202, CFLOW_NORMAL }, diff --git a/SheepShaver/src/kpx_cpu/src/test/test-powerpc.cpp b/SheepShaver/src/kpx_cpu/src/test/test-powerpc.cpp index bab1195b..a33b95cf 100644 --- a/SheepShaver/src/kpx_cpu/src/test/test-powerpc.cpp +++ b/SheepShaver/src/kpx_cpu/src/test/test-powerpc.cpp @@ -22,6 +22,7 @@ #include "sysdeps.h" #include "cpu/ppc/ppc-cpu.hpp" +#define TEST_RA_IS_0 0 #define TEST_ADD 0 #define TEST_SUB 0 #define TEST_MUL 0 @@ -31,7 +32,7 @@ #define TEST_MISC 0 #define TEST_LOGICAL 0 #define TEST_COMPARE 0 -#define TEST_CR_LOGICAL 1 +#define TEST_CR_LOGICAL 0 // Partial PowerPC runtime assembler from GNU lightning #define _I(X) ((uint32)(X)) @@ -108,7 +109,11 @@ private: enum { R_ = -1, RD = 10, +#if TEST_RA_IS_0 + RA = 0, +#else RA = 11, +#endif RB = 12 }; @@ -121,6 +126,7 @@ private: void test_logical(void); void test_compare(void); void test_cr_logical(void); + void test_load_multiple(void); }; void powerpc_test_cpu::execute_return(uint32 opcode) @@ -179,18 +185,25 @@ void powerpc_test_cpu::print_flags(uint32 cr, uint32 xer, int crf) const (xer & XER_CA_field::mask() ? "CA" : "__")); } +#if TEST_RA_IS_0 +#define ASM_RA_REG asm("r0") +#else +#define ASM_RA_REG /**/ +#endif + #define TEST_ASM______(OP,D0,A0,A1,A2,A3) asm volatile (OP : : : "cc") #define TEST_ASM_R____(OP,RD,A0,A1,A2,A3) asm volatile (OP " %0" : "=r" (RD) : : "cc") -#define TEST_ASM_RR___(OP,RD,RA,A1,A2,A3) asm volatile (OP " %0,%1" : "=r" (RD) : "r" (RA) : "cc") +#define TEST_ASM_RA_OR_0(RA, ASM_EXPR) do { register uint32 _RA ASM_RA_REG = RA; asm volatile ASM_EXPR; } while (0) +#define TEST_ASM_RR___(OP,RD,RA,A1,A2,A3) TEST_ASM_RA_OR_0(RA, (OP " %0,%1" : "=r" (RD) : "r" (_RA) : "cc")) +#define TEST_ASM_RRS__(OP,RD,RA,IM,A2,A3) TEST_ASM_RA_OR_0(RA, (OP " %0,%1,%2" : "=r" (RD) : "r" (_RA), "i" (IM) : "cc")) +#define TEST_ASM_RRI__(OP,RD,RA,IM,A2,A3) TEST_ASM_RA_OR_0(RA, (OP " %0,%1,%2" : "=r" (RD) : "r" (_RA), "I" (int16(IM)) : "cc")) +#define TEST_ASM_RRK__(OP,RD,RA,IM,A2,A3) TEST_ASM_RA_OR_0(RA, (OP " %0,%1,%2" : "=r" (RD) : "r" (_RA), "K" (IM) : "cc")) +#define TEST_ASM_RRR__(OP,RD,RA,RB,A2,A3) TEST_ASM_RA_OR_0(RA, (OP " %0,%1,%2" : "=r" (RD) : "r" (_RA), "r" (RB) : "cc")) +#define TEST_ASM_RRIII(OP,RD,RA,SH,MB,ME) TEST_ASM_RA_OR_0(RA, (OP " %0,%1,%2,%3,%4" : "+r" (RD) : "r" (_RA), "i" (SH), "i" (MB), "i" (ME))) +#define TEST_ASM_RRRII(OP,RD,RA,RB,MB,ME) TEST_ASM_RA_OR_0(RA, (OP " %0,%1,%2,%3,%4" : "+r" (RD) : "r" (_RA), "r" (RB), "i" (MB), "i" (ME))) #define TEST_ASM_CRR__(OP,RD,CR,RA,RB,A3) asm volatile (OP " %0,%1,%2" : : "i" (CR), "r" (RA), "r" (RB) : "cc") #define TEST_ASM_CRI__(OP,RD,CR,RA,IM,A3) asm volatile (OP " %0,%1,%2" : : "i" (CR), "r" (RA), "I" (int16(IM)) : "cc") #define TEST_ASM_CRK__(OP,RD,CR,RA,IM,A3) asm volatile (OP " %0,%1,%2" : : "i" (CR), "r" (RA), "K" (IM) : "cc") -#define TEST_ASM_RRS__(OP,RD,RA,IM,A2,A3) asm volatile (OP " %0,%1,%2" : "=r" (RD) : "r" (RA), "i" (IM) : "cc") -#define TEST_ASM_RRI__(OP,RD,RA,IM,A2,A3) asm volatile (OP " %0,%1,%2" : "=r" (RD) : "r" (RA), "I" (int16(IM)) : "cc") -#define TEST_ASM_RRK__(OP,RD,RA,IM,A2,A3) asm volatile (OP " %0,%1,%2" : "=r" (RD) : "r" (RA), "K" (IM) : "cc") -#define TEST_ASM_RRR__(OP,RD,RA,RB,A2,A3) asm volatile (OP " %0,%1,%2" : "=r" (RD) : "r" (RA), "r" (RB) : "cc") -#define TEST_ASM_RRIII(OP,RD,RA,SH,MB,ME) asm volatile (OP " %0,%1,%2,%3,%4" : "+r" (RD) : "r" (RA), "i" (SH), "i" (MB), "i" (ME)) -#define TEST_ASM_RRRII(OP,RD,RA,RB,MB,ME) asm volatile (OP " %0,%1,%2,%3,%4" : "+r" (RD) : "r" (RA), "r" (RB), "i" (MB), "i" (ME)) #define TEST_ASM_CCC__(OP,RD,RA,RB,RC,A3) asm volatile (OP " %0,%1,%2" : : "i" (RA), "i" (RB), "i" (RC) : "cc") #define TEST_ASM(FORMAT, OP, RD, CR, XER, A0, A1, A2, A3) do { \ @@ -624,7 +637,7 @@ void powerpc_test_cpu::test_div(void) void powerpc_test_cpu::test_logical(void) { -#if TEST_GENERIC_ARITH +#if TEST_LOGICAL TEST_INSTRUCTION(RRR__,"and.", _X (31,RA,RD,RB,28,1)); TEST_INSTRUCTION(RRR__,"andc.", _X (31,RA,RD,RB,60,1)); TEST_INSTRUCTION(RRK__,"andi.", _D (28,RA,RD,00)); @@ -694,6 +707,18 @@ void powerpc_test_cpu::test_cr_logical(void) #endif } +void powerpc_test_cpu::test_load_multiple(void) +{ +#if TEST_LOAD_MULTIPLE && 0 + uint16 tab[] = { 0x1234, 0x5678, 0x9abc, 0xdef0 }; + uint32 opcode = _X(31,RD,RA,RB,790,0); + gpr(RA) = (uintptr)&tab[0]; + gpr(RB) = 0; + execute(opcode); + printf("%08x\n", gpr(RD)); +#endif +} + bool powerpc_test_cpu::test(void) { // Tests initialization @@ -711,6 +736,7 @@ bool powerpc_test_cpu::test(void) test_logical(); test_compare(); test_cr_logical(); + test_load_multiple(); printf("%u errors out of %u tests\n", errors, tests); return errors != 0;