diff options
author | Max Horn | 2008-05-15 11:40:38 +0000 |
---|---|---|
committer | Max Horn | 2008-05-15 11:40:38 +0000 |
commit | defc030143487550057cac1fb617d31ce9ab1ab2 (patch) | |
tree | 715887c6224f2536333730c79a964846f18107b1 /backends/platform/gp32/debug-gdbstub-usb.cpp | |
parent | 6206fb2a188b28db426cb85653e8c6bf00d1f1d3 (diff) | |
download | scummvm-rg350-defc030143487550057cac1fb617d31ce9ab1ab2.tar.gz scummvm-rg350-defc030143487550057cac1fb617d31ce9ab1ab2.tar.bz2 scummvm-rg350-defc030143487550057cac1fb617d31ce9ab1ab2.zip |
Removed the GP32 port
svn-id: r32139
Diffstat (limited to 'backends/platform/gp32/debug-gdbstub-usb.cpp')
-rw-r--r-- | backends/platform/gp32/debug-gdbstub-usb.cpp | 1927 |
1 files changed, 0 insertions, 1927 deletions
diff --git a/backends/platform/gp32/debug-gdbstub-usb.cpp b/backends/platform/gp32/debug-gdbstub-usb.cpp deleted file mode 100644 index 76b7fad13b..0000000000 --- a/backends/platform/gp32/debug-gdbstub-usb.cpp +++ /dev/null @@ -1,1927 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* - * - * Basic GP32 USB GDB Debug Stub - Use with Multi-firmware that supports GDB - * Mithris kindly gave me the basic stub code. - * - */ -#include <sys/types.h> -#include <gpcomm.h> -#include <gpos_def.h> -#include <gpdef.h> -#include <gpmain.h> -#include <gpos_def.h> -#include <gpstdio.h> -#include <gpgraphic.h> -#include <gpfont.h> -#include <gpstdlib.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> - -//#define USE_PRINTF // If there is a Printf(const char *pFormat,...) implemented - -/////////////////////////////////////////////////////////////// -// Externs -extern int __text_start; -extern int __data_start; -extern int __bss_start; -#ifdef USE_PRINTF -extern void Printf(char *pFormat, ...); -#endif -/////////////////////////////////////////////////////////////// - -extern "C" { - int OpenUSB(); - void InstallISR(); -} - -struct g_Namedregisters { - unsigned int r0; - unsigned int r1; - unsigned int r2; - unsigned int r3; - unsigned int r4; - unsigned int r5; - unsigned int r6; - unsigned int r7; - unsigned int r8; - unsigned int r9; - unsigned int r10; - unsigned int r11; - unsigned int r12; - unsigned int sp; - unsigned int lr; - unsigned int pc; - unsigned int fps; - unsigned int fcpsr; -}; - -/////////////////////////////////////////////////////////////// -// Defines - - -#define _REG_R1 0 -#define _REG_R2 2 -#define _REG_R3 3 -#define _REG_R4 4 -#define _REG_R5 5 -#define _REG_R6 6 -#define _REG_R7 7 -#define _REG_R8 8 -#define _REG_R9 9 -#define _REG_R10 10 -#define _REG_R11 11 -#define _REG_R12 12 -#define _REG_FP 11 -#define _REG_IP 12 -#define _REG_SL 10 -#define _REG_SP 13 -#define _REG_LR 14 -#define _REG_PC 15 - -#define PACKET_SIZE 0x100 - -#define MODE_USER 0 -#define MODE_FIQ 1 -#define MODE_IRQ 2 -#define MODE_SUPERVISOR 3 -#define MODE_ABORT 4 -#define MODE_UNDEF 5 -#define MODE_SYSTEM 6 -#define MODE_DUNNO -1 - -/////////////////////////////////////////////////////////////// -// Global stuff - -// Register array. -int g_Registers[50] = {1, 2, 3, 4 ,5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, - 21, 22, 23, 24, 25, 26, 27, 28, 29, - 31, 32, 33, 34, 35, 36, 37, 38, 39, - 41, 42, 43, 44, 45, 46, 47, 48, 49}; - -// Register name strings, not used right now. -static char * arm_register_name_strings[] = -{"r0", "r1", "r2", "r3", /* 0 1 2 3 */ - "r4", "r5", "r6", "r7", /* 4 5 6 7 */ - "r8", "r9", "r10", "r11", /* 8 9 10 11 */ - "r12", "sp", "lr", "pc", /* 12 13 14 15 */ - "f0", "f1", "f2", "f3", /* 16 17 18 19 */ - "f4", "f5", "f6", "f7", /* 20 21 22 23 */ - "fps", "cpsr" }; /* 24 25 */ - - -// Some USB stuff -GPN_DESC g_CommDesc; -GPN_COMM g_Comm; -const char HexDigits[17] = "0123456789abcdef"; -char g_SendBuffer[256]; -char g_TempBuffer[256]; -char g_ReadBuffer[0x100]; -unsigned int g_CurrentCSPR = 0; -unsigned int g_SavedStepInstruction = 0; -unsigned int g_StepAddress = 0; -bool g_LastWasStep = false; -int g_iTrap = 0; -bool g_GDBConnected = false; -/////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////// -// Prototypes -void BreakPoint(); -int GetException(unsigned int CSPR); -unsigned int *GetNextInstruction(unsigned int *pAddr); -bool CondWillExecute(unsigned int uiCond, unsigned int CSPR); -unsigned int DecodeInstruction(unsigned int uiInstruction, unsigned int PC); - -/////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////// -// Code Begins here -/////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////// -// Open usb comms stuff -int OpenUSB() -{ - int iResult; - - g_CommDesc.port_kind = COMM_USB_D; - g_CommDesc.tr_mode = 1; - g_CommDesc.tr_buf_size = PACKET_SIZE; - g_CommDesc.sz_pkt = PACKET_SIZE; - g_CommDesc.isr_comm_ram = 0; - - - iResult = GpCommCreate(&g_CommDesc, &g_Comm); - return iResult; -} - -/////////////////////////////////////////////////////////////// -// No need for explanation -void CloseUSB() -{ - GpCommDelete(&g_CommDesc); -} - -/////////////////////////////////////////////////////////////// -// No need for explanation -int SendUSB(const void *pData, unsigned int uiSize) -{ - return g_Comm.comm_send((unsigned char *)pData, uiSize); -} - - -/////////////////////////////////////////////////////////////// -// No need for explanation -int RecvUSB(char *pBuffer, unsigned int uiSize) -{ - return g_Comm.comm_recv((unsigned char *)pBuffer, uiSize); -} - -/////////////////////////////////////////////////////////////// -// Waits for an acknowledge from the server -void WaitACK() -{ - bool bBreak = false; - int iResult; - - while (!bBreak) { - iResult = g_Comm.comm_recv((unsigned char *)g_SendBuffer, 0x100); - if (iResult > 0) { - bBreak = true; - } - } -} -/////////////////////////////////////////////////////////////// -// Formats and sends a command to the server, -// it also calculates checksum -void SendCommand(unsigned char *pCommand) -{ - int iOffset; - unsigned int iCheckSum; - - iOffset = 4; - g_SendBuffer[iOffset++] = '$'; - - iCheckSum = 0; - while (*pCommand != 0) { - g_SendBuffer[iOffset++] = *pCommand; - iCheckSum += *pCommand++; - } - - g_SendBuffer[iOffset++] = '#'; - iCheckSum = iCheckSum & 0xff; - g_SendBuffer[iOffset++] = HexDigits[(iCheckSum & 0xf0) >> 4]; - g_SendBuffer[iOffset++] = HexDigits[(iCheckSum & 0x0f)]; - g_SendBuffer[iOffset] = 0; - - (*(int *)&g_SendBuffer[0]) = (iOffset - 4); - SendUSB(g_SendBuffer, 0x100); - WaitACK(); -} - -/////////////////////////////////////////////////////////////// -// This function creates and sends a package which tells gdb that -// the last command was unsupported -void UnSupportedCommand() -{ - (*(int *)&g_SendBuffer[0]) = 4; - g_SendBuffer[4] = '$'; - g_SendBuffer[5] = '#'; - g_SendBuffer[6] = '0'; - g_SendBuffer[7] = '0'; - g_SendBuffer[8] = '0'; - SendUSB(g_SendBuffer, 0x100); - - WaitACK(); - -} - - -/////////////////////////////////////////////////////////////// -// This function is quite similar to the SendCommand above -// But it allows the user to set the package length. -// If the length of a package exceeds 256bytes including -// the protocol stuff and the package length you can split -// the packages by sending the package size * -1. -// The server will then merge all packages until a package -// with a length >0 is recieved. -void SendCommandSize(unsigned char *pCommand, int iSize) -{ - int iOffset; - unsigned int iCheckSum; - - iOffset = 4; - g_SendBuffer[iOffset++] = '$'; - - iCheckSum = 0; - while (*pCommand != 0) { - g_SendBuffer[iOffset++] = *pCommand; - iCheckSum += *pCommand++; - } - - g_SendBuffer[iOffset++] = '#'; - iCheckSum = iCheckSum & 0xff; - g_SendBuffer[iOffset++] = HexDigits[(iCheckSum & 0xf0) >> 4]; - g_SendBuffer[iOffset++] = HexDigits[(iCheckSum & 0x0f)]; - g_SendBuffer[iOffset] = 0; - - (*(int *)&g_SendBuffer[0]) = iSize; - SendUSB(g_SendBuffer, 0x100); - - WaitACK(); -} - - -/////////////////////////////////////////////////////////////// -// Writes a 32bit hexadeciman number in ascii to the string. -void HexToString(char *pString, int iNumber) -{ - pString[0] = HexDigits[(iNumber >> 28) & 0x0f]; - pString[1] = HexDigits[(iNumber >> 24) & 0x0f]; - pString[2] = HexDigits[(iNumber >> 20) & 0x0f]; - pString[3] = HexDigits[(iNumber >> 16) & 0x0f]; - pString[4] = HexDigits[(iNumber >> 12) & 0x0f]; - pString[5] = HexDigits[(iNumber >> 8) & 0x0f]; - pString[6] = HexDigits[(iNumber >> 4) & 0x0f]; - pString[7] = HexDigits[(iNumber) & 0x0f]; - -} - -/////////////////////////////////////////////////////////////// -// This does the same, but in a differend endian. -void HexToStringBW(char *pString, int iNumber) -{ - pString[6] = HexDigits[(iNumber >> 28) & 0x0f]; - pString[7] = HexDigits[(iNumber >> 24) & 0x0f]; - pString[4] = HexDigits[(iNumber >> 20) & 0x0f]; - pString[5] = HexDigits[(iNumber >> 16) & 0x0f]; - pString[2] = HexDigits[(iNumber >> 12) & 0x0f]; - pString[3] = HexDigits[(iNumber >> 8) & 0x0f]; - pString[0] = HexDigits[(iNumber >> 4) & 0x0f]; - pString[1] = HexDigits[(iNumber) & 0x0f]; - - pString[8] = 0; - -} - - -/////////////////////////////////////////////////////////////// -// equiv to strcat i imagine -void PrintToString(char *pString, char *pOtherString) -{ - while (*pOtherString != 0) { - *pString = *pOtherString; - *pString++; - *pOtherString++; - } -} - -/////////////////////////////////////////////////////////////// -// converts "ff" -> 0xff -unsigned char StringToByte(char *pString) -{ - unsigned char ucValue = 0; - - for (int i = 0; i < 2; i++) { - ucValue = ucValue << 4; - switch(pString[i]) { - case '0': - break; - case '1': - ucValue |= (0x01); - break; - case '2': - ucValue |= (0x02); - break; - case '3': - ucValue |= (0x03); - break; - case '4': - ucValue |= (0x04); - break; - case '5': - ucValue |= (0x05); - break; - case '6': - ucValue |= (0x06); - break; - case '7': - ucValue |= (0x07); - break; - case '8': - ucValue |= (0x08); - break; - case '9': - ucValue |= (0x09); - break; - case 'a': - ucValue |= (0x0a); - break; - case 'b': - ucValue |= (0x0b); - break; - case 'c': - ucValue |= (0x0c); - break; - case 'd': - ucValue |= (0x0d); - break; - case 'e': - ucValue |= (0x0e); - break; - case 'f': - ucValue |= (0x0f); - break; - - } - } - - return ucValue; -} - -/////////////////////////////////////////////////////////////// -// Sends a package with the program offsets to GDB -// Of some reason all offsets should be NULL. -void SendOffsets() -{ - char String[255]; - int a = 0;//(int)&__text_start; - int b = 0;//(int)&__data_start; - int c = 0;//(int)&__bss_start; - - PrintToString(String, "Text="); - HexToString(&String[5], a); - PrintToString(&String[5+8], ";Data="); - HexToString(&String[5+8+6], b); - PrintToString(&String[5+8+6+8], ";Bss="); - HexToString(&String[5+8+6+8+5], c); - String[5+8+6+8+5+8] = 0; - - SendCommand((unsigned char *)String); -} - -/////////////////////////////////////////////////////////////// -// This function dumps all registers to GDB -// It utilizes the SendCommandSize function to split the package. -void DumpRegisters() -{ - char Buffer[0x100]; - // Ugly hack so far. - - for (int i = 0; i < 21; i++) { - //g_Registers[i] = i; - HexToStringBW(&Buffer[i * 8], g_Registers[i]); - } - Buffer[21*8] = 0; - SendCommandSize((unsigned char *)Buffer, -1 * (21 * 8 + 4)); - for (int i = 0; i < 21; i++) { - //g_Registers[20 + i] = i; - HexToStringBW(&Buffer[i * 8], g_Registers[21 + i]); - } - Buffer[21*8] = 0; - - SendCommandSize((unsigned char *)Buffer, (21 * 8) + 4); -} - -/////////////////////////////////////////////////////////////// -// This function extracts an address from a string. -void *GetAddr(char *pBuffer) -{ - int iAddr; - int i = 0; - iAddr = 0; - - while (pBuffer[i] != ',') { - iAddr = iAddr << 4; - switch(pBuffer[i]) { - case '0': - //iAddr |= - break; - case '1': - iAddr |= (0x01); - break; - case '2': - iAddr |= (0x02); - break; - case '3': - iAddr |= (0x03); - break; - case '4': - iAddr |= (0x04); - break; - case '5': - iAddr |= (0x05); - break; - case '6': - iAddr |= (0x06); - break; - case '7': - iAddr |= (0x07); - break; - case '8': - iAddr |= (0x08); - break; - case '9': - iAddr |= (0x09); - break; - case 'a': - iAddr |= (0x0a); - break; - case 'b': - iAddr |= (0x0b); - break; - case 'c': - iAddr |= (0x0c); - break; - case 'd': - iAddr |= (0x0d); - break; - case 'e': - iAddr |= (0x0e); - break; - case 'f': - iAddr |= (0x0f); - break; - - } - i++; - } - return (void *)iAddr; -} -/////////////////////////////////////////////////////////////// -// This function does pretty much the same, but returns an int -// I know, some redundant code. -int GetBytes(char *pBuffer) -{ - int iBytes = 0; - int i = 0; - - - while ((pBuffer[i] != '#') && (pBuffer[i] != ':')) { - iBytes = iBytes << 4; - switch(pBuffer[i]) { - case '0': - //iAddr |= - break; - case '1': - iBytes |= 0x01; - break; - case '2': - iBytes |= 0x02; - break; - case '3': - iBytes |= 0x03; - break; - case '4': - iBytes |= 0x04; - break; - case '5': - iBytes |= 0x05; - break; - case '6': - iBytes |= 0x06; - break; - case '7': - iBytes |= 0x07; - break; - case '8': - iBytes |= 0x08; - break; - case '9': - iBytes |= 0x09; - break; - case 'a': - iBytes |= 0x0a; - break; - case 'b': - iBytes |= 0x0b; - break; - case 'c': - iBytes |= 0x0c; - break; - case 'd': - iBytes |= 0x0d; - break; - case 'e': - iBytes |= 0x0e; - break; - case 'f': - iBytes |= 0x0f; - break; - - } - - i++; - } - return iBytes; -} - -/////////////////////////////////////////////////////////////// -// This function reads memory and sends it back to GDB. -void SendMemory(void *pAddr, int iBytes) -{ - unsigned char *pData; - unsigned char iData; - int iBufferPos = 0; - int iBytesToSend; - char Byte; - int i; - - pData = (unsigned char *)pAddr; - - - do { - if (iBytes > 100) { - iBytesToSend = 100; - iBytes -= 100; - } else { - iBytesToSend = iBytes; - iBytes = 0; - } - iBufferPos = 0; - for (i = 0; i < iBytesToSend; i+=1) { - iData = *pData++; - g_TempBuffer[iBufferPos++] = HexDigits[(iData & 0xf0) >> 4]; - g_TempBuffer[iBufferPos++] = HexDigits[(iData & 0x0f)]; - - } - if (iBytes > 0) { - // This mean that we have not yet sent our last command. - g_TempBuffer[iBufferPos] = 0; - SendCommandSize((unsigned char *)g_TempBuffer, -1 * (i + 1 + 4)); - } - } while (iBytes > 0 ); - g_TempBuffer[iBufferPos] = 0; - SendCommand((unsigned char *)g_TempBuffer); -} - - - -/////////////////////////////////////////////////////////////// -// Does pretty much what it says. -void WriteMemory(void *pAddr, unsigned int uiBytes, char *pHexString) -{ - unsigned char *pData = ((unsigned char *)pAddr); - unsigned int uiOffset = 0; - unsigned char ucByte; - - //Printf("0x%x 0x%x", pAddr, uiBytes); - for (unsigned int i = 0; i < uiBytes ; i++) { - ucByte = StringToByte(&pHexString[uiOffset]); - //Printf("0x%x", ucByte); - *pData++ = ucByte; - uiOffset += 2; - } - /* - while (1); - unsigned int *piData = (unsigned int *)pAddr; - *piData = 0xe7ffdefe;//0xfedeffe7; - */ - -} - - -/////////////////////////////////////////////////////////////// -// Sends the required information about a trap -// TODO: correct numbers need to be placed there. -void SendBreakPoint() -{ - int iOffset = 0; - - g_TempBuffer[iOffset++] = 'T'; - g_TempBuffer[iOffset++] = '0'; - g_TempBuffer[iOffset++] = '5'; - g_TempBuffer[iOffset++] = '0'; - g_TempBuffer[iOffset++] = 'd'; - g_TempBuffer[iOffset++] = ':'; - HexToStringBW(&g_TempBuffer[iOffset], g_Registers[_REG_SP]); - iOffset += 8; - g_TempBuffer[iOffset++] = ';'; - g_TempBuffer[iOffset++] = '0'; - g_TempBuffer[iOffset++] = 'b'; - g_TempBuffer[iOffset++] = ':'; - HexToStringBW(&g_TempBuffer[iOffset], g_Registers[_REG_FP]); - iOffset += 8; - g_TempBuffer[iOffset++] = ';'; - g_TempBuffer[iOffset++] = '0'; - g_TempBuffer[iOffset++] = 'f'; - g_TempBuffer[iOffset++] = ':'; - HexToStringBW(&g_TempBuffer[iOffset], g_Registers[_REG_PC]); - iOffset += 8; - g_TempBuffer[iOffset++] = ';'; - g_TempBuffer[iOffset] = 0; - - SendCommand((unsigned char *)g_TempBuffer); - - - - -} - - -/////////////////////////////////////////////////////////////// -// Finds a character in a string and returns the offset. -int FindChar(char *pBuffer, char sign) -{ - int iRetVal = 0; - - while (*pBuffer != sign) { - iRetVal++; - *pBuffer++; - } - return iRetVal; -} - - -// Attibute naked. -/////////////////////////////////////////////////////////////// -// This is the ISR(Interrupt Service Routine) which handles -// All traps, it's basically a context switcher. -void ISR() __attribute__ ((naked)); -void ISR() -{ - // Lets snatch the registers! - - asm volatile(" \n" - " str r4, [%0, #0x10] \n" - " str r5, [%0, #0x14] \n" - " str r6, [%0, #0x18] \n" - " str r7, [%0, #0x1C] \n" - " str r8, [%0, #0x20] \n" - " str r9, [%0, #0x24] \n" - " str r10, [%0, #0x28] \n" - " str r11, [%0, #0x2C] \n" - " str r12, [%0, #0x30] \n" - - " str r14, [%0, #0x3C] \n" - - " @// skip 8 * 12byte(96bit) = 0x60 \n" - - " mov r4, %0 \n" - " ldmia sp!, {r0, r1, r2, r3} \n" - " str r0, [r4, #0x00] \n" - " str r1, [r4, #0x04] \n" - " str r2, [r4, #0x08] \n" - " str r3, [r4,#0x0C] \n" - - " mrs r1, SPSR \n" - " str r1, [r4, #0x48] \n" - " str r1, [r4,#0xA0] \n" - " str r1, [r4,#0xA4] \n" - - " mrs r1, CPSR \n" - " mov r2, r1 \n" - - - " @// Let us set the mode to supervisor so we can get r13 and r14 \n" - " bic r1, r1, #0x1f \n" - " orr r1, r1, #0x13 \n" - " msr CPSR_c, r1 \n" - " @// Just remember that we're in the supervisor stack aswell now \n" - " str r13, [r4,#0x34] \n" - " str r14, [r4,#0x38] \n" - " @// Lets move back to whatever mode we was in. \n" - " @// Make sure that IRQ's are turned on \n" - " bic r2, r2, #0x80 \n" - " msr CPSR_fsxc, r2 \n" - - - - - " \n" - : - : "r" (g_Registers) - : "%0", "r1", "r2", "r4"); - - - // Get Current CSPR and save LR - asm volatile(" \n" - " mrs r0, CPSR \n" - " str r0, [%0] \n" - - " str r14, [%1, #0x40] \n" - " str r0, [%1, #0x44] \n" - " str r13, [%1, #0x4C] \n" - " \n" - : - : "r" (&g_CurrentCSPR), "r" (g_Registers) - : "r0"); - - - switch(g_CurrentCSPR & 0x1f) { - case 0x10: // USER - g_iTrap = 0; - break; - case 0x11: // FIQ - g_iTrap = 1; - break; - case 0x12: // IRQ - g_iTrap = 2; - break; - case 0x13: // Supervisor - g_iTrap = 3; - break; - case 0x17: // Abort - g_iTrap = 4; - break; - case 0x1B: // Undefined/Breakpoint - // We cannot continue like this! - g_Registers[15] -= 4; - g_Registers[16] -= 4; - g_iTrap = 5; - break; - case 0x1F: // System - g_iTrap = 6; - break; - default: - g_iTrap = -1; - } - - - #ifdef USE_PRINTF - Printf("Trap@0x%x:%d", g_Registers[15], g_iTrap); - #endif - /* - switch (g_iTrap) { - case MODE_USER: - break; - case MODE_FIQ: - break; - case MODE_IRQ: - break; - case MODE_SUPERVISOR: - break; - case MODE_ABORT: - break; - case MODE_UNDEF: - break; - case MODE_SYSTEM: - break; - case MODE_DUNNO: - default: - while (1); - } - */ - SendBreakPoint(); - BreakPoint(); - - //Printf("0x%x 0x%x", g_Registers[15], g_Registers[16]); - // Okay, it's time to continue. - - - switch (g_iTrap) { - case MODE_USER: - //Printf("Dunno!!\n"); - break; - case MODE_FIQ: - //Printf("Dunno!!\n"); - break; - case MODE_IRQ: - //Printf("Dunno!!\n"); - break; - case MODE_SUPERVISOR: - //Printf("Dunno!!\n"); - break; - case MODE_ABORT: - asm volatile(" \n" - " mov r10, #0 \n" - " @Invalidate I&D cache \n" - " mcr p15, 0, r10, c7, c7 \n" - " @ restore the registers \n" - " ldr r1,[%0, #0x04] \n" - " ldr r2,[%0, #0x08] \n" - " ldr r4,[%0, #0x10] \n" - " ldr r5,[%0, #0x14] \n" - " ldr r6,[%0, #0x18] \n" - " ldr r7,[%0, #0x1C] \n" - " ldr r8,[%0, #0x20] \n" - " ldr r9,[%0, #0x24] \n" - " ldr r10,[%0, #0x28] \n" - " ldr r11,[%0, #0x2C] \n" - " ldr r12,[%0, #0x30] \n" - " ldr r14,[%0, #0x40] \n" - " ldr r0, [%0, #0x44] \n" - " msr CPSR_fsxc, r0 \n" - " ldr r0, [%0, #0x48] \n" - " msr SPSR_fsxc, r0 \n" - - " ldr r0,[%0, #0x00] \n" - " ldr r3,[%0, #0x0C] \n" - - " subs pc, lr, #0x04 \n" - - " \n" - : - :"r" (g_Registers) - :"r0"); - break; - case MODE_UNDEF: - // This will be the breakpoint i'm gonna test with. - asm volatile(" \n" - " mov r10, #0 \n" - " @Invalidate I&D cache \n" - " mcr p15, 0, r10, c7, c7 \n" - " @ restore the registers \n" - " ldr r1,[%0, #0x04] \n" - " ldr r2,[%0, #0x08] \n" - " ldr r4,[%0, #0x10] \n" - " ldr r5,[%0, #0x14] \n" - " ldr r6,[%0, #0x18] \n" - " ldr r7,[%0, #0x1C] \n" - " ldr r8,[%0, #0x20] \n" - " ldr r9,[%0, #0x24] \n" - " ldr r10,[%0, #0x28] \n" - " ldr r11,[%0, #0x2C] \n" - " ldr r12,[%0, #0x30] \n" - " ldr r14,[%0, #0x40] \n" - " ldr r0, [%0, #0x44] \n" - " msr CPSR_fsxc, r0 \n" - " ldr r0, [%0, #0x48] \n" - " msr SPSR_fsxc, r0 \n" - - " ldr r0,[%0, #0x00] \n" - " ldr r3,[%0, #0x0C] \n" - " @ The subbing has already been done! \n" - " @subs pc, lr, #0x04 \n" - " movs pc, lr \n" - " \n" - : - :"r" (g_Registers) - :"r0"); - - - break; - case MODE_SYSTEM: - //Printf("Dunno!!\n"); - break; - case MODE_DUNNO: - default: - //Printf("Dunno!!\n"); - while (1); - } - - - - -} - -/////////////////////////////////////////////////////////////// -// Returns which exception occured based on CSPR -int GetException(unsigned int CSPR) -{ - switch(CSPR & 0x1f) { - case 0x10: // USER - return 0; - case 0x11: // FIQ - return 1; - case 0x12: // IRQ - return 2; - case 0x13: // Supervisor - return 3; - case 0x17: // Abort - return 4; - case 0x1B: // Undefined/Breakpoint - return 5; - case 0x1F: // System - return 6; - default: - return -1; - } -} - - -/////////////////////////////////////////////////////////////// -// Installs the ISR address into the system RAM -void InstallISR() -{ - int *pPointer = (int *)(0x0c7ac040); - int *pPointer2 = (int *)(0x0c7ac018); - - void (*pISR)(); - - pISR = ISR; - - *pPointer = (int)pISR; - *pPointer2 = (int)pISR; - -} - -void DEBUG_Print(char *pFormat, ...) -{ - char Temp[0x100]; - va_list VaList; - int iLength; - int iOffset; - unsigned char MyChar; - - if (!g_GDBConnected) return; - - va_start(VaList , pFormat); - vsnprintf(Temp, 0x100, pFormat , VaList); - va_end(VaList); - - iLength = strlen(Temp); - if (iLength > 100) iLength = 100; - - g_TempBuffer[0] = 'O'; - iOffset = 1; - for (int i = 0; i < iLength; i++) { - MyChar = (unsigned char)Temp[i]; - g_TempBuffer[iOffset++] = HexDigits[(MyChar & 0xf0) >> 4]; - g_TempBuffer[iOffset++] = HexDigits[(MyChar & 0x0f)]; - } - g_TempBuffer[iOffset] = 0; - SendCommand((unsigned char *)g_TempBuffer); - -} - - -/////////////////////////////////////////////////////////////// -// The main thread when the GDB thread has control -void BreakPoint() -{ - unsigned int *pNextInstruction; - bool bBreakLoop = false; - int iResult; - int iMessageLength; - int iOffsetAdd; - int iNullVal = 0; - void *pAddr; - int iOffset; - int iBytes; - - - // Find out if we got here through a STEP command - if (g_LastWasStep) { - #ifdef USE_PRINTF - Printf("I:0x%x 0x%x", *((unsigned int *)(g_Registers[15] + 4)), *((unsigned int *)(g_Registers[15]))); - Printf("S: 0x%x", g_StepAddress); - #endif - if ((unsigned int)g_Registers[15] == g_StepAddress) { - // Yes it was, Lets restore the instruction. - *((unsigned int *)g_StepAddress) = g_SavedStepInstruction; - #ifdef USE_PRINTF - Printf("Restore: 0x%x", g_SavedStepInstruction); - #endif - } else { - while (1); - } - g_LastWasStep = false; - } - - - while (!bBreakLoop) { - iResult = RecvUSB(g_ReadBuffer, 0x100); - //Printf("%d\n", iResult); - - if (iResult > 0) { - // If we recieve a package we can assume that GDB is connected.. or smth..:D - g_GDBConnected = true; - // Well, we have recieved a package, lets print the contents. - iMessageLength = *(int *)&g_ReadBuffer[0]; - g_ReadBuffer[4 + iMessageLength] = 0; - //Printf("%s\n %d", &g_ReadBuffer[4], iMessageLength); - - // Let us also send an ACK '+' - (*(int *)&g_SendBuffer[0]) = 1; - g_SendBuffer[4] = '+'; - SendUSB((const void *)g_SendBuffer, 0x100); - WaitACK(); - - // I can see that i get a bunch of '+' and '-' in the messages.. lets remove them. - iOffsetAdd = 4; - while ((g_ReadBuffer[iOffsetAdd] == '+') || (g_ReadBuffer[iOffsetAdd] == '-')) iOffsetAdd++; - - // Check whether it's legimit command - if (g_ReadBuffer[iOffsetAdd] == '$') { - // Well it is! - switch(g_ReadBuffer[iOffsetAdd + 1]) { - case 'H': // Set thread, we're not having any threads.. so.. just return OK - SendCommand((unsigned char *)"OK"); - break; - case 'q': // Query, there are some queries, but GDB first asks for Offsets - switch(g_ReadBuffer[iOffsetAdd + 2]) { - case 'O': // Offsets - SendOffsets(); - break; - case 'C': - SendCommand((unsigned char *)"QC0000"); - //SendBreakPoint(); - break; - - } - break; - case '?': - // This will have to be modified later to send the correct signal. - SendBreakPoint(); - break; - case 'g': - DumpRegisters(); - break; - case 'm': - pAddr = GetAddr(&g_ReadBuffer[iOffsetAdd + 2]); - iOffset = FindChar(&g_ReadBuffer[iOffsetAdd + 2], ','); - iBytes = GetBytes(&g_ReadBuffer[iOffsetAdd + 2 + iOffset]); - SendMemory(pAddr, iBytes); - break; - case 'X': //Write memory binary, which we DON't support.. ofcourse. - UnSupportedCommand(); - break; - case 'P': // Write register - { - SendCommand((unsigned char *)"OK"); - - } - break; - case 'M': // Write memory not binary - { - pAddr = GetAddr(&g_ReadBuffer[iOffsetAdd + 2]); - iOffset = FindChar(&g_ReadBuffer[iOffsetAdd + 2], ','); - iBytes = GetBytes(&g_ReadBuffer[iOffsetAdd + 2 + iOffset]); - iOffset = FindChar(&g_ReadBuffer[iOffsetAdd + 2], ':'); - WriteMemory(pAddr, iBytes, &g_ReadBuffer[iOffsetAdd + 2 + iOffset + 1]); - SendCommand((unsigned char *)"OK"); - - } - break; - case 'c': // continue - { - return; - - } - break; - - case 's': // Stepping. - { - // Get the address of the next instruction. - pNextInstruction = GetNextInstruction((unsigned int *)g_Registers[15]); - - // Read whatsever there. - g_SavedStepInstruction = *pNextInstruction; - g_StepAddress = (unsigned int)pNextInstruction; - g_LastWasStep = true; - - //Printf("Curr: 0x%x", g_Registers[15]); - #ifdef USE_PRINTF - Printf("Next: 0x%x->0x%x", g_Registers[15], pNextInstruction); - #endif - //Printf("Trap: 0x%x", GetException((unsigned int)g_Registers[40])); - // Write a breakpoint instruction to the address. - *pNextInstruction = 0xe7ffdefe; - return; - - } - break; - case 'Z': // BreakPoint. - { - switch(g_ReadBuffer[iOffsetAdd + 2]) { - case '0': - // Software breakpoint, i think it's up to me to add, it, lets send OK for now. - UnSupportedCommand(); - break; - default: - // We only support software breakpoints for now, lets return unsupported. - // Actually we don't even support SW breakpoints now - UnSupportedCommand(); - break; - } - } - break; - - default: - UnSupportedCommand(); - break; - - } - } - - } - - } - -} - -/////////////////////////////////////////////////////////////// -// Tries to find the next instruction to be executed after a break -unsigned int *GetNextInstruction(unsigned int *pAddr) -{ - unsigned int uiInstruction = *pAddr; - unsigned int uiAndVal = 0; - unsigned int iNewPC = 0; - int iNewAddr = 0; - int iRegsbeforePC = 0; - unsigned int uiBaseRegister = 0; - unsigned int uiRegVal = 0; - unsigned int uiData = 0; - unsigned int uiCondMask = 0; - int iPCOffset = 0; - - unsigned int uiNewPC = DecodeInstruction(uiInstruction, (unsigned int)pAddr); - return (unsigned int *)uiNewPC; - - - // Set new PC to pAddr + 4, because we really hope that is the case...:D - iNewPC = (unsigned int)pAddr; - iNewPC += 4; // Next instruction (atleast in ARM mode, we don't support thumb yet) - - // Now it's a good point to find out if the instruction would be executed anyway. - uiCondMask = (uiInstruction & 0xf0000000) >> 28; - - if (CondWillExecute(uiCondMask, (unsigned int)g_Registers[18])) { - //Printf("Condition will execute"); - // Find out if it's a B or BL instruction. (This is the easy one) - if ((uiInstruction & 0xE000000 ) == 0xA000000) { - #ifdef USE_PRINTF - Printf("0x%x", uiInstruction); - #endif - // Okay, it's a branch instruction, lets get the address it's for - iNewAddr = uiInstruction & 0xffffff; - // We might need to sign extend this instruction. - if ((iNewAddr & 0x00800000) != 0) { - #ifdef USE_PRINTF - printf("Sign extending"); - #endif - //iNewAddr *= -1; - iNewAddr |= 0xff000000; - } - #ifdef USE_PRINTF - Printf("0x%x", iNewAddr); - #endif - iNewAddr *= 4; // Instruction size. - iNewPC = ((int)pAddr + iNewAddr + 8); - } - - // Well, it might be a ldm(ea)? - - if ((uiInstruction & 0xE000000) == 0x8000000) { - #ifdef USE_PRINTF - Printf("LDM"); - #endif - // this is a LDM/STM alright. - if ((uiInstruction & 0x100000) != 0) { - // This is a LDM instruction - // Lets see if the PC is ever loaded. - #ifdef USE_PRINTF - Printf("includes PC"); - #endif - if ((uiInstruction & 0x8000) != 0) { - // Well (damn the PC is loaded) - for (int i = 0; i < 15; i++) { - uiAndVal = 1 << i; - if ((uiInstruction & uiAndVal) != 0) iRegsbeforePC++; - } - #ifdef USE_PRINTF - Printf("%d regs", iRegsbeforePC); - #endif - /* - <mr_spiv> da = fa - <mr_spiv> ia = fd - <mr_spiv> db = ea - <mr_spiv> ib = ed - */ - // Lets find out which register is used as base for this operation. - uiBaseRegister = (uiInstruction & 0xF0000) >> 16; - uiRegVal = ((unsigned int *)g_Registers)[uiBaseRegister]; - // First, have a look at the U bit. - if ((uiInstruction & (1 << 23)) != 0) { - - // Transfer is made descending - // Which also means that the PC is closest to the base register i just found out. - // Lets check the P bit (If i'm supposed to increment before or after. - - iPCOffset = iRegsbeforePC * 4; - if (((uiInstruction) & (1 << 24)) != 0) iPCOffset += 4; - - } else { - // Transfer is done ascending - // Lets check the P bit (If i'm supposed to decrement before or after. - if (((uiInstruction) & (1 << 24)) != 0) iPCOffset = -4; - } - - - iNewPC = *(unsigned int *)((((int)uiRegVal) + iPCOffset) & ~0x03); - } - } - } - - // Check if it's a mov pc, Rn - - } - - return (unsigned int *)iNewPC; -} - -/////////////////////////////////////////////////////////////// -// Determines if uiCond will be true with this CSPR -bool CondWillExecute(unsigned int uiCond, unsigned int CSPR) -{ - - switch(uiCond) { - case 0: // EQ - // This is true if Z is set in CSPR - if ((CSPR & (1 << 30)) != 0) return true; - else return false; - case 1: // NE - // This should be true if Z is not set. - if ((CSPR & (1 << 30)) == 0) return true; - else return false; - case 2: // CS/HS - // this one should be true if C is set. - if ((CSPR & (1 << 29)) != 0) return true; - else return false; - case 3: // CC/LO - // this one should be true if C is clear. - if ((CSPR & (1 << 29)) == 0) return true; - else return false; - case 4: // MI - // this one should be true if N is set - if ((CSPR & (1 << 31)) != 0) return true; - else return false; - case 5: // PL - // this one should be true if N is clear. - if ((CSPR & (1 << 31)) == 0) return true; - else return false; - case 6: // VS - // this one should be true if V is set - if ((CSPR & (1 << 28)) != 0) return true; - else return false; - case 7: // VC - // this one should be true if V is clear. - if ((CSPR & (1 << 28)) == 0) return true; - else return false; - case 8: // HI - // This is true if C and Z is clear - if (((CSPR & (1 << 30)) == 0) && ((CSPR & (1 << 29)) == 0)) return true; - else return false; - case 9: // LS - // C clear OR Z set - if (((CSPR & (1 << 29)) == 0) || ((CSPR & (1 << 30)) != 0)) return true; - else return false; - case 10: // GE - // N set AND V set || N clear and V clear - if ((CSPR & (1 << 31)) == (CSPR & (1 << 28))) return true; - else return false; - case 11: // LT - // N != V - if ((CSPR & (1 << 31)) != (CSPR & (1 << 28))) return true; - else return false; - case 12: // GT - // Z == 0, N == V - if (((CSPR & (1 << 30)) == 0) && ((CSPR & (1 << 31)) == (CSPR & (1 << 28)))) return true; - else return false; - case 13: // LE - if (((CSPR & (1 << 30)) == 1) && ((CSPR & (1 << 31)) != (CSPR & (1 << 28)))) return true; - else return false; - case 14: // AL - return true; - default: - break; - } - - -} -// I got the idea for this layout from the singlestep.c (found in eCos) -// But i thought the code was a bit tricky to port, and i wanna learn more about this anyway so, i'll just do smth similar to that - - - -typedef struct -{ - unsigned Rm : 4; // Rm - unsigned resv2 : 1; // Reserved 2 (0) - unsigned shift : 2; // hmm.. dunno actually but probably (LSL, LSR, ASR, ROR ) - unsigned amount : 5; // Shift amount 0-31 - unsigned Rd : 4; // Rd - unsigned Rn : 4; // Rn - unsigned s : 1; // S-flag - unsigned opcode : 4; // Opcode (Mov etc) - unsigned resv1 : 3; // Reserved 1 (000) - unsigned cond : 4; // Condition - -} dpisr; // Data Processing Immediate Register Shift -#define DPISR_R1 0 -#define DPISR_R2 0 -// Example <opcode> Rd, Rm, <shift> amount -typedef struct -{ - unsigned Rm : 4; // Rm - unsigned resv3 : 1; // Reserved 3 (1) - unsigned shift : 2; // (LSL, LSR, ASR, ROR ) - unsigned resv2 : 1; // Reserved 2 (0) - unsigned Rs : 4; // Rs - unsigned Rd : 4; // Rd - unsigned Rn : 4; // Rn - unsigned s : 1; // S-flag - unsigned opcode : 4; // Opcode - unsigned resv1 : 3; // Reserved 1 (000) - unsigned cond : 4; // Condition -} dprrs; // Data Processing Register Register Shift -#define DPRRS_R1 0 -#define DPRRS_R2 0 -#define DPRRS_R3 1 -// Example <opcode> Rd, Rn, Rm <shift> Rs -// This intruction is unpredictable if R15 is one of the used registers anyway. -typedef struct -{ - unsigned immed : 8; // Immediate value - unsigned rotate : 4; // rotate - unsigned Rd : 4; // Rd - unsigned Rn : 4; // Rn - unsigned s : 1; // S-flag - unsigned opcode : 4; // Opcode - unsigned resv1 : 3; // Reserved 1 (001) - unsigned cond : 4; // Condition -} dpi; // Data processing immediate -// example add r0, r1, (ror <immed>, <rotate * 2>) -#define DPI_R1 1 - -typedef struct -{ - unsigned immed : 12; // Immediate - unsigned Rd : 4; // Rd - unsigned Rn : 4; // Rn - unsigned L : 1; // L-bit (Load/Store)? - unsigned W : 1; // W-bit - unsigned B : 1; // B-bit - unsigned U : 1; // U-bit - unsigned p : 1; // P-bit - unsigned resv1 : 3; // Reserved 1 (010) - unsigned cond : 4; // Condition -} lsio; // Load/store immediate offset -// Example ldr Rd, [Rn, #<immed>] -#define LSIO_R1 2 - - -typedef struct -{ - unsigned Rm : 4; // Rm - unsigned resv2 : 1; // Reserved 2 (0) - unsigned shift : 2; // Shit type (LSL, LSR, ASR, ROR ) - unsigned amount : 5; // Shift amount (0-31) - unsigned Rd : 4; // Rd - unsigned Rn : 4; // Rn - unsigned L : 1; // L-bit (Load/Store)? - unsigned W : 1; // W-bit - unsigned B : 1; // B-bit - unsigned U : 1; // U-bit - unsigned p : 1; // P-bit - unsigned resv1 : 3; // Reserved 1 (011) - unsigned cond : 4; // Condition -} lsro; // Load/Store register offset -// Example ldr Rd, [Rn + Rm lsl 5] -#define LSRO_R1 3 -#define LSRO_R2 0 - - -typedef struct -{ - unsigned regs : 16; // Register mask - unsigned Rn : 4; // Rn - unsigned L : 1; // L-bit (Load/Store)? - unsigned W : 1; // W-bit - unsigned S : 1; // B-bit - unsigned U : 1; // U-bit - unsigned p : 1; // P-bit - - unsigned resv1 : 3; // Reserved 1 (100) - unsigned cond : 4; // Condition -} lsm; // Load store multiple -// Example: ldm r0, {r1, r2, r3} -#define LSM_R1 4 - -typedef struct -{ - unsigned offset : 24; // Branch offset - unsigned link : 1; // Link flag - unsigned resv1 : 3; // Reserved 1 (101) - unsigned cond : 4; // Condition -} bl; // Branch with link(optional) -#define BL_R1 5 - -typedef union { - dpisr DPISR; - dprrs DPRRS; - dpi DPI; - lsio LSIO; - lsro LSRO; - lsm LSM; - bl BL; - unsigned int uiInstruction; -} Instruction; - -/* -#define DPISR_R1 0 -#define DPISR_R2 0 - - -#define DPRRS_R1 0 -#define DPRRS_R2 0 -#define DPRRS_R3 1 - -#define DPI_R1 1 - -#define LSIO_R1 2 - -#define LSRO_R1 3 -#define LSRO_R2 0 - -#define LSM_R1 4 - -#define BL_R1 5 -*/ - -/* - * Data Processiong Opcode field values - */ -#define OPCODE_MOV 0xD -#define OPCODE_MVN 0xF -#define OPCODE_ADD 0x4 -#define OPCODE_ADC 0x5 -#define OPCODE_SUB 0x2 -#define OPCODE_SBC 0x6 -#define OPCODE_RSB 0x3 -#define OPCODE_RSC 0x7 -#define OPCODE_AND 0x0 -#define OPCODE_EOR 0x1 -#define OPCODE_ORR 0xC -#define OPCODE_BIC 0xE -#define OPCODE_CMP 0xA -#define OPCODE_CMN 0xB -#define OPCODE_TST 0x8 -#define OPCODE_TEQ 0x9 - -/* - * Shift field values - */ -#define SHIFT_LSL 0x0 -#define SHIFT_LSR 0x1 -#define SHIFT_ASR 0x2 -#define SHIFT_ROR 0x3 -#define SHIFT_RRX 0x3 /* Special case: ROR(0) implies RRX */ - - -unsigned int DecodeDPISR(dpisr Instr, unsigned int PC); -unsigned int DecodeDPRRS(dprrs Instr, unsigned int PC); -unsigned int DecodeDPI(dpi Instr, unsigned int PC); -unsigned int DecodeLSIO(lsio Instr, unsigned int PC); -unsigned int DecodeLSRO(lsro Instr, unsigned int PC); -unsigned int DecodeLSM(lsm Instr, unsigned int PC); -unsigned int DecodeBL(bl Instr, unsigned int PC); - - -/////////////////////////////////////////////////////////////// -// -unsigned int DecodeInstruction(unsigned int uiInstruction, unsigned int PC) -{ - Instruction myInstruction; - unsigned int uiCondMask; - - uiCondMask = (uiInstruction & 0xf0000000) >> 28; - - // This instruction can do whatever it wants, but if it doesn't execute we don't give a shit. - if (!CondWillExecute(uiCondMask, (unsigned int)g_Registers[18])) return PC + 4; - //Printf("CondWillExec"); - - myInstruction.uiInstruction = uiInstruction; - - // Start decoding.. phuu - - if ((myInstruction.DPISR.resv1 == DPISR_R1) && (myInstruction.DPISR.resv2 == DPISR_R2)) return DecodeDPISR(myInstruction.DPISR, PC); - else if ((myInstruction.DPRRS.resv1 == DPRRS_R1) && - (myInstruction.DPRRS.resv2 == DPRRS_R2) && - (myInstruction.DPRRS.resv3 == DPRRS_R3)) return DecodeDPRRS(myInstruction.DPRRS, PC); - else if ((myInstruction.DPI.resv1 == DPI_R1)) return DecodeDPI(myInstruction.DPI, PC); - else if ((myInstruction.LSIO.resv1 == LSIO_R1)) return DecodeLSIO(myInstruction.LSIO, PC); - - else if ((myInstruction.LSRO.resv1 == LSRO_R1) && - (myInstruction.LSRO.resv2 == LSRO_R2)) return DecodeLSRO(myInstruction.LSRO, PC); - else if (myInstruction.LSM.resv1 == LSM_R1) return DecodeLSM(myInstruction.LSM, PC); - else if (myInstruction.BL.resv1 == BL_R1) return DecodeBL(myInstruction.BL, PC); - - return 0; -} - -/////////////////////////////////////////////////////////////// -// -unsigned int LSL(unsigned int uiValue, unsigned int uiSteps) -{ - return uiValue << uiSteps; -} - -/////////////////////////////////////////////////////////////// -// -unsigned int LSR(unsigned int uiValue, unsigned int uiSteps) -{ - return uiValue >> uiSteps; -} - -/////////////////////////////////////////////////////////////// -// -// This one could be trickier since, i'm nor sure if a signed shift really is a signed shift. -unsigned int ASR(unsigned int uiValue, unsigned int uiSteps) -{ - unsigned int uiSignMask = 0; - - // Check if it's a negative number - if (uiValue & 0x80000000) { - // Yes, damn - uiSignMask = ((~0) << (32 - uiSteps)); - } - - return ((uiValue >> uiSteps) | uiSignMask); -} - -/////////////////////////////////////////////////////////////// -// -unsigned int ROR(unsigned int uiValue, unsigned int uiSteps) -{ - unsigned int uiRetval; - - while (uiSteps-- > 0) { - if (uiValue & 0x01) { - uiValue = (uiValue >> 1) | 0x80000000; - } else { - uiValue = uiValue >> 1; - } - } - return uiValue; -} - - -/////////////////////////////////////////////////////////////// -// -unsigned int Shift_Operand(unsigned int Rm, unsigned int amount, unsigned int shift) -{ - unsigned int uiRegisterValue; - - - - - uiRegisterValue = g_Registers[Rm]; - if (Rm == 0x0f) { - // Rm is PC, and PC is offseted by 8. - uiRegisterValue += 8; - } - - // Determine the shift mode. - //(LSL, LSR, ASR, ROR ) - switch (shift) { - case 0: // LSL - return LSL(uiRegisterValue, amount); - case 1: // LSR - return LSR(uiRegisterValue, amount); - case 2: // ASR - return ASR(uiRegisterValue, amount); - case 3: // ROR - return ROR(uiRegisterValue, amount); - default: - break; - } - return 0; -} - -/////////////////////////////////////////////////////////////// -// -// Example <opcode> Rd, Rm, <shift> amount -unsigned int DecodeDPISR(dpisr Instr, unsigned int uiPC) -{ - unsigned int uiOperand = Shift_Operand(Instr.Rm, Instr.amount, Instr.shift); - unsigned int uiRnVal = g_Registers[Instr.Rn]; - - - - // Only do this i Pc is Rd - if (Instr.Rd != 0x0f) return uiPC + 4; - - // The actual value that PC contains when executing this instruction is the instruction address+8 - if (Instr.Rn == 0x0f) uiRnVal += 8; - - // Check what opcode it is! - switch (Instr.opcode) { - case OPCODE_MOV: - return uiOperand; - case OPCODE_MVN: - return ~uiOperand; - case OPCODE_ADD: - return uiRnVal + uiOperand; - case OPCODE_ADC: - return uiRnVal + uiOperand + (((g_Registers[18] & (1 << 29))) == 0?0:1); - case OPCODE_SUB: - return uiRnVal - uiOperand; - case OPCODE_SBC: - return uiRnVal - uiOperand - (((g_Registers[18] & (1 << 29))) == 0?1:0); - case OPCODE_RSB: - return uiOperand - uiRnVal; - case OPCODE_RSC: - return uiOperand - uiRnVal - (((g_Registers[18] & (1 << 29))) == 0?1:0); - case OPCODE_AND: - return (uiRnVal & uiOperand); - case OPCODE_EOR: - return (uiRnVal^uiOperand); - case OPCODE_ORR: - return (uiRnVal | uiOperand); - case OPCODE_BIC: - return (uiRnVal & ~uiOperand); - default: - return 0; - } -} - - -/////////////////////////////////////////////////////////////// -// -//dprrs; // Data Processing Register Register Shift -// Example <opcode> Rd, Rn, Rm <shift> Rs -unsigned int DecodeDPRRS(dprrs Instr, unsigned int uiPC) -{ - unsigned int uiRmValue = g_Registers[Instr.Rm]; - unsigned int uiRsValue = g_Registers[Instr.Rs]; - unsigned int uiRnVal = g_Registers[Instr.Rn]; - if ((Instr.Rm = 0x0f)) uiRmValue += 8; - - - unsigned int uiOperand = Shift_Operand(uiRmValue, uiRsValue, Instr.shift); - - // Check if destination is PC - if (Instr.Rd != 0x0f) return uiPC + 4; - if ((Instr.Rn = 0x0f)) uiRnVal += 8; - - // Check what opcode it is! - switch (Instr.opcode) { - case OPCODE_MOV: - return uiOperand; - case OPCODE_MVN: - return ~uiOperand; - case OPCODE_ADD: - return uiRnVal + uiOperand; - case OPCODE_ADC: - return uiRnVal + uiOperand + (((g_Registers[18] & (1 << 29))) == 0?0:1); - case OPCODE_SUB: - return uiRnVal - uiOperand; - case OPCODE_SBC: - return uiRnVal - uiOperand - (((g_Registers[18] & (1 << 29))) == 0?1:0); - case OPCODE_RSB: - return uiOperand - uiRnVal; - case OPCODE_RSC: - return uiOperand - uiRnVal - (((g_Registers[18] & (1 << 29))) == 0?1:0); - case OPCODE_AND: - return (uiRnVal & uiOperand); - case OPCODE_EOR: - return (uiRnVal^uiOperand); - case OPCODE_ORR: - return (uiRnVal | uiOperand); - case OPCODE_BIC: - return (uiRnVal & ~uiOperand); - default: - return 0; - } - -} - -/////////////////////////////////////////////////////////////// -// -// dpi; // Data processing immediate -// example add r0, r1, (ror <immed>, <rotate * 2>) -unsigned int DecodeDPI(dpi Instr, unsigned int uiPC) -{ - unsigned int uiOperand = (ROR(Instr.immed, Instr.rotate << 1)); - unsigned int uiRnVal = g_Registers[Instr.Rn]; - - // Check if PC is destination - if (Instr.Rd != 0x0f) return uiPC + 4; // Next instruction - if ((Instr.Rn = 0x0f)) uiRnVal += 8; - - // Check what opcode it is! - switch ((Instr.opcode)) { - case OPCODE_MOV: - return uiOperand; - case OPCODE_MVN: - return ~uiOperand; - case OPCODE_ADD: - return uiRnVal + uiOperand; - case OPCODE_ADC: - return uiRnVal + uiOperand + (((g_Registers[18] & (1 << 29))) == 0?0:1); - case OPCODE_SUB: - return uiRnVal - uiOperand; - case OPCODE_SBC: - return uiRnVal - uiOperand - (((g_Registers[18] & (1 << 29))) == 0?1:0); - case OPCODE_RSB: - return uiOperand - uiRnVal; - case OPCODE_RSC: - return uiOperand - uiRnVal - (((g_Registers[18] & (1 << 29))) == 0?1:0); - case OPCODE_AND: - return (uiRnVal & uiOperand); - case OPCODE_EOR: - return (uiRnVal^uiOperand); - case OPCODE_ORR: - return (uiRnVal | uiOperand); - case OPCODE_BIC: - return (uiRnVal & ~uiOperand); - default: - return 0; - } - -} - -/////////////////////////////////////////////////////////////// -// -// lsio; // Load/store immediate offset -// Example ldr Rd, [Rn, #<immed>] -unsigned int DecodeLSIO(lsio Instr, unsigned int uiPC) -{ - unsigned int uiRnValue = g_Registers[Instr.Rn]; - unsigned int uiMemValue; - - // Check if destination is PC - if (Instr.Rd != 0x0f) return uiPC + 4; - // Check if it's a LDR instruction - if (Instr.L != 1) return uiPC + 4; - - if (Instr.Rn == 0x0f) uiRnValue += 8; - - // Check if it's pre-indexed - if (Instr.p == 1){ - - if (Instr.U == 1) { - // Add offset - uiRnValue += Instr.immed; - } else { - // Sub offset - uiRnValue -= Instr.immed; - } - } - - uiMemValue = *(unsigned int *)(uiRnValue); - - return uiMemValue; - -} - -/////////////////////////////////////////////////////////////// -// -// lsro; // Load/Store register offset -// Example ldr Rd, [Rn + Rm lsl 5] -unsigned int DecodeLSRO(lsro Instr, unsigned int uiPC) -{ - unsigned int uiRnValue = g_Registers[Instr.Rn]; - unsigned int uiRmValue = g_Registers[Instr.Rm]; - unsigned int uiIndex; - unsigned int uiMemValue; - - if (Instr.Rm == 0x0f) uiRmValue += 8; - if (Instr.Rn == 0x0f) uiRnValue += 8; - - // Check if destination is PC and that it's LDR instruction - if ((Instr.Rd != 0x0f) || (Instr.L != 1)) return uiPC + 4; - - uiIndex = Shift_Operand(Instr.Rm, Instr.amount, Instr.shift); - - if (Instr.p == 1){ - - if (Instr.U == 1) { - // Add offset - uiRnValue += uiIndex; - } else { - // Sub offset - uiRnValue -= uiIndex; - } - } - - uiMemValue = *(unsigned int *)(uiRnValue); - - return uiMemValue; - - -} -/////////////////////////////////////////////////////////////// -// -// lsm; // Load store multiple -// Example: ldm r0, {r1, r2, r3} -unsigned int DecodeLSM(lsm Instr, unsigned int uiPC) -{ - unsigned int uiRnValue = g_Registers[Instr.Rn]; - unsigned int uiOffsetToPC = 0; - unsigned int uiMemValue; - - // Make sure PC is destination and it's Load instruction - if (((Instr.regs & (1 << 15)) == 0) || (Instr.L != 1)) return uiPC + 4; - - - // Check if U bit it set - if (Instr.U == 0) { - // This means that it's ascending - // Also means that the PC is closest to Rn - if (Instr.p == 1) { - // Pre decrement. - uiOffsetToPC -= 4; - } else { - uiOffsetToPC = 0; - } - } else { - // The stack is descending, that means that the PC is as far away as possible. - // Lets find out how many registers before it. - for (int i = 0; i < 15; i++) { - if ((Instr.regs & (1 << i)) != 0) uiOffsetToPC += 4; - } - - // If the P bit is set, it uses pre increment - if (Instr.p == 1) uiOffsetToPC += 4; - } - - // read from out calculated address. - uiMemValue = *(unsigned int *)((uiRnValue + uiOffsetToPC) & ~0x03); - - return uiMemValue; - -} - -/////////////////////////////////////////////////////////////// -// -// bl; // Branch with link(optional) -unsigned int DecodeBL(bl Instr, unsigned int uiPC) -{ - //Printf("Decode BL"); - unsigned int uiAddress; - - uiAddress = Instr.offset; - if (uiAddress & 0x00800000) { - uiAddress |= 0xff000000; - } - - uiAddress <<= 2; - uiAddress += 8; - - return uiPC + uiAddress; - -} |