aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/gp32/debug-gdbstub-usb.cpp
diff options
context:
space:
mode:
authorMax Horn2008-05-15 11:40:38 +0000
committerMax Horn2008-05-15 11:40:38 +0000
commitdefc030143487550057cac1fb617d31ce9ab1ab2 (patch)
tree715887c6224f2536333730c79a964846f18107b1 /backends/platform/gp32/debug-gdbstub-usb.cpp
parent6206fb2a188b28db426cb85653e8c6bf00d1f1d3 (diff)
downloadscummvm-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.cpp1927
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;
-
-}