Skip to content

Commit

Permalink
cpu/cop test
Browse files Browse the repository at this point in the history
  • Loading branch information
JaCzekanski committed Jul 30, 2020
1 parent bf46f58 commit d9be557
Show file tree
Hide file tree
Showing 9 changed files with 398 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ IMAGES = common \
cdrom/timing \
cpu/access-time \
cpu/code-in-scratchpad \
cpu/cop \
dma/chain-looping \
dma/otc-test \
gpu/bandwidth \
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Name | Description
-------------------------|------------
access-time | Test CPU access time to different parts of memory map
code-in-scratchpad | **(Not finished)** Check whether code execution from Scratchpad is possible
cop | Check how CPU behave when accessing missing/disabled coprocessors

### DMA

Expand Down
2 changes: 2 additions & 0 deletions common/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ extern struct TEST __test;

#define assertEquals(given, expected) assertEqualsWithComment(given, expected, "")

#define assertTrue(given) assertEqualsWithComment(given, true, "")
#define assertFalse(given) assertEqualsWithComment(given, false, "")

#define TEST_MULTIPLE_BEGIN() \
[]() { \
Expand Down
3 changes: 3 additions & 0 deletions cpu/cop/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
TARGET = cop.elf

include ../../common-test.mk
113 changes: 113 additions & 0 deletions cpu/cop/cop0.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#pragma once
#include <stdint.h>

// From Avocado (src/cpu/cop0.h)

namespace cop0 {
// cop0r7 DCIC - breakpoint control
union DCIC {
struct {
uint32_t breakpointHit : 1;
uint32_t codeBreakpointHit : 1;
uint32_t dataBreakpointHit : 1;
uint32_t dataReadBreakpointHit : 1;
uint32_t dataWriteBreakpointHit : 1;
uint32_t jumpBreakpointHit : 1;
uint32_t : 6; // not used

uint32_t jumpRedirection : 2; // 0 - disabled, 1..3 - enabled

uint32_t : 2; // Unknown
uint32_t : 7; // not used

uint32_t superMasterEnable1 : 1; // bits 24..29

uint32_t breakOnCode : 1;
uint32_t breakOnData : 1;
uint32_t breakOnDataRead : 1;
uint32_t breakOnDataWrite : 1;
uint32_t breakOnJump : 1;

uint32_t masterEnableBreakAnyJump : 1;
uint32_t masterEnableBreakpoints : 1; // bits 24..27
uint32_t superMasterEnable2 : 1; // bits 24..29
};

uint32_t _reg;
};
// cop0r13 cause, ro, bit8-9 are rw
union CAUSE {
enum class Exception {
interrupt = 0,
addressErrorLoad = 4,
addressErrorStore = 5,
busErrorInstruction = 6,
busErrorData = 7,
syscall = 8,
breakpoint = 9,
reservedInstruction = 10,
coprocessorUnusable = 11,
arithmeticOverflow = 12
};

struct {
uint32_t : 2;
Exception exception : 5;
uint32_t : 1;
uint32_t interruptPending : 8;
uint32_t : 12;
uint32_t coprocessorNumber : 2; // If coprocessor caused the exception
uint32_t branchTaken : 1; /** When the branchDelay bit is set, the branchTaken Bit determines whether or not the
* branch is taken. A value of one in branchTaken indicates that the branch is
* taken. The Target Address Register holds the return address.
*
* source: L64360 datasheet
*/
uint32_t branchDelay : 1; /** CPU sets this bit to one to indicate that the last exception
* was taken while executing in a branch delay slot.
*
* source: L64360 datasheet
*/
};

uint32_t _reg;
};

// cop0r12 System status, rw
union STATUS {
enum class Mode : uint32_t { kernel = 0, user = 1 };
enum class BootExceptionVectors { ram = 0, rom = 1 };
struct {
uint32_t interruptEnable : 1;
Mode mode : 1;

uint32_t previousInterruptEnable : 1;
Mode previousMode : 1;

uint32_t oldInterruptEnable : 1;
Mode oldMode : 1;

uint32_t : 2;

uint32_t interruptMask : 8;
uint32_t isolateCache : 1;
uint32_t swappedCache : 1;
uint32_t writeZeroAsParityBits : 1;
uint32_t : 1; // CM
uint32_t cacheParityError : 1;
uint32_t tlbShutdown : 1; // TS

BootExceptionVectors bootExceptionVectors : 1;
uint32_t : 2;
uint32_t reverseEndianness : 1;
uint32_t : 2;

uint32_t cop0Enable : 1;
uint32_t cop1Enable : 1;
uint32_t cop2Enable : 1;
uint32_t cop3Enable : 1;
};

uint32_t _reg;
};
}
46 changes: 46 additions & 0 deletions cpu/cop/exception.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <psxapi.h>
#include "exception.h"

// #define DEBUG

// From __globals table
static uint32_t* A0 = (uint32_t*)0x200;

void hookUnresolvedExceptionHandler(void_fn_ptr fn) {
A0[0x40] = (uint32_t)fn;
}

Thread* getCurrentThread() {
Process** processes = (struct Process**)0x108;
return processes[0]->thread;
}

bool wasExceptionThrown() {
Thread* currentThread = getCurrentThread();

bool ret = getCurrentThread()->unknown[0];
currentThread->unknown[0] = 0;
return ret;
}

cop0::CAUSE::Exception getExceptionType() {
Thread* currentThread = getCurrentThread();

return (cop0::CAUSE::Exception)getCurrentThread()->unknown[1];
}

void exceptionHandler() {
Thread* currentThread = getCurrentThread();
auto exception = currentThread->registers.cause.exception;

currentThread->unknown[0] = 1; // Exception was thrown flag
currentThread->unknown[1] = (int)exception;

#ifdef DEBUG
printf("\n"
"!! Custom exception handler\n"
"!! Exception '%s' (%d) thrown at address 0x%08x\n", exceptionName[(int)exception], (int)exception, currentThread->registers.returnPC);
#endif

currentThread->registers.returnPC += 4; // Skip failing instruction
}
29 changes: 29 additions & 0 deletions cpu/cop/exception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once
#include <stdint.h>
#include "cop0.h"

typedef void (*void_fn_ptr)();

struct Registers {
uint32_t r[32];
uint32_t returnPC;
uint32_t hi, lo;
cop0::STATUS sr;
cop0::CAUSE cause;
};

struct Thread {
uint32_t flags, flags2;
Registers registers;
uint32_t unknown[9];
};

struct Process {
Thread* thread;
};

Thread* getCurrentThread();
void hookUnresolvedExceptionHandler(void_fn_ptr fn);
bool wasExceptionThrown();
cop0::CAUSE::Exception getExceptionType();
void exceptionHandler();
Loading

0 comments on commit d9be557

Please sign in to comment.