diff options
| author | lameguy64 <lameguy64@github.com> | 2024-05-04 18:55:05 +0800 |
|---|---|---|
| committer | lameguy64 <lameguy64@github.com> | 2024-05-04 18:55:05 +0800 |
| commit | 702bb601fb5712e2ae962a34b89204c646fe98f5 (patch) | |
| tree | 765f400d1535d37c5ff4df61d01229a7dc7d8207 /indev/psn00bdbg-mk2/testutil | |
| parent | 00abe5963fbead092f91935b90390aa5a9111c43 (diff) | |
| download | psn00bsdk-702bb601fb5712e2ae962a34b89204c646fe98f5.tar.gz | |
Included PSn00bDBG-mk2 monitor and test utility
Diffstat (limited to 'indev/psn00bdbg-mk2/testutil')
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/cmdefs.h | 36 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/comms.c | 817 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/exec.c | 413 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/exec.h | 24 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/main.c | 131 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/main.h | 38 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/makefile | 31 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/makefile-linux | 11 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/mips_disassembler.c | 663 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/mips_disassembler.h | 10 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/prompt.c | 518 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/pstypes.h | 81 | ||||
| -rw-r--r-- | indev/psn00bdbg-mk2/testutil/serial.c | 273 |
13 files changed, 3046 insertions, 0 deletions
diff --git a/indev/psn00bdbg-mk2/testutil/cmdefs.h b/indev/psn00bdbg-mk2/testutil/cmdefs.h new file mode 100644 index 0000000..82e57e9 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/cmdefs.h @@ -0,0 +1,36 @@ +#ifndef _CMDEFS_H
+#define _CMDEFS_H
+
+/* status values */
+
+#define DB_STAT_STOP 0 /* target is stopped */
+#define DB_STAT_BREAK 1 /* breakpoint (not by break opcodes ) */
+#define DB_STAT_EXCEPT 2 /* unhandled exception */
+#define DB_STAT_RUN 3 /* target is running */
+
+/* general commands */
+
+#define CMD_REBOOT 0xA0 /* soft reboot console */
+
+/* debug and execution commands */
+
+#define CMD_DB_GETSTAT 0xD0 /* get target status */
+#define CMD_DB_GETINFO 0xD1 /* get debug monitor info */
+#define CMD_DB_SETEXEC 0xD2 /* execution control */
+#define CMD_DB_RUNTO 0xD3 /* run to address */
+#define CMD_DB_SETBRK 0xD4 /* Set a program breakpoint */
+#define CMD_DB_CLRBRK 0xD5 /* Clear all program breakpoints */
+#define CMD_DB_GETREGS 0xD6 /* get registers */
+#define CMD_DB_GETMEM 0xD7 /* get memory */
+#define CMD_DB_WORD 0xD8 /* get a word value */
+#define CMD_DB_GETBRK 0xD9 /* get current breakpoints */
+#define CMD_DB_SETREG 0xDA /* set processor registers */
+#define CMD_DB_SETBDREG 0xDB /* set data breakpoint registers */
+
+/* exec control values for CMD_DB_SETEXEC */
+
+#define CMD_EXEC_STOP 0
+#define CMD_EXEC_STEP 1
+#define CMD_EXEC_RESUME 2
+
+#endif /* _CMDEFS_H */
diff --git a/indev/psn00bdbg-mk2/testutil/comms.c b/indev/psn00bdbg-mk2/testutil/comms.c new file mode 100644 index 0000000..46ec1f3 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/comms.c @@ -0,0 +1,817 @@ +#include <stdio.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif /* _WIN32 */
+#include "cmdefs.h"
+#include "main.h"
+#include "mips_disassembler.h"
+
+#ifdef _WIN32 /* platform specific macros */
+
+#define SIO_DELAY() ( Sleep( 10 ) )
+
+#else
+
+#define SIO_DELAY() ( usleep( 10000 ) )
+
+#endif /* _WIN32 */
+
+static const char *msg_sendfail = "Failed to send command.\n";
+static const char *msg_recfail = "Error on receive.\n";
+static const char *msg_noack = "No acknowledgement from target.\n";
+
+static char *regnames_param[] =
+{
+ "r0", "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",
+ "pc", "hi", "lo", "sr"
+};
+
+int dbGetInfo( void )
+{
+ int i;
+
+ if( commWriteByte( CMD_DB_GETINFO ) > 0 )
+ {
+ printf( "Debug monitor info string: " );
+ while( i = commReadByte() )
+ {
+ if( i < 0 )
+ {
+ puts( msg_recfail );
+ return( 1 );
+ }
+ putchar( i );
+ }
+ putchar( '\n' );
+ }
+ else
+ {
+ puts( msg_sendfail );
+ return( 1 );
+ }
+
+ return( 0 );
+
+} /* dbGetInfo */
+
+void dbGetStatus( void )
+{
+ int i;
+
+ if( commWriteByte( CMD_DB_GETSTAT ) > 0 )
+ {
+ if( (i = commReadByte()) < 0 )
+ {
+ puts( msg_recfail );
+ }
+ else
+ {
+ printf( "Target status: %d (", i );
+
+ switch( i )
+ {
+ case DB_STAT_STOP:
+ printf( "stopped" );
+ break;
+ case DB_STAT_BREAK:
+ printf( "breakpoint" );
+ break;
+ case DB_STAT_EXCEPT:
+ printf( "unhandled exception" );
+ break;
+ case DB_STAT_RUN:
+ printf( "running" );
+ break;
+ default:
+ printf( "undefined" );
+ }
+ printf( ")\n" );
+ }
+ }
+ else
+ {
+ puts( msg_sendfail );
+ }
+
+} /* dbGetStatus */
+
+int dbGetStatusPoll(void)
+{
+ int i;
+
+ if( commWriteByte( CMD_DB_GETSTAT ) > 0 )
+ {
+ if( (i = commReadByte()) < 0 )
+ {
+ return(-1);
+ }
+ }
+ else
+ {
+ return(-1);
+ }
+
+ return(i);
+
+} /* dbGetStatus */
+
+int dbSetExec( int exec )
+{
+ if( commWriteByte( CMD_DB_SETEXEC ) < 0 ) /* send command */
+ {
+ puts( msg_sendfail );
+ return(1);
+ }
+
+ if( commWriteByte( exec) < 0 ) /* send exec value */
+ {
+ puts( msg_sendfail );
+ return(1);
+ }
+
+ if( commReadByte() < 0 ) /* check for acknowledgment */
+ {
+ puts( msg_noack );
+ return(1);
+ }
+
+ return(0);
+
+} /* dbSetExec */
+
+void dbRunTo(unsigned int addr, int flag)
+{
+ if( commWriteByte(CMD_DB_RUNTO) < 0 ) /* send command */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ if( commWriteByte(flag) < 0 ) /* send flag */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ if( commWriteBytes( &addr, 4 ) < 4 ) /* send runto address */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ if( commReadByte() < 0 ) /* check for acknowledgment */
+ {
+ puts( msg_noack );
+ return;
+ }
+
+} /* dbRunTo */
+
+void dbSetBreak(unsigned int addr, unsigned int flag, int count)
+{
+ int ret;
+
+ if( commWriteByte(CMD_DB_SETBRK) < 0 ) /* send command */
+ {
+ puts(msg_sendfail);
+ return;
+ }
+
+ if( commWriteBytes(&addr, 4) < 4 ) /* send breakpoint address */
+ {
+ puts(msg_sendfail);
+ return;
+ }
+
+ SIO_DELAY(); /* delay otherwise last byte doesn't get sent somehow */
+
+ ret = (flag&0xFF) | (count<<16); /* send flag value */
+ if( commWriteBytes(&ret, 4) < 4 )
+ {
+ puts(msg_sendfail);
+ return;
+ }
+
+ SIO_DELAY();
+
+ if( (ret = commReadByte()) < 0 ) /* check for acknowledgment */
+ {
+ puts( msg_noack );
+ return;
+ }
+
+ if( ret == 0 )
+ {
+ printf("Bad breakpoint address.\n");
+ }
+ else if( ret == 1 )
+ {
+ printf("Breakpoint set/update.\n");
+ }
+ else
+ {
+ printf("Unknown response value: %d\n", ret);
+ }
+
+} /* dbSetBreak */
+
+void dbClearBreaks()
+{
+ int ret;
+
+ if( commWriteByte(CMD_DB_CLRBRK) < 0 ) /* send command */
+ {
+ puts(msg_sendfail);
+ return;
+ }
+
+ if( (ret = commReadByte()) < 0 ) /* check for acknowledgment */
+ {
+ puts( msg_noack );
+ return;
+ }
+
+} /* dbClearBreaks */
+
+void dbReboot( void )
+{
+ if( commWriteByte( CMD_REBOOT ) < 0 ) /* send command */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+} /* dbReboot */
+
+void dbUploadMemFile( unsigned int addr, const char *infile, size_t len )
+{
+ FILE *fp;
+ int i,progress,olen;
+ unsigned char buffer[100];
+ size_t file_sz;
+
+ fp = fopen( infile, "rb" );
+
+ if( !fp )
+ {
+ printf( "File not found.\n" );
+ return;
+ }
+
+ fseek( fp, 0, SEEK_END ); /* determine file size */
+ file_sz = ftell( fp );
+ fseek( fp, 0, SEEK_SET );
+
+ if( len > file_sz )
+ len = file_sz;
+
+ if( commWriteByte( CMD_DB_GETMEM ) < 0 ) /* send getmem command */
+ {
+ puts( msg_sendfail );
+ fclose( fp );
+ return;
+ }
+
+ if( commWriteByte( 1 ) < 1 ) /* send operation */
+ {
+ puts( msg_sendfail );
+ fclose( fp );
+ return;
+ }
+
+ SIO_DELAY();
+
+ if( commWriteBytes( &addr, 4 ) < 4 ) /* send write address */
+ {
+ puts( msg_sendfail );
+ fclose( fp );
+ return;
+ }
+
+ SIO_DELAY();
+
+ if( commWriteBytes( &len, 4 ) < 4 ) /* send write length */
+ {
+ puts( msg_sendfail );
+ fclose( fp );
+ return;
+ }
+
+ putchar( ' ' ); /* draw a progress bar */
+ for( i=0; i<70; i++ )
+ {
+ putchar( '.' );
+ }
+ putchar( ']' );
+ putchar( '\r' );
+ putchar( '[' );
+ fflush( stdout );
+
+ progress = 0;
+ olen = len;
+
+ while( len > 0 ) /* send the incoming bytes */
+ {
+ i = len;
+ if( i > 10 )
+ i = 10;
+
+ i = fread( buffer, 1, i, fp );
+ if( i <= 0 )
+ {
+ break;
+ }
+
+ if( ( i = commWriteBytes( buffer, i ) ) < 0 )
+ {
+ puts( msg_recfail );
+ break;
+ }
+ len -= i;
+
+ i = (70*((1024*((olen-len)>>2))/ /* draw out progress */
+ (olen>>2)))/1024;
+ if( i > progress )
+ {
+ progress = i;
+ putchar( '#' );
+ fflush( stdout );
+ }
+ }
+
+ for( i=0; i<(70-progress); i++ )
+ putchar( '#' );
+
+ putchar( '\n' );
+
+ fclose( fp );
+
+} /* dbUploadMemFile */
+
+int dbUploadMem( unsigned int addr, char *buff, size_t len )
+{
+ int i,progress,olen;
+
+ if( commWriteByte( CMD_DB_GETMEM ) < 0 ) /* send getmem command */
+ {
+ puts( msg_sendfail );
+ return(1);
+ }
+
+ if( commWriteByte( 1 ) < 1 ) /* send operation */
+ {
+ puts( msg_sendfail );
+ return(1);
+ }
+
+ SIO_DELAY();
+
+ if( commWriteBytes( &addr, 4 ) < 4 ) /* send write address */
+ {
+ puts( msg_sendfail );
+ return(1);
+ }
+
+ SIO_DELAY();
+
+ if( commWriteBytes( &len, 4 ) < 4 ) /* send write length */
+ {
+ puts( msg_sendfail );
+ return(1);
+ }
+
+ putchar( ' ' ); /* draw a progress bar */
+ for( i=0; i<70; i++ )
+ {
+ putchar( '.' );
+ }
+ putchar( ']' );
+ putchar( '\r' );
+ putchar( '[' );
+ fflush( stdout );
+
+ progress = 0;
+ olen = len;
+
+ while( len > 0 ) /* send the incoming bytes */
+ {
+ i = len;
+ if( i > 10 )
+ i = 10;
+
+ if( ( i = commWriteBytes( buff, i ) ) < 0 )
+ {
+ puts( msg_recfail );
+ break;
+ }
+ len -= i;
+ buff += i;
+
+ i = (70*((1024*((olen-len)>>2))/ /* draw out progress */
+ (olen>>2)))/1024;
+ if( i > progress )
+ {
+ progress = i;
+ putchar( '#' );
+ fflush( stdout );
+ }
+ }
+
+ for( i=0; i<(70-progress); i++ )
+ putchar( '#' );
+
+ putchar( '\n' );
+
+ return(0);
+
+} /* dbUploadMem */
+
+void dbGetMem( unsigned int addr, int len, const char *outfile )
+{
+ FILE *fp;
+ int i,progress,olen;
+ unsigned char buffer[100];
+
+ fp = fopen( outfile, "wb" );
+
+ if( !fp )
+ {
+ printf( "Cannot create output file.\n" );
+ return;
+ }
+
+ if( commWriteByte( CMD_DB_GETMEM ) < 0 ) /* send getmem command */
+ {
+ puts( msg_sendfail );
+ fclose( fp );
+ return;
+ }
+
+ if( commWriteByte( 0 ) < 1 ) /* send operation */
+ {
+ puts( msg_sendfail );
+ fclose( fp );
+ return;
+ }
+
+ SIO_DELAY();
+
+ if( commWriteBytes( &addr, 4 ) < 4 ) /* send read address */
+ {
+ puts( msg_sendfail );
+ fclose( fp );
+ return;
+ }
+
+ SIO_DELAY();
+
+ if( commWriteBytes( &len, 4 ) < 4 ) /* send read length */
+ {
+ puts( msg_sendfail );
+ fclose( fp );
+ return;
+ }
+
+ putchar( ' ' ); /* draw a progress bar */
+ for( i=0; i<70; i++ )
+ {
+ putchar( '.' );
+ }
+ putchar( ']' );
+ putchar( '\r' );
+ putchar( '[' );
+ fflush( stdout );
+
+ progress = 0;
+ olen = len;
+
+ while( len > 0 ) /* receive the incoming bytes */
+ {
+ i = len;
+ if( i > 10 )
+ i = 10;
+
+ if( ( i = commReadBytes( buffer, i ) ) < 0 )
+ {
+ puts( msg_recfail );
+ break;
+ }
+
+ fwrite( buffer, 1, i, fp );
+ len -= i;
+
+ i = (70*((1024*((olen-len)>>2))/ /* draw out progress */
+ (olen>>2)))/1024;
+ if( i > progress )
+ {
+ progress = i;
+ putchar( '#' );
+ fflush( stdout );
+ }
+ }
+
+ for( i=0; i<(70-progress); i++ )
+ putchar( '#' );
+
+ putchar( '\n' );
+
+ fclose( fp );
+
+} /* dbGetMem */
+
+unsigned int dbReadValue( int wordsz, unsigned int addr )
+{
+ unsigned int val;
+
+ if( commWriteByte( CMD_DB_WORD ) < 0 ) /* send value command */
+ {
+ puts( msg_sendfail );
+ return( 0 );
+ }
+
+ if( commWriteByte( 0 ) < 0 ) /* perform read operation */
+ {
+ puts( msg_sendfail );
+ return( 0 );
+ }
+
+ if( commWriteByte( wordsz ) < 0 ) /* send word size */
+ {
+ puts( msg_sendfail );
+ return( 0 );
+ }
+
+ if( commWriteBytes( &addr, 4 ) < 4 ) /* send address */
+ {
+ puts( msg_sendfail );
+ return( 0 );
+ }
+
+ if( commReadBytes( &val, 4 ) < 4 ) /* retrieve value */
+ {
+ puts( msg_recfail );
+ return( 0 );
+ }
+
+ return( val );
+
+} /* dbReadValue */
+
+void dbWriteValue( int wordsz, unsigned int addr, unsigned int val )
+{
+ if( commWriteByte( CMD_DB_WORD ) < 0 ) /* send value command */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ if( commWriteByte( 1 ) < 0 ) /* perform write operation */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ if( commWriteByte( wordsz ) < 0 ) /* send word size */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ if( commWriteBytes( &addr, 4 ) < 4 ) /* send address */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ SIO_DELAY();
+
+ if( commWriteBytes( &val, 4 ) < 4 ) /* send value */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ if( commReadByte() < 0 )
+ {
+ puts( msg_noack );
+ }
+
+} /* dbWriteValue */
+
+static const char *regnames[] =
+{
+ "r0=","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=",
+ "pc=","hi=","lo="
+};
+
+static const char *cop0names[] =
+{
+ "SR =",
+ "CAUSE =",
+ "BADVADDR =",
+ "JUMPDEST =",
+ "DCIC =",
+ "OPCODE[0] =",
+ "OPCODE[1] ="
+};
+
+void dbGetRegs( void )
+{
+ int i;
+ unsigned int regval;
+ unsigned int pc;
+ char textbuff[32];
+
+ if( commWriteByte( CMD_DB_GETREGS ) < 0 ) /* send getmem command */
+ {
+ puts( msg_sendfail );
+ return;
+ }
+
+ for( i=0; i<35; i++ )
+ {
+ if( commReadBytes( ®val, 4 ) < 4 )
+ {
+ puts( msg_recfail );
+ return;
+ }
+
+ printf( "%s%08X ", regnames[i], regval );
+ if( (i&0x3) == 3 )
+ printf( "\n" );
+
+ if( i == 32 )
+ pc = regval;
+ }
+
+ printf( "\n\n" );
+
+ for( i=0; i<7; i++ )
+ {
+ if( commReadBytes( ®val, 4 ) < 4 )
+ {
+ puts( msg_recfail );
+ return;
+ }
+ printf( "%s%08X", cop0names[i], regval );
+ if( i < 5 )
+ putchar( '\n' );
+ if( i >= 5 )
+ {
+ mips_Decode( regval, pc+((i>5)?4:0), textbuff, 0 );
+ printf( " %s\n", textbuff );
+ }
+ }
+
+ printf( "\n" );
+
+} /* dbGetRegs */
+
+void dbGetBreaks(void)
+{
+ unsigned int regval;
+
+ if( commWriteByte(CMD_DB_GETBRK) < 0 ) /* send get breaks command */
+ {
+ puts(msg_sendfail);
+ return;
+ }
+
+ while(1)
+ {
+ if( commReadBytes(®val, 4) < 4 )
+ {
+ puts(msg_recfail);
+ return;
+ }
+
+ if( regval == 0xFFFFFFFF )
+ {
+ break;
+ }
+
+ printf("PC=%08X ", regval);
+
+ if( commReadBytes(®val, 4) < 4 )
+ {
+ puts(msg_recfail);
+ return;
+ }
+
+ printf("FLAG=%08X ", regval);
+
+ if( commReadBytes(®val, 4) < 4 )
+ {
+ puts(msg_recfail);
+ return;
+ }
+
+ printf("CNT=%08X\n", regval);
+ }
+
+} /* dbGetBreaks */
+
+int dbSetReg(const char *regname, unsigned int value)
+{
+ int regnum;
+ int found;
+
+ found = 0;
+ for(regnum=0; regnum<36; regnum++)
+ {
+ if( strcmp(regname, regnames_param[regnum]) == 0 )
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if( found == 0 )
+ {
+ printf("Invalid register name.\n");
+ return(1);
+ }
+
+ if( commWriteByte(CMD_DB_SETREG) < 0 ) /* send set register command */
+ {
+ puts(msg_sendfail);
+ return(1);
+ }
+
+ if( commWriteByte(regnum) < 0 ) /* send register byte */
+ {
+ puts(msg_sendfail);
+ return(1);
+ }
+
+ if( commWriteBytes(&value, 4) < 4 ) /* send new register value */
+ {
+ puts(msg_sendfail);
+ return(1);
+ }
+
+ SIO_DELAY();
+
+ if( commReadByte() < 0 )
+ {
+ puts(msg_noack);
+ }
+
+ return(0);
+
+} /* dbSetReg */
+
+int dbSetBDregs(unsigned int addr, unsigned int mask, unsigned char flags)
+{
+ /* send set data break command */
+ if( commWriteByte(CMD_DB_SETBDREG) < 0 )
+ {
+ puts(msg_sendfail);
+ return 1;
+ }
+
+ if( commWriteBytes(&addr, 4) < 4 )
+ {
+ puts(msg_sendfail);
+ return 1;
+ }
+
+ if( commWriteBytes(&mask, 4) < 4 )
+ {
+ puts(msg_sendfail);
+ return 1;
+ }
+
+ if( commWriteByte(flags) < 0 )
+ {
+ puts(msg_sendfail);
+ return 1;
+ }
+
+ SIO_DELAY();
+
+ if( commReadByte() < 0 )
+ {
+ puts(msg_noack);
+ }
+
+ return 0;
+
+} /* dbSetDBregs */
diff --git a/indev/psn00bdbg-mk2/testutil/exec.c b/indev/psn00bdbg-mk2/testutil/exec.c new file mode 100644 index 0000000..bcd91ef --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/exec.c @@ -0,0 +1,413 @@ +#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "exec.h"
+
+#define MAX_prg_entry_count 128
+
+#pragma pack(push, 1)
+
+typedef struct _ELF_HEADER {
+
+ unsigned int magic; // 0-3
+ unsigned char word_size; // 4
+ unsigned char endianness; // 5
+ unsigned char elf_version; // 6
+ unsigned char os_abi; // 7
+ unsigned int unused[2]; // 8-15
+
+ unsigned short type; // 16-17
+ unsigned short instr_set; // 18-19
+ unsigned int elf_version2; // 20-23
+
+ unsigned int prg_entry_addr; // 24-27
+ unsigned int prg_head_pos; // 28-31
+ unsigned int sec_head_pos; // 32-35
+ unsigned int flags; // 36-39
+ unsigned short head_size; // 40-41
+ unsigned short prg_entry_size; // 42-23
+ unsigned short prg_entry_count; // 44-45
+ unsigned short sec_entry_size; // 46-47
+ unsigned short sec_entry_count; // 48-49
+ unsigned short sec_names_index; // 50-51
+
+} ELF_HEADER;
+
+typedef struct _PRG_HEADER {
+ unsigned int seg_type;
+ unsigned int p_offset;
+ unsigned int p_vaddr;
+ unsigned int undefined;
+ unsigned int p_filesz;
+ unsigned int p_memsz;
+ unsigned int flags;
+ unsigned int alignment;
+} PRG_HEADER;
+
+#pragma pack(pop)
+
+typedef struct _PSEXE {
+ char header[8];
+ char pad[8];
+ EXEC params;
+ char license[64];
+ char pad2[1908];
+} PSEXE;
+
+typedef struct _EXEPARAM {
+ EXEC params;
+ unsigned int crc32;
+ unsigned int flags;
+} EXEPARAM;
+
+typedef struct _BINPARAM {
+ int size;
+ unsigned int addr;
+ unsigned int crc32;
+} BINPARAM;
+
+
+void* loadELF(FILE* fp, EXEC* param)
+{
+ int i;
+ ELF_HEADER head;
+ PRG_HEADER prg_heads[MAX_prg_entry_count];
+ unsigned int exe_taddr = 0xffffffff;
+ unsigned int exe_haddr = 0;
+ unsigned int exe_tsize = 0;
+ unsigned char* binary;
+ size_t read_n;
+
+ fseek(fp, 0, SEEK_SET);
+ read_n = fread(&head, 1, sizeof(head), fp);
+
+ // Check header
+ if( head.magic != 0x464c457f ) {
+
+ printf("File is neither a PS-EXE, CPE or ELF binary.\n");
+ return NULL;
+
+ }
+
+ if( head.type != 2 ) {
+
+ printf("Only executable ELF files are supported.\n");
+ return NULL;
+
+ }
+
+ if( head.instr_set != 8 ) {
+
+ printf("ELF file is not a MIPS binary.\n");
+ return NULL;
+
+ }
+
+ if( head.word_size != 1 ) {
+
+ printf("Only 32-bit ELF files are supported.\n");
+ return NULL;
+
+ }
+
+ if( head.endianness != 1 ) {
+
+ printf("Only little endian ELF files are supported.\n");
+ return NULL;
+
+ }
+
+
+ // Load program headers and determine binary size and load address
+
+ fseek(fp, head.prg_head_pos, SEEK_SET);
+ for( i=0; i<head.prg_entry_count; i++ ) {
+
+ read_n = fread( &prg_heads[i], 1, sizeof(PRG_HEADER), fp );
+
+ if( prg_heads[i].flags == 4 ) {
+ continue;
+ }
+
+ if( prg_heads[i].p_vaddr < exe_taddr ) {
+ exe_taddr = prg_heads[i].p_vaddr;
+ }
+
+ if( prg_heads[i].p_vaddr > exe_haddr ) {
+ exe_haddr = prg_heads[i].p_vaddr;
+ }
+
+ }
+
+ exe_tsize = (exe_haddr-exe_taddr);
+ exe_tsize += prg_heads[head.prg_entry_count-1].p_filesz;
+
+
+ // Check if load address is appropriate in main RAM locations
+ if( ( ( exe_taddr>>24 ) == 0x0 ) || ( ( exe_taddr>>24 ) == 0x80 ) ||
+ ( ( exe_taddr>>24 ) == 0xA0 ) ) {
+
+ if( ( exe_taddr&0x00ffffff ) < 65536 ) {
+
+ printf( "WARNING: Program text address overlaps kernel area!\n" );
+
+ }
+
+ }
+
+
+ // Pad out the size to multiples of 2KB
+ exe_tsize = 2048*((exe_tsize+2047)/2048);
+
+ // Load the binary data
+ binary = (unsigned char*)malloc( exe_tsize );
+ memset( binary, 0x0, exe_tsize );
+
+ for( i=0; i<head.prg_entry_count; i++ ) {
+
+ if( prg_heads[i].flags == 4 ) {
+ continue;
+ }
+
+ fseek( fp, prg_heads[i].p_offset, SEEK_SET );
+ read_n = fread( &binary[(int)(prg_heads[i].p_vaddr-exe_taddr)],
+ 1, prg_heads[i].p_filesz, fp );
+
+ }
+
+ memset(param, 0, sizeof(EXEC));
+ param->pc0 = head.prg_entry_addr;
+ param->t_addr = exe_taddr;
+ param->t_size = exe_tsize;
+
+ return binary;
+
+}
+
+void* loadCPE(FILE* fp, EXEC* param) {
+
+ int i, val, exe_size = 0;
+ unsigned int uv, exe_entry = 0;
+ unsigned int *addr_list = NULL;
+ int addr_list_len = 0;
+ char* exe_buff;
+ unsigned int addr_upper=0;
+ unsigned int addr_lower=0;
+ size_t read_n;
+
+ // Check CPE magic word
+ fseek(fp, 0, SEEK_SET);
+ read_n = fread(&val, 1, 4, fp);
+
+ if( val != 0x01455043 )
+ {
+ return NULL;
+ }
+
+ // Clear EXEC parameters
+ memset(param, 0x0, sizeof(EXEC));
+
+ // Begin parsing CPE data
+ val = 0;
+ read_n = fread(&val, 1, 1, fp);
+
+ while( val )
+ {
+ switch( val )
+ {
+ case 0x1: // Binary chunk
+
+ read_n = fread(&uv, 1, 4, fp);
+ read_n = fread(&val, 1, 4, fp);
+
+ addr_list_len++;
+ addr_list = (unsigned int*)realloc(addr_list,
+ sizeof(unsigned int)*addr_list_len);
+
+ addr_list[addr_list_len-1] = uv;
+ exe_size += val;
+
+ fseek(fp, val, SEEK_CUR);
+ break;
+
+ case 0x3: // Set register, ignored
+
+ val = 0;
+ read_n = fread(&val, 1, 2, fp);
+
+ if( val != 0x90 )
+ {
+ printf("Warning: Unknown SETREG code: %d\n", val);
+ }
+
+ read_n = fread(&exe_entry, 1, 4, fp);
+ break;
+
+ case 0x8: // Select unit, ignored
+
+ val = 0;
+ read_n = fread(&val, 1, 1, fp);
+ break;
+
+ default:
+
+ printf("Unknown chunk found: %d\n", val);
+ free(addr_list);
+ return NULL;
+
+ }
+
+ // Read next code
+ val = 0;
+ read_n = fread(&val, 1, 1, fp);
+
+ }
+
+ // Begin loading the executable data
+
+ // Find the highest chunk address
+ for(i=0; i<addr_list_len; i++) {
+
+ if( addr_list[i] > addr_upper ) {
+
+ addr_upper = addr_list[i];
+
+ }
+
+ }
+
+ // Find the lowest chunk address
+ addr_lower = addr_upper;
+
+ for(i=0; i<addr_list_len; i++) {
+
+ if ( addr_list[i] < addr_lower ) {
+
+ addr_lower = addr_list[i];
+
+ }
+
+ }
+
+ // Pad executable size to multiples of 2KB and allocate
+ exe_size = 2048*((exe_size+2047)/2048);
+
+ exe_buff = (char*)malloc(exe_size);
+ memset(exe_buff, 0x0, exe_size);
+
+ // Load binary chunks
+ val = 0;
+ fseek(fp, 4, SEEK_SET);
+ read_n = fread(&val, 1, 1, fp);
+
+ while( val ) {
+
+ switch( val ) {
+ case 0x1: // Binary chunk
+
+ read_n = fread(&uv, 1, 4, fp);
+ read_n = fread(&val, 1, 4, fp);
+
+ read_n = fread(exe_buff+(uv-addr_lower), 1, val, fp);
+
+ break;
+
+ case 0x3: // Set register (skipped)
+
+ val = 0;
+ read_n = fread(&val, 1, 2, fp);
+
+ if( val == 0x90 ) {
+
+ fseek(fp, 4, SEEK_CUR);
+
+ }
+
+ break;
+
+ case 0x8: // Select unit (skipped)
+
+ fseek(fp, 1, SEEK_CUR);
+
+ break;
+ }
+
+ val = 0;
+ read_n = fread(&val, 1, 1, fp);
+
+ }
+
+ // Set program text and entrypoint
+ param->pc0 = exe_entry;
+ param->t_addr = addr_lower;
+ param->t_size = exe_size;
+
+ return exe_buff;
+
+}
+
+void *loadExecutable(const char* exefile, EXEC *param) {
+
+ PSEXE exe;
+ unsigned char* buffer;
+
+ FILE* fp = fopen(exefile, "rb");
+
+ if( fp == NULL )
+ {
+ printf("File not found.\n");
+ return(NULL);
+ }
+
+ // Load PS-EXE header
+ if( fread(&exe, 1, sizeof(PSEXE), fp) != sizeof(PSEXE) )
+ {
+ printf("Read error or invalid file.\n");
+ fclose(fp);
+ return(NULL);
+ }
+
+ // Check file ID
+ if( strcmp(exe.header, "PS-X EXE") ) {
+
+ // If not PS-EXE, try loading it as CPE
+ buffer = (unsigned char*)loadCPE(fp, param);
+
+ if( buffer == NULL ) {
+
+ // If not CPE, try loading it as ELF
+ buffer = (unsigned char*)loadELF(fp, param);
+
+ if( buffer == NULL ) {
+
+ fclose(fp);
+ return(NULL);
+
+ }
+
+ }
+
+ } else {
+
+ // Load PS-EXE body, simple
+ buffer = (unsigned char*)malloc(param->t_size);
+
+ if( fread(buffer, 1, param->t_size, fp) != param->t_size ) {
+
+ printf("Incomplete file or read error.\n");
+ free(buffer);
+ fclose(fp);
+
+ return(NULL);
+
+ }
+
+ memcpy(param, &exe.params, sizeof(EXEC));
+
+ }
+
+ // Done with the file
+ fclose(fp);
+
+ return(buffer);
+}
diff --git a/indev/psn00bdbg-mk2/testutil/exec.h b/indev/psn00bdbg-mk2/testutil/exec.h new file mode 100644 index 0000000..24688c0 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/exec.h @@ -0,0 +1,24 @@ +#ifndef _EXEC_H
+#define _EXEC_H
+
+typedef struct _EXEC {
+ unsigned int pc0;
+ unsigned int gp0;
+ unsigned int t_addr;
+ unsigned int t_size;
+ unsigned int d_addr;
+ unsigned int d_size;
+ unsigned int b_addr;
+ unsigned int b_size;
+ unsigned int sp_addr;
+ unsigned int sp_size;
+ unsigned int sp;
+ unsigned int fp;
+ unsigned int gp;
+ unsigned int ret;
+ unsigned int base;
+} EXEC;
+
+void *loadExecutable(const char* exefile, EXEC *param);
+
+#endif /* _EXEC_H */
diff --git a/indev/psn00bdbg-mk2/testutil/main.c b/indev/psn00bdbg-mk2/testutil/main.c new file mode 100644 index 0000000..bb17731 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/main.c @@ -0,0 +1,131 @@ +#include <stdio.h>
+#include <string.h>
+#ifdef _WIN32
+#include <conio.h>
+#include <windows.h>
+#include <winbase.h>
+#else
+#include <unistd.h>
+#endif /* _WIN32 */
+#include "exec.h"
+#include "cmdefs.h"
+#include "main.h"
+
+#ifdef _WIN32
+const char *com_port = "COM1";
+#define delay(t) Sleep(t)
+#else
+const char *com_port = "/dev/ttyUSB0";
+#define delay(t) usleep(1000*t);
+#endif
+int com_baud = 115200;
+
+static const char *msg_minargs = "Not enough arguments.\n";
+
+int UploadExec(const char *exefile)
+{
+ EXEC exec;
+ char *exebuff;
+
+ /* load the PS-EXE */
+ printf("Loading executable file... ");
+ fflush(stdout);
+ exebuff = loadExecutable(exefile, &exec);
+ if( !exebuff )
+ return(1);
+ printf("Done.\n");
+
+ /* stop the target */
+ printf("Target stop... ");
+ fflush(stdout);
+ if( dbSetExec(CMD_EXEC_STOP) )
+ return(1);
+ delay(100);
+ printf("Done.\n");
+
+ /* modify target's registers for new program execution */
+ printf("Setup target (pc0=%08X)... ", exec.pc0);
+ fflush(stdout);
+ delay(100);
+ if( dbSetReg("pc", exec.pc0) )
+ return(1);
+ delay(100);
+ if( dbSetReg("sr", 0x00000400) )
+ return(1);
+ delay(100);
+ if( dbSetReg("sp", 0x801FFFF0) )
+ return(1);
+ delay(100);
+ printf("Done.\n");
+
+ /* upload program text */
+ printf("Program upload (t_addr=%08X)...\n", exec.t_addr);
+ if( dbUploadMem(exec.t_addr, exebuff, exec.t_size) )
+ return(1);
+
+ printf("Target ready.\n");
+
+ return(0);
+
+} /* UploadExec */
+
+int main( int argc, const char *argv[] )
+{
+ int i;
+ const char *psexe;
+
+ printf( "PSn00bDBG-mk2 Monitor Test Utility\n\n" );
+
+ psexe = NULL;
+ for( i=1; i<argc; i++ )
+ {
+ if( strcasecmp( "/p", argv[i] ) == 0 ) /* specify serial port */
+ {
+ if( ( argc-i ) < 2 )
+ {
+ puts( msg_minargs );
+ return( 1 );
+ }
+ i++;
+ com_port = argv[i];
+ }
+ else if( ( strcasecmp( "/?", argv[i] ) == 0 ) ||
+ ( strcasecmp( "/h", argv[i] ) == 0 ) )
+ {
+ printf( "%s [params] [exe]\n\n", argv[0] );
+ printf( "Parameters:\n" );
+ printf( " /p <COMx> - Specify serial port (default: COM1)\n" );
+ printf( " /? or /h - Show help\n\n" );
+ return( 0 );
+ }
+ else
+ {
+ psexe = argv[i];
+ }
+ }
+
+ if( commOpen( com_port, com_baud ) )
+ return( 1 );
+
+ if( dbGetInfo() )
+ {
+ printf( "Unable to confirm connection with debug monitor.\n" );
+ return( 1 );
+ }
+
+ /* perform PS-EXE upload */
+ if( psexe )
+ {
+ UploadExec(psexe);
+ promptMode();
+ }
+ else
+ {
+ promptMode();
+ }
+
+ commClose();
+
+ return( 0 );
+
+} /* main */
diff --git a/indev/psn00bdbg-mk2/testutil/main.h b/indev/psn00bdbg-mk2/testutil/main.h new file mode 100644 index 0000000..87f1ce4 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/main.h @@ -0,0 +1,38 @@ +#ifndef _MAIN_H
+#define _MAIN_H
+
+/* globals */
+extern const char *com_port;
+extern int com_baud;
+
+/* comms.c */
+int dbGetInfo( void );
+void dbGetStatus( void );
+int dbGetStatusPoll(void);
+int dbSetExec( int exec );
+void dbRunTo(unsigned int addr, int flag);
+void dbSetBreak(unsigned int addr, unsigned int flag, int count);
+void dbClearBreaks(void);
+void dbGetBreaks(void);
+void dbGetRegs( void );
+int dbSetReg(const char *regname, unsigned int value);
+void dbReboot( void );
+void dbGetMem( unsigned int addr, int len, const char *outfile );
+int dbUploadMem( unsigned int addr, char *buff, size_t len );
+void dbUploadMemFile( unsigned int addr, const char *infile, size_t len );
+unsigned int dbReadValue( int wordsz, unsigned int addr );
+void dbWriteValue( int wordsz, unsigned int addr, unsigned int val );
+
+/* prompt.c */
+void promptMode( void );
+
+/* serial.c */
+int commOpen( const char *port, int baud );
+int commWriteByte( int value );
+int commWriteBytes( void *buff, int len );
+int commReadByte( void );
+int commReadBytes( void *buff, int len );
+int commPendingBytes(void);
+void commClose( void );
+
+#endif /* _MAIN_H */
diff --git a/indev/psn00bdbg-mk2/testutil/makefile b/indev/psn00bdbg-mk2/testutil/makefile new file mode 100644 index 0000000..be3fbe1 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/makefile @@ -0,0 +1,31 @@ +CC = wcc386 +LNK = wlink + +CFLAGS = -q -bt=nt -w3 -d2 -odhl + +all : psdbtest.exe + +psdbtest.exe : main.obj prompt.obj comms.obj serial.obj mips_disassembler.obj exec.obj + wlink name psdbtest system nt f main,prompt,comms,serial,mips_disassembler,exec + +main.obj : main.c main.h cmdefs.h + $(CC) $(CFLAGS) main.c + +comms.obj : comms.c main.h cmdefs.h + $(CC) $(CFLAGS) comms.c + +prompt.obj : prompt.c main.h cmdefs.h + $(CC) $(CFLAGS) prompt.c + +serial.obj : serial.c + $(CC) $(CFLAGS) serial.c + +mips_disassembler.obj : mips_disassembler.c mips_disassembler.h + $(CC) $(CFLAGS) mips_disassembler.c + +exec.obj : exec.c exec.h + $(CC) $(CFLAGS) exec.c + +clean : .SYMBOLIC + del psdbtest.exe + del *.obj
\ No newline at end of file diff --git a/indev/psn00bdbg-mk2/testutil/makefile-linux b/indev/psn00bdbg-mk2/testutil/makefile-linux new file mode 100644 index 0000000..83611d1 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/makefile-linux @@ -0,0 +1,11 @@ +OFILES = main.o exec.o prompt.o comms.o serial.o mips_disassembler.o + +CFLAGS = -g -O2 + +CC = gcc + +all: $(OFILES) + $(CC) $(CFLAGS) $(OFILES) -o psdbtest + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/indev/psn00bdbg-mk2/testutil/mips_disassembler.c b/indev/psn00bdbg-mk2/testutil/mips_disassembler.c new file mode 100644 index 0000000..c7effb7 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/mips_disassembler.c @@ -0,0 +1,663 @@ +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdlib.h> +#include "mips_disassembler.h" +#include "pstypes.h" + +#define OPCODE1(p) ( (p>>26)&0x3F ) +#define OPCODE2(p) ( p&0x3F ) +#define OPREGS(p) ( (p>>21)&0x1f ) +#define OPREGT(p) ( (p>>16)&0x1f ) +#define OPREGD(p) ( (p>>11)&0x1f ) + +#define OPIMM5(p) ( (p>>6)&0x1f ) +#define OPIMM16(p) ( p&0xffff ) +#define OPIMM20(p) ( (p>>6)&0x1FFFFF ) +#define OPIMM25(p) ( p&0x1FFFFFF ) +#define OPIMM26(p) ( p&0x3FFFFFF ) +#define EXTEND26(p) (((int)(p<<6))>>6) +#define EXTEND16(p) (((int)(p<<16))>>16) + +static const char* regs[] = { + "r0","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" +}; + +static void Decode_cop(unsigned int opcode, char* output) { + + int copnum = OPCODE1(opcode)&0x3; + + const char* cop0_nick[32] = { + "N/A","N/A","N/A","BPC", // r0-r3 + "N/A","BDA","JUMPDEST","DCIC", // r4-r7 + "BadVaddr","BDAM","N/A","BPCM", // r8-r11 + "SR","CAUSE","EPC","PRID", // r12-r15 + "N/A","N/A","N/A","N/A", + "N/A","N/A","N/A","N/A", + "N/A","N/A","N/A","N/A", + "N/A","N/A","N/A","N/A", + }; + + const char* cop2_data_nick[32] = { + "VXY0","VZ0","VXY1","VZ1", // r0-r3 + "VXY2","VZ2","RGBC","OTZ", // r4-r7 + "IR0","IR1","IR2","IR3", // r8-r11 + "SXY0","SXY1","SXY2","SXYP", // r12-r15 + "SZ0","SZ1","SZ2","SZ3", + "RGB0","RGB1","RGB2","RES1", + "MAC0","MAC1","MAC2","MAC3", + "IRGB","ORGB","LZCS","LZCR", + }; + + const char* cop2_ctrl_nick[32] = { + "RT11","RT12","RT13","RT21", // r0-r3 + "RT22","RT23","RT31","RT32", // r4-r7 + "RT33","TRX","TRY","TRZ", // r8-r11 + "LR1","LR2","LR3","LG1", // r12-r15 + "LG2","LG3","LB1","LB2", + "LB3","RFC","GFC","BFC", + "OFX","OFY","H","DQA", + "DQB","ZSF3","ZSF4","FLAG", + }; + + char temp[16]; + + if( (OPCODE1(opcode)&0x20) == 0 ) { + + switch(OPREGS(opcode)) { + case 0x0: // mfc? + sprintf( output, "mfc%d %s, r%d", copnum, + regs[OPREGT(opcode)], + OPREGD(opcode) ); + + if ( copnum == 0 ) { + + sprintf( temp, " (%s)", cop0_nick[OPREGD(opcode)] ); + strcat( output, temp ); + + } else if ( copnum == 2 ) { + + sprintf( temp, " (%s)", cop2_data_nick[OPREGD(opcode)] ); + strcat( output, temp ); + + } + + break; + case 0x2: // cfc? + + sprintf( output, "cfc%d %s, r%d", copnum, + regs[OPREGT(opcode)], + OPREGD(opcode) ); + + if ( copnum == 2 ) { + + sprintf( temp, " (%s)", cop2_ctrl_nick[OPREGD(opcode)] ); + strcat( output, temp ); + + } + + break; + case 0x4: // mtc? + + sprintf( output, "mtc%d %s, r%d", copnum, + regs[OPREGT(opcode)], + OPREGD(opcode) ); + + if ( copnum == 0 ) { + + sprintf( temp, " (%s)", cop0_nick[OPREGD(opcode)] ); + strcat( output, temp ); + + } else if ( copnum == 2 ) { + + sprintf( temp, " (%s)", cop2_data_nick[OPREGD(opcode)] ); + strcat( output, temp ); + + } + + break; + case 0x6: // ctc? + + sprintf( output, "ctc%d %s, r%d", copnum, + regs[OPREGT(opcode)], OPREGT(opcode) ); + + if ( copnum == 2 ) + { + sprintf( temp, " (%s)", cop2_ctrl_nick[OPREGT(opcode)] ); + strcat( output, temp ); + } + + break; + + case 0x8: // bc?f bc?t + if( OPREGT(opcode) == 1 ) + { + sprintf( output, "bc%dt $%X", copnum, + OPIMM16(opcode) ); + } + else + { + sprintf( output, "bc%df $%X", copnum, + OPIMM16(opcode) ); + } + break; + + default: // cop? + + //strcpy( output, "cp" ); + //sprintf( output, "%x", OPREGS(opcode) ); + + if( OPREGS(opcode)&0x10 ) + { + sprintf( output, "cop%d $%X", copnum, OPIMM25(opcode) ); + } + break; + } + + } else { + + if( (OPCODE1(opcode)&0x8) == 0 ) { + + sprintf( output, "lwc%d r%d,%d(%s)", copnum, + OPREGT(opcode), EXTEND16(OPIMM16(opcode)), + regs[OPREGS(opcode)] ); + + if ( copnum == 0 ) { + + sprintf( temp, " (%s)", cop0_nick[OPREGT(opcode)] ); + strcat( output, temp ); + + } else if ( copnum == 2 ) { + + sprintf( temp, " (%s)", cop2_data_nick[OPREGT(opcode)] ); + strcat( output, temp ); + + } + + } else { + + sprintf( output, "swc%d r%d,%d(%s)", copnum, + OPREGT(opcode), EXTEND16(OPIMM16(opcode)), + regs[OPREGS(opcode)] ); + + if ( copnum == 0 ) { + + sprintf( temp, " (%s)", cop0_nick[OPREGT(opcode)] ); + strcat( output, temp ); + + } else if ( copnum == 2 ) { + + sprintf( temp, " (%s)", cop2_data_nick[OPREGT(opcode)] ); + strcat( output, temp ); + + } + + } + + } + +} + +void mips_Decode(unsigned int opcode, unsigned int addr, char* output, int arrows) { + + char temp[32]; + int immval; + + const char* pri_op[] = { + NULL ,NULL ,"j " ,"jal ",//4 + "beq " ,"bne " ,"blez " ,"bgtz ",//8 + "addi " ,"addiu " ,"slti " ,"sltiu ",//12 + "andi " ,"ori " ,"xori " ,"lui ",//16 + "cop0 " ,"cop1<!> " ,"cop2 " ,"cop3<!> ",//24 + NULL , NULL ,NULL , NULL, //32 + NULL , NULL ,NULL , NULL, //36 + NULL , NULL ,NULL , NULL, //40 + "lb " ,"lh " ,"lwl " ,"lw ",//44 + "lbu " ,"lhu " ,"lwr " ,NULL, //48 + "sb " ,"sh " ,"swl " ,"sw ", + NULL ,NULL ,"swr " ,NULL, + }; + + const char* sc_op[] = { + "sll " ,NULL ,"srl " ,"sra " , //0 + "sllv " ,NULL ,"srlv " ,"srav " , //4 + "jr " ,"jalr " ,NULL ,NULL , //8 + "syscall " ,"break " ,NULL ,NULL , //12 + "mfhi " ,"mthi " ,"mflo " ,"mtlo " , //16 + NULL ,NULL ,NULL ,NULL , //20 + "mult " ,"multu " ,"div " ,"divu " , //24 + NULL ,NULL ,NULL ,NULL , //28 + "add " ,"addu " ,"sub " ,"subu " , //32 + "and " ,"or " ,"xor " ,"nor " , //36 + NULL ,NULL ,"slt " ,"sltu " , //38 + }; + + strcpy( output, "???" ); + + if( opcode ) { + + // Secondary codes + if( OPCODE1(opcode) == 0 ) { + + switch( OPCODE2(opcode) ) { + case 0x0: // sll, srl, sra + case 0x2: + case 0x3: + strcpy( output, sc_op[OPCODE2(opcode)] ); + sprintf( temp, "%s, %s, %d", + regs[OPREGD(opcode)], regs[OPREGT(opcode)], OPIMM5(opcode) ); + strcat( output, temp ); + break; + case 0x4: // sllv, srlv, srav + case 0x6: + case 0x7: + strcpy( output, sc_op[OPCODE2(opcode)] ); + sprintf( temp, "%s, %s, %s", regs[OPREGT(opcode)], + regs[OPREGD(opcode)], regs[OPREGS(opcode)] ); + strcat( output, temp ); + break; + case 0x8: // jr + strcpy( output, sc_op[OPCODE2(opcode)] ); + strcat( output, regs[OPREGS(opcode)] ); + break; + case 0x9: // jalr + strcpy( output, sc_op[OPCODE2(opcode)] ); + sprintf( temp, "%s, %s", regs[OPREGD(opcode)], + regs[OPREGS(opcode)] ); + strcat( output, temp ); + break; + case 0xc: // syscall, break + case 0xd: + strcpy( output, sc_op[OPCODE2(opcode)] ); + sprintf( temp, "$%x", OPIMM20(opcode) ); + strcat( output, temp ); + break; + case 0x10: // mfhi, mflo + case 0x12: + strcpy( output, sc_op[OPCODE2(opcode)] ); + strcat( output, regs[OPREGD(opcode)] ); + break; + case 0x11: // mthi, mtlo + case 0x13: + strcpy( output, sc_op[OPCODE2(opcode)] ); + strcat( output, regs[OPREGS(opcode)] ); + break; + case 0x18: // mult, multu, div, divu + case 0x19: + case 0x1a: + case 0x1b: + strcpy( output, sc_op[OPCODE2(opcode)] ); + sprintf( temp, "%s, %s", regs[OPREGS(opcode)], + regs[OPREGT(opcode)] ); + strcat( output, temp ); + break; + case 0x2a: // slt, sltu + case 0x2b: + strcpy( output, sc_op[OPCODE2(opcode)] ); + sprintf( temp, "%s, %s, %s", regs[OPREGD(opcode)], + regs[OPREGS(opcode)], regs[OPREGT(opcode)] ); + strcat( output, temp ); + break; + default: + + if( ( OPCODE2(opcode) >= 0x20 ) && ( OPCODE2(opcode) <= 0x27 ) ) { + strcpy( output, sc_op[OPCODE2(opcode)] ); + sprintf( temp, "%s, %s, %s", regs[OPREGD(opcode)], + regs[OPREGT(opcode)], regs[OPREGS(opcode)] ); + strcat( output, temp ); + } + + break; + } + + // Primary + } else { + + if( OPCODE1(opcode) == 0x1 ) { // Branches + + switch((opcode>>16)&0x1f) { + case 0x0: + strcpy(output, "bltz "); + break; + case 0x1: + strcpy(output, "bgez "); + break; + case 0x10: + strcpy(output, "bltzal "); + break; + case 0x11: + strcpy(output, "bgtzal "); + break; + } + + sprintf( temp, "%s,$%08X ", regs[OPREGS(opcode)], + addr+4+(EXTEND16(OPIMM16(opcode))*4) ); + strcat( output, temp ); + + if( arrows ) { + if ( addr+4+(EXTEND16(OPIMM16(opcode))*4) > addr ) { + strcat( output, "▼" ); + } else { + strcat( output, "▲" ); + } + } + + } else if( ( OPCODE1(opcode) == 0x2 ) || ( OPCODE1(opcode) == 0x3 ) ) { // j, jal + + unsigned int dest = (OPIMM26(opcode)*4)|(addr&0xf0000000); + + strcpy( output, pri_op[OPCODE1(opcode)] ); + sprintf( temp, "$%08X ", dest ); + strcat( output, temp ); + + if( arrows ) { + if ( dest > addr ) { + strcat( output, "▼" ); + } else { + strcat( output, "▲" ); + } + } + } else if( ( OPCODE1(opcode) >= 0x8 ) && + ( OPCODE1(opcode) <= 0x9 ) ) { + + strcpy( output, pri_op[OPCODE1(opcode)] ); + + sprintf( temp, "%s, %s, %d", regs[OPREGT(opcode)], + regs[OPREGS(opcode)], EXTEND16(OPIMM16(opcode)) ); + strcat( output, temp ); + + } else if( ( OPCODE1(opcode) >= 0xa ) && + ( OPCODE1(opcode) <= 0xe ) ) { + + strcpy( output, pri_op[OPCODE1(opcode)] ); + + sprintf( temp, "%s, %s, $%lX", regs[OPREGT(opcode)], + regs[OPREGS(opcode)], labs( OPIMM16(opcode) ) ); + strcat( output, temp ); + + } else if( OPCODE1(opcode) == 0xf ) { + + strcpy( output, pri_op[OPCODE1(opcode)] ); + sprintf( temp, "%s, $%X", + regs[OPREGT(opcode)], OPIMM16(opcode) ); + strcat( output, temp ); + + } else if( ( OPCODE1(opcode) >= 0x20 ) && + ( OPCODE1(opcode) <= 0x2e ) ) { + + switch( OPCODE1(opcode) ) { + case 0x27: + case 0x2c: + case 0x2d: + return; + } + + strcpy( output, pri_op[OPCODE1(opcode)] ); + sprintf( temp, "%s,", + regs[OPREGT(opcode)] ); + strcat( output, temp ); + + immval = EXTEND16(OPIMM16(opcode)); + sprintf( temp, "$%lX", labs( immval ) ); + if( immval < 0 ) { + strcat( output, "-" ); + } else { + strcat( output, " " ); + } + strcat( output, temp ); + + sprintf( temp, "(%s)", regs[OPREGS(opcode)] ); + strcat( output, temp ); + + } else if ( OPCODE1(opcode)&0x10 ) { + + Decode_cop( opcode, output ); + + } else { + + switch( OPCODE1(opcode) ) { + case 0x4: + case 0x5: + strcpy( output, pri_op[OPCODE1(opcode)] ); + sprintf( temp, "%s, %s, $%08X ", + regs[OPREGS(opcode)], + regs[OPREGT(opcode)], + addr+4+(EXTEND16(OPIMM16(opcode))*4) ); + strcat( output, temp ); + + if( arrows ) { + if ( addr+4+(EXTEND16(OPIMM16(opcode))*4) > addr ) { + strcat( output, "▼" ); + } else { + strcat( output, "▲" ); + } + } + + break; + case 0x6: + case 0x7: + strcpy( output, pri_op[OPCODE1(opcode)] ); + sprintf( temp, "%s, $%08X ", + regs[OPREGS(opcode)], + addr+4+(EXTEND16(OPIMM16(opcode))*4) ); + strcat( output, temp ); + + if( arrows ) { + if ( addr+4+(EXTEND16(OPIMM16(opcode))*4) > addr ) { + strcat( output, "▼" ); + } else { + strcat( output, "▲" ); + } + } + + break; + } + + } + + } + + } else { + + strcpy( output, "nop" ); + + } + +} + +unsigned int mips_GetNextPc(unsigned int *regs, int stepover) { + + unsigned int dest = regs[PS_REG_epc]+4; + unsigned int opcode = regs[PS_REG_opcode]; + unsigned int rv,rt; + + if( OPCODE1(opcode) == 0 ) { + + if( ( OPCODE2(opcode) == 8 )||( OPCODE2(opcode) == 9 ) ) { // jr, jalr + + if( ( OPCODE2(opcode) == 9 ) && ( stepover ) ) { + + dest += 4; + + } else { + + if( OPREGS(opcode) == 0 ) + dest = 0; + else + dest = regs[OPREGS(opcode)-1]; + + } + + } + + } else if( OPCODE1(opcode) == 1 ) { + + if( OPREGS(opcode) == 0 ) + rv = 0; + else + rv = regs[OPREGS(opcode)-1]; + + switch(OPREGT(opcode)) { + case 0x0: // bltz + if ( (((int)0)|rv) < 0 ) { + dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4); + } else { + dest += 4; + } + break; + case 0x1: // bgez + if ( (((int)0)|rv) >= 0 ) { + dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4); + } else { + dest += 4; + } + break; + case 0x8: // bltzal + if ( (((int)0)|rv) < 0 ) { + dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4); + } else { + dest += 4; + } + break; + case 0x9: // bgezal + if ( (((int)0)|rv) >= 0 ) { + dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4); + } else { + dest += 4; + } + break; + } + + } else if( ( OPCODE1(opcode) == 2 ) || ( OPCODE1(opcode) == 3 ) ) { // j,jal + + if( ( OPCODE1(opcode) == 3 ) && ( stepover ) ) { + + dest += 4; + + } else { + + dest = (regs[PS_REG_epc]&0xf0000000)|(OPIMM26(opcode)*4); + + } + + } else if( OPCODE1(opcode) == 4 ) { // beq + + if( OPREGS(opcode) == 0 ) { + rv = 0; + } else { + rv = regs[OPREGS(opcode)-1]; + } + + if( OPREGT(opcode) == 0 ) { + rt = 0; + } else { + rt = regs[OPREGT(opcode)-1]; + } + + if( rv == rt ) { + + dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4); + + } else { + + dest += 4; + + } + + } else if( OPCODE1(opcode) == 5 ) { // bne + + if( OPREGS(opcode) == 0 ) { + rv = 0; + } else { + rv = regs[OPREGS(opcode)-1]; + } + + if( OPREGT(opcode) == 0 ) { + rt = 0; + } else { + rt = regs[OPREGT(opcode)-1]; + } + + if( rv != rt ) { + + dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4); + + } else { + + dest += 4; + + } + + } else if( OPCODE1(opcode) == 6 ) { // blez + + if( OPREGS(opcode) == 0 ) { + rv = 0; + } else { + rv = regs[OPREGS(opcode)-1]; + } + + if( (((int)0)|rv) <= 0 ) { + + dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4); + + } else { + + dest += 4; + + } + + } else if( OPCODE1(opcode) == 7 ) { // bgtz + + if( OPREGS(opcode) == 0 ) { + rv = 0; + } else { + rv = regs[OPREGS(opcode)-1]; + } + + if( (((int)0)|rv) > 0 ) { + + dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4); + + } else { + + dest += 4; + + } + + } + + return dest; +} + +unsigned int mips_GetJumpAddr(unsigned int addr, unsigned int opcode) { + + if( OPCODE1(opcode) == 1 ) { + + switch(OPREGT(opcode)) { + case 0x0: // bltz + case 0x1: // bgez + case 0x8: // bltzal + case 0x9: // bgezal + return addr+4+(EXTEND16(OPIMM16(opcode))*4); + } + + } else if( ( OPCODE1(opcode) == 2 ) || ( OPCODE1(opcode) == 3 ) ) { // j,jal + + return (addr&0xf0000000)|(OPIMM26(opcode)*4); + + } else if( ( OPCODE1(opcode) >= 4 ) && ( OPCODE1(opcode) <= 7 ) ) { // beq + + return addr+4+(EXTEND16(OPIMM16(opcode))*4); + + } + + return 0; + +} diff --git a/indev/psn00bdbg-mk2/testutil/mips_disassembler.h b/indev/psn00bdbg-mk2/testutil/mips_disassembler.h new file mode 100644 index 0000000..41e604f --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/mips_disassembler.h @@ -0,0 +1,10 @@ +#ifndef DISASSEMBLER_H +#define DISASSEMBLER_H + +void mips_Decode(unsigned int opcode, unsigned int addr, char* output, int arrows); + +unsigned int mips_GetNextPc(unsigned int *regs, int stepover); +unsigned int mips_GetJumpAddr(unsigned int addr, unsigned int opcode); + +#endif /* DISASSEMBLER_H */ + diff --git a/indev/psn00bdbg-mk2/testutil/prompt.c b/indev/psn00bdbg-mk2/testutil/prompt.c new file mode 100644 index 0000000..e51e203 --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/prompt.c @@ -0,0 +1,518 @@ +#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <conio.h>
+
+#else
+
+#include <sys/time.h>
+#include <unistd.h>
+#include <termios.h>
+#include <signal.h>
+
+#endif /* _WIN32 */
+
+#include "cmdefs.h"
+#include "main.h"
+
+static int prompt_quit;
+int UploadExec(const char *exefile);
+
+#ifdef _WIN32
+
+#define _kbhit kbhit
+
+#else
+
+struct termios orig_term;
+
+void enable_raw_mode()
+{
+ struct termios term;
+ tcgetattr(0, &orig_term);
+
+ term = orig_term;
+ term.c_lflag &= ~(ICANON | ECHO); // Disable echo as well
+ tcsetattr(0, TCSANOW, &term);
+}
+
+void disable_raw_mode()
+{
+ tcsetattr(0, TCSANOW, &orig_term);
+}
+
+int _kbhit()
+{
+ struct timeval tv = { 0L, 0L };
+
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+
+ return select(1, &fds, NULL, NULL, &tv);
+
+} /* _kbhit */
+
+void term_func(int signum)
+{
+ disable_raw_mode();
+ exit( 0 );
+
+} /* term_func */
+
+#endif /* _WIN32 */
+
+static void promptHelp( void )
+{
+ printf("? View help\n");
+ printf("up <addr> <len> <file> Upload memory from <file>\n");
+ printf("down <addr> <len> <file> Download memory to <file>\n");
+ printf("rv <8|16|32> <addr> Read a value from <addr>\n");
+ printf("wv <8|16|32> <addr> <val> Write a value to <addr>\n");
+ printf("sb <addr> <mode> [count] Set program breakpoint at <addr>\n");
+ printf("cb Clear all breakpoints\n");
+ printf("lb List breakpoints\n");
+ printf("sr <regname> <value> Set register value\n");
+ printf("stop Stop target\n");
+ printf("cont Resume target\n");
+ printf("stat Show target status\n");
+ printf("r / regs Show registers\n");
+ printf("t / trace Trace\n");
+ printf("rt / runto <addr> Run until <addr>\n");
+ printf("tt / traceto <addr> Run until <addr> or jump/branch\n");
+ printf("reboot Reboot target and quit\n");
+ printf("q / quit Quit\n\n");
+ printf("Commands can be stacked as one keystroke like so:\n");
+ printf("trace regs - Performs a trace operation then shows registers\n\n");
+
+} /* promptHelp */
+
+static char *getarg( const char *msg )
+{
+ char *arg;
+
+ arg = strtok( NULL, " " );
+
+ if( !arg )
+ {
+ printf( "Missing %s argument.\n", msg );
+ return( NULL );
+ }
+
+ return( arg );
+
+} /* getarg */
+
+void promptMode( void )
+{
+ int inkey;
+ int bytebuff;
+ char inbuff[100];
+ int inpos;
+ int inlen;
+ char *inptr;
+ char *arg;
+
+ unsigned int addr;
+ int len;
+ const char *file;
+
+ int wordsz;
+ unsigned int value;
+
+ int firsttime;
+ int pollcount;
+ int laststat;
+ int pollstat;
+
+#ifdef _WIN32
+#else
+ struct sigaction st;
+#endif /* _WIN32 */
+
+ printf( "Enter ? for list of directives.\n\n" );
+
+ prompt_quit = 0;
+
+#ifdef _WIN32
+#else
+ st.sa_handler = term_func;
+ sigemptyset( &st.sa_mask );
+ st.sa_flags = SA_RESTART;
+ sigaction( SIGINT, &st, NULL );
+
+ enable_raw_mode();
+#endif /* _WIN32 */
+
+ if( (laststat = dbGetStatusPoll()) < 0 )
+ {
+ printf("Error polling target status.\n");
+ laststat = 0;
+ }
+
+ while( !prompt_quit )
+ {
+ memset( inbuff, 0, 100 );
+#if 1//def _WIN32
+ //gets( inbuff );
+#else
+ fgets( inbuff, 100, stdin );
+
+ while( arg = strchr( inbuff, '\n' ) ) /* remove newlines from input */
+ {
+ *arg = 0;
+ }
+#endif
+
+ printf("nDB>");
+ inpos = 0;
+ fflush(stdout);
+ firsttime = 1;
+ pollcount = 0;
+ while(1)
+ {
+ if( commPendingBytes() > 0 )
+ {
+ /* routine that simply flushes the serial interface */
+ bytebuff = commReadByte();
+ printf("\rReceived byte: %02x\n", bytebuff);
+
+ printf("nDB>%s", inbuff);
+ fflush(stdout);
+ pollcount = 0;
+ }
+
+ if( _kbhit() )
+ {
+#ifdef _WIN32
+ inkey = getch();
+ if( inkey == 13 )
+#else
+ inkey = getchar();
+ if( inkey == '\n' )
+#endif
+ {
+ fputc('\n', stdout);
+ fflush(stdout);
+ break;
+ }
+#ifdef _WIN32
+ else if( inkey == 8 )
+#else
+ else if( inkey == 127 ) /* linux backspace */
+#endif /* _WIN32 */
+ {
+ if( inpos > 0 )
+ {
+ fputc('\b', stdout);
+ fputc(' ', stdout);
+ fputc('\b', stdout);
+ fflush(stdout);
+ inpos--;
+ inbuff[inpos] = 0;
+ continue;
+ }
+ }
+ else
+ {
+ if( inpos < 100 )
+ {
+ fputc(inkey, stdout);
+ fflush(stdout);
+ inbuff[inpos] = inkey;
+ inpos++;
+ inbuff[inpos] = 0;
+ continue;
+ }
+ }
+ }
+#ifdef _WIN32
+ Sleep(10);
+#else
+ usleep(1000);
+#endif /* _WIN32 */
+
+ pollcount++;
+ if( pollcount > 10 )
+ {
+ if( (pollstat = dbGetStatusPoll()) < 0 )
+ {
+ printf("Error polling target status.\n");
+ }
+ else
+ {
+ if( pollstat != laststat )
+ {
+ laststat = pollstat;
+ switch(pollstat)
+ {
+ case DB_STAT_STOP:
+ printf("\rTarget stopped.\n");
+ break;
+ case DB_STAT_BREAK:
+ printf("\rBreakpoint/trace complete.\n");
+ break;
+ case DB_STAT_EXCEPT:
+ printf("\rUnhandled exception.\n");
+ break;
+ default:
+ printf("\rUndefined target state (%d).\n", pollstat);
+ }
+ dbGetRegs();
+ printf("nDB>%s", inbuff);
+ fflush(stdout);
+ }
+ }
+ pollcount = 0;
+ }
+ }
+
+ if( ( inlen = strlen( inbuff ) ) == 0 )
+ continue;
+
+ inptr = inbuff;
+ while( arg = strtok( inptr, " " ) )
+ {
+ inptr = NULL;
+
+ /* quit parsing when end of string is reached */
+
+ if( strcasecmp( "?", arg ) == 0 )
+ {
+ promptHelp();
+ }
+ else if( strcasecmp( "rv", arg ) == 0 ) /* read value */
+ {
+ if( !(arg = getarg( "word size" ) ) ) /* get word size arg */
+ break;
+ sscanf( arg, "%d", &wordsz );
+
+ if( !(arg = getarg( "address" ) ) ) /* get address arg */
+ break;
+ sscanf( arg, "%x", &addr );
+
+ switch( wordsz )
+ {
+ case 8:
+ wordsz = 0;
+ break;
+ case 16:
+ wordsz = 1;
+ break;
+ case 32:
+ wordsz = 2;
+ break;
+ default:
+ printf( "Unknown word size: %d\n", wordsz );
+ wordsz = -1;
+ }
+
+ if( wordsz >= 0 )
+ {
+ value = dbReadValue( wordsz, addr );
+ switch( wordsz )
+ {
+ case 0:
+ printf( "%08X=%02X\n", addr, value );
+ break;
+ case 1:
+ printf( "%08X=%04X\n", addr, value );
+ break;
+ case 2:
+ printf( "%08X=%08X\n", addr, value );
+ break;
+ }
+ }
+ }
+ else if( strcasecmp( "wv", arg ) == 0 ) /* read value */
+ {
+ if( !(arg = getarg( "word size" ) ) ) /* get word size arg */
+ break;
+ sscanf( arg, "%d", &wordsz );
+
+ if( !(arg = getarg( "address" ) ) ) /* get address arg */
+ break;
+ sscanf( arg, "%x", &addr );
+
+ if( !(arg = getarg( "value" ) ) ) /* get value */
+ break;
+ sscanf( arg, "%x", &value );
+
+ switch( wordsz )
+ {
+ case 8:
+ wordsz = 0;
+ break;
+ case 16:
+ wordsz = 1;
+ break;
+ case 32:
+ wordsz = 2;
+ break;
+ default:
+ printf( "Unknown word size: %d\n", wordsz );
+ wordsz = -1;
+ }
+
+ dbWriteValue( wordsz, addr, value );
+ }
+ else if( strcasecmp( "exe", arg ) == 0 ) /* upload executable */
+ {
+ if( !(file = getarg( "file name" ) ) ) /* get file arg */
+ break;
+
+ UploadExec(file);
+
+ laststat = DB_STAT_STOP;
+ }
+ else if( strcasecmp( "up", arg ) == 0 ) /* upload memory */
+ {
+ if( !(arg = getarg( "address" ) ) ) /* get address arg */
+ break;
+ sscanf( arg, "%x", &addr );
+
+ if( !(arg = getarg( "length" ) ) ) /* get length arg */
+ break;
+ sscanf( arg, "%d", &len );
+
+ if( !(file = getarg( "file name" ) ) ) /* get file arg */
+ break;
+
+ printf( "Performing memory upload of %d byte(s) to %08X from %s\n",
+ len, addr, file );
+
+ dbUploadMemFile( addr, file, len );
+ }
+ else if( strcasecmp( "down", arg ) == 0 ) /* download memory */
+ {
+ if( !(arg = getarg( "address" ) ) ) /* get address arg */
+ break;
+ sscanf( arg, "%x", &addr );
+
+ if( !(arg = getarg( "length" ) ) ) /* get length arg */
+ break;
+ sscanf( arg, "%d", &len );
+
+ if( !(file = getarg( "file name" ) ) ) /* get file arg */
+ break;
+
+ printf( "Performing memory dump of %d byte(s) from %08X to %s\n",
+ len, addr, file );
+
+ dbGetMem( addr, len, file );
+ }
+ else if( strcasecmp("sb", arg) == 0 ) /* set breakpoint */
+ {
+ if( !(arg = getarg("address") ) ) /* get address arg */
+ break;
+ sscanf(arg, "%x", &addr);
+ if( !(arg = getarg("flag") ) ) /* get flag arg */
+ break;
+ sscanf(arg, "%d", &value);
+ if( value == 2 )
+ {
+ if( !(arg = getarg("count") ) ) /* get flag arg */
+ break;
+ sscanf(arg, "%d", &len);
+ }
+ else
+ {
+ len = 0;
+ }
+ dbSetBreak(addr, value, len);
+ }
+ else if( strcasecmp("cb", arg) == 0 ) /* clear breakpoints */
+ {
+ dbClearBreaks();
+ }
+ else if( strcasecmp("lb", arg) == 0 )
+ {
+ dbGetBreaks();
+ }
+ else if( strcasecmp( "stat", arg ) == 0 ) /* get target status */
+ {
+ dbGetStatus();
+ }
+ else if( strcasecmp( "stop", arg ) == 0 ) /* stop target */
+ {
+ dbSetExec( CMD_EXEC_STOP );
+ }
+ else if( strcasecmp( "cont", arg ) == 0 ) /* continue target */
+ {
+ dbSetExec( CMD_EXEC_RESUME );
+ laststat = DB_STAT_RUN;
+ }
+ else if( ( strcasecmp( "t", arg ) == 0 ) ||
+ ( strcasecmp( "trace", arg ) == 0 ) )
+ {
+ dbSetExec( CMD_EXEC_STEP );
+ laststat = DB_STAT_RUN;
+ }
+ else if( ( strcasecmp( "rt", arg ) == 0 ) || /* runto address */
+ ( strcasecmp( "runto", arg ) == 0 ) )
+ {
+ if( !(arg = getarg( "program address" ) ) ) /* get address arg */
+ break;
+ sscanf( arg, "%x", &addr );
+ dbRunTo(addr, 0);
+ laststat = DB_STAT_RUN;
+ }
+ else if( ( strcasecmp( "tt", arg ) == 0 ) || /* traceto address */
+ ( strcasecmp( "traceto", arg ) == 0 ) )
+ {
+ if( !(arg = getarg( "program address" ) ) ) /* get address arg */
+ break;
+ sscanf( arg, "%x", &addr );
+ dbRunTo(addr, 1);
+ laststat = DB_STAT_RUN;
+ }
+ else if( ( strcasecmp( "r", arg ) == 0 ) || /* get registers */
+ ( strcasecmp( "regs", arg ) == 0 ) )
+ {
+ dbGetRegs();
+ }
+ else if( strcasecmp("sr", arg) == 0 ) /* set register value */
+ {
+ if( !(arg = getarg("register") ) ) /* get address arg */
+ break;
+ file = arg;
+ if( !(arg = getarg("value") ) ) /* get flag arg */
+ break;
+ sscanf(arg, "%x", &value);
+ dbSetReg(file, value);
+ }
+ else if( strcasecmp( "reboot", arg ) == 0 )
+ {
+ dbReboot();
+ prompt_quit = 1;
+ break;
+ }
+ else if( ( strcasecmp( "q", arg ) == 0 ) || /* quit program */
+ ( strcasecmp( "quit", arg ) == 0 ) )
+ {
+ prompt_quit = 1;
+ break;
+ }
+ else
+ {
+ printf( "Unknown directive: %s\n", arg );
+ }
+ /* delay before executing next directive */
+#ifdef _WIN32
+ Sleep(100);
+#else
+ usleep(1000);
+#endif /* _WIN32 */
+ }
+ }
+
+#ifdef _WIN32
+#else
+ disable_raw_mode();
+#endif /* _WIN32 */
+
+} /* promptMode */
diff --git a/indev/psn00bdbg-mk2/testutil/pstypes.h b/indev/psn00bdbg-mk2/testutil/pstypes.h new file mode 100644 index 0000000..5767cbd --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/pstypes.h @@ -0,0 +1,81 @@ +#ifndef PSTYPES_H +#define PSTYPES_H + +// CPU +#define PS_REG_at 0 +#define PS_REG_v0 1 +#define PS_REG_v1 2 +#define PS_REG_a0 3 +#define PS_REG_a1 4 +#define PS_REG_a2 5 +#define PS_REG_a3 6 +#define PS_REG_t0 7 +#define PS_REG_t1 8 +#define PS_REG_t2 9 +#define PS_REG_t3 10 +#define PS_REG_t4 11 +#define PS_REG_t5 12 +#define PS_REG_t6 13 +#define PS_REG_t7 14 +#define PS_REG_s0 15 +#define PS_REG_s1 16 +#define PS_REG_s2 17 +#define PS_REG_s3 18 +#define PS_REG_s4 19 +#define PS_REG_s5 20 +#define PS_REG_s6 21 +#define PS_REG_s7 22 +#define PS_REG_t8 23 +#define PS_REG_t9 24 +#define PS_REG_k0 25 +#define PS_REG_k1 26 +#define PS_REG_gp 27 +#define PS_REG_sp 28 +#define PS_REG_fp 29 +#define PS_REG_ra 30 +#define PS_REG_lo 31 +#define PS_REG_hi 32 + +// cop0 +#define PS_REG_epc 33 +#define PS_REG_cause 34 +#define PS_REG_status 35 +#define PS_REG_baddr 36 +#define PS_REG_tar 37 +#define PS_REG_dcic 38 +#define PS_REG_opcode 39 + +typedef struct { + unsigned int pc0; + unsigned int gp0; + unsigned int t_addr; + unsigned int t_size; + unsigned int d_addr; + unsigned int d_size; + unsigned int b_addr; + unsigned int b_size; + unsigned int sp_addr; + unsigned int sp_size; + unsigned int sp; + unsigned int fp; + unsigned int gp; + unsigned int ret; + unsigned int base; +} EXEC; + +typedef struct { + char header[8]; + char pad[8]; + EXEC params; + char license[64]; + char pad2[1908]; +} PSEXE; + +typedef struct { + EXEC params; + unsigned int crc32; + unsigned int flags; +} EXEPARAM; + +#endif /* PSTYPES_H */ + diff --git a/indev/psn00bdbg-mk2/testutil/serial.c b/indev/psn00bdbg-mk2/testutil/serial.c new file mode 100644 index 0000000..445a6de --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/serial.c @@ -0,0 +1,273 @@ +#include <stdio.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <winbase.h>
+#else
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+#endif /* _WIN32 */
+
+#ifdef _WIN32
+HANDLE hComm;
+#else
+int hComm;
+#endif /* _WIN32 */
+
+int commOpen( const char *port, int baud )
+{
+
+#ifdef _WIN32
+
+ DCB dcbParams;
+ COMMTIMEOUTS timeouts;
+
+ hComm = CreateFile( port, /* open serial port */
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+
+ if( hComm == INVALID_HANDLE_VALUE )
+ {
+ printf( "Cannot open port %s.\n", port );
+ return( 1 );
+ }
+
+ if( !GetCommState( hComm, &dcbParams ) ) /* get DCB parameters */
+ {
+ CloseHandle( hComm );
+ printf( "Cannot get comm state.\n" );
+ return( 2 );
+ }
+
+ dcbParams.BaudRate = baud; /* adjust DCB parameters */
+ dcbParams.ByteSize = 8;
+ dcbParams.StopBits = ONESTOPBIT;
+ dcbParams.Parity = NOPARITY;
+ dcbParams.fOutxCtsFlow = TRUE;
+ dcbParams.fOutxDsrFlow = TRUE;
+ dcbParams.fDtrControl = DTR_CONTROL_ENABLE;
+ dcbParams.fDsrSensitivity = FALSE;
+ dcbParams.fOutX = FALSE;
+ dcbParams.fInX = FALSE;
+ dcbParams.fErrorChar = FALSE;
+ dcbParams.fNull = FALSE;
+ dcbParams.fRtsControl = RTS_CONTROL_ENABLE;//RTS_CONTROL_HANDSHAKE;
+ dcbParams.fAbortOnError = FALSE;
+
+ if( !SetCommState( hComm, &dcbParams ) ) /* apply DCB parameters */
+ {
+ CloseHandle( hComm );
+ printf( "Cannot set desired comm state.\n" );
+ return( 3 );
+ }
+
+ timeouts.ReadIntervalTimeout = 100;
+ timeouts.ReadTotalTimeoutConstant = 50;
+ timeouts.ReadTotalTimeoutMultiplier = 10;
+ timeouts.WriteTotalTimeoutConstant = 50;
+ timeouts.WriteTotalTimeoutMultiplier = 10;
+
+ if( !SetCommTimeouts( hComm, &timeouts ) )
+ {
+ CloseHandle( hComm );
+ printf( "Cannot set desired timeouts.\n" );
+ return( 4 );
+ }
+
+ Sleep( 50 ); /* delay for the PS1 to receive the DSR signal */
+
+#else
+
+ struct termios tty;
+
+ memset( &tty, 0, sizeof(struct termios) );
+
+ hComm = open( port, O_RDWR|O_NOCTTY );
+
+ if( hComm == -1 )
+ {
+ printf( "Cannot open serial device %s.\n", port );
+ return( 1 );
+ }
+
+ cfsetspeed( &tty, (speed_t)baud );
+
+ tty.c_cflag &= ~PARENB;
+ tty.c_cflag &= ~CSTOPB;
+ tty.c_cflag &= ~CSIZE;
+ tty.c_cflag |= (CS8 | CREAD | CLOCAL);
+ //tty.c_cflag |= (CS8 | CREAD | CLOCAL | CRTSCTS);
+
+ tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+
+ tty.c_iflag &= ~(IXON | IXOFF | IXANY);
+ tty.c_iflag |= IGNPAR;
+
+ tty.c_oflag &= ~OPOST;
+
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 5;
+
+ if ( tcsetattr( hComm, TCSANOW, &tty ) != 0 )
+ {
+ printf( "Cannot set desired comms parameters.\n" );
+ return( 3 );
+ }
+
+#endif /* _WIN32 */
+
+ return( 0 );
+
+} /* commOpen */
+
+int commWriteByte( int value )
+{
+#ifdef _WIN32
+
+ DWORD nwritten;
+
+ if( !WriteFile( hComm, (LPCVOID)&value, 1, &nwritten, NULL ) )
+ {
+ return( -1 );
+ }
+
+ if( nwritten == 0 )
+ {
+ return( -1 );
+ }
+
+#else
+
+ if( write( hComm, &value, 1 ) < 1 )
+ {
+ return( -1 );
+ }
+
+#endif /* _WIN32 */
+
+ return( 1 );
+
+} /* commWriteByte */
+
+int commWriteBytes( void *buff, int len )
+{
+#ifdef _WIN32
+
+ DWORD nwritten;
+
+ if( !WriteFile( hComm, (LPCVOID)buff, len, &nwritten, NULL ) )
+ {
+ return( -1 );
+ }
+
+ return( nwritten );
+
+#else
+
+ int nwritten;
+
+ nwritten = write( hComm, buff, len );
+
+ return( nwritten );
+
+#endif /* _WIN32 */
+
+} /* commWriteBytes */
+
+int commReadByte( void )
+{
+ int recval;
+
+#ifdef _WIN32
+
+ DWORD nread;
+
+ recval = 0;
+ if( !ReadFile(hComm, (LPVOID)&recval, 1, &nread, NULL) )
+ {
+ return(-1);
+ }
+
+ if( nread == 0 )
+ {
+ return(-1);
+ }
+
+#else
+
+ recval = 0;
+ if( read(hComm, &recval, 1) < 1 )
+ return(-1);
+
+#endif /* _WIN32 */
+
+ return( recval );
+
+} /* commReadByte */
+
+int commPendingBytes(void)
+{
+#ifdef _WIN32
+
+ DWORD dwErrorFlags;
+ COMSTAT ComStat;
+
+ ClearCommError(hComm, &dwErrorFlags, &ComStat);
+
+ return( (int)ComStat.cbInQue );
+
+#else
+
+ int bytes;
+ ioctl(hComm, FIONREAD, &bytes);
+
+ return( bytes );
+
+#endif /* _WIN32 */
+
+} /* commPendingBytes */
+
+int commReadBytes( void *buff, int len )
+{
+#ifdef _WIN32
+
+ DWORD nread;
+
+ if( !ReadFile( hComm, (LPVOID)buff, len, &nread, NULL ) )
+ {
+ return( -1 );
+ }
+
+#else
+
+ int nread;
+
+ nread = read( hComm, buff, len );
+
+#endif /* _WIN32 */
+
+ return( nread );
+
+} /* commReadBytes */
+
+void commClose( void )
+{
+#ifdef _WIN32
+
+ Sleep( 50 );
+
+ CloseHandle( hComm );
+
+#else
+
+ close( hComm );
+
+#endif /* _WIN32 */
+
+} /* commClose */
|
