first commit

This commit is contained in:
Dan Peori
2010-10-18 12:54:49 -03:00
commit 8a3bef9012
612 changed files with 74685 additions and 0 deletions

50
src/debug/Makefile.am Normal file
View File

@@ -0,0 +1,50 @@
libdir = @PSPSDK_LIBDIR@
CC = @PSP_CC@
CCAS = $(CC)
AR = @PSP_AR@
RANLIB = @PSP_RANLIB@
INCLUDES = -I$(top_srcdir)/src/base \
-I$(top_srcdir)/src/kernel \
-I$(top_srcdir)/src/display \
-I$(top_srcdir)/src/ge \
-I$(top_srcdir)/src/user \
-I$(top_srcdir)/src/ctrl
CFLAGS = @PSPSDK_CFLAGS@
CCASFLAGS = $(CFLAGS) $(INCLUDES)
SCRPRINT_OBJS = pspDebugScreenInit.o pspDebugScreenPrintf.o pspDebugScreenKprintf.o
libpspdebugincludedir = @PSPSDK_INCLUDEDIR@
libpspdebuginclude_HEADERS = \
pspdebug.h pspdebugkb.h
lib_LIBRARIES = libpspdebug.a libpspgdb.a libpspgdb_user.a libpspgdb_kernel.a libpspdebugkb.a
libpspdebug_a_SOURCES = \
callstack.c \
callstackget.S \
font.c \
scr_printf.c \
exception.c \
exception_asm.S \
kprintf.c \
stacktrace.c \
profiler.c \
stdio.c \
sio.c
libpspdebug_a_LIBADD = $(SCRPRINT_OBJS)
libpspgdb_a_SOURCES = gdb-stub.c
libpspgdb_user_a_SOURCES = gdb-userlib.c
libpspgdb_kernel_a_SOURCES = gdb-kernellib.c
libpspdebugkb_a_SOURCES = pspdebugkb.c
$(SCRPRINT_OBJS): scr_printf.c
$(COMPILE) -DF_$* $< -c -o $@

256
src/debug/callstack.c Normal file
View File

@@ -0,0 +1,256 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* callstack.c - Return stack generation for MIPS processors.
*
* Copyright (c) 1992, 1998 The Open Group
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
*
* $Id: callstack.c 1492 2005-11-26 23:19:30Z mrbrown $
*/
#include "pspdebug.h"
/*
* $Xorg: getretmips.c,v 1.4 2001/02/09 02:06:19 xorgcvs Exp$
*
Copyright 1992, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*
* Author: Keith Packard, MIT X Consortium
* cleaned up slighly by emoon and added ee related opcodes and checking.
*/
/* Return stack generation for MIPS processors
* This is tricky as MIPS stack frames aren't
* easily unrolled -- we look for pc restoration
* and stack adjustment instructions beyond the return
* address to discover the correct values
*/
/* lw $31,const($sp) is : 100 011 11101 11111 const */
/* 1000 1111 1011 1111 */
#define RESTORE_RETURNVAL 0x8fbf0000
#define RESTORE_RETURNVAL_MASK 0xffff0000
/* ld $31,const($sp) is : 110 111 11101 11111 const */
/* 1101 1111 1011 1111 */
#define RESTORE_RETURNVAL2 0xdfbf0000
/* lq $31,const($sp) is : 011110 11101 11111 const */
/* ee Related 0111 1011 1011 1111 */
#define RESTORE_RETURNVAL3 0x7bbf0000
/* addiu $sp, $sp, const is 001 001 11101 11101 const */
/* 0010 0111 1011 1101 const */
#define ADJUST_STACKP_C 0x27bd0000
#define ADJUST_STACKP_C_MASK 0xffff0000
/* addu $sp, $sp, $at is 000 000 11101 00001 11101 00000 100 001 */
/* 0000 0011 1010 0001 1110 1000 0010 0001 */
#define ADJUST_STACKP_V 0x03a1e821
#define ADJUST_STACKP_V_MASK 0xffffffff
/* lui $at, const is 001 111 00000 00001 const */
/* 0011 1100 0000 0001 const */
#define SET_UPPER_C 0x3c010000
#define SET_UPPER_C_MASK 0xffff0000
/* ori $at, $at, const is 001 101 00001 00001 const */
/* 0011 0100 0010 0001 const */
#define OR_LOWER_C 0x34210000
#define OR_LOWER_C_MASK 0xffff0000
/* ori $at, $zero, const is 001 101 00000 00001 const */
/* 0011 0100 0000 0001 const */
#define SET_LOWER_C 0x34010000
#define SET_LOWER_C_MASK 0xffff0000
/* jr $ra */
#define RETURN 0x03e00008
#define CALL(f) (0x0c000000 | (((int) (f)) >> 2))
/*
* This computation is expensive, so we cache the results;
* a simple hash function and straight-forward replacement.
*/
#define HASH_SIZE 256
typedef struct _returnCache
{
unsigned int *returnAddress;
int raOffset;
int spAdjust;
} ReturnCacheRec, *ReturnCachePtr;
static ReturnCacheRec returnCache[HASH_SIZE];
#define HASH(ra) ((((int) (ra)) >> 2) & (HASH_SIZE - 1))
typedef int Bool;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
extern unsigned int *pspGetReturnAddress();
extern unsigned int *pspGetStackPointer();
extern int main();
int pspDebugGetStackTrace(unsigned int *results, int max)
{
unsigned int *ra;
unsigned int *ra_limit;
unsigned int *sp;
unsigned int inst;
unsigned int mainCall;
unsigned short const_upper;
unsigned short const_lower;
int ra_offset;
int sp_adjust;
Bool found_ra_offset, found_sp_adjust;
Bool found_const_upper, found_const_lower;
ReturnCachePtr rc;
int total = max;
ra = pspGetReturnAddress();
sp = pspGetStackPointer();
mainCall = CALL(main);
while (ra && max)
{
rc = &returnCache[HASH(ra)];
if (rc->returnAddress != ra)
{
found_ra_offset = FALSE;
found_sp_adjust = FALSE;
found_const_upper = FALSE;
found_const_lower = FALSE;
const_upper = 0;
const_lower = 0;
rc->returnAddress = ra;
ra_limit = (unsigned int *) 0x200000;
ra_offset = 0;
sp_adjust = -1;
while ((!found_ra_offset || !found_sp_adjust) && ra < ra_limit)
{
inst = *ra;
/* look for the offset of the PC in the stack frame */
if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL)
{
ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
found_ra_offset = TRUE;
}
else if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL2)
{
ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
found_ra_offset = TRUE;
}
else if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL3)
{
ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
found_ra_offset = TRUE;
}
else if ((inst & ADJUST_STACKP_C_MASK) == ADJUST_STACKP_C)
{
sp_adjust = inst & ~ADJUST_STACKP_C_MASK;
found_sp_adjust = TRUE;
}
else if ((inst & ADJUST_STACKP_V_MASK) == ADJUST_STACKP_V)
{
sp_adjust = 0;
found_sp_adjust = TRUE;
}
else if ((inst & SET_UPPER_C_MASK) == SET_UPPER_C)
{
const_upper = inst & ~SET_UPPER_C_MASK;
const_lower = 0;
found_const_upper = TRUE;
}
else if ((inst & OR_LOWER_C_MASK) == OR_LOWER_C)
{
const_lower = inst & ~OR_LOWER_C_MASK;
found_const_lower = TRUE;
}
else if ((inst & SET_LOWER_C_MASK) == SET_LOWER_C)
{
const_lower = inst & ~SET_LOWER_C_MASK;
const_upper = 0;
found_const_lower = TRUE;
}
else if (inst == RETURN)
ra_limit = ra + 2;
ra++;
}
if (sp_adjust == 0 && (found_const_upper || found_const_lower))
sp_adjust = (const_upper << 16) | const_lower;
rc->raOffset = ra_offset;
rc->spAdjust = sp_adjust;
}
/* if something went wrong, punt */
if (rc->spAdjust <= 0)
{
*results++ = 0;
break;
}
ra = (unsigned int *) sp[rc->raOffset >> 2];
sp += rc->spAdjust >> 2;
if (ra == 0)
{
*results++ = 0;
break;
}
*results++ = ((unsigned int) ra) - 8;
max--;
if (ra[-2] == mainCall)
{
*results++ = 0;
break;
}
}
return total - max;
}

46
src/debug/callstackget.S Normal file
View File

@@ -0,0 +1,46 @@
/*
* $XConsortium: mipsstack.s,v 1.3 94/04/17 20:59:45 keith Exp $
*
Copyright (c) 1992 X Consortium
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the X Consortium shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the X Consortium.
*
* Author: Keith Packard, MIT X Consortium
*/
.globl pspGetReturnAddress
.ent pspGetReturnAddress
pspGetReturnAddress:
.frame $sp, 0, $31
move $2,$31
j $31
.end pspGetReturnAddress
.globl pspGetStackPointer
.ent pspGetStackPointer
pspGetStackPointer:
.frame $sp, 0, $31
move $2,$29
j $31
.end pspGetStackPointer

103
src/debug/exception.c Normal file
View File

@@ -0,0 +1,103 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* pspexception.c - Basic exception handler for applications.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: exception.c 1777 2006-02-01 22:23:22Z tyranid $
*/
#include <pspkernel.h>
#include <pspdisplay.h>
#include <pspdebug.h>
static PspDebugErrorHandler curr_handler = NULL;
void _pspDebugExceptionHandler(void);
PspDebugRegBlock _pspDebugExceptRegs;
int sceKernelRegisterDefaultExceptionHandler(void *func);
/* Install an error handler */
int pspDebugInstallErrorHandler(PspDebugErrorHandler handler)
{
u32 addr;
curr_handler = handler;
addr = (u32) _pspDebugExceptionHandler;
addr |= 0x80000000;
return sceKernelRegisterDefaultExceptionHandler((void *) addr);
}
/* Mnemonic register names */
static const unsigned char regName[32][5] =
{
"zr", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
};
/* Taken from the ps2, might not be 100% correct */
static const char *codeTxt[32] =
{
"Interrupt", "TLB modification", "TLB load/inst fetch", "TLB store",
"Address load/inst fetch", "Address store", "Bus error (instr)",
"Bus error (data)", "Syscall", "Breakpoint", "Reserved instruction",
"Coprocessor unusable", "Arithmetic overflow", "Unknown 13", "Unknown 14",
"FPU Exception", "Unknown 16", "Unknown 17", "Unknown 18",
"Unknown 20", "Unknown 21", "Unknown 22", "Unknown 23",
"Unknown 24", "Unknown 25", "Unknown 26", "Unknown 27",
"Unknown 28", "Unknown 29", "Unknown 30", "Unknown 31"
};
/* Dump an exception to screen */
void pspDebugDumpException(PspDebugRegBlock *regs)
{
int i;
pspDebugScreenPrintf("Exception - %s\n", codeTxt[(regs->cause >> 2) & 31]);
pspDebugScreenPrintf("EPC - %08X\n", regs->epc);
pspDebugScreenPrintf("Cause - %08X\n", regs->cause);
pspDebugScreenPrintf("Status - %08X\n", regs->status);
pspDebugScreenPrintf("BadVAddr - %08X\n", regs->badvaddr);
for(i = 0; i < 32; i+=4)
{
pspDebugScreenPrintf("%s:%08X %s:%08X %s:%08X %s:%08X\n", regName[i], regs->r[i],
regName[i+1], regs->r[i+1], regName[i+2], regs->r[i+2], regName[i+3], regs->r[i+3]);
}
sceDisplayWaitVblankStart();
}
/* Our default handler in case nothing else is installed */
static void _pspDebugDefaultHandler(PspDebugRegBlock *regs)
{
pspDebugScreenInit();
pspDebugDumpException(regs);
}
/**
* The entry point for our exception "trap"
*/
void _pspDebugTrapEntry(void)
{
/* No special stack is used here, if the thread's stack is trashed we might be in trouble */
if(curr_handler != NULL)
{
curr_handler(&_pspDebugExceptRegs);
}
else
{
_pspDebugDefaultHandler(&_pspDebugExceptRegs);
}
/* Kill this thread as we cannot necessarily continue */
/* Technically you might be able to "restart" after something like a break */
sceKernelExitDeleteThread(0);
}

334
src/debug/exception_asm.S Normal file
View File

@@ -0,0 +1,334 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* pspexception_asm.S - Basic exception handler for applications.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id$
*/
#include "as_reg_compat.h"
.set noreorder
.set noat
#define BadVAddr $8 // Address for the most recent address-related exception
#define Status $12 // Processor status and control
#define Cause $13 // Cause of last general exception
#define EPC $14 // Program counter at last exception
#define PRId $15 // Processor identification and revision
#define FSR $31
#define FIR $0
#define REG_GPR_0 (6*4)
#define REG_GPR_1 (REG_GPR_0 + 4)
#define REG_GPR_2 (REG_GPR_1 + 4)
#define REG_GPR_3 (REG_GPR_2 + 4)
#define REG_GPR_4 (REG_GPR_3 + 4)
#define REG_GPR_5 (REG_GPR_4 + 4)
#define REG_GPR_6 (REG_GPR_5 + 4)
#define REG_GPR_7 (REG_GPR_6 + 4)
#define REG_GPR_8 (REG_GPR_7 + 4)
#define REG_GPR_9 (REG_GPR_8 + 4)
#define REG_GPR_10 (REG_GPR_9 + 4)
#define REG_GPR_11 (REG_GPR_10 + 4)
#define REG_GPR_12 (REG_GPR_11 + 4)
#define REG_GPR_13 (REG_GPR_12 + 4)
#define REG_GPR_14 (REG_GPR_13 + 4)
#define REG_GPR_15 (REG_GPR_14 + 4)
#define REG_GPR_16 (REG_GPR_15 + 4)
#define REG_GPR_17 (REG_GPR_16 + 4)
#define REG_GPR_18 (REG_GPR_17 + 4)
#define REG_GPR_19 (REG_GPR_18 + 4)
#define REG_GPR_20 (REG_GPR_19 + 4)
#define REG_GPR_21 (REG_GPR_20 + 4)
#define REG_GPR_22 (REG_GPR_21 + 4)
#define REG_GPR_23 (REG_GPR_22 + 4)
#define REG_GPR_24 (REG_GPR_23 + 4)
#define REG_GPR_25 (REG_GPR_24 + 4)
#define REG_GPR_26 (REG_GPR_25 + 4)
#define REG_GPR_27 (REG_GPR_26 + 4)
#define REG_GPR_28 (REG_GPR_27 + 4)
#define REG_GPR_29 (REG_GPR_28 + 4)
#define REG_GPR_30 (REG_GPR_29 + 4)
#define REG_GPR_31 (REG_GPR_30 + 4)
#define REG_STATUS (REG_GPR_31 + 4)
#define REG_LO (REG_STATUS + 4)
#define REG_HI (REG_LO + 4)
#define REG_BADVADDR (REG_HI + 4)
#define REG_CAUSE (REG_BADVADDR + 4)
#define REG_EPC (REG_CAUSE + 4)
#define REG_FPR_0 (REG_EPC + 4)
#define REG_FPR_1 (REG_FPR_0 + 4)
#define REG_FPR_2 (REG_FPR_1 + 4)
#define REG_FPR_3 (REG_FPR_2 + 4)
#define REG_FPR_4 (REG_FPR_3 + 4)
#define REG_FPR_5 (REG_FPR_4 + 4)
#define REG_FPR_6 (REG_FPR_5 + 4)
#define REG_FPR_7 (REG_FPR_6 + 4)
#define REG_FPR_8 (REG_FPR_7 + 4)
#define REG_FPR_9 (REG_FPR_8 + 4)
#define REG_FPR_10 (REG_FPR_9 + 4)
#define REG_FPR_11 (REG_FPR_10 + 4)
#define REG_FPR_12 (REG_FPR_11 + 4)
#define REG_FPR_13 (REG_FPR_12 + 4)
#define REG_FPR_14 (REG_FPR_13 + 4)
#define REG_FPR_15 (REG_FPR_14 + 4)
#define REG_FPR_16 (REG_FPR_15 + 4)
#define REG_FPR_17 (REG_FPR_16 + 4)
#define REG_FPR_18 (REG_FPR_17 + 4)
#define REG_FPR_19 (REG_FPR_18 + 4)
#define REG_FPR_20 (REG_FPR_19 + 4)
#define REG_FPR_21 (REG_FPR_20 + 4)
#define REG_FPR_22 (REG_FPR_21 + 4)
#define REG_FPR_23 (REG_FPR_22 + 4)
#define REG_FPR_24 (REG_FPR_23 + 4)
#define REG_FPR_25 (REG_FPR_24 + 4)
#define REG_FPR_26 (REG_FPR_25 + 4)
#define REG_FPR_27 (REG_FPR_26 + 4)
#define REG_FPR_28 (REG_FPR_27 + 4)
#define REG_FPR_29 (REG_FPR_28 + 4)
#define REG_FPR_30 (REG_FPR_29 + 4)
#define REG_FPR_31 (REG_FPR_30 + 4)
#define REG_FSR (REG_FPR_31 + 4)
#define REG_FIR (REG_FSR + 4)
#define REG_FP (REG_FIR + 4)
.extern _pspDebugExceptRegs
.extern _pspDebugTrapEntry
.global pspDebugResumeFromException
.ent pspDebugResumeFromException
pspDebugResumeFromException:
break
.end pspDebugResumeFromException
.global _pspDebugExceptionHandler
.ent _pspDebugExceptionHandler
_pspDebugExceptionHandler:
nop
nop
la $v1, pspDebugResumeFromException
mfc0 $v0, EPC
beq $v0, $v1, _pspDebugExceptionResume
nop
la $v0, _pspDebugExceptRegs
sw $0, REG_GPR_0($v0)
sw $1, REG_GPR_1($v0)
cfc0 $1, $4 # Get original v0
sw $1, REG_GPR_2($v0)
cfc0 $1, $5 # Get original v1
sw $1, REG_GPR_3($v0)
sw $4, REG_GPR_4($v0)
sw $5, REG_GPR_5($v0)
sw $6, REG_GPR_6($v0)
sw $7, REG_GPR_7($v0)
sw $8, REG_GPR_8($v0)
sw $9, REG_GPR_9($v0)
sw $10, REG_GPR_10($v0)
sw $11, REG_GPR_11($v0)
sw $12, REG_GPR_12($v0)
sw $13, REG_GPR_13($v0)
sw $14, REG_GPR_14($v0)
sw $15, REG_GPR_15($v0)
sw $16, REG_GPR_16($v0)
sw $17, REG_GPR_17($v0)
sw $18, REG_GPR_18($v0)
sw $19, REG_GPR_19($v0)
sw $20, REG_GPR_20($v0)
sw $21, REG_GPR_21($v0)
sw $22, REG_GPR_22($v0)
sw $23, REG_GPR_23($v0)
sw $24, REG_GPR_24($v0)
sw $25, REG_GPR_25($v0)
sw $26, REG_GPR_26($v0)
sw $27, REG_GPR_27($v0)
sw $28, REG_GPR_28($v0)
sw $29, REG_GPR_29($v0)
sw $30, REG_GPR_30($v0)
sw $31, REG_GPR_31($v0)
mflo $v1
sw $v1, REG_LO($v0)
mfhi $v1
sw $v1, REG_HI($v0)
mfc0 $v1, BadVAddr
sw $v1, REG_BADVADDR($v0)
mfc0 $v1, Cause
sw $v1, REG_CAUSE($v0)
mfc0 $v1, EPC
sw $v1, REG_EPC($v0)
mfc0 $v1, Status
sw $v1, REG_STATUS($v0)
# Check if cop1 is enable and skip if not
lui $a0, 0x2000
and $a0, $a0, $v1
beq $a0, $0, 1f
nop
swc1 $0, REG_FPR_0($v0)
swc1 $1, REG_FPR_1($v0)
swc1 $2, REG_FPR_2($v0)
swc1 $3, REG_FPR_3($v0)
swc1 $4, REG_FPR_4($v0)
swc1 $5, REG_FPR_5($v0)
swc1 $6, REG_FPR_6($v0)
swc1 $7, REG_FPR_7($v0)
swc1 $8, REG_FPR_8($v0)
swc1 $9, REG_FPR_9($v0)
swc1 $10, REG_FPR_10($v0)
swc1 $11, REG_FPR_11($v0)
swc1 $12, REG_FPR_12($v0)
swc1 $13, REG_FPR_13($v0)
swc1 $14, REG_FPR_14($v0)
swc1 $15, REG_FPR_15($v0)
swc1 $16, REG_FPR_16($v0)
swc1 $17, REG_FPR_17($v0)
swc1 $18, REG_FPR_18($v0)
swc1 $19, REG_FPR_19($v0)
swc1 $20, REG_FPR_20($v0)
swc1 $21, REG_FPR_21($v0)
swc1 $22, REG_FPR_22($v0)
swc1 $23, REG_FPR_23($v0)
swc1 $24, REG_FPR_24($v0)
swc1 $25, REG_FPR_25($v0)
swc1 $26, REG_FPR_26($v0)
swc1 $27, REG_FPR_27($v0)
swc1 $28, REG_FPR_28($v0)
swc1 $29, REG_FPR_29($v0)
swc1 $30, REG_FPR_30($v0)
swc1 $31, REG_FPR_31($v0)
cfc1 $t0, FSR
sw $t0, REG_FSR($v0)
cfc1 $t0, FIR
sw $t0, REG_FIR($v0)
ctc1 $0, FSR # Clear any cause flags
# Jump target for ignore cop1
1:
sw $sp, REG_FP($v0)
la $2, _pspDebugTrapEntry
mtc0 $2, $14
nop
nop
eret
nop
nop
.end _pspDebugExceptionHandler
.ent _pspDebugExceptionResume
_pspDebugExceptionResume:
# Resume from the exception in user mode (possibly, could be kernel but we don't really know that)
la $v0, _pspDebugExceptRegs
lw $v1, REG_STATUS($v0)
# Check if cop1 is enable and skip if not
lui $a0, 0x2000
and $a0, $a0, $v1
beq $a0, $0, 1f
nop
lwc1 $0, REG_FPR_0($v0)
lwc1 $1, REG_FPR_1($v0)
lwc1 $2, REG_FPR_2($v0)
lwc1 $3, REG_FPR_3($v0)
lwc1 $4, REG_FPR_4($v0)
lwc1 $5, REG_FPR_5($v0)
lwc1 $6, REG_FPR_6($v0)
lwc1 $7, REG_FPR_7($v0)
lwc1 $8, REG_FPR_8($v0)
lwc1 $9, REG_FPR_9($v0)
lwc1 $10, REG_FPR_10($v0)
lwc1 $11, REG_FPR_11($v0)
lwc1 $12, REG_FPR_12($v0)
lwc1 $13, REG_FPR_13($v0)
lwc1 $14, REG_FPR_14($v0)
lwc1 $15, REG_FPR_15($v0)
lwc1 $16, REG_FPR_16($v0)
lwc1 $17, REG_FPR_17($v0)
lwc1 $18, REG_FPR_18($v0)
lwc1 $19, REG_FPR_19($v0)
lwc1 $20, REG_FPR_20($v0)
lwc1 $21, REG_FPR_21($v0)
lwc1 $22, REG_FPR_22($v0)
lwc1 $23, REG_FPR_23($v0)
lwc1 $24, REG_FPR_24($v0)
lwc1 $25, REG_FPR_25($v0)
lwc1 $26, REG_FPR_26($v0)
lwc1 $27, REG_FPR_27($v0)
lwc1 $28, REG_FPR_28($v0)
lwc1 $29, REG_FPR_29($v0)
lwc1 $30, REG_FPR_30($v0)
lwc1 $31, REG_FPR_31($v0)
lw $t0, REG_FSR($v0)
li $t1, 0xFFFC0F83
and $t0, $t0, $t1 # Clear the cause and flags before ret
ctc1 $t0, FSR
1:
# lw $0, REG_GPR_0($v0)
# lw $1, REG_GPR_1($v0)
# Don't do 2 yet
lw $3, REG_GPR_3($v0)
lw $4, REG_GPR_4($v0)
lw $5, REG_GPR_5($v0)
lw $6, REG_GPR_6($v0)
lw $7, REG_GPR_7($v0)
lw $8, REG_GPR_8($v0)
lw $9, REG_GPR_9($v0)
lw $10, REG_GPR_10($v0)
lw $11, REG_GPR_11($v0)
lw $12, REG_GPR_12($v0)
lw $13, REG_GPR_13($v0)
lw $14, REG_GPR_14($v0)
lw $15, REG_GPR_15($v0)
lw $16, REG_GPR_16($v0)
lw $17, REG_GPR_17($v0)
lw $18, REG_GPR_18($v0)
lw $19, REG_GPR_19($v0)
lw $20, REG_GPR_20($v0)
lw $21, REG_GPR_21($v0)
lw $22, REG_GPR_22($v0)
lw $23, REG_GPR_23($v0)
lw $24, REG_GPR_24($v0)
lw $25, REG_GPR_25($v0)
lw $26, REG_GPR_26($v0)
lw $27, REG_GPR_27($v0)
lw $28, REG_GPR_28($v0)
lw $29, REG_GPR_29($v0)
lw $30, REG_GPR_30($v0)
lw $31, REG_GPR_31($v0)
lw $1, REG_EPC($v0)
mtc0 $1, EPC
# Restore 1 + 2 now
lw $1, REG_GPR_1($v0)
lw $2, REG_GPR_2($v0)
nop
nop
eret
.end _pspDebugExceptionResume

147
src/debug/font.c Normal file
View File

@@ -0,0 +1,147 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* font.c - Debug Font.
*
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
*
* $Id: font.c 540 2005-07-08 19:35:10Z warren $
*/
#include <psptypes.h>
u8 msx[]=
"\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x42\xa5\x81\xa5\x99\x42\x3c"
"\x3c\x7e\xdb\xff\xff\xdb\x66\x3c\x6c\xfe\xfe\xfe\x7c\x38\x10\x00"
"\x10\x38\x7c\xfe\x7c\x38\x10\x00\x10\x38\x54\xfe\x54\x10\x38\x00"
"\x10\x38\x7c\xfe\xfe\x10\x38\x00\x00\x00\x00\x30\x30\x00\x00\x00"
"\xff\xff\xff\xe7\xe7\xff\xff\xff\x38\x44\x82\x82\x82\x44\x38\x00"
"\xc7\xbb\x7d\x7d\x7d\xbb\xc7\xff\x0f\x03\x05\x79\x88\x88\x88\x70"
"\x38\x44\x44\x44\x38\x10\x7c\x10\x30\x28\x24\x24\x28\x20\xe0\xc0"
"\x3c\x24\x3c\x24\x24\xe4\xdc\x18\x10\x54\x38\xee\x38\x54\x10\x00"
"\x10\x10\x10\x7c\x10\x10\x10\x10\x10\x10\x10\xff\x00\x00\x00\x00"
"\x00\x00\x00\xff\x10\x10\x10\x10\x10\x10\x10\xf0\x10\x10\x10\x10"
"\x10\x10\x10\x1f\x10\x10\x10\x10\x10\x10\x10\xff\x10\x10\x10\x10"
"\x10\x10\x10\x10\x10\x10\x10\x10\x00\x00\x00\xff\x00\x00\x00\x00"
"\x00\x00\x00\x1f\x10\x10\x10\x10\x00\x00\x00\xf0\x10\x10\x10\x10"
"\x10\x10\x10\x1f\x00\x00\x00\x00\x10\x10\x10\xf0\x00\x00\x00\x00"
"\x81\x42\x24\x18\x18\x24\x42\x81\x01\x02\x04\x08\x10\x20\x40\x80"
"\x80\x40\x20\x10\x08\x04\x02\x01\x00\x10\x10\xff\x10\x10\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20\x20\x20\x00\x00\x20\x00"
"\x50\x50\x50\x00\x00\x00\x00\x00\x50\x50\xf8\x50\xf8\x50\x50\x00"
"\x20\x78\xa0\x70\x28\xf0\x20\x00\xc0\xc8\x10\x20\x40\x98\x18\x00"
"\x40\xa0\x40\xa8\x90\x98\x60\x00\x10\x20\x40\x00\x00\x00\x00\x00"
"\x10\x20\x40\x40\x40\x20\x10\x00\x40\x20\x10\x10\x10\x20\x40\x00"
"\x20\xa8\x70\x20\x70\xa8\x20\x00\x00\x20\x20\xf8\x20\x20\x00\x00"
"\x00\x00\x00\x00\x00\x20\x20\x40\x00\x00\x00\x78\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x60\x60\x00\x00\x00\x08\x10\x20\x40\x80\x00"
"\x70\x88\x98\xa8\xc8\x88\x70\x00\x20\x60\xa0\x20\x20\x20\xf8\x00"
"\x70\x88\x08\x10\x60\x80\xf8\x00\x70\x88\x08\x30\x08\x88\x70\x00"
"\x10\x30\x50\x90\xf8\x10\x10\x00\xf8\x80\xe0\x10\x08\x10\xe0\x00"
"\x30\x40\x80\xf0\x88\x88\x70\x00\xf8\x88\x10\x20\x20\x20\x20\x00"
"\x70\x88\x88\x70\x88\x88\x70\x00\x70\x88\x88\x78\x08\x10\x60\x00"
"\x00\x00\x20\x00\x00\x20\x00\x00\x00\x00\x20\x00\x00\x20\x20\x40"
"\x18\x30\x60\xc0\x60\x30\x18\x00\x00\x00\xf8\x00\xf8\x00\x00\x00"
"\xc0\x60\x30\x18\x30\x60\xc0\x00\x70\x88\x08\x10\x20\x00\x20\x00"
"\x70\x88\x08\x68\xa8\xa8\x70\x00\x20\x50\x88\x88\xf8\x88\x88\x00"
"\xf0\x48\x48\x70\x48\x48\xf0\x00\x30\x48\x80\x80\x80\x48\x30\x00"
"\xe0\x50\x48\x48\x48\x50\xe0\x00\xf8\x80\x80\xf0\x80\x80\xf8\x00"
"\xf8\x80\x80\xf0\x80\x80\x80\x00\x70\x88\x80\xb8\x88\x88\x70\x00"
"\x88\x88\x88\xf8\x88\x88\x88\x00\x70\x20\x20\x20\x20\x20\x70\x00"
"\x38\x10\x10\x10\x90\x90\x60\x00\x88\x90\xa0\xc0\xa0\x90\x88\x00"
"\x80\x80\x80\x80\x80\x80\xf8\x00\x88\xd8\xa8\xa8\x88\x88\x88\x00"
"\x88\xc8\xc8\xa8\x98\x98\x88\x00\x70\x88\x88\x88\x88\x88\x70\x00"
"\xf0\x88\x88\xf0\x80\x80\x80\x00\x70\x88\x88\x88\xa8\x90\x68\x00"
"\xf0\x88\x88\xf0\xa0\x90\x88\x00\x70\x88\x80\x70\x08\x88\x70\x00"
"\xf8\x20\x20\x20\x20\x20\x20\x00\x88\x88\x88\x88\x88\x88\x70\x00"
"\x88\x88\x88\x88\x50\x50\x20\x00\x88\x88\x88\xa8\xa8\xd8\x88\x00"
"\x88\x88\x50\x20\x50\x88\x88\x00\x88\x88\x88\x70\x20\x20\x20\x00"
"\xf8\x08\x10\x20\x40\x80\xf8\x00\x70\x40\x40\x40\x40\x40\x70\x00"
"\x00\x00\x80\x40\x20\x10\x08\x00\x70\x10\x10\x10\x10\x10\x70\x00"
"\x20\x50\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x00"
"\x40\x20\x10\x00\x00\x00\x00\x00\x00\x00\x70\x08\x78\x88\x78\x00"
"\x80\x80\xb0\xc8\x88\xc8\xb0\x00\x00\x00\x70\x88\x80\x88\x70\x00"
"\x08\x08\x68\x98\x88\x98\x68\x00\x00\x00\x70\x88\xf8\x80\x70\x00"
"\x10\x28\x20\xf8\x20\x20\x20\x00\x00\x00\x68\x98\x98\x68\x08\x70"
"\x80\x80\xf0\x88\x88\x88\x88\x00\x20\x00\x60\x20\x20\x20\x70\x00"
"\x10\x00\x30\x10\x10\x10\x90\x60\x40\x40\x48\x50\x60\x50\x48\x00"
"\x60\x20\x20\x20\x20\x20\x70\x00\x00\x00\xd0\xa8\xa8\xa8\xa8\x00"
"\x00\x00\xb0\xc8\x88\x88\x88\x00\x00\x00\x70\x88\x88\x88\x70\x00"
"\x00\x00\xb0\xc8\xc8\xb0\x80\x80\x00\x00\x68\x98\x98\x68\x08\x08"
"\x00\x00\xb0\xc8\x80\x80\x80\x00\x00\x00\x78\x80\xf0\x08\xf0\x00"
"\x40\x40\xf0\x40\x40\x48\x30\x00\x00\x00\x90\x90\x90\x90\x68\x00"
"\x00\x00\x88\x88\x88\x50\x20\x00\x00\x00\x88\xa8\xa8\xa8\x50\x00"
"\x00\x00\x88\x50\x20\x50\x88\x00\x00\x00\x88\x88\x98\x68\x08\x70"
"\x00\x00\xf8\x10\x20\x40\xf8\x00\x18\x20\x20\x40\x20\x20\x18\x00"
"\x20\x20\x20\x00\x20\x20\x20\x00\xc0\x20\x20\x10\x20\x20\xc0\x00"
"\x40\xa8\x10\x00\x00\x00\x00\x00\x00\x00\x20\x50\xf8\x00\x00\x00"
"\x70\x88\x80\x80\x88\x70\x20\x60\x90\x00\x00\x90\x90\x90\x68\x00"
"\x10\x20\x70\x88\xf8\x80\x70\x00\x20\x50\x70\x08\x78\x88\x78\x00"
"\x48\x00\x70\x08\x78\x88\x78\x00\x20\x10\x70\x08\x78\x88\x78\x00"
"\x20\x00\x70\x08\x78\x88\x78\x00\x00\x70\x80\x80\x80\x70\x10\x60"
"\x20\x50\x70\x88\xf8\x80\x70\x00\x50\x00\x70\x88\xf8\x80\x70\x00"
"\x20\x10\x70\x88\xf8\x80\x70\x00\x50\x00\x00\x60\x20\x20\x70\x00"
"\x20\x50\x00\x60\x20\x20\x70\x00\x40\x20\x00\x60\x20\x20\x70\x00"
"\x50\x00\x20\x50\x88\xf8\x88\x00\x20\x00\x20\x50\x88\xf8\x88\x00"
"\x10\x20\xf8\x80\xf0\x80\xf8\x00\x00\x00\x6c\x12\x7e\x90\x6e\x00"
"\x3e\x50\x90\x9c\xf0\x90\x9e\x00\x60\x90\x00\x60\x90\x90\x60\x00"
"\x90\x00\x00\x60\x90\x90\x60\x00\x40\x20\x00\x60\x90\x90\x60\x00"
"\x40\xa0\x00\xa0\xa0\xa0\x50\x00\x40\x20\x00\xa0\xa0\xa0\x50\x00"
"\x90\x00\x90\x90\xb0\x50\x10\xe0\x50\x00\x70\x88\x88\x88\x70\x00"
"\x50\x00\x88\x88\x88\x88\x70\x00\x20\x20\x78\x80\x80\x78\x20\x20"
"\x18\x24\x20\xf8\x20\xe2\x5c\x00\x88\x50\x20\xf8\x20\xf8\x20\x00"
"\xc0\xa0\xa0\xc8\x9c\x88\x88\x8c\x18\x20\x20\xf8\x20\x20\x20\x40"
"\x10\x20\x70\x08\x78\x88\x78\x00\x10\x20\x00\x60\x20\x20\x70\x00"
"\x20\x40\x00\x60\x90\x90\x60\x00\x20\x40\x00\x90\x90\x90\x68\x00"
"\x50\xa0\x00\xa0\xd0\x90\x90\x00\x28\x50\x00\xc8\xa8\x98\x88\x00"
"\x00\x70\x08\x78\x88\x78\x00\xf8\x00\x60\x90\x90\x90\x60\x00\xf0"
"\x20\x00\x20\x40\x80\x88\x70\x00\x00\x00\x00\xf8\x80\x80\x00\x00"
"\x00\x00\x00\xf8\x08\x08\x00\x00\x84\x88\x90\xa8\x54\x84\x08\x1c"
"\x84\x88\x90\xa8\x58\xa8\x3c\x08\x20\x00\x00\x20\x20\x20\x20\x00"
"\x00\x00\x24\x48\x90\x48\x24\x00\x00\x00\x90\x48\x24\x48\x90\x00"
"\x28\x50\x20\x50\x88\xf8\x88\x00\x28\x50\x70\x08\x78\x88\x78\x00"
"\x28\x50\x00\x70\x20\x20\x70\x00\x28\x50\x00\x20\x20\x20\x70\x00"
"\x28\x50\x00\x70\x88\x88\x70\x00\x50\xa0\x00\x60\x90\x90\x60\x00"
"\x28\x50\x00\x88\x88\x88\x70\x00\x50\xa0\x00\xa0\xa0\xa0\x50\x00"
"\xfc\x48\x48\x48\xe8\x08\x50\x20\x00\x50\x00\x50\x50\x50\x10\x20"
"\xc0\x44\xc8\x54\xec\x54\x9e\x04\x10\xa8\x40\x00\x00\x00\x00\x00"
"\x00\x20\x50\x88\x50\x20\x00\x00\x88\x10\x20\x40\x80\x28\x00\x00"
"\x7c\xa8\xa8\x68\x28\x28\x28\x00\x38\x40\x30\x48\x48\x30\x08\x70"
"\x00\x00\x00\x00\x00\x00\xff\xff\xf0\xf0\xf0\xf0\x0f\x0f\x0f\x0f"
"\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x3c\x3c\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00"
"\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x0f\x0f\x0f\x0f\xf0\xf0\xf0\xf0"
"\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\x03\x03\x03\x03\x03\x03\x03\x03"
"\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x11\x22\x44\x88\x11\x22\x44\x88"
"\x88\x44\x22\x11\x88\x44\x22\x11\xfe\x7c\x38\x10\x00\x00\x00\x00"
"\x00\x00\x00\x00\x10\x38\x7c\xfe\x80\xc0\xe0\xf0\xe0\xc0\x80\x00"
"\x01\x03\x07\x0f\x07\x03\x01\x00\xff\x7e\x3c\x18\x18\x3c\x7e\xff"
"\x81\xc3\xe7\xff\xff\xe7\xc3\x81\xf0\xf0\xf0\xf0\x00\x00\x00\x00"
"\x00\x00\x00\x00\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x00\x00\x00\x00"
"\x00\x00\x00\x00\xf0\xf0\xf0\xf0\x33\x33\xcc\xcc\x33\x33\xcc\xcc"
"\x00\x20\x20\x50\x50\x88\xf8\x00\x20\x20\x70\x20\x70\x20\x20\x00"
"\x00\x00\x00\x50\x88\xa8\x50\x00\xff\xff\xff\xff\xff\xff\xff\xff"
"\x00\x00\x00\x00\xff\xff\xff\xff\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0"
"\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xff\xff\xff\xff\x00\x00\x00\x00"
"\x00\x00\x68\x90\x90\x90\x68\x00\x30\x48\x48\x70\x48\x48\x70\xc0"
"\xf8\x88\x80\x80\x80\x80\x80\x00\xf8\x50\x50\x50\x50\x50\x98\x00"
"\xf8\x88\x40\x20\x40\x88\xf8\x00\x00\x00\x78\x90\x90\x90\x60\x00"
"\x00\x50\x50\x50\x50\x68\x80\x80\x00\x50\xa0\x20\x20\x20\x20\x00"
"\xf8\x20\x70\xa8\xa8\x70\x20\xf8\x20\x50\x88\xf8\x88\x50\x20\x00"
"\x70\x88\x88\x88\x50\x50\xd8\x00\x30\x40\x40\x20\x50\x50\x50\x20"
"\x00\x00\x00\x50\xa8\xa8\x50\x00\x08\x70\xa8\xa8\xa8\x70\x80\x00"
"\x38\x40\x80\xf8\x80\x40\x38\x00\x70\x88\x88\x88\x88\x88\x88\x00"
"\x00\xf8\x00\xf8\x00\xf8\x00\x00\x20\x20\xf8\x20\x20\x00\xf8\x00"
"\xc0\x30\x08\x30\xc0\x00\xf8\x00\x18\x60\x80\x60\x18\x00\xf8\x00"
"\x10\x28\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xa0\x40"
"\x00\x20\x00\xf8\x00\x20\x00\x00\x00\x50\xa0\x00\x50\xa0\x00\x00"
"\x00\x18\x24\x24\x18\x00\x00\x00\x00\x30\x78\x78\x30\x00\x00\x00"
"\x00\x00\x00\x00\x30\x00\x00\x00\x3e\x20\x20\x20\xa0\x60\x20\x00"
"\xa0\x50\x50\x50\x00\x00\x00\x00\x40\xa0\x20\x40\xe0\x00\x00\x00"
"\x00\x38\x38\x38\x38\x38\x38\x00\x00\x00\x00\x00\x00\x00\x00";

91
src/debug/gdb-kernellib.c Normal file
View File

@@ -0,0 +1,91 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* gdb-kernellib.c - GDB support functions for kernel mode.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: gdb-kernellib.c 1492 2005-11-26 23:19:30Z mrbrown $
*/
#include <pspkernel.h>
#include <pspdebug.h>
/* GDB Debug putchar */
void putDebugChar(char ch)
{
pspDebugSioPutchar(ch);
}
/* GDB Debug getchar */
char getDebugChar(void)
{
int ch = 0;
while(1)
{
ch = pspDebugSioGetchar();
if(ch != -1)
{
break;
}
}
return ch;
}
void sceKernelDcacheWBinvAll(void);
void sceKernelIcacheClearAll(void);
void _gdbSupportLibFlushCaches(void)
{
pspKernelSetKernelPC();
sceKernelDcacheWBinvAll();
sceKernelIcacheClearAll();
}
int _gdbSupportLibReadByte(unsigned char *address, unsigned char *dest)
{
u32 addr;
addr = (u32) address;
if((addr >= 0x08400000) && (addr < 0x0a000000))
{
*dest = *address;
return 1;
}
else if((addr >= 0x88000000) && (addr < 0x8a000000))
{
*dest = *address;
return 1;
}
return 0;
}
int _gdbSupportLibWriteByte(char val, unsigned char *dest)
{
u32 addr;
addr = (u32) dest;
if((addr >= 0x08400000) && (addr < 0x0a000000))
{
*dest = val;
return 1;
}
else if((addr >= 0x88000000) && (addr < 0x8a000000))
{
*dest = val;
return 1;
}
return 0;
}
int _gdbSupportLibInit(void)
{
/* Do nothing */
return 0;
}

822
src/debug/gdb-stub.c Normal file
View File

@@ -0,0 +1,822 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* gdb-stub.c - Simple remote GDB stub for the psp.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: gdb-stub.c 1152 2005-10-16 20:37:00Z tyranid $
*/
/* Note: there is the odd small bit which comes from the gdb stubs/linux mips stub */
/* As far as I am aware they didn't have an explicit license on them so... */
#include <pspkernel.h>
#include <pspdebug.h>
#include <string.h>
#include <signal.h>
//#define DEBUG
#ifdef DEBUG
#define DEBUG_PRINTF(fmt, ...) pspDebugScreenPrintf(fmt, ## __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif
/*
* breakpoint and test functions
*/
void pspDebugBreakpoint(void);
void putDebugChar(char ch);
char getDebugChar(void);
int _gdbSupportLibWriteByte(char val, unsigned char *dest);
int _gdbSupportLibReadByte(unsigned char *address, unsigned char *dest);
//void _pspDebugExceptionResume(void);
void pspDebugResumeFromException(void);
void _gdbSupportLibFlushCaches(void);
extern u32 _pspDebugResumePatch;
extern int sceKernelSuspendIntr(void);
extern void sceKernelResumeIntr(int intr);
static void handle_exception(PspDebugRegBlock *regs);
#define MAX_BUF 2048
void _GdbExceptionHandler(void);
static PspDebugRegBlock *_GdbExceptRegs;
static int initialised = 0;
static char input[MAX_BUF];
static char output[MAX_BUF];
static const char hexchars[]="0123456789abcdef";
static char last_cmd = 0;
static int attached = 0;
/* Define a software breakpoint structure */
struct sw_breakpoint
{
unsigned int addr;
unsigned int oldinst;
unsigned int active;
};
static struct sw_breakpoint g_stepbp[2];
/*
* send the packet in buffer.
*/
static void putpacket(unsigned char *buffer)
{
unsigned char checksum;
int count;
unsigned char ch;
/*
* $<packet info>#<checksum>.
*/
do {
putDebugChar('$');
checksum = 0;
count = 0;
while ((ch = buffer[count]) != 0) {
checksum += ch;
count += 1;
putDebugChar(ch);
}
putDebugChar('#');
putDebugChar(hexchars[(checksum >> 4) & 0xf]);
putDebugChar(hexchars[checksum & 0xf]);
DEBUG_PRINTF("calculated checksum = %02X\n", checksum);
}
while ((getDebugChar() & 0x7f) != '+');
}
static char get_char(void)
{
int ch;
while((ch = pspDebugSioGetchar()) == -1);
return ch;
}
/*
* send the packet in buffer.
*/
static int stdout_handler(const char *data, int len)
{
unsigned char checksum;
int count;
unsigned char ch;
if(!attached)
{
return 0;
}
/*
* $<packet info>#<checksum>.
*/
do {
pspDebugSioPutchar('$');
pspDebugSioPutchar('O');
checksum = 'O';
count = 0;
while(1)
{
if(count == len)
{
break;
}
ch = hexchars[(data[count] >> 4) & 0xF];
pspDebugSioPutchar(ch);
checksum += ch;
ch = hexchars[data[count] & 0xF];
pspDebugSioPutchar(ch);
checksum += ch;
count += 1;
}
pspDebugSioPutchar('#');
pspDebugSioPutchar(hexchars[(checksum >> 4) & 0xf]);
pspDebugSioPutchar(hexchars[checksum & 0xf]);
}
while ((get_char() & 0x7f) != '+');
return count;
}
/*
* Convert ch from a hex digit to an int
*/
static int hex(unsigned char ch)
{
if (ch >= 'a' && ch <= 'f')
return ch-'a'+10;
if (ch >= '0' && ch <= '9')
return ch-'0';
if (ch >= 'A' && ch <= 'F')
return ch-'A'+10;
return -1;
}
/*
* scan for the sequence $<data>#<checksum>
*/
static void getpacket(char *buffer)
{
unsigned char checksum;
unsigned char xmitcsum;
int i;
int count;
unsigned char ch;
do {
/*
* wait around for the start character,
* ignore all other characters
*/
while ((ch = (getDebugChar() & 0x7f)) != '$') ;
checksum = 0;
xmitcsum = -1;
count = 0;
/*
* now, read until a # or end of buffer is found
*/
while (count < MAX_BUF) {
ch = getDebugChar();
if (ch == '#')
break;
checksum = checksum + ch;
buffer[count] = ch;
count = count + 1;
}
if (count >= MAX_BUF)
continue;
buffer[count] = 0;
if (ch == '#') {
xmitcsum = hex(getDebugChar() & 0x7f) << 4;
xmitcsum |= hex(getDebugChar() & 0x7f);
if (checksum != xmitcsum)
putDebugChar('-'); /* failed checksum */
else {
putDebugChar('+'); /* successful transfer */
/*
* if a sequence char is present,
* reply the sequence ID
*/
if (buffer[2] == ':') {
putDebugChar(buffer[0]);
putDebugChar(buffer[1]);
/*
* remove sequence chars from buffer
*/
count = strlen(buffer);
for (i=3; i <= count; i++)
buffer[i-3] = buffer[i];
}
}
}
}
while (checksum != xmitcsum);
}
static struct hard_trap_info {
unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */
unsigned char signo; /* Signal that we map this trap into */
} hard_trap_info[] = {
{ 6, SIGBUS }, /* instruction bus error */
{ 7, SIGBUS }, /* data bus error */
{ 9, SIGTRAP }, /* break */
{ 10, SIGILL }, /* reserved instruction */
{ 12, SIGFPE }, /* overflow */
{ 13, SIGTRAP }, /* trap */
{ 14, SIGSEGV }, /* virtual instruction cache coherency */
{ 15, SIGFPE }, /* floating point exception */
{ 23, SIGSEGV }, /* watch */
{ 31, SIGSEGV }, /* virtual data cache coherency */
{ 0, 0} /* Must be last */
};
static int computeSignal(int tt)
{
struct hard_trap_info *ht;
for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
if (ht->tt == tt)
return ht->signo;
return SIGHUP; /* default for things we don't know about */
}
static void _GdbTrapEntry(PspDebugRegBlock *regs)
{
/* Get the current priority and increment by one ? */
_GdbExceptRegs = regs;
handle_exception(regs);
/* Flush caches */
_gdbSupportLibFlushCaches();
pspDebugResumeFromException();
}
int _gdbSupportLibInit(void);
void pspDebugGdbStubInit(void)
{
_gdbSupportLibInit();
/* Read out any pending data */
memset(g_stepbp, 0, 2 * sizeof(struct sw_breakpoint));
pspDebugInstallStdoutHandler(stdout_handler);
pspDebugInstallStderrHandler(stdout_handler);
pspDebugInstallErrorHandler(_GdbTrapEntry);
initialised = 1;
attached = 1;
}
static char *mem2hex(unsigned char *mem, char *buf, int count)
{
unsigned char ch;
while (count-- > 0) {
if (_gdbSupportLibReadByte(mem++, &ch) == 0)
{
return NULL;
}
*buf++ = hexchars[(ch >> 4) & 0xf];
*buf++ = hexchars[ch & 0xf];
}
*buf = 0;
return buf;
}
static char *hex2mem(char *buf, char *mem, int count, int binary)
{
int i;
unsigned char ch;
for (i=0; i<count; i++)
{
if (binary) {
ch = *buf++;
if (ch == 0x7d)
ch = 0x20 ^ *buf++;
}
else {
ch = hex(*buf++) << 4;
ch |= hex(*buf++);
}
if (_gdbSupportLibWriteByte(ch, (unsigned char *) mem++) == 0)
return 0;
}
return mem;
}
static int hexToInt(char **ptr, unsigned int *intValue)
{
int numChars = 0;
int hexValue;
*intValue = 0;
while (**ptr) {
hexValue = hex(**ptr);
if (hexValue < 0)
break;
*intValue = (*intValue << 4) | hexValue;
numChars ++;
(*ptr)++;
}
return numChars;
}
#define SW_BREAK_INST 0x0000000d
/* Define some opcode stuff for the stepping function */
#define BEQ_OPCODE 0x4
#define BEQL_OPCODE 0x14
#define BGTZ_OPCODE 0x7
#define BGTZL_OPCODE 0x17
#define BLEZ_OPCODE 0x6
#define BLEZL_OPCODE 0x16
#define BNE_OPCODE 0x5
#define BNEL_OPCODE 0x15
/* Reg Imm */
#define REGIMM_OPCODE 0x1
#define BGEZ_OPCODE 0x1
#define BGEZAL_OPCODE 0x11
#define BGEZALL_OPCODE 0x13
#define BGEZL_OPCODE 0x3
#define BLTZ_OPCODE 0
#define BLTZAL_OPCODE 0x10
#define BLTZALL_OPCODE 0x12
#define BLTZL_OPCODE 0x2
#define J_OPCODE 0x2
#define JAL_OPCODE 0x3
/* Special opcode */
#define SPECIAL_OPCODE 0
#define JALR_OPCODE 0x9
#define JR_OPCODE 0x8
/* Cop Branches (all the same) */
#define COP0_OPCODE 0x10
#define COP1_OPCODE 0x11
#define COP2_OPCODE 0x12
#define BCXF_OPCODE 0x100
#define BCXFL_OPCODE 0x102
#define BCXT_OPCODE 0x101
#define BCXTL_OPCODE 0x103
/* Generic step command , if skip then will try to skip over jals */
static void step_generic(PspDebugRegBlock *regs, int skip)
{
u32 opcode;
u32 epc;
u32 targetpc;
int branch = 0;
int cond = 0;
int link = 0;
epc = regs->epc;
targetpc = epc + 4;
opcode = _lw(epc);
switch(opcode >> 26)
{
case BEQ_OPCODE:
case BEQL_OPCODE:
case BGTZ_OPCODE:
case BGTZL_OPCODE:
case BLEZ_OPCODE:
case BLEZL_OPCODE:
case BNE_OPCODE:
case BNEL_OPCODE:
{
short ofs;
ofs = (short) (opcode & 0xffff);
cond = 1;
branch = 1;
targetpc += ofs * 4;
}
break;
case REGIMM_OPCODE: {
switch((opcode >> 16) & 0x1f)
{
case BGEZ_OPCODE:
case BGEZAL_OPCODE:
case BGEZALL_OPCODE:
case BGEZL_OPCODE:
case BLTZ_OPCODE:
case BLTZAL_OPCODE:
case BLTZALL_OPCODE:
case BLTZL_OPCODE: {
short ofs;
ofs = (short) (opcode & 0xffff);
cond = 1;
branch = 1;
targetpc += ofs * 4;
}
break;
}
}
break;
case JAL_OPCODE: link = 1;
case J_OPCODE: {
u32 ofs;
ofs = opcode & 0x3ffffff;
targetpc = (ofs << 2) | (targetpc & 0xf0000000);
branch = 1;
cond = 0;
}
break;
case SPECIAL_OPCODE:
{
switch(opcode & 0x3f)
{
case JALR_OPCODE: link = 1;
case JR_OPCODE:
{
u32 rs;
rs = (opcode >> 21) & 0x1f;
targetpc = regs->r[rs];
branch = 1;
cond = 0;
}
break;
};
}
break;
case COP0_OPCODE:
case COP1_OPCODE:
case COP2_OPCODE:
{
switch((opcode >> 16) & 0x3ff)
{
case BCXF_OPCODE:
case BCXFL_OPCODE:
case BCXT_OPCODE:
case BCXTL_OPCODE:
{
short ofs;
ofs = (short) (opcode & 0xffff);
cond = 1;
branch = 1;
targetpc += ofs * 4;
}
break;
};
}
break;
};
if(link && skip)
{
g_stepbp[1].addr = epc + 8;
g_stepbp[1].oldinst = _lw(epc + 8);
g_stepbp[1].active = 1;
_sw(SW_BREAK_INST, epc + 8);
}
else if(branch)
{
g_stepbp[0].addr = targetpc;
g_stepbp[0].oldinst = _lw(targetpc);
g_stepbp[0].active = 1;
_sw(SW_BREAK_INST, targetpc);
if((cond) && (targetpc != (epc + 8)))
{
g_stepbp[1].addr = epc + 8;
g_stepbp[1].oldinst = _lw(epc + 8);
g_stepbp[1].active = 1;
_sw(SW_BREAK_INST, epc + 8);
}
}
else
{
g_stepbp[0].addr = targetpc;
g_stepbp[0].active = 1;
g_stepbp[0].oldinst = _lw(targetpc);
_sw(SW_BREAK_INST, targetpc);
}
}
void build_trap_cmd(int sigval, PspDebugRegBlock *regs)
{
char *ptr;
/*
* reply to host that an exception has occurred
*/
ptr = output;
*ptr++ = 'T';
*ptr++ = hexchars[(sigval >> 4) & 0xf];
*ptr++ = hexchars[sigval & 0xf];
/*
* Send Error PC
*/
*ptr++ = hexchars[37 >> 4];
*ptr++ = hexchars[37 & 0xf];
*ptr++ = ':';
ptr = mem2hex((unsigned char *) &regs->epc, ptr, sizeof(u32));
*ptr++ = ';';
/*
* Send frame pointer
*/
*ptr++ = hexchars[30 >> 4];
*ptr++ = hexchars[30 & 0xf];
*ptr++ = ':';
ptr = mem2hex((unsigned char *)&regs->r[30], ptr, sizeof(u32));
*ptr++ = ';';
/*
* Send stack pointer
*/
*ptr++ = hexchars[29 >> 4];
*ptr++ = hexchars[29 & 0xf];
*ptr++ = ':';
ptr = mem2hex((unsigned char *)&regs->r[29], ptr, sizeof(u32));
*ptr++ = ';';
*ptr++ = 0;
}
static void handle_query(char *str)
{
static SceUID threads[100];
static int thread_count = 0;
static int thread_loc = 0;
switch(str[0])
{
case 'f':
if(strncmp(str, "fThreadInfo", strlen("fThreadInfo")) == 0)
{
thread_count = sceKernelGetThreadmanIdList(SCE_KERNEL_TMID_Thread, threads, 100, &thread_count);
if(thread_count > 0)
{
thread_loc = 0;
output[0] = 'm';
mem2hex((unsigned char *) &threads[thread_loc], &output[1], 4);
output[9] = 0;
thread_loc++;
}
}
break;
case 's':
if(strncmp(str, "sThreadInfo", strlen("sThreadInfo")) == 0)
{
if(thread_loc < thread_count)
{
output[0] = 'm';
mem2hex((unsigned char *) &threads[thread_loc], &output[1], 4);
output[9] = 0;
thread_loc++;
}
else
{
strcpy(output, "l");
}
}
break;
case 'P':
break;
};
}
static void handle_exception (PspDebugRegBlock *regs)
{
int trap;
int sigval;
unsigned int addr;
unsigned int length;
char *ptr;
int bflag = 0;
trap = (regs->cause & 0x7c) >> 2;
sigval = computeSignal(trap);
if(sigval == SIGHUP)
{
DEBUG_PRINTF("Trap %d\n", trap);
}
/* We stopped in breakpoint, so set epc to our ra */
if((regs->epc == (u32) pspDebugBreakpoint) && (trap == 9))
{
regs->epc = regs->r[31];
}
/* If step breakpoints set then put back the old values */
if(g_stepbp[0].active)
{
_sw(g_stepbp[0].oldinst, g_stepbp[0].addr);
g_stepbp[0].active = 0;
}
if(g_stepbp[1].active)
{
_sw(g_stepbp[1].oldinst, g_stepbp[1].addr);
g_stepbp[1].active = 0;
}
if(last_cmd != 0)
{
build_trap_cmd(sigval, regs);
putpacket((unsigned char *) output);
}
while(1)
{
getpacket(input);
DEBUG_PRINTF("Received packet '%s'\n", input);
output[0] = 0;
switch (input[0])
{
case '?':
if(last_cmd == 0)
{
build_trap_cmd(sigval, regs);
}
else
{
output[0] = 'S';
output[1] = hexchars[sigval >> 4];
output[2] = hexchars[sigval & 0xf];
output[3] = 0;
}
break;
case 'c':
ptr = &input[1];
if (hexToInt(&ptr, &addr))
{
regs->epc = addr;
}
goto restart;
break;
case 'D':
putpacket((unsigned char *) output);
attached = 0;
goto restart;
break;
case 'g':
ptr = output;
ptr = (char*) mem2hex((unsigned char *)&regs->r[0], ptr, 32*sizeof(u32)); /* r0...r31 */
ptr = (char*) mem2hex((unsigned char *)&regs->status, ptr, 6*sizeof(u32)); /* cp0 */
ptr = (char*) mem2hex((unsigned char *)&regs->fpr[0], ptr, 32*sizeof(u32)); /* f0...31 */
ptr = (char*) mem2hex((unsigned char *)&regs->fsr, ptr, 2*sizeof(u32)); /* cp1 */
ptr = (char*) mem2hex((unsigned char *)&regs->frame_ptr, ptr, 2*sizeof(u32)); /* frp */
ptr = (char*) mem2hex((unsigned char *)&regs->index, ptr, 16*sizeof(u32)); /* cp0 */
break;
case 'G':
ptr = &input[1];
hex2mem(ptr, (char *)&regs->r[0], 32*sizeof(unsigned int), 0);
ptr += 32*(2*sizeof(unsigned int));
hex2mem(ptr, (char *)&regs->status, 6*sizeof(unsigned int), 0);
ptr += 6*(2*sizeof(unsigned int));
hex2mem(ptr, (char *)&regs->fpr[0], 32*sizeof(unsigned int), 0);
ptr += 32*(2*sizeof(unsigned int));
hex2mem(ptr, (char *)&regs->fsr, 2*sizeof(unsigned int), 0);
ptr += 2*(2*sizeof(unsigned int));
hex2mem(ptr, (char *)&regs->frame_ptr, 2*sizeof(unsigned int), 0);
ptr += 2*(2*sizeof(unsigned int));
hex2mem(ptr, (char *)&regs->index, 16*sizeof(unsigned int), 0);
strcpy(output,"OK");
break;
/*
* mAA..AA,LLLL Read LLLL bytes at address AA..AA
*/
case 'm':
ptr = &input[1];
if (hexToInt(&ptr, &addr)
&& *ptr++ == ','
&& hexToInt(&ptr, &length)) {
if (mem2hex((unsigned char *)addr, output, length))
break;
strcpy (output, "E03");
} else
strcpy(output,"E01");
break;
/*
* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA
*/
case 'X':
bflag = 1;
/* fall through */
/*
* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
*/
case 'M':
ptr = &input[1];
if (hexToInt(&ptr, &addr)
&& *ptr++ == ','
&& hexToInt(&ptr, &length)
&& *ptr++ == ':') {
if (hex2mem(ptr, (char *)addr, length, bflag))
strcpy(output, "OK");
else
strcpy(output, "E03");
}
else
strcpy(output, "E02");
bflag = 0;
break;
case 's': ptr = &input[1];
if (hexToInt(&ptr, &addr))
{
regs->epc = addr;
}
step_generic(regs, 0);
goto restart;
break;
case 'q': handle_query(&input[1]);
break;
/*
* kill the program; let us try to restart the machine
* Reset the whole machine.
*/
case 'k':
case 'r': sceKernelExitGame();
break;
default:
break;
}
/*
* reply to the request
*/
putpacket((unsigned char *) output);
} /* while */
restart:
last_cmd = input[0];
return ;
}
/* Define the breakpoint function */
asm (
".global pspDebugBreakpoint\n"
".set noreorder\n"
"pspDebugBreakpoint:\tbreak\n"
"jr $31\n"
"nop\n"
);

195
src/debug/gdb-userlib.c Normal file
View File

@@ -0,0 +1,195 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* gdb-userlib.c - GDB support functions for user mode.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: gdb-userlib.c 2166 2007-02-04 10:52:49Z tyranid $
*/
#include <pspkernel.h>
#include <pspdebug.h>
#include <string.h>
static int sio_fd = -1;
/* GDB Debug putchar */
void putDebugChar(char ch)
{
sceIoWrite(sio_fd, &ch, 1);
}
/* GDB Debug getchar */
char getDebugChar(void)
{
char ch = 0;
int count = 0;
while(count <= 0)
{
count = sceIoRead(sio_fd, &ch, 1);
}
return ch;
}
int g_initialised = 0;
static int io_init(PspIoDrvArg *arg)
{
return 0;
}
static int io_exit(PspIoDrvArg *arg)
{
return 0;
}
static int io_read(PspIoDrvFileArg *arg, char *data, int len)
{
int ret = 0;
int ch;
while(ret < len)
{
ch = pspDebugSioGetchar();
if(ch != -1)
{
data[ret++] = ch & 0xFF;
}
else
{
break;
}
}
return ret;
}
static int io_write(PspIoDrvFileArg *arg, const char *data, int len)
{
int ret = 0;
while(ret < len)
{
pspDebugSioPutchar(data[ret++]);
}
return ret;
}
void sceKernelDcacheWBinvAll(void);
void sceKernelIcacheClearAll(void);
static int io_devctl(PspIoDrvFileArg *arg, const char *devname, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen)
{
pspKernelSetKernelPC();
sceKernelDcacheWBinvAll();
sceKernelIcacheClearAll();
return 0;
}
static PspIoDrvFuncs sio_funcs =
{
io_init,
io_exit,
NULL,
NULL,
io_read,
io_write,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
io_devctl,
NULL,
};
static PspIoDrv sio_driver =
{
"sio", 0x10, 0x800, "SIO", &sio_funcs
};
int _gdbSupportLibReadByte(unsigned char *address, unsigned char *dest)
{
u32 addr;
addr = (u32) address;
if((addr >= 0x08400000) && (addr < 0x0a000000))
{
*dest = *address;
return 1;
}
/*
else if((addr >= 0x88000000) && (addr < 0x8a000000))
{
*dest = *address;
return 1;
}
*/
return 0;
}
int _gdbSupportLibWriteByte(char val, unsigned char *dest)
{
u32 addr;
addr = (u32) dest;
if((addr >= 0x08400000) && (addr < 0x0a000000))
{
*dest = val;
return 1;
}
/*
else if((addr >= 0x88000000) && (addr < 0x8a000000))
{
*dest = val;
return 1;
}
*/
return 0;
}
void _gdbSupportLibFlushCaches(void)
{
sceIoDevctl("sio:", 0, NULL, 0, NULL, 0);
}
int _gdbSupportLibInit(void)
{
int ret;
if(!g_initialised)
{
(void) sceIoDelDrv("sio"); /* Ignore error */
ret = sceIoAddDrv(&sio_driver);
if(ret < 0)
{
return ret;
}
sio_fd = sceIoOpen("sio:", PSP_O_RDWR, 0);
g_initialised = 1;
}
return 0;
}

45
src/debug/kprintf.c Normal file
View File

@@ -0,0 +1,45 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* kprintf.c - Basic Kprintf handling for applications.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: kprintf.c 1095 2005-09-27 21:02:16Z jim $
*/
#include <pspkernel.h>
#include <pspdebug.h>
/* The current kprintf handler */
static PspDebugKprintfHandler curr_handler;
int sceKernelRegisterKprintfHandler(void *func, void *args);
/* Default kprintf handler */
static void _pspDebugDefaultKprintfHandler(const char *format, u32 *args)
{
pspDebugScreenPrintf(format, args[0], args[1], args[2], args[3]);
}
/* The registered kprintf handler */
static void _pspDebugKprintfHandler(void *arg, const char *format, u32 *args)
{
if(curr_handler != NULL)
{
curr_handler(format, args);
}
else
{
_pspDebugDefaultKprintfHandler(format, args);
}
}
/* Install a kprintf handler */
int pspDebugInstallKprintfHandler(PspDebugKprintfHandler handler)
{
curr_handler = handler;
return sceKernelRegisterKprintfHandler(_pspDebugKprintfHandler, NULL);
}

97
src/debug/profiler.c Normal file
View File

@@ -0,0 +1,97 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* profiler.c - Debug profiler functions.
*
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
*
* $Id: profiler.c 2190 2007-02-25 21:00:40Z tyranid $
*/
#include <pspkernel.h>
#include <pspdebug.h>
#define PROFILER_REG_BASE 0xBC400000
#define PROFILER_REG_COUNT 21
void pspDebugProfilerEnable(void)
{
_sw(1, PROFILER_REG_BASE);
}
void pspDebugProfilerDisable(void)
{
_sw(0, PROFILER_REG_BASE);
asm("sync\r\n");
}
void pspDebugProfilerClear(void)
{
u32 addr;
int i;
addr = PROFILER_REG_BASE;
/* Don't clear the enable register */
for(i = 1; i < PROFILER_REG_COUNT; i++)
{
addr += 4;
_sw(0, addr);
}
}
void pspDebugProfilerGetRegs(PspDebugProfilerRegs *regs)
{
u32 *p_regs;
u32 addr;
int i;
if(regs == NULL)
{
return;
}
p_regs = (u32 *) regs;
addr = PROFILER_REG_BASE;
for(i = 0; i < PROFILER_REG_COUNT; i++)
{
p_regs[i] = _lw(addr);
addr += 4;
}
}
void pspDebugProfilerPrint(void)
{
PspDebugProfilerRegs regs;
pspDebugProfilerGetRegs(&regs);
pspDebugScreenPrintf("********** Profile ***********\n");
pspDebugScreenPrintf("enable : %10u\n", regs.enable);
pspDebugScreenPrintf("systemck : %10u [cycles]\n", regs.systemck);
pspDebugScreenPrintf("cpu ck : %10u [cycles]\n", regs.cpuck);
pspDebugScreenPrintf("stall : %10u [cycles]\n", regs.internal + regs.memory +
regs.copz + regs.vfpu);
pspDebugScreenPrintf("+(internal) : %10u [cycles]\n", regs.internal);
pspDebugScreenPrintf("+--(memory) : %10u [cycles]\n", regs.memory);
pspDebugScreenPrintf("+----(COPz) : %10u [cycles]\n", regs.copz);
pspDebugScreenPrintf("+----(VFPU) : %10u [cycles]\n", regs.vfpu);
pspDebugScreenPrintf("sleep : %10u [cycles]\n", regs.sleep);
pspDebugScreenPrintf("bus access : %10u [cycles]\n", regs.bus_access);
pspDebugScreenPrintf("uncached load : %10u [times]\n", regs.uncached_load);
pspDebugScreenPrintf("uncached store : %10u [times]\n", regs.uncached_store);
pspDebugScreenPrintf("cached load : %10u [times]\n", regs.cached_load);
pspDebugScreenPrintf("cached store : %10u [times]\n", regs.cached_store);
pspDebugScreenPrintf("I cache miss : %10u [times]\n", regs.i_miss);
pspDebugScreenPrintf("D cache miss : %10u [times]\n", regs.d_miss);
pspDebugScreenPrintf("D cache wb : %10u [times]\n", regs.d_writeback);
pspDebugScreenPrintf("COP0 inst. : %10u [inst.]\n", regs.cop0_inst);
pspDebugScreenPrintf("FPU inst. : %10u [inst.]\n", regs.fpu_inst);
pspDebugScreenPrintf("VFPU inst. : %10u [inst.]\n", regs.vfpu_inst);
pspDebugScreenPrintf("local bus : %10u [cycles]\n", regs.local_bus);
}

443
src/debug/pspdebug.h Normal file
View File

@@ -0,0 +1,443 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* pspdebug.h - Prototypes for the pspDebug library
*
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
*
* $Id: pspdebug.h 2450 2009-01-04 23:53:02Z oopo $
*/
#ifndef __DEBUG_H__
#define __DEBUG_H__
#include <psptypes.h>
#include <pspmoduleinfo.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup Debug Debug Utility Library */
/** @addtogroup Debug */
/*@{*/
/**
* Initialise the debug screen
*/
void pspDebugScreenInit(void);
/**
* Extended debug screen init
*
* @param vram_base - Base address of frame buffer, if NULL then sets a default
* @param mode - Colour mode
* @param setup - Setup the screen if 1
*/
void pspDebugScreenInitEx(void *vram_base, int mode, int setup);
/**
* Do a printf to the debug screen.
*
* @param fmt - Format string to print
* @param ... - Arguments
*/
void pspDebugScreenPrintf(const char *fmt, ...) __attribute__((format(printf,1,2)));
/**
* Do a printf to the debug screen.
* @note This is for kernel mode only as it uses a kernel function
* to perform the printf instead of using vsnprintf, use normal printf for
* user mode.
*
* @param format - Format string to print
* @param ... - Arguments
*/
void pspDebugScreenKprintf(const char *format, ...) __attribute__((format(printf,1,2)));
/**
* Enable or disable background colour writing (defaults to enabled)
*
* @param enable - Set 1 to to enable background color, 0 for disable
*/
void pspDebugScreenEnableBackColor(int enable);
/**
* Set the background color for the text
* @note To reset the entire screens bg colour you need to call pspDebugScreenClear
*
* @param color - A 32bit RGB colour
*/
void pspDebugScreenSetBackColor(u32 color);
/**
* Set the text color
*
* @param color - A 32 bit RGB color
*/
void pspDebugScreenSetTextColor(u32 color);
/**
* Set the color mode (you must have switched the frame buffer appropriately)
*
* @param mode - Color mode
*/
void pspDebugScreenSetColorMode(int mode);
/**
* Draw a single character to the screen.
*
* @param x - The x co-ordinate to draw to (pixel units)
* @param y - The y co-ordinate to draw to (pixel units)
* @param color - The text color to draw
* @param ch - The character to draw
*/
void pspDebugScreenPutChar(int x, int y, u32 color, u8 ch);
/**
* Set the current X and Y co-ordinate for the screen (in character units)
*/
void pspDebugScreenSetXY(int x, int y);
/**
* Set the video ram offset used for the screen
*
* @param offset - Offset in bytes
*/
void pspDebugScreenSetOffset(int offset);
/**
* Set the video ram base used for the screen
*
* @param base - Base address in bytes
*/
void pspDebugScreenSetBase(u32* base);
/**
* Get the current X co-ordinate (in character units)
*
* @return The X co-ordinate
*/
int pspDebugScreenGetX(void);
/**
* Get the current Y co-ordinate (in character units)
*
* @return The Y co-ordinate
*/
int pspDebugScreenGetY(void);
/**
* Clear the debug screen.
*/
void pspDebugScreenClear(void);
/**
* Print non-nul terminated strings.
*
* @param buff - Buffer containing the text.
* @param size - Size of the data
*
* @return The number of characters written
*/
int pspDebugScreenPrintData(const char *buff, int size);
/**
* Print a string
*
* @param str - String
*
* @return The number of characters written
*/
int pspDebugScreenPuts(const char *str);
/**
* Get a MIPS stack trace (might work :P)
*
* @param results - List of points to store the results of the trace, (up to max)
* @param max - Maximum number of back traces
*
* @return The number of frames stored in results.
*/
int pspDebugGetStackTrace(unsigned int* results, int max);
/**
* Enable the clear line function that allows debug to clear the screen
*/
void pspDebugScreenClearLineEnable(void);
/**
* Disable the clear line function that causes flicker on constant refreshes
*/
void pspDebugScreenClearLineDisable(void);
/** Structure to hold the register data associated with an exception */
typedef struct _PspDebugRegBlock
{
u32 frame[6];
/** Array of the 32 GPRs */
u32 r[32];
/** The status register */
u32 status;
/** lo */
u32 lo;
u32 hi;
u32 badvaddr;
u32 cause;
u32 epc;
float fpr[32];
u32 fsr;
u32 fir;
u32 frame_ptr;
u32 unused;
/* Unused on PSP */
u32 index;
u32 random;
u32 entrylo0;
u32 entrylo1;
u32 context;
u32 pagemask;
u32 wired;
u32 cop0_7;
u32 cop0_8;
u32 cop0_9;
u32 entryhi;
u32 cop0_11;
u32 cop0_12;
u32 cop0_13;
u32 cop0_14;
/* PRId should still be okay */
u32 prid;
u32 padding[100];
} PspDebugRegBlock;
/** Defines a debug error handler */
typedef void (*PspDebugErrorHandler)(PspDebugRegBlock *regs);
/**
* Install an error handler to catch unhandled exceptions.
*
* @param handler - Pointer to a handler function. If set to NULL it will default
* to resetting the screen and dumping the error.
* @return < 0 on error
*/
int pspDebugInstallErrorHandler(PspDebugErrorHandler handler);
/**
* Dump an exception to screen using the pspDebugScreen functions.
* @note This function will not setup the screen for debug output, you should call sceDebugScreenInit
* before using it if it isn't already.
*
* @param regs - Pointer to a register block.
*
*/
void pspDebugDumpException(PspDebugRegBlock *regs);
/** Type for Kprintf handler */
typedef int (*PspDebugKprintfHandler)(const char *format, u32 *args);
/**
* Install a Kprintf handler into the system.
*
* @param handler - Function pointer to the handler.
* @return < 0 on error.
*/
int pspDebugInstallKprintfHandler(PspDebugKprintfHandler handler);
/** Structure to hold a single stack trace entry */
typedef struct _PspDebugStackTrace
{
/** The address which called the function */
u32 call_addr;
/** The address of the function called */
u32 func_addr;
} PspDebugStackTrace;
/**
* Do a stack trace from the current exception.
* @note This function really isn't too general purpose and it is more than likely to generate a few
* false positives but I consider that better then missing out calls entirely. You have to use your
* discretion, your code and a objdump to work out if some calls are completely surprious or not ;)
*
* @param regs - Pointer to a register block from an exception.
* @param trace - Pointer to an array of PspDebugStackTrace structures.
* @param max - The maximum number of traces to make.
*
* @return The number of functions found.
*/
int pspDebugGetStackTrace2(PspDebugRegBlock *regs, PspDebugStackTrace *trace, int max);
/** Structure to hold the psp profiler register values */
typedef struct _PspDebugProfilerRegs
{
volatile u32 enable;
volatile u32 systemck;
volatile u32 cpuck;
volatile u32 internal;
volatile u32 memory;
volatile u32 copz;
volatile u32 vfpu;
volatile u32 sleep;
volatile u32 bus_access;
volatile u32 uncached_load;
volatile u32 uncached_store;
volatile u32 cached_load;
volatile u32 cached_store;
volatile u32 i_miss;
volatile u32 d_miss;
volatile u32 d_writeback;
volatile u32 cop0_inst;
volatile u32 fpu_inst;
volatile u32 vfpu_inst;
volatile u32 local_bus;
} PspDebugProfilerRegs;
/** Enables the profiler hardware */
void pspDebugProfilerEnable(void);
/** Disables the profiler hardware */
void pspDebugProfilerDisable(void);
/** Clear the profiler registers */
void pspDebugProfilerClear(void);
/** Get the profiler register state
*
* @param regs - A pointer to a PspDebugProfilerRegs structure.
*/
void pspDebugProfilerGetRegs(PspDebugProfilerRegs *regs);
/** Print the profiler registers to screen */
void pspDebugProfilerPrint(void);
/** Type for the debug print handlers */
typedef int (*PspDebugPrintHandler)(const char *data, int len);
/** Type for the debug input handler */
typedef int (*PspDebugInputHandler)(char *data, int len);
/**
* Install a handler for stdin (so you can use normal stdio functions)
*
* @param handler - A pointer to input handler, NULL to disable.
*
* @return < 0 on error, else 0.
*/
int pspDebugInstallStdinHandler(PspDebugInputHandler handler);
/**
* Install a print handler for stdout (so you can use normal print functions)
*
* @param handler - A pointer to print handler, NULL to disable.
*
* @return < 0 on error, else 0.
*/
int pspDebugInstallStdoutHandler(PspDebugPrintHandler handler);
/**
* Install a print handler for stderr (so you can use normal print functions)
*
* @param handler - A pointer to print handler, NULL to disable.
*
* @return < 0 on error, else 0.
*/
int pspDebugInstallStderrHandler(PspDebugPrintHandler handler);
/**
* Put a character to the remote sio.
*
* @param ch - Character to write.
*/
void pspDebugSioPutchar(int ch);
/**
* Get a character from the remote sio
*
* @return The character read or -1 if no characters available.
*/
int pspDebugSioGetchar(void);
/**
* Write a string to the sio port.
*
* @param str - String to write.
*/
void pspDebugSioPuts(const char *str);
/**
* Write a set of data to the sio port
*
* @param data - Pointer to the data to send.
* @param len - Length of the data.
*
* @return Number of characters written.
*/
int pspDebugSioPutData(const char *data, int len);
/**
* Write a set of data to the sio port converting single
* line feeds to CRLF and single CR to CRLF
*
* @param data - Pointer to the data to send.
* @param len - Length of the data.
*
* @return Number of characters written.
*/
int pspDebugSioPutText(const char *data, int len);
/**
* Initialise the remote SIO port (defaults to 4800 8N1).
* @note will delay 2 seconds to wait for the power to come up.
*/
void pspDebugSioInit(void);
/**
* Set the baud rate of the SIO, e.g. 4800/9600..115200.
* @param baud - The baudrate to set.
*/
void pspDebugSioSetBaud(int baud);
/**
* Enable debug character output. Needs to be called in order
* for the default Kprintf handler to work.
*/
void pspDebugEnablePutchar(void);
/**
* Install a kprintf debug putchar handler. Implicitly calls ::pspDebugEnablePutchar
* so you do not need to call it explicitly. Sio must be initialised before calling
* this function however.
*/
void pspDebugSioInstallKprintf(void);
/**
* Install the gdb stub handler.
*/
void pspDebugGdbStubInit(void);
/**
* Generate a breakpoint exception.
*/
void pspDebugBreakpoint(void);
/**
* Enable the kprintf handler (once installed)
*/
void pspDebugSioEnableKprintf(void);
/**
* Disable the kprintf handler (once installed)
*/
void pspDebugSioDisableKprintf(void);
/*@}*/
#ifdef __cplusplus
}
#endif
#endif

292
src/debug/pspdebugkb.c Normal file
View File

@@ -0,0 +1,292 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* pspdebugkb.c - Simple screen debug keyboard
*
* Copyright (c) 2006 Mike Mallett <mike@nerdcore.net>
*
* $Id: pspdebugkb.c 2112 2006-12-22 10:53:20Z tyranid $
*/
#include <pspdebug.h>
#include <pspctrl.h>
#include <stdio.h>
#include <string.h>
#include "pspdebugkb.h"
static char loCharTable[PSP_DEBUG_KB_NUM_ROWS][PSP_DEBUG_KB_NUM_CHARS] = {
{ '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=' },
{ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\' },
{ '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\0' },
{ '\0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\0', '\0' }
};
static char hiCharTable[PSP_DEBUG_KB_NUM_ROWS][PSP_DEBUG_KB_NUM_CHARS] = {
{ '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+' },
{ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '|' },
{ '\0', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '\0' },
{ '\0', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0' }
};
static char *commandRow[] = { "Shift", "[ ]", "Back", "Clear", "Done" };
char charTable[PSP_DEBUG_KB_NUM_ROWS][PSP_DEBUG_KB_NUM_CHARS];
/* Switch charTable when Shift is pressed */
void pspDebugKbShift(int* shiftState) {
int i, j;
if (*shiftState != 0) {
for (i=0; i<PSP_DEBUG_KB_NUM_ROWS; i++) {
for (j=0; j<PSP_DEBUG_KB_NUM_CHARS; j++) {
charTable[i][j] = loCharTable[i][j];
}
}
*shiftState = 0;
} else {
for (i=0; i<PSP_DEBUG_KB_NUM_ROWS; i++) {
for (j=0; j<PSP_DEBUG_KB_NUM_CHARS; j++) {
charTable[i][j] = hiCharTable[i][j];
}
}
*shiftState = 1;
}
pspDebugKbDrawBox();
}
void pspDebugKbDrawKey(int row, int col, int highlight) {
int i;
int spacing = 0;
int charsTo = 0;
int charsTotal = 0;
if (highlight) {
pspDebugScreenSetTextColor(PSP_DEBUG_KB_CHAR_HIGHLIGHT);
pspDebugScreenSetBackColor(PSP_DEBUG_KB_BACK_HIGHLIGHT);
} else {
pspDebugScreenSetTextColor(PSP_DEBUG_KB_CHAR_COLOUR);
pspDebugScreenSetBackColor(PSP_DEBUG_KB_BACK_COLOUR);
}
if (row == PSP_DEBUG_KB_COMMAND_ROW) {
for (i=0; i<PSP_DEBUG_KB_NUM_COMMANDS; i++) {
charsTotal += strlen(commandRow[i]);
if (i < col) { charsTo += strlen(commandRow[i]); }
}
spacing = (PSP_DEBUG_KB_BOX_WIDTH - charsTotal) / (PSP_DEBUG_KB_NUM_COMMANDS + 1);
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + (spacing * (col + 1)) + charsTo, PSP_DEBUG_KB_BOX_Y + (PSP_DEBUG_KB_SPACING_Y * (row + 2)));
pspDebugScreenPrintf("%s", commandRow[col]);
} else {
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + PSP_DEBUG_KB_OFFSET_X + (PSP_DEBUG_KB_SPACING_X * col), PSP_DEBUG_KB_BOX_Y + (PSP_DEBUG_KB_SPACING_Y * (row + 2)));
if (charTable[row][col] == '\0') {
pspDebugScreenPrintf(" ");
} else {
pspDebugScreenPrintf("%c", charTable[row][col]);
}
}
}
void pspDebugKbClearBox() {
int i, j;
pspDebugScreenSetTextColor(PSP_DEBUG_KB_CHAR_COLOUR);
pspDebugScreenSetBackColor(PSP_DEBUG_KB_BACK_COLOUR);
for (i = PSP_DEBUG_KB_BOX_X; i <= PSP_DEBUG_KB_BOX_X + PSP_DEBUG_KB_BOX_WIDTH; i++) {
for (j = PSP_DEBUG_KB_BOX_Y; j <= PSP_DEBUG_KB_BOX_Y + PSP_DEBUG_KB_BOX_HEIGHT; j++) {
pspDebugScreenSetXY(i, j);
pspDebugScreenPrintf(" ");
}
}
}
void pspDebugKbDrawBox() {
int i, j;
pspDebugScreenSetTextColor(PSP_DEBUG_KB_CHAR_COLOUR);
pspDebugScreenSetBackColor(PSP_DEBUG_KB_BACK_COLOUR);
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X, PSP_DEBUG_KB_BOX_Y);
pspDebugScreenPrintf("+");
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X, PSP_DEBUG_KB_BOX_Y + PSP_DEBUG_KB_BOX_HEIGHT);
pspDebugScreenPrintf("+");
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + PSP_DEBUG_KB_BOX_WIDTH, PSP_DEBUG_KB_BOX_Y);
pspDebugScreenPrintf("+");
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + PSP_DEBUG_KB_BOX_WIDTH, PSP_DEBUG_KB_BOX_Y + PSP_DEBUG_KB_BOX_HEIGHT);
pspDebugScreenPrintf("+");
for (i = 1; i < PSP_DEBUG_KB_BOX_WIDTH; i++) {
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + i, PSP_DEBUG_KB_BOX_Y);
pspDebugScreenPrintf("-");
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + i, PSP_DEBUG_KB_BOX_Y + PSP_DEBUG_KB_BOX_HEIGHT);
pspDebugScreenPrintf("-");
}
for (i = 1; i < PSP_DEBUG_KB_BOX_HEIGHT; i++) {
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X, PSP_DEBUG_KB_BOX_Y + i);
pspDebugScreenPrintf("|");
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + PSP_DEBUG_KB_BOX_WIDTH, PSP_DEBUG_KB_BOX_Y + i);
pspDebugScreenPrintf("|");
}
for (i = 0; i < PSP_DEBUG_KB_NUM_ROWS; i++) {
for (j = 0; j < PSP_DEBUG_KB_NUM_CHARS; j++) {
pspDebugKbDrawKey(i, j, 0);
}
}
for (i = 0; i < PSP_DEBUG_KB_NUM_COMMANDS; i++) {
pspDebugKbDrawKey(PSP_DEBUG_KB_COMMAND_ROW, i, 0);
}
}
void pspDebugKbDrawString(char* str) {
int i;
pspDebugScreenSetTextColor(PSP_DEBUG_KB_CHAR_COLOUR);
pspDebugScreenSetBackColor(PSP_DEBUG_KB_BACK_COLOUR);
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + ((PSP_DEBUG_KB_BOX_WIDTH - PSP_DEBUG_KB_MAXLEN) / 2), PSP_DEBUG_KB_BOX_Y + 1);
for (i=0; i<PSP_DEBUG_KB_MAXLEN; i++) {
pspDebugScreenPrintf("_");
}
pspDebugScreenSetXY(PSP_DEBUG_KB_BOX_X + ((PSP_DEBUG_KB_BOX_WIDTH - PSP_DEBUG_KB_MAXLEN) / 2), PSP_DEBUG_KB_BOX_Y + 1);
pspDebugScreenPrintf("%s", str);
}
void pspDebugKbInit(char* str) {
int row = PSP_DEBUG_KB_COMMAND_ROW;
int col = PSP_DEBUG_KB_NUM_COMMANDS - 1;
int shifted = 1;
int inputDelay = 200000;
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);
SceCtrlData input, lastinput;
sceCtrlReadBufferPositive(&input, 1);
sceCtrlReadBufferPositive(&lastinput, 1);
unsigned int inputTime = input.TimeStamp;
pspDebugKbClearBox();
// Initialize charTable
pspDebugKbShift(&shifted);
pspDebugKbDrawBox();
pspDebugKbDrawKey(row, col, 1);
pspDebugKbDrawString(str);
while (1) {
sceCtrlReadBufferPositive(&input, 1);
if (input.Buttons & PSP_CTRL_LEFT && col > 0
&& (row == PSP_DEBUG_KB_COMMAND_ROW || charTable[row][col - 1])
&& (input.Buttons != lastinput.Buttons || input.TimeStamp >= inputTime + inputDelay)) {
// Unhighlight the old character
pspDebugKbDrawKey(row, col, 0);
// Print the new character highlighted
pspDebugKbDrawKey(row, --col, 1);
// Update inputTime
inputTime = input.TimeStamp;
}
if (input.Buttons & PSP_CTRL_RIGHT
&& ((row == PSP_DEBUG_KB_COMMAND_ROW && col < PSP_DEBUG_KB_NUM_COMMANDS - 1)
|| (row != PSP_DEBUG_KB_COMMAND_ROW && col < PSP_DEBUG_KB_NUM_CHARS - 1
&& charTable[row][col + 1]))
&& (input.Buttons != lastinput.Buttons || input.TimeStamp >= inputTime + inputDelay)) {
pspDebugKbDrawKey(row, col, 0);
pspDebugKbDrawKey(row, ++col, 1);
inputTime = input.TimeStamp;
}
if (input.Buttons & PSP_CTRL_UP && row > 0
&& (input.Buttons != lastinput.Buttons || input.TimeStamp >= inputTime + inputDelay)) {
if (row == PSP_DEBUG_KB_COMMAND_ROW) {
pspDebugKbDrawKey(row, col, 0);
if (col == PSP_DEBUG_KB_NUM_COMMANDS - 1) {
col = PSP_DEBUG_KB_NUM_CHARS - 1;
} else {
col = (col * (PSP_DEBUG_KB_NUM_CHARS - 1)) / (PSP_DEBUG_KB_NUM_COMMANDS - 1);
}
do {
row--;
} while (charTable[row][col] == '\0' && row > 0);
pspDebugKbDrawKey(row, col, 1);
} else if (charTable[row - 1][col]) {
pspDebugKbDrawKey(row, col, 0);
pspDebugKbDrawKey(--row, col, 1);
}
inputTime = input.TimeStamp;
}
if (input.Buttons & PSP_CTRL_DOWN && row != PSP_DEBUG_KB_COMMAND_ROW
&& (input.Buttons != lastinput.Buttons || input.TimeStamp >= inputTime + inputDelay)) {
pspDebugKbDrawKey(row, col, 0);
do {
row++;
} while (charTable[row][col] == '\0' &&
row != PSP_DEBUG_KB_COMMAND_ROW);
if (row == PSP_DEBUG_KB_COMMAND_ROW) {
col = (col * (PSP_DEBUG_KB_NUM_COMMANDS - 1)) / (PSP_DEBUG_KB_NUM_CHARS - 1);
}
pspDebugKbDrawKey(row, col, 1);
inputTime = input.TimeStamp;
}
if (input.Buttons != lastinput.Buttons && input.Buttons & PSP_CTRL_SELECT) {
pspDebugKbShift(&shifted);
pspDebugKbDrawKey(row, col, 1);
}
if (input.Buttons != lastinput.Buttons
&& (input.Buttons & PSP_CTRL_CROSS || input.Buttons & PSP_CTRL_CIRCLE)) {
if (row == PSP_DEBUG_KB_COMMAND_ROW) {
switch(col) {
case 0: // Shift
pspDebugKbShift(&shifted);
pspDebugKbDrawKey(row, col, 1);
break;
case 1: // Space
if (strlen(str) < PSP_DEBUG_KB_MAXLEN) {
snprintf(str, strlen(str)+2, "%s ", str);
pspDebugKbDrawString(str);
}
break;
case 2: // Back
if (strlen(str) > 0) {
str[strlen(str)-1] = '\0';
pspDebugKbDrawString(str);
}
break;
case 3: // Clear
bzero(str, PSP_DEBUG_KB_MAXLEN);
pspDebugKbDrawString(str);
break;
case 4:
// Clean up the screen
pspDebugKbClearBox();
return;
};
} else {
if (strlen(str) < PSP_DEBUG_KB_MAXLEN) {
snprintf(str, strlen(str)+2, "%s%c", str, charTable[row][col]);
pspDebugKbDrawString(str);
}
}
}
if (input.Buttons != lastinput.Buttons
&& (input.Buttons & PSP_CTRL_TRIANGLE || input.Buttons & PSP_CTRL_SQUARE)) {
if (strlen(str) > 0) {
str[strlen(str)-1] = '\0';
pspDebugKbDrawString(str);
}
}
lastinput = input;
}
}

96
src/debug/pspdebugkb.h Normal file
View File

@@ -0,0 +1,96 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* pspdebugkb.h - Simple screen debug keyboard
*
* Copyright (c) 2006 Mike Mallett <mike@nerdcore.net>
*
* $Id: pspdebugkb.h 2110 2006-12-19 14:50:27Z tyranid $
*/
#ifndef __PSPDEBUGKB_H
#define __PSPDEBUGKB_H
#ifdef __cplusplus
extern "C" {
#endif
enum PspDebugKbSettings {
/** Maximum string length */
PSP_DEBUG_KB_MAXLEN = 40,
/** Place the box' upper-left corner at this location */
PSP_DEBUG_KB_BOX_X = 6,
PSP_DEBUG_KB_BOX_Y = 8,
/** FG and BG colour of unhighlighted characters */
PSP_DEBUG_KB_CHAR_COLOUR = 0xffffffff,
PSP_DEBUG_KB_BACK_COLOUR = 0xff000000,
/** FG and BG colour of highlighted character */
PSP_DEBUG_KB_CHAR_HIGHLIGHT = 0xff00ff00,
PSP_DEBUG_KB_BACK_HIGHLIGHT = 0xff101010,
/** Indent the printed characters by (X_OFFSET,Y_OFFSET) */
PSP_DEBUG_KB_OFFSET_X = 6,
PSP_DEBUG_KB_OFFSET_Y = 4,
/** Distance from one character to the next */
PSP_DEBUG_KB_SPACING_X = 3,
PSP_DEBUG_KB_SPACING_Y = 2,
/** Number of columns/rows (respectively) in charTable(s) */
PSP_DEBUG_KB_NUM_CHARS = 13,
PSP_DEBUG_KB_NUM_ROWS = 4,
/** Box width and height */
PSP_DEBUG_KB_BOX_WIDTH = (PSP_DEBUG_KB_NUM_CHARS * PSP_DEBUG_KB_SPACING_X) + (2 * PSP_DEBUG_KB_OFFSET_X),
PSP_DEBUG_KB_BOX_HEIGHT = ((PSP_DEBUG_KB_NUM_ROWS + 1) * PSP_DEBUG_KB_SPACING_Y) + PSP_DEBUG_KB_OFFSET_Y,
/** Array index of commandRow */
PSP_DEBUG_KB_COMMAND_ROW = 4,
/** Number of commands on bottom row */
PSP_DEBUG_KB_NUM_COMMANDS = 5
};
/**
* Switch charTable when SHIFT is pressed
*
* @param shiftState - Pointer to an int indicating Caps Lock
*/
void pspDebugKbShift(int *shiftState);
/**
* Draw the specified key on the keyboard.
*
* @param row - The row of the character to print (in charTable)
* @param col - The column of the character to print (in charTable)
* @param highlight - 0 for plain; otherwise highlighted
*/
void pspDebugKbDrawKey(int row, int col, int highlight);
/**
* Draw the string at the top of the box
*
* @param str - The string to print
*/
void pspDebugKbDrawString(char *str);
/**
* Clear the area where the box resides.
* Called from pspDebugKbDrawBox and pspDebugKbInit (on exit).
*/
void pspDebugKbClearBox();
/**
* Draw the entire box on the desbug screen.
* Called from shift() and doInputBox(char*)
*/
void pspDebugKbDrawBox();
/**
* Make the text box happen
*
* @param str - The string to edit
*/
void pspDebugKbInit(char *str);
#ifdef __cplusplus
}
#endif
#endif

478
src/debug/scr_printf.c Normal file
View File

@@ -0,0 +1,478 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* scr_printf.c - Debug screen functions.
*
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
*
* $Id: scr_printf.c 2450 2009-01-04 23:53:02Z oopo $
*/
#include <stdio.h>
#include <psptypes.h>
#include <pspkernel.h>
#include <pspdisplay.h>
#include <pspsysclib.h>
#include <pspge.h>
#include <stdarg.h>
#include <pspdebug.h>
#include <string.h>
#define PSP_SCREEN_WIDTH 480
#define PSP_SCREEN_HEIGHT 272
#define PSP_LINE_SIZE 512
/* baseado nas libs do Duke... */
#ifdef F_pspDebugScreenInit
void _pspDebugScreenClearLine( int Y);
static int X = 0, Y = 0;
static int MX=68, MY=34;
static u32 bg_col = 0, fg_col = 0xFFFFFFFF;
static int bg_enable = 1;
static void* g_vram_base = (u32 *) 0x04000000;
static int g_vram_offset = 0;
static int g_vram_mode = PSP_DISPLAY_PIXEL_FORMAT_8888;
static int init = 0;
static int clearline_en = 1;
static u16 convert_8888_to_565(u32 color)
{
int r, g, b;
b = (color >> 19) & 0x1F;
g = (color >> 10) & 0x3F;
r = (color >> 3) & 0x1F;
return r | (g << 5) | (b << 11);
}
static u16 convert_8888_to_5551(u32 color)
{
int r, g, b, a;
a = (color >> 24) ? 0x8000 : 0;
b = (color >> 19) & 0x1F;
g = (color >> 11) & 0x1F;
r = (color >> 3) & 0x1F;
return a | r | (g << 5) | (b << 10);
}
static u16 convert_8888_to_4444(u32 color)
{
int r, g, b, a;
a = (color >> 28) & 0xF;
b = (color >> 20) & 0xF;
g = (color >> 12) & 0xF;
r = (color >> 4) & 0xF;
return (a << 12) | r | (g << 4) | (b << 8);
}
static void clear_screen_16(u16 color)
{
int x;
u16 *vram = g_vram_base;
vram += (g_vram_offset >> 1);
for(x = 0; x < (PSP_LINE_SIZE * PSP_SCREEN_HEIGHT); x++)
{
*vram++ = color;
}
}
static void clear_screen_32(u32 color)
{
int x;
u32 *vram = g_vram_base;
vram += (g_vram_offset>>2);
for(x = 0; x < (PSP_LINE_SIZE * PSP_SCREEN_HEIGHT); x++)
{
*vram++ = color;
}
}
static void clear_screen(u32 color)
{
if(g_vram_mode == PSP_DISPLAY_PIXEL_FORMAT_8888)
{
clear_screen_32(color);
}
else
{
u16 c = 0;
switch(g_vram_mode)
{
case PSP_DISPLAY_PIXEL_FORMAT_565: c = convert_8888_to_565(color);
break;
case PSP_DISPLAY_PIXEL_FORMAT_5551: c = convert_8888_to_5551(color);
break;
case PSP_DISPLAY_PIXEL_FORMAT_4444: c = convert_8888_to_4444(color);
break;
};
clear_screen_16(c);
}
}
void pspDebugScreenInitEx(void *vram_base, int mode, int setup)
{
switch(mode)
{
case PSP_DISPLAY_PIXEL_FORMAT_565:
case PSP_DISPLAY_PIXEL_FORMAT_5551:
case PSP_DISPLAY_PIXEL_FORMAT_4444:
case PSP_DISPLAY_PIXEL_FORMAT_8888:
break;
default: mode = PSP_DISPLAY_PIXEL_FORMAT_8888;
};
X = Y = 0;
/* Place vram in uncached memory */
if(vram_base == NULL)
{
vram_base = (void*) (0x40000000 | (u32) sceGeEdramGetAddr());
}
g_vram_base = vram_base;
g_vram_offset = 0;
g_vram_mode = mode;
if(setup)
{
sceDisplaySetMode(0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
sceDisplaySetFrameBuf((void *) g_vram_base, PSP_LINE_SIZE, mode, 1);
}
clear_screen(bg_col);
init = 1;
}
void pspDebugScreenInit()
{
X = Y = 0;
pspDebugScreenInitEx(NULL, PSP_DISPLAY_PIXEL_FORMAT_8888, 1);
}
void pspDebugScreenEnableBackColor(int enable)
{
bg_enable = enable;
}
void pspDebugScreenSetBackColor(u32 colour)
{
bg_col = colour;
}
void pspDebugScreenSetTextColor(u32 colour)
{
fg_col = colour;
}
void pspDebugScreenSetColorMode(int mode)
{
switch(mode)
{
case PSP_DISPLAY_PIXEL_FORMAT_565:
case PSP_DISPLAY_PIXEL_FORMAT_5551:
case PSP_DISPLAY_PIXEL_FORMAT_4444:
case PSP_DISPLAY_PIXEL_FORMAT_8888:
break;
default: mode = PSP_DISPLAY_PIXEL_FORMAT_8888;
};
g_vram_mode = mode;
}
int pspDebugScreenGetX()
{
return X;
}
int pspDebugScreenGetY()
{
return Y;
}
void pspDebugScreenClear()
{
int y;
if(!init)
{
return;
}
for(y=0;y<MY;y++)
{
_pspDebugScreenClearLine(y);
}
pspDebugScreenSetXY(0,0);
clear_screen(bg_col);
}
void pspDebugScreenSetXY(int x, int y)
{
if( x<MX && x>=0 ) X=x;
if( y<MY && y>=0 ) Y=y;
}
void pspDebugScreenSetOffset(int offset)
{
g_vram_offset = offset;
}
void pspDebugScreenSetBase(u32* base)
{
g_vram_base = base;
}
extern u8 msx[];
static void debug_put_char_32(int x, int y, u32 color, u32 bgc, u8 ch)
{
int i,j, l;
u8 *font;
u32 *vram_ptr;
u32 *vram;
if(!init)
{
return;
}
vram = g_vram_base;
vram += (g_vram_offset >> 2) + x;
vram += (y * PSP_LINE_SIZE);
font = &msx[ (int)ch * 8];
for (i=l=0; i < 8; i++, l+= 8, font++)
{
vram_ptr = vram;
for (j=0; j < 8; j++)
{
if ((*font & (128 >> j)))
*vram_ptr = color;
else if(bg_enable)
*vram_ptr = bgc;
vram_ptr++;
}
vram += PSP_LINE_SIZE;
}
}
static void debug_put_char_16(int x, int y, u16 color, u16 bgc, u8 ch)
{
int i,j, l;
u8 *font;
u16 *vram_ptr;
u16 *vram;
if(!init)
{
return;
}
vram = g_vram_base;
vram += (g_vram_offset >> 1) + x;
vram += (y * PSP_LINE_SIZE);
font = &msx[ (int)ch * 8];
for (i=l=0; i < 8; i++, l+= 8, font++)
{
vram_ptr = vram;
for (j=0; j < 8; j++)
{
if ((*font & (128 >> j)))
*vram_ptr = color;
else if(bg_enable)
*vram_ptr = bgc;
vram_ptr++;
}
vram += PSP_LINE_SIZE;
}
}
void
pspDebugScreenPutChar( int x, int y, u32 color, u8 ch)
{
if(g_vram_mode == PSP_DISPLAY_PIXEL_FORMAT_8888)
{
debug_put_char_32(x, y, color, bg_col, ch);
}
else
{
u16 c = 0;
u16 b = 0;
switch(g_vram_mode)
{
case PSP_DISPLAY_PIXEL_FORMAT_565: c = convert_8888_to_565(color);
b = convert_8888_to_565(bg_col);
break;
case PSP_DISPLAY_PIXEL_FORMAT_5551: c = convert_8888_to_5551(color);
b = convert_8888_to_5551(bg_col);
break;
case PSP_DISPLAY_PIXEL_FORMAT_4444: c = convert_8888_to_4444(color);
b = convert_8888_to_4444(bg_col);
break;
};
debug_put_char_16(x, y, c, b, ch);
}
}
void _pspDebugScreenClearLine( int Y)
{
if(clearline_en)
{
int i;
if(bg_enable)
{
for (i=0; i < MX; i++)
{
pspDebugScreenPutChar( i*7 , Y * 8, bg_col, 219);
}
}
}
return;
}
void pspDebugScreenClearLineEnable(void)
{
clearline_en = 1;
return;
}
void pspDebugScreenClearLineDisable(void)
{
clearline_en = 0;
return;
}
/* Print non-nul terminated strings */
int pspDebugScreenPrintData(const char *buff, int size)
{
int i;
int j;
char c;
if(!init)
{
return 0;
}
for (i = 0; i < size; i++)
{
c = buff[i];
switch (c)
{
case '\r':
X = 0;
break;
case '\n':
X = 0;
Y ++;
if (Y == MY)
Y = 0;
_pspDebugScreenClearLine(Y);
break;
case '\t':
for (j = 0; j < 5; j++) {
pspDebugScreenPutChar( X*7 , Y * 8, fg_col, ' ');
X++;
}
break;
default:
pspDebugScreenPutChar( X*7 , Y * 8, fg_col, c);
X++;
if (X == MX)
{
X = 0;
Y++;
if (Y == MY)
Y = 0;
_pspDebugScreenClearLine(Y);
}
}
}
return i;
}
int pspDebugScreenPuts(const char *str)
{
return pspDebugScreenPrintData(str, strlen(str));
}
#endif
#ifdef F_pspDebugScreenPrintf
void pspDebugScreenPrintf(const char *format, ...)
{
va_list opt;
char buff[2048];
int bufsz;
va_start(opt, format);
bufsz = vsnprintf( buff, (size_t) sizeof(buff), format, opt);
(void) pspDebugScreenPrintData(buff, bufsz);
}
#endif
/* Kernel screen printf, uses the prnt function instead of vsnprintf */
#ifdef F_pspDebugScreenKprintf
#define MAX_CLI 4096
#define CTX_BUF_SIZE 128
struct prnt_ctx
{
unsigned short len;
char buf[CTX_BUF_SIZE];
};
static void cb(struct prnt_ctx *ctx, int type)
{
if(type == 0x200)
{
ctx->len = 0;
}
else if(type == 0x201)
{
pspDebugScreenPrintData(ctx->buf, ctx->len);
ctx->len = 0;
}
else
{
if(type != '\r')
{
ctx->buf[ctx->len++] = type;
if(ctx->len == CTX_BUF_SIZE)
{
pspDebugScreenPrintData(ctx->buf, ctx->len);
ctx->len = 0;
}
}
}
}
void pspDebugScreenKprintf(const char *format, ...)
{
struct prnt_ctx ctx;
va_list opt;
ctx.len = 0;
va_start(opt, format);
prnt((prnt_callback) cb, (void*) &ctx, format, opt);
va_end(opt);
}
#endif

178
src/debug/sio.c Normal file
View File

@@ -0,0 +1,178 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* sio.c - Some basic SIO (remote port) functions.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: sio.c 2152 2007-01-27 10:09:15Z tyranid $
*/
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsyscon.h>
/* Define some important parameters, not really sure on names. Probably doesn't matter */
#define PSP_UART4_FIFO 0xBE500000
#define PSP_UART4_STAT 0xBE500018
#define PSP_UART4_DIV1 0xBE500024
#define PSP_UART4_DIV2 0xBE500028
#define PSP_UART4_CTRL 0xBE50002C
#define PSP_UART_CLK 96000000
#define PSP_UART_TXFULL 0x20
#define PSP_UART_RXEMPTY 0x10
static int g_enablekprintf = 0;
/* Some function prototypes we will need */
int sceHprmEnd(void);
int sceSysregUartIoEnable(int uart);
extern u32 sceKernelRemoveByDebugSection;
void pspDebugSioPutchar(int ch)
{
while(_lw(PSP_UART4_STAT) & PSP_UART_TXFULL);
_sw(ch, PSP_UART4_FIFO);
}
int pspDebugSioGetchar(void)
{
if(_lw(PSP_UART4_STAT) & PSP_UART_RXEMPTY)
{
return -1;
}
return _lw(PSP_UART4_FIFO);
}
void pspDebugSioPuts(const char *str)
{
while(*str)
{
pspDebugSioPutchar(*str);
str++;
}
pspDebugSioPutchar('\r');
pspDebugSioPutchar('\n');
}
int pspDebugSioPutData(const char *data, int len)
{
int i;
for(i = 0; i < len; i++)
{
pspDebugSioPutchar(data[i]);
}
return len;
}
/* Put data to SIO converting any line feeds as necessary */
int pspDebugSioPutText(const char *data, int len)
{
int i;
for(i = 0; i < len; i++)
{
/* If just line feed add a carriage return */
if(data[i] == '\n')
{
if(((i > 0) && (data[i-1] != '\r')) || (i == 0))
{
pspDebugSioPutchar('\r');
}
}
pspDebugSioPutchar(data[i]);
if((i < (len - 1)) && (data[i] == '\r') && (data[i+1] != '\n'))
{
pspDebugSioPutchar('\n');
}
}
return len;
}
void pspDebugSioSetBaud(int baud)
{
int div1, div2;
/* rate set using the rough formula div1 = (PSP_UART_CLK / baud) >> 6 and
* div2 = (PSP_UART_CLK / baud) & 0x3F
* The uart4 driver actually uses a slightly different formula for div 2 (it
* adds 32 before doing the AND, but it doesn't seem to make a difference
*/
div1 = PSP_UART_CLK / baud;
div2 = div1 & 0x3F;
div1 >>= 6;
_sw(div1, PSP_UART4_DIV1);
_sw(div2, PSP_UART4_DIV2);
_sw(0x60, PSP_UART4_CTRL);
}
void pspDebugSioInit(void)
{
/* Shut down the remote driver */
sceHprmEnd();
/* Enable UART 4 */
sceSysregUartIoEnable(4);
/* Enable remote control power */
sceSysconCtrlHRPower(1);
/* Delay thread for a but */
sceKernelDelayThread(2000000);
}
static u32 *get_debug_register(void)
{
u32 *pData;
u32 ptr;
pData = (u32 *) (0x80000000 | ((sceKernelRemoveByDebugSection & 0x03FFFFFF) << 2));
ptr = ((pData[0] & 0xFFFF) << 16) + (short) (pData[2] & 0xFFFF);
return (u32 *) ptr;
}
void pspDebugEnablePutchar(void)
{
u32 *pData;
pData = get_debug_register();
*pData |= 0x1000;
}
static void PutCharDebug(unsigned short *data, unsigned int type)
{
if(((type & 0xFF00) == 0) && (g_enablekprintf))
{
if(type == '\n')
{
pspDebugSioPutchar('\r');
}
pspDebugSioPutchar(type);
}
}
void pspDebugSioInstallKprintf(void)
{
pspDebugEnablePutchar();
sceKernelRegisterDebugPutchar(PutCharDebug);
g_enablekprintf = 1;
}
void pspDebugSioEnableKprintf(void)
{
g_enablekprintf = 1;
}
void pspDebugSioDisableKprintf(void)
{
g_enablekprintf = 0;
}

111
src/debug/stacktrace.c Normal file
View File

@@ -0,0 +1,111 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* callstack.c - Return stack generation for MIPS processors.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: stacktrace.c 1095 2005-09-27 21:02:16Z jim $
*/
#include <pspkernel.h>
#include <pspdebug.h>
#include <string.h>
#define CALL 0x0C000000
#define CALL_MASK 0xFC000000
#define IS_CALL(x) (((x) & CALL_MASK) == CALL)
#define CALL_ADDR(x) (((x) & ~CALL_MASK) << 2)
extern u32 _ftext;
extern u32 _etext;
/* Ideally should be something which is automatic */
#define ELF_START (&_ftext)
#define ELF_END (&_etext)
/* This is a blatently wrong way of doing a stack trace, but I felt as long as you use some intelligence you
could easily work out if some calls in the trace were invalid :P */
static int _pspDebugDoStackTrace(u32 *sp, u32 *sp_end, u32 *ra, PspDebugStackTrace *trace, int max)
{
int count = 0;
int recurse = 0;
if((ra >= (ELF_START + 2)) && (ra < ELF_END) && (IS_CALL(ra[-2])))
{
trace[count].func_addr = CALL_ADDR(ra[-2]);
trace[count].call_addr = (u32) (&ra[-2]);
count++;
}
while((count < max) && (sp < sp_end))
{
u32 *addr;
/* Try and find all the pointers on the stack, then see if they are within range
and point to a valid return address. There is possible false positives with this
but tbh it is better than nothing */
addr = (u32*) *sp;
/* Check that the address could possibly be a valid ra address */
if((addr >= (ELF_START + 2)) && (addr < ELF_END))
{
if(IS_CALL(addr[-2]))
{
if((count == 1) && (addr == ra) && (!recurse))
{
/* Set recurse to 1 so any further calls from ra will be caught */
/* This is not ideal, but it is to try and prevent the more likely case
of the first ra being found on the stack when first parsing */
recurse = 1;
}
else
{
trace[count].func_addr = CALL_ADDR(addr[-2]);
trace[count].call_addr = (u32) (&addr[-2]);
count++;
}
}
}
sp++;
}
return count;
}
int pspDebugGetStackTrace2(PspDebugRegBlock *regs, PspDebugStackTrace *trace, int max)
{
u32 *curr_sp;
u32 *sp_end;
u32 *curr_ra;
int curr_thid;
int count = 0;
SceKernelThreadInfo th_stat;
/* This is a real simple (and dirty way) of getting a stack trace, none of this code following shitz */
/* Relies on the system not being totally vaporised on an exception */
if((trace == NULL) || (max < 1))
{
return 0;
}
curr_thid = sceKernelGetThreadId();
if(curr_thid >= 0)
{
memset(&th_stat, 0, sizeof(th_stat));
th_stat.size = sizeof(th_stat);
if(sceKernelReferThreadStatus(curr_thid, &th_stat) >= 0)
{
sp_end = (u32*) ((u8*) th_stat.stack + th_stat.stackSize);
curr_sp = (u32*) (regs->r[29] & ~3);
curr_ra = (u32*) (regs->r[31]);
count = _pspDebugDoStackTrace(curr_sp, sp_end, curr_ra, trace, max);
}
}
return count;
}

291
src/debug/stdio.c Normal file
View File

@@ -0,0 +1,291 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* stdio.c - Debug functions to enable stdout and stderr handlers
*
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
*
* $Id: stdio.c 1925 2006-05-29 14:22:53Z tyranid $
*/
#include <pspkernel.h>
#include <pspdebug.h>
#include <unistd.h>
#define dbgprintf pspDebugScreenPrintf
static int g_initialised = 0;
static PspDebugInputHandler g_stdin_handler = NULL;
static PspDebugPrintHandler g_stdout_handler = NULL;
static PspDebugPrintHandler g_stderr_handler = NULL;
static SceUID g_in_sema = 0;
/* Probably stdout and stderr should not be guarded by the same mutex */
static SceUID g_out_sema = 0;
static int io_init(PspIoDrvArg *arg)
{
return 0;
}
static int io_exit(PspIoDrvArg *arg)
{
return 0;
}
static int io_open(PspIoDrvFileArg *arg, char *file, int mode, SceMode mask)
{
if((arg->fs_num != STDIN_FILENO) && (arg->fs_num != STDOUT_FILENO) && (arg->fs_num != STDERR_FILENO))
{
return SCE_KERNEL_ERROR_NOFILE;
}
return 0;
}
static int io_close(PspIoDrvFileArg *arg)
{
return 0;
}
static int io_read(PspIoDrvFileArg *arg, char *data, int len)
{
int ret = 0;
(void) sceKernelWaitSema(g_in_sema, 1, 0);
if((arg->fs_num == STDIN_FILENO) && (g_stdin_handler != NULL))
{
ret = g_stdin_handler(data, len);
}
(void) sceKernelSignalSema(g_in_sema, 1);
return ret;
}
static int io_write(PspIoDrvFileArg *arg, const char *data, int len)
{
int ret = 0;
(void) sceKernelWaitSema(g_out_sema, 1, 0);
if((arg->fs_num == STDOUT_FILENO) && (g_stdout_handler != NULL))
{
ret = g_stdout_handler(data, len);
}
else if((arg->fs_num == STDERR_FILENO) && (g_stderr_handler != NULL))
{
ret = g_stderr_handler(data, len);
}
(void) sceKernelSignalSema(g_out_sema, 1);
return ret;
}
static SceOff io_lseek(PspIoDrvFileArg *arg, SceOff ofs, int whence)
{
return 0;
}
static int io_ioctl(PspIoDrvFileArg *arg, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen)
{
return 0;
}
static int io_remove(PspIoDrvFileArg *arg, const char *name)
{
return 0;
}
static int io_mkdir(PspIoDrvFileArg *arg, const char *name, SceMode mode)
{
return 0;
}
static int io_rmdir(PspIoDrvFileArg *arg, const char *name)
{
return 0;
}
static int io_dopen(PspIoDrvFileArg *arg, const char *dir)
{
return 0;
}
static int io_dclose(PspIoDrvFileArg *arg)
{
return 0;
}
static int io_dread(PspIoDrvFileArg *arg, SceIoDirent *dir)
{
return 0;
}
static int io_getstat(PspIoDrvFileArg *arg, const char *file, SceIoStat *stat)
{
return 0;
}
static int io_chstat(PspIoDrvFileArg *arg, const char *file, SceIoStat *stat, int bits)
{
return 0;
}
static int io_rename(PspIoDrvFileArg *arg, const char *oldname, const char *newname)
{
return 0;
}
static int io_chdir(PspIoDrvFileArg *arg, const char *dir)
{
return 0;
}
static int io_mount(PspIoDrvFileArg *arg)
{
return 0;
}
static int io_umount(PspIoDrvFileArg *arg)
{
return 0;
}
static int io_devctl(PspIoDrvFileArg *arg, const char *devname, unsigned int cmd, void *indata, int inlen, void *outdata, int outlen)
{
return 0;
}
static int io_unknown(PspIoDrvFileArg *arg)
{
return 0;
}
static PspIoDrvFuncs tty_funcs =
{
io_init,
io_exit,
io_open,
io_close,
io_read,
io_write,
io_lseek,
io_ioctl,
io_remove,
io_mkdir,
io_rmdir,
io_dopen,
io_dclose,
io_dread,
io_getstat,
io_chstat,
io_rename,
io_chdir,
io_mount,
io_umount,
io_devctl,
io_unknown,
};
static PspIoDrv tty_driver =
{
"tty", 0x10, 0x800, "TTY", &tty_funcs
};
static int tty_init(void)
{
int ret;
(void) sceIoDelDrv("tty"); /* Ignore error */
ret = sceIoAddDrv(&tty_driver);
if(ret < 0)
{
return ret;
}
g_in_sema = sceKernelCreateSema("TtyInMutex", 0, 1, 1, NULL);
if(g_in_sema < 0)
{
return g_in_sema;
}
g_out_sema = sceKernelCreateSema("TtyOutMutex", 0, 1, 1, NULL);
if(g_out_sema < 0)
{
return g_out_sema;
}
ret = sceIoReopen("tty0:", PSP_O_RDONLY, 0777, sceKernelStdin());
if(ret < 0)
{
return ret;
}
ret = sceKernelStdoutReopen("tty1:", PSP_O_WRONLY, 0777);
if(ret < 0)
{
return ret;
}
ret = sceKernelStderrReopen("tty2:", PSP_O_WRONLY, 0777);
if(ret < 0)
{
return ret;
}
g_initialised = 1;
return 0;
}
int pspDebugInstallStdinHandler(PspDebugInputHandler handler)
{
if(g_initialised == 0)
{
int ret;
ret = tty_init();
if(ret < 0)
{
return ret;
}
}
g_stdin_handler = handler;
return 0;
}
int pspDebugInstallStdoutHandler(PspDebugPrintHandler handler)
{
if(g_initialised == 0)
{
int ret;
ret = tty_init();
if(ret < 0)
{
return ret;
}
}
g_stdout_handler = handler;
return 0;
}
int pspDebugInstallStderrHandler(PspDebugPrintHandler handler)
{
if(g_initialised == 0)
{
int ret;
ret = tty_init();
if(ret < 0)
{
return ret;
}
}
g_stderr_handler = handler;
return 0;
}