aboutsummaryrefslogtreecommitdiff
path: root/backends/platform
diff options
context:
space:
mode:
authorYotam Barnoy2010-11-18 07:52:04 +0000
committerYotam Barnoy2010-11-18 07:52:04 +0000
commit5c8b4dbee7deaebd89f3f7a18bb51172859e6998 (patch)
tree68b957b385a325190c959b5c9b0a2c104529dc8a /backends/platform
parentb77ef177ed6ccfb685ca88e7de568f9ff287d0d2 (diff)
downloadscummvm-rg350-5c8b4dbee7deaebd89f3f7a18bb51172859e6998.tar.gz
scummvm-rg350-5c8b4dbee7deaebd89f3f7a18bb51172859e6998.tar.bz2
scummvm-rg350-5c8b4dbee7deaebd89f3f7a18bb51172859e6998.zip
PSP: added backtracing function for debugging
Currently not used by anything. svn-id: r54312
Diffstat (limited to 'backends/platform')
-rw-r--r--backends/platform/psp/trace.cpp81
-rw-r--r--backends/platform/psp/trace.h1
2 files changed, 82 insertions, 0 deletions
diff --git a/backends/platform/psp/trace.cpp b/backends/platform/psp/trace.cpp
index 7bac6534da..74c2f64300 100644
--- a/backends/platform/psp/trace.cpp
+++ b/backends/platform/psp/trace.cpp
@@ -28,6 +28,8 @@
#include <pspdebug.h>
#include <stdarg.h>
#include <stdio.h>
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "common/scummsys.h"
int psp_debug_indent = 0;
bool firstWriteToFile = true;
@@ -58,3 +60,82 @@ void PspDebugTrace(bool alsoToScreen, const char *format, ...) {
if (alsoToScreen)
fprintf(stderr, buffer);
}
+
+// Assembly functions to get the Return Address register and the Stack pointer register
+#define GET_RET(retAddr) \
+ asm volatile ("move %0,$ra\n\t" \
+ : "=&r" (retAddr) : )
+
+#define GET_SP(stackPtr) \
+ asm volatile ("move %0,$sp\n\t" \
+ : "=&r" (stackPtr) : )
+
+// Function to retrieve a backtrace for the MIPS processor
+// This is not trivial since the MIPS doesn't use a frame pointer.
+// Takes the number of levels wanted above the calling function (included) and an array of void *
+//
+void mipsBacktrace(uint32 levels, void **addresses) {
+ // get the current return address
+ register byte *retAddr;
+ register byte *stackPointer;
+ GET_RET(retAddr);
+ GET_SP(stackPointer);
+ char string[100];
+
+ if (!levels)
+ return;
+
+ memset(addresses, 0, sizeof(void *) * levels);
+
+ uint32 curLevel = 0;
+
+ const uint32 SP_SUBTRACT = 0x27bd8000; // The instruction to subtract from the SP looks like this
+ const uint32 SP_SUB_HIGH_MASK = 0xffff8000; // The mask to check for the subtract SP instruction
+ const uint32 SP_SUB_LOW_MASK = 0x0000ffff; // The mask that gives us how much was subtracted
+
+ // make sure we go out of the stack of this current level
+ // we already have the return address for this level from the register
+ if (curLevel < levels) {
+ void *thisFunc = (void *)mipsBacktrace;
+ for (uint32 *seekPtr = (uint32 *)thisFunc; ; seekPtr++) {
+ if ((*seekPtr & SP_SUB_HIGH_MASK) == SP_SUBTRACT) {
+ // we found the $sp subtraction at the beginning of the function
+ int16 subAmount = (int16)((*seekPtr) & SP_SUB_LOW_MASK);
+ //sprintf(string, "found local $sp sub at %p. Data[%x]. Sub amount %d\n", seekPtr, *seekPtr, subAmount);
+ //fputs(string, stderr);
+ stackPointer -= subAmount;
+ byte *testRetAddr = (byte *)*((uint32 *)(stackPointer - 4));
+ if (testRetAddr != retAddr) {
+ sprintf(string, "mismatch in testretAddr.\n");
+ fputs(string, stderr);
+ }
+ break;
+ }
+ }
+ }
+
+ // keep scanning while more levels are requested
+ while (curLevel < levels) {
+ // now scan backwards from the return address to find the size of the stack
+ for(uint32 *seekPtr = (uint32 *)retAddr; ; seekPtr--) {
+ if (((*seekPtr) & SP_SUB_HIGH_MASK) == SP_SUBTRACT) {
+ // we found the $sp subtraction at the beginning of the function
+ int16 subAmount = (int16)((*seekPtr) & SP_SUB_LOW_MASK);
+ //sprintf(string, "found $sp sub at %p. Data[%x]. Sub amount %d\n", seekPtr, *seekPtr, subAmount);
+ //fputs(string, stderr);
+ stackPointer -= subAmount;
+ retAddr = (byte *)*((uint32 *)(stackPointer - 4));
+ if (retAddr < (byte *)0x8900000 || retAddr > (byte *)0xC900000) {
+ sprintf(string, "invalid retAddr %p\n", retAddr);
+ fputs(string, stderr);
+ return;
+ }
+ //sprintf(string, "retAddr[%p]\n", retAddr);
+ //fputs(string, stderr);
+ addresses[curLevel++] = retAddr;
+ break;
+ }
+ }
+ }
+}
+
diff --git a/backends/platform/psp/trace.h b/backends/platform/psp/trace.h
index 625aa60772..39b335b16c 100644
--- a/backends/platform/psp/trace.h
+++ b/backends/platform/psp/trace.h
@@ -55,6 +55,7 @@
__PSP_PRINT__(format, ## __VA_ARGS__); }
void PspDebugTrace(bool alsoToScreen, const char *format, ...);
+void mipsBacktrace(uint32 levels, void **addresses);
extern int psp_debug_indent;