RAssertDolphin fixes

This commit is contained in:
Phillip Stephens 2023-10-05 12:54:11 -07:00
parent f03293a9f9
commit 67cc8b5cc7
13 changed files with 1384 additions and 155 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ orig/*/*
tools/mwcc_compiler/*
!tools/mwcc_compiler/.gitkeep
/*.txt
ctx.c

View File

@ -84,7 +84,8 @@ Kyoto/Basics/CStopwatch.cpp:
Kyoto/Basics/RAssertDolphin.cpp:
.text start:0x8028C28C end:0x8028C9C8
.rodata start:0x803AEAC8 end:0x803AED58
.sbss start:0x8041981C end:0x80419828
.sbss start:0x80419818 end:0x80419828
.sdata2 start:0x8041E268 end:0x8041E278
Kyoto/Graphics/CGX.cpp:
.text start:0x802BCBEC end:0x802BE31C

View File

@ -15327,7 +15327,7 @@ fn_8033EC4C = .text:0x8033EC4C; // type:function size:0x38
fn_8033EC84 = .text:0x8033EC84; // type:function size:0x20
fn_8033ECA4 = .text:0x8033ECA4; // type:function size:0x28
fn_8033ECCC = .text:0x8033ECCC; // type:function size:0x58
fn_8033ED24 = .text:0x8033ED24; // type:function size:0x64
fn_8033ED24__Fi = .text:0x8033ED24; // type:function size:0x64
fn_8033ED88 = .text:0x8033ED88; // type:function size:0x20
fn_8033EDA8 = .text:0x8033EDA8; // type:function size:0x4C
fn_8033EDF4 = .text:0x8033EDF4; // type:function size:0x38
@ -15934,10 +15934,10 @@ DVDGetDriveStatus = .text:0x80362A6C; // type:function size:0xAC scope:global
fn_80362B18 = .text:0x80362B18; // type:function size:0x10
fn_80362B28 = .text:0x80362B28; // type:function size:0x50
fn_80362B78 = .text:0x80362B78; // type:function size:0x27C
fn_80362DF4 = .text:0x80362DF4; // type:function size:0xAC
fn_80362EA0 = .text:0x80362EA0; // type:function size:0x24 align:4
fn_80362EC4 = .text:0x80362EC4; // type:function size:0xEC
fn_80362FB0 = .text:0x80362FB0; // type:function size:0x8
DVDCancel = .text:0x80362DF4; // type:function size:0xAC
cbForCancelSync = .text:0x80362EA0; // type:function size:0x24 scope:local align:4
DVDCancelAll = .text:0x80362EC4; // type:function size:0xEC
DVDGetCurrentDiskID = .text:0x80362FB0; // type:function size:0x8
fn_80362FB8 = .text:0x80362FB8; // type:function size:0xF8
fn_803630B0 = .text:0x803630B0; // type:function size:0x11C
fn_803631CC = .text:0x803631CC; // type:function size:0x38 align:4
@ -16422,19 +16422,19 @@ THPInit = .text:0x803810E4; // type:function size:0xA0 align:4
THPAudioDecode = .text:0x80381184; // type:function size:0x464
__THPAudioGetNewSample = .text:0x803815E8; // type:function size:0x90
__THPAudioInitialize = .text:0x80381678; // type:function size:0x3C
fn_803816B4 = .text:0x803816B4; // type:function size:0x44
AIInitDMA__FUlUl = .text:0x803816F8; // type:function size:0x88 scope:global
AIStartDMA__Fv = .text:0x80381780; // type:function size:0x18 scope:global
fn_80381798 = .text:0x80381798; // type:function size:0x18
fn_803817B0 = .text:0x803817B0; // type:function size:0x1C align:4
fn_803817CC = .text:0x803817CC; // type:function size:0x44
fn_80381810 = .text:0x80381810; // type:function size:0x18
fn_80381828 = .text:0x80381828; // type:function size:0xC
fn_80381834 = .text:0x80381834; // type:function size:0xD8
fn_8038190C = .text:0x8038190C; // type:function size:0x10
fn_8038191C = .text:0x8038191C; // type:function size:0xE0
fn_803819FC = .text:0x803819FC; // type:function size:0x14
fn_80381A10 = .text:0x80381A10; // type:function size:0xD4
AIRegisterDMACallback = .text:0x803816B4; // type:function size:0x44
AIInitDMA = .text:0x803816F8; // type:function size:0x88 scope:global
AIStartDMA = .text:0x80381780; // type:function size:0x18 scope:global
AIStopDMA = .text:0x80381798; // type:function size:0x18
AIGetDMAStartAddr = .text:0x803817B0; // type:function size:0x1C align:4
AIRegisterStreamCallback = .text:0x803817CC; // type:function size:0x44
AIResetStreamSampleCount = .text:0x80381810; // type:function size:0x18
AISetStreamTrigger = .text:0x80381828; // type:function size:0xC
AISetStreamPlayState = .text:0x80381834; // type:function size:0xD8
AIGetStreamPlayState = .text:0x8038190C; // type:function size:0x10
AISetDSPSampleRate = .text:0x8038191C; // type:function size:0xE0
AIGetDSPSampleRate = .text:0x803819FC; // type:function size:0x14
__AI_set_stream_sample_rate = .text:0x80381A10; // type:function size:0xD4
fn_80381AE4 = .text:0x80381AE4; // type:function size:0x10
fn_80381AF4 = .text:0x80381AF4; // type:function size:0x1C
fn_80381B10 = .text:0x80381B10; // type:function size:0x10
@ -17705,7 +17705,7 @@ lbl_803AEA80 = .rodata:0x803AEA80; // type:object size:0x18 data:double
lbl_803AEA98 = .rodata:0x803AEA98; // type:object size:0x18
lbl_803AEAB0 = .rodata:0x803AEAB0; // type:object size:0x8
lbl_803AEAB8 = .rodata:0x803AEAB8; // type:object size:0x10
lbl_803AEAC8 = .rodata:0x803AEAC8; // type:object size:0x290
@stringBase0 = .rodata:0x803AEAC8; // type:object size:0x290 scope:local data:string_table
lbl_803AED58 = .rodata:0x803AED58; // type:object size:0x8
lbl_803AED60 = .rodata:0x803AED60; // type:object size:0x8
lbl_803AED68 = .rodata:0x803AED68; // type:object size:0x8
@ -20639,9 +20639,9 @@ lbl_80419800 = .sbss:0x80419800; // type:object size:0x4 data:4byte
lbl_80419804 = .sbss:0x80419804; // type:object size:0x4 data:4byte
mGlobalTimer__10CStopwatch = .sbss:0x80419808; // type:object size:0x8 scope:global align:8 data:8byte
lbl_80419810 = .sbss:0x80419810; // type:object size:0x8 data:byte
lbl_80419818 = .sbss:0x80419818; // type:object size:0x1 data:byte
SkipFatal = .sbss:0x80419818; // type:object size:0x1 data:byte
rs_debugger_buffer = .sbss:0x8041981C; // type:object size:0x4 scope:local data:4byte
lbl_80419820 = .sbss:0x80419820; // type:object size:0x4 data:4byte
rs_debugger_size = .sbss:0x80419820; // type:object size:0x4 data:4byte
lbl_80419828 = .sbss:0x80419828; // type:object size:0x1 data:byte
lbl_8041982C = .sbss:0x8041982C; // type:object size:0x1 data:byte
lbl_80419830 = .sbss:0x80419830; // type:object size:0x1 data:byte
@ -23929,7 +23929,7 @@ lbl_8041D53C = .sdata2:0x8041D53C; // type:object size:0x4 data:float
lbl_8041D540 = .sdata2:0x8041D540; // type:object size:0x4 data:float
lbl_8041D544 = .sdata2:0x8041D544; // type:object size:0x4 data:float
lbl_8041D548 = .sdata2:0x8041D548; // type:object size:0x8 data:float
lbl_8041D550 = .sdata2:0x8041D550; // type:object size:0x8 data:4byte
BuildTime = .sdata2:0x8041D550; // type:object size:0x8 data:4byte
lbl_8041D558 = .sdata2:0x8041D558; // type:object size:0x4
lbl_8041D55C = .sdata2:0x8041D55C; // type:object size:0x4 data:float
lbl_8041D560 = .sdata2:0x8041D560; // type:object size:0x4 data:float
@ -24635,9 +24635,9 @@ lbl_8041E248 = .sdata2:0x8041E248; // type:object size:0x4 data:float
@148 = .sdata2:0x8041E254; // type:object size:0x4 scope:local data:float
lbl_8041E258 = .sdata2:0x8041E258; // type:object size:0x4 data:float
lbl_8041E260 = .sdata2:0x8041E260; // type:object size:0x8 data:double
lbl_8041E268 = .sdata2:0x8041E268; // type:object size:0x4 data:4byte
lbl_8041E26C = .sdata2:0x8041E26C; // type:object size:0x4 data:4byte
lbl_8041E270 = .sdata2:0x8041E270; // type:object size:0x8 data:4byte
bg = .sdata2:0x8041E268; // type:object size:0x4 scope:local data:4byte
fg = .sdata2:0x8041E26C; // type:object size:0x4 scope:local data:4byte
ExitButtons = .sdata2:0x8041E270; // type:object size:0x4 scope:local data:4byte
lbl_8041E278 = .sdata2:0x8041E278; // type:object size:0x8 data:float
lbl_8041E280 = .sdata2:0x8041E280; // type:object size:0x4 data:float
lbl_8041E284 = .sdata2:0x8041E284; // type:object size:0x4 data:float

View File

@ -5,6 +5,14 @@
#include "dolphin/os.h"
#define BUILD_INFO_TAG "!#$MetroidBuildInfo!#$"
// TODO: Add handling for build info
#define BUILD_TIME_DUMMY "Build v1.028 10/18/2004 10:44:32\0AD"
extern const char* BuildTime;
#define BUILD_INFO BUILD_INFO_TAG BUILD_TIME_DUMMY
#define BUILD_INFO_TAG_SIZE sizeof(BUILD_INFO_TAG) - 1
void ErrorHandler(OSError code, OSContext* context, int, uint);
void SetErrorHandlers();
void rs_debugger_printf(const char* format, ...);

View File

@ -3,6 +3,9 @@
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*AISCallback)(u32 count);
typedef void (*AIDCallback)();
@ -33,4 +36,8 @@ void AIInit(u8* stack);
BOOL AICheckInit();
void AIReset();
#ifdef __cplusplus
}
#endif
#endif // _DOLPHIN_AI

View File

@ -96,7 +96,7 @@ s32 DVDGetCommandBlockStatus(const DVDCommandBlock* block);
BOOL DVDCancelAsync(DVDCommandBlock* block, DVDCBCallback callback);
s32 DVDCancel(DVDCommandBlock* block);
BOOL DVDCancelAllAsync(DVDCBCallback callback);
s32 DVDCancelAll(void);
s32 DVDCancelAll(DVDCBCallback callback);
BOOL DVDPrepareStreamAsync(DVDFileInfo* fInfo, u32 length, u32 offset, DVDCallback callback);
s32 DVDPrepareStream(DVDFileInfo* fInfo, u32 length, u32 offset);

View File

@ -39,6 +39,8 @@ struct OSResetFunctionInfo {
OSResetFunctionInfo* prev;
};
void OSResetSystem(int reset, u32 resetCode, BOOL forceMenu);
#ifdef __cplusplus
}
#endif

13
libc/stdbool.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef STDBOOL_H
#define STDBOOL_h
#define bool _Bool
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#endif

550
src/Dolphin/os/OSContext.c Normal file
View File

@ -0,0 +1,550 @@
#include <dolphin/os.h>
#include <dolphin/db.h>
#define HID2 920
volatile OSContext* __OSCurrentContext : (OS_BASE_CACHED | 0x00D4);
volatile OSContext* __OSFPUContext : (OS_BASE_CACHED | 0x00D8);
static asm void __OSLoadFPUContext(register u32, register OSContext* fpuContext) {
// clang-format off
nofralloc
lhz r5, fpuContext->state;
clrlwi. r5, r5, 31
beq _return
lfd fp0, OS_CONTEXT_FPSCR(fpuContext)
mtfsf 0xFF, fp0
mfspr r5, HID2
rlwinm. r5, r5, 3, 31, 31
beq _regular_FPRs
psq_l fp0, OS_CONTEXT_PSF0(fpuContext), 0, 0
psq_l fp1, OS_CONTEXT_PSF1(fpuContext), 0, 0
psq_l fp2, OS_CONTEXT_PSF2(fpuContext), 0, 0
psq_l fp3, OS_CONTEXT_PSF3(fpuContext), 0, 0
psq_l fp4, OS_CONTEXT_PSF4(fpuContext), 0, 0
psq_l fp5, OS_CONTEXT_PSF5(fpuContext), 0, 0
psq_l fp6, OS_CONTEXT_PSF6(fpuContext), 0, 0
psq_l fp7, OS_CONTEXT_PSF7(fpuContext), 0, 0
psq_l fp8, OS_CONTEXT_PSF8(fpuContext), 0, 0
psq_l fp9, OS_CONTEXT_PSF9(fpuContext), 0, 0
psq_l fp10, OS_CONTEXT_PSF10(fpuContext), 0, 0
psq_l fp11, OS_CONTEXT_PSF11(fpuContext), 0, 0
psq_l fp12, OS_CONTEXT_PSF12(fpuContext), 0, 0
psq_l fp13, OS_CONTEXT_PSF13(fpuContext), 0, 0
psq_l fp14, OS_CONTEXT_PSF14(fpuContext), 0, 0
psq_l fp15, OS_CONTEXT_PSF15(fpuContext), 0, 0
psq_l fp16, OS_CONTEXT_PSF16(fpuContext), 0, 0
psq_l fp17, OS_CONTEXT_PSF17(fpuContext), 0, 0
psq_l fp18, OS_CONTEXT_PSF18(fpuContext), 0, 0
psq_l fp19, OS_CONTEXT_PSF19(fpuContext), 0, 0
psq_l fp20, OS_CONTEXT_PSF20(fpuContext), 0, 0
psq_l fp21, OS_CONTEXT_PSF21(fpuContext), 0, 0
psq_l fp22, OS_CONTEXT_PSF22(fpuContext), 0, 0
psq_l fp23, OS_CONTEXT_PSF23(fpuContext), 0, 0
psq_l fp24, OS_CONTEXT_PSF24(fpuContext), 0, 0
psq_l fp25, OS_CONTEXT_PSF25(fpuContext), 0, 0
psq_l fp26, OS_CONTEXT_PSF26(fpuContext), 0, 0
psq_l fp27, OS_CONTEXT_PSF27(fpuContext), 0, 0
psq_l fp28, OS_CONTEXT_PSF28(fpuContext), 0, 0
psq_l fp29, OS_CONTEXT_PSF29(fpuContext), 0, 0
psq_l fp30, OS_CONTEXT_PSF30(fpuContext), 0, 0
psq_l fp31, OS_CONTEXT_PSF31(fpuContext), 0, 0
_regular_FPRs:
lfd fp0, fpuContext->fpr[0]
lfd fp1, fpuContext->fpr[1]
lfd fp2, fpuContext->fpr[2]
lfd fp3, fpuContext->fpr[3]
lfd fp4, fpuContext->fpr[4]
lfd fp5, fpuContext->fpr[5]
lfd fp6, fpuContext->fpr[6]
lfd fp7, fpuContext->fpr[7]
lfd fp8, fpuContext->fpr[8]
lfd fp9, fpuContext->fpr[9]
lfd fp10, fpuContext->fpr[10]
lfd fp11, fpuContext->fpr[11]
lfd fp12, fpuContext->fpr[12]
lfd fp13, fpuContext->fpr[13]
lfd fp14, fpuContext->fpr[14]
lfd fp15, fpuContext->fpr[15]
lfd fp16, fpuContext->fpr[16]
lfd fp17, fpuContext->fpr[17]
lfd fp18, fpuContext->fpr[18]
lfd fp19, fpuContext->fpr[19]
lfd fp20, fpuContext->fpr[20]
lfd fp21, fpuContext->fpr[21]
lfd fp22, fpuContext->fpr[22]
lfd fp23, fpuContext->fpr[23]
lfd fp24, fpuContext->fpr[24]
lfd fp25, fpuContext->fpr[25]
lfd fp26, fpuContext->fpr[26]
lfd fp27, fpuContext->fpr[27]
lfd fp28, fpuContext->fpr[28]
lfd fp29, fpuContext->fpr[29]
lfd fp30, fpuContext->fpr[30]
lfd fp31, fpuContext->fpr[31]
_return:
blr
// clang-format on
}
static asm void __OSSaveFPUContext(register u32, register u32, register OSContext* fpuContext) {
// clang-format off
nofralloc
lhz r3, fpuContext->state
ori r3, r3, 1
sth r3, fpuContext->state
stfd fp0, fpuContext->fpr[0]
stfd fp1, fpuContext->fpr[1]
stfd fp2, fpuContext->fpr[2]
stfd fp3, fpuContext->fpr[3]
stfd fp4, fpuContext->fpr[4]
stfd fp5, fpuContext->fpr[5]
stfd fp6, fpuContext->fpr[6]
stfd fp7, fpuContext->fpr[7]
stfd fp8, fpuContext->fpr[8]
stfd fp9, fpuContext->fpr[9]
stfd fp10, fpuContext->fpr[10]
stfd fp11, fpuContext->fpr[11]
stfd fp12, fpuContext->fpr[12]
stfd fp13, fpuContext->fpr[13]
stfd fp14, fpuContext->fpr[14]
stfd fp15, fpuContext->fpr[15]
stfd fp16, fpuContext->fpr[16]
stfd fp17, fpuContext->fpr[17]
stfd fp18, fpuContext->fpr[18]
stfd fp19, fpuContext->fpr[19]
stfd fp20, fpuContext->fpr[20]
stfd fp21, fpuContext->fpr[21]
stfd fp22, fpuContext->fpr[22]
stfd fp23, fpuContext->fpr[23]
stfd fp24, fpuContext->fpr[24]
stfd fp25, fpuContext->fpr[25]
stfd fp26, fpuContext->fpr[26]
stfd fp27, fpuContext->fpr[27]
stfd fp28, fpuContext->fpr[28]
stfd fp29, fpuContext->fpr[29]
stfd fp30, fpuContext->fpr[30]
stfd fp31, fpuContext->fpr[31]
mffs fp0
stfd fp0, OS_CONTEXT_FPSCR(fpuContext)
lfd fp0, fpuContext->fpr[0]
mfspr r3, HID2
rlwinm. r3, r3, 3, 31, 31
bc 12, 2, _return
psq_st fp0, OS_CONTEXT_PSF0(fpuContext), 0, 0
psq_st fp1, OS_CONTEXT_PSF1(fpuContext), 0, 0
psq_st fp2, OS_CONTEXT_PSF2(fpuContext), 0, 0
psq_st fp3, OS_CONTEXT_PSF3(fpuContext), 0, 0
psq_st fp4, OS_CONTEXT_PSF4(fpuContext), 0, 0
psq_st fp5, OS_CONTEXT_PSF5(fpuContext), 0, 0
psq_st fp6, OS_CONTEXT_PSF6(fpuContext), 0, 0
psq_st fp7, OS_CONTEXT_PSF7(fpuContext), 0, 0
psq_st fp8, OS_CONTEXT_PSF8(fpuContext), 0, 0
psq_st fp9, OS_CONTEXT_PSF9(fpuContext), 0, 0
psq_st fp10, OS_CONTEXT_PSF10(fpuContext), 0, 0
psq_st fp11, OS_CONTEXT_PSF11(fpuContext), 0, 0
psq_st fp12, OS_CONTEXT_PSF12(fpuContext), 0, 0
psq_st fp13, OS_CONTEXT_PSF13(fpuContext), 0, 0
psq_st fp14, OS_CONTEXT_PSF14(fpuContext), 0, 0
psq_st fp15, OS_CONTEXT_PSF15(fpuContext), 0, 0
psq_st fp16, OS_CONTEXT_PSF16(fpuContext), 0, 0
psq_st fp17, OS_CONTEXT_PSF17(fpuContext), 0, 0
psq_st fp18, OS_CONTEXT_PSF18(fpuContext), 0, 0
psq_st fp19, OS_CONTEXT_PSF19(fpuContext), 0, 0
psq_st fp20, OS_CONTEXT_PSF20(fpuContext), 0, 0
psq_st fp21, OS_CONTEXT_PSF21(fpuContext), 0, 0
psq_st fp22, OS_CONTEXT_PSF22(fpuContext), 0, 0
psq_st fp23, OS_CONTEXT_PSF23(fpuContext), 0, 0
psq_st fp24, OS_CONTEXT_PSF24(fpuContext), 0, 0
psq_st fp25, OS_CONTEXT_PSF25(fpuContext), 0, 0
psq_st fp26, OS_CONTEXT_PSF26(fpuContext), 0, 0
psq_st fp27, OS_CONTEXT_PSF27(fpuContext), 0, 0
psq_st fp28, OS_CONTEXT_PSF28(fpuContext), 0, 0
psq_st fp29, OS_CONTEXT_PSF29(fpuContext), 0, 0
psq_st fp30, OS_CONTEXT_PSF30(fpuContext), 0, 0
psq_st fp31, OS_CONTEXT_PSF31(fpuContext), 0, 0
_return:
blr
// clang-format on
}
asm void OSLoadFPUContext(register OSContext* fpuContext) {
// clang-format off
nofralloc
addi r4, fpuContext, 0
b __OSLoadFPUContext
// clang-format on
}
asm void OSSaveFPUContext(register OSContext* fpuContext) {
// clang-format off
nofralloc
addi r5, fpuContext, 0
b __OSSaveFPUContext
// clang-format on
}
asm void OSSetCurrentContext(register OSContext* context){
// clang-format off
nofralloc
addis r4, r0, OS_CACHED_REGION_PREFIX
stw context, 0x00D4(r4)
clrlwi r5, context, 2
stw r5, 0x00C0(r4)
lwz r5, 0x00D8(r4)
cmpw r5, context
bne _disableFPU
lwz r6, context->srr1
ori r6, r6, 0x2000
stw r6, context->srr1
mfmsr r6
ori r6, r6, 2
mtmsr r6
blr
_disableFPU:
lwz r6, context->srr1
rlwinm r6, r6, 0, 19, 17
stw r6, context->srr1
mfmsr r6
rlwinm r6, r6, 0, 19, 17
ori r6, r6, 2
mtmsr r6
isync
blr
// clang-format on
}
OSContext* OSGetCurrentContext(void) {
return (OSContext*)__OSCurrentContext;
}
asm u32 OSSaveContext(register OSContext* context) {
// clang-format off
nofralloc
stmw r13, context->gpr[13]
mfspr r0, GQR1
stw r0, context->gqr[1]
mfspr r0, GQR2
stw r0, context->gqr[2]
mfspr r0, GQR3
stw r0, context->gqr[3]
mfspr r0, GQR4
stw r0, context->gqr[4]
mfspr r0, GQR5
stw r0, context->gqr[5]
mfspr r0, GQR6
stw r0, context->gqr[6]
mfspr r0, GQR7
stw r0, context->gqr[7]
mfcr r0
stw r0, context->cr
mflr r0
stw r0, context->lr
stw r0, context->srr0
mfmsr r0
stw r0, context->srr1
mfctr r0
stw r0, context->ctr
mfxer r0
stw r0, context->xer
stw r1, context->gpr[1]
stw r2, context->gpr[2]
li r0, 0x1
stw r0, context->gpr[3]
li r3, 0
blr
// clang-format on
}
extern void __RAS_OSDisableInterrupts_begin();
extern void __RAS_OSDisableInterrupts_end();
asm void OSLoadContext(register OSContext* context) {
// clang-format off
nofralloc
lis r4,__RAS_OSDisableInterrupts_begin@ha
lwz r6,context->srr0
addi r5,r4,__RAS_OSDisableInterrupts_begin@l
cmplw r6,r5
ble _notInRAS
lis r4,__RAS_OSDisableInterrupts_end@ha
addi r0,r4,__RAS_OSDisableInterrupts_end@l
cmplw r6,r0
bge _notInRAS
stw r5,context->srr0
_notInRAS:
lwz r0, context->gpr[0]
lwz r1, context->gpr[1]
lwz r2, context->gpr[2]
lhz r4, context->state
rlwinm. r5, r4, 0, 30, 30
beq notexc
rlwinm r4, r4, 0, 31, 29
sth r4, context->state
lmw r5, context->gpr[5]
b misc
notexc:
lmw r13, context->gpr[13]
misc:
lwz r4, context->gqr[1]
mtspr GQR1, r4
lwz r4, context->gqr[2]
mtspr GQR2, r4
lwz r4, context->gqr[3]
mtspr GQR3, r4
lwz r4, context->gqr[4]
mtspr GQR4, r4
lwz r4, context->gqr[5]
mtspr GQR5, r4
lwz r4, context->gqr[6]
mtspr GQR6, r4
lwz r4, context->gqr[7]
mtspr GQR7, r4
lwz r4, context->cr
mtcr r4
lwz r4, context->lr
mtlr r4
lwz r4, context->ctr
mtctr r4
lwz r4, context->xer
mtxer r4
mfmsr r4
rlwinm r4, r4, 0, 17, 15
rlwinm r4, r4, 0, 31, 29
mtmsr r4
lwz r4, context->srr0
mtsrr0 r4
lwz r4, context->srr1
mtsrr1 r4
lwz r4, context->gpr[4]
lwz r3, context->gpr[3]
rfi
// clang-format on
}
asm u32 OSGetStackPointer() {
// clang-format off
nofralloc
mr r3, r1
blr
// clang-format on
}
asm u32 OSSwitchStack(register u32 newsp) {
// clang-format off
nofralloc
mr r5, r1
mr r1, newsp
mr r3, r5
blr
// clang-format on
}
asm int OSSwitchFiber(register u32 pc, register u32 newsp) {
// clang-format off
nofralloc
mflr r0
mr r5, r1
stwu r5, -8(newsp)
mr r1, newsp
stw r0, 4(r5)
mtlr pc
blrl
lwz r5, 0(r1)
lwz r0, 4(r5)
mtlr r0
mr r1, r5
blr
// clang-format on
}
void OSClearContext(register OSContext* context) {
context->mode = 0;
context->state = 0;
if (context == __OSFPUContext)
__OSFPUContext = NULL;
}
asm void OSInitContext(register OSContext* context, register u32 pc, register u32 newsp) {
// clang-format off
nofralloc
stw pc, OS_CONTEXT_SRR0(context)
stw newsp, OS_CONTEXT_R1(context)
li r11, 0
ori r11, r11, 0x00008000 | 0x00000020 | 0x00000010 | 0x00000002 | 0x00001000
stw r11, OS_CONTEXT_SRR1(context)
li r0, 0x0
stw r0, OS_CONTEXT_CR(context)
stw r0, OS_CONTEXT_XER(context)
stw r2, OS_CONTEXT_R2(context)
stw r13, OS_CONTEXT_R13(context)
stw r0, OS_CONTEXT_R3(context)
stw r0, OS_CONTEXT_R4(context)
stw r0, OS_CONTEXT_R5(context)
stw r0, OS_CONTEXT_R6(context)
stw r0, OS_CONTEXT_R7(context)
stw r0, OS_CONTEXT_R8(context)
stw r0, OS_CONTEXT_R9(context)
stw r0, OS_CONTEXT_R10(context)
stw r0, OS_CONTEXT_R11(context)
stw r0, OS_CONTEXT_R12(context)
stw r0, OS_CONTEXT_R14(context)
stw r0, OS_CONTEXT_R15(context)
stw r0, OS_CONTEXT_R16(context)
stw r0, OS_CONTEXT_R17(context)
stw r0, OS_CONTEXT_R18(context)
stw r0, OS_CONTEXT_R19(context)
stw r0, OS_CONTEXT_R20(context)
stw r0, OS_CONTEXT_R21(context)
stw r0, OS_CONTEXT_R22(context)
stw r0, OS_CONTEXT_R23(context)
stw r0, OS_CONTEXT_R24(context)
stw r0, OS_CONTEXT_R25(context)
stw r0, OS_CONTEXT_R26(context)
stw r0, OS_CONTEXT_R27(context)
stw r0, OS_CONTEXT_R28(context)
stw r0, OS_CONTEXT_R29(context)
stw r0, OS_CONTEXT_R30(context)
stw r0, OS_CONTEXT_R31(context)
stw r0, OS_CONTEXT_GQR0(context)
stw r0, OS_CONTEXT_GQR1(context)
stw r0, OS_CONTEXT_GQR2(context)
stw r0, OS_CONTEXT_GQR3(context)
stw r0, OS_CONTEXT_GQR4(context)
stw r0, OS_CONTEXT_GQR5(context)
stw r0, OS_CONTEXT_GQR6(context)
stw r0, OS_CONTEXT_GQR7(context)
b OSClearContext
// clang-format on
}
void OSDumpContext(OSContext* context) {
u32 i;
u32* p;
OSReport("------------------------- Context 0x%08x -------------------------\n", context);
for (i = 0; i < 16; ++i) {
OSReport("r%-2d = 0x%08x (%14d) r%-2d = 0x%08x (%14d)\n", i, context->gpr[i],
context->gpr[i], i + 16, context->gpr[i + 16], context->gpr[i + 16]);
}
OSReport("LR = 0x%08x CR = 0x%08x\n", context->lr, context->cr);
OSReport("SRR0 = 0x%08x SRR1 = 0x%08x\n", context->srr0, context->srr1);
OSReport("\nGQRs----------\n");
for (i = 0; i < 4; ++i) {
OSReport("gqr%d = 0x%08x \t gqr%d = 0x%08x\n", i, context->gqr[i], i + 4, context->gqr[i + 4]);
}
if (context->state & OS_CONTEXT_STATE_FPSAVED) {
OSContext* currentContext;
OSContext fpuContext;
BOOL enabled;
enabled = OSDisableInterrupts();
currentContext = OSGetCurrentContext();
OSClearContext(&fpuContext);
OSSetCurrentContext(&fpuContext);
OSReport("\n\nFPRs----------\n");
for (i = 0; i < 32; i += 2) {
OSReport("fr%d \t= %d \t fr%d \t= %d\n", i, (u32)context->fpr[i], i + 1,
(u32)context->fpr[i + 1]);
}
OSReport("\n\nPSFs----------\n");
for (i = 0; i < 32; i += 2) {
OSReport("ps%d \t= 0x%x \t ps%d \t= 0x%x\n", i, (u32)context->psf[i], i + 1,
(u32)context->psf[i + 1]);
}
OSClearContext(&fpuContext);
OSSetCurrentContext(currentContext);
OSRestoreInterrupts(enabled);
}
OSReport("\nAddress: Back Chain LR Save\n");
for (i = 0, p = (u32*)context->gpr[1]; p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) {
OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]);
}
}
static asm void OSSwitchFPUContext(register __OSException exception, register OSContext* context) {
// clang-format off
nofralloc
mfmsr r5
ori r5, r5, 0x2000
mtmsr r5
isync
lwz r5, OS_CONTEXT_SRR1(context)
ori r5, r5, 0x2000
mtsrr1 r5
addis r3, r0, OS_CACHED_REGION_PREFIX
lwz r5, 0x00D8(r3)
stw context, 0x00D8(r3)
cmpw r5, r4
beq _restoreAndExit
cmpwi r5, 0x0
beq _loadNewFPUContext
bl __OSSaveFPUContext
_loadNewFPUContext:
bl __OSLoadFPUContext
_restoreAndExit:
lwz r3, OS_CONTEXT_CR(context)
mtcr r3
lwz r3, OS_CONTEXT_LR(context)
mtlr r3
lwz r3, OS_CONTEXT_SRR0(context)
mtsrr0 r3
lwz r3, OS_CONTEXT_CTR(context)
mtctr r3
lwz r3, OS_CONTEXT_XER(context)
mtxer r3
lhz r3, context->state
rlwinm r3, r3, 0, 31, 29
sth r3, context->state
lwz r5, OS_CONTEXT_R5(context)
lwz r3, OS_CONTEXT_R3(context)
lwz r4, OS_CONTEXT_R4(context)
rfi
// clang-format on
}
void __OSContextInit(void) {
__OSSetExceptionHandler(__OS_EXCEPTION_FLOATING_POINT, OSSwitchFPUContext);
__OSFPUContext = NULL;
DBPrintf("FPU-unavailable handler installed\n");
}

205
src/Dolphin/os/OSError.c Normal file
View File

@ -0,0 +1,205 @@
#include <dolphin/PPCArch.h>
#include <dolphin/hw_regs.h>
#include <dolphin/os.h>
#include <stdio.h>
OSThread* __OSCurrentThread : (OS_BASE_CACHED | 0x00E4);
OSThreadQueue __OSActiveThreadQueue : (OS_BASE_CACHED | 0x00DC);
volatile OSContext* __OSFPUContext : (OS_BASE_CACHED | 0x00D8);
OSErrorHandler __OSErrorTable[OS_ERROR_MAX];
#define FPSCR_ENABLE (FPSCR_VE | FPSCR_OE | FPSCR_UE | FPSCR_ZE | FPSCR_XE)
u32 __OSFpscrEnableBits = FPSCR_ENABLE;
__declspec(weak) void OSReport(const char* msg, ...) {
va_list args;
va_start(args, msg);
vprintf(msg, args);
va_end(args);
}
__declspec(weak) void OSVReport(const char* msg, va_list list) { vprintf(msg, list); }
__declspec(weak) void OSPanic(const char* file, int line, const char* msg, ...) {
va_list marker;
u32 i;
u32* p;
OSDisableInterrupts();
va_start(marker, msg);
vprintf(msg, marker);
va_end(marker);
OSReport(" in \"%s\" on line %d.\n", file, line);
OSReport("\nAddress: Back Chain LR Save\n");
for (i = 0, p = (u32*)OSGetStackPointer(); p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) {
OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]);
}
PPCHalt();
}
OSErrorHandler OSSetErrorHandler(OSError error, OSErrorHandler handler) {
OSErrorHandler oldHandler;
BOOL enabled;
enabled = OSDisableInterrupts();
oldHandler = __OSErrorTable[error];
__OSErrorTable[error] = handler;
if (error == OS_ERROR_FPE) {
u32 msr;
u32 fpscr;
OSThread* thread;
msr = PPCMfmsr();
PPCMtmsr(msr | MSR_FP);
fpscr = PPCMffpscr();
if (handler) {
for (thread = __OSActiveThreadQueue.head; thread; thread = thread->linkActive.next) {
thread->context.srr1 |= MSR_FE0 | MSR_FE1;
if ((thread->context.state & OS_CONTEXT_STATE_FPSAVED) == 0) {
int i;
thread->context.state |= OS_CONTEXT_STATE_FPSAVED;
for (i = 0; i < 32; ++i) {
*(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL;
*(u64*)&thread->context.psf[i] = (u64)0xffffffffffffffffLL;
}
thread->context.fpscr = FPSCR_NI;
}
thread->context.fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE;
thread->context.fpscr &=
~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN |
FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX |
FPSCR_OX | FPSCR_FX | FPSCR_FI);
}
fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE;
msr |= MSR_FE0 | MSR_FE1;
} else {
for (thread = __OSActiveThreadQueue.head; thread; thread = thread->linkActive.next) {
thread->context.srr1 &= ~(MSR_FE0 | MSR_FE1);
thread->context.fpscr &= ~FPSCR_ENABLE;
thread->context.fpscr &=
~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN |
FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX |
FPSCR_OX | FPSCR_FX | FPSCR_FI);
}
fpscr &= ~FPSCR_ENABLE;
msr &= ~(MSR_FE0 | MSR_FE1);
}
fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN |
FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX |
FPSCR_OX | FPSCR_FX | FPSCR_FI);
PPCMtfpscr(fpscr);
PPCMtmsr(msr);
}
OSRestoreInterrupts(enabled);
return oldHandler;
}
void __OSUnhandledException(__OSException exception, OSContext* context, u32 dsisr, u32 dar) {
OSTime now;
now = OSGetTime();
if (!(context->srr1 & MSR_RI)) {
OSReport("Non-recoverable Exception %d", exception);
} else {
if (exception == __OS_EXCEPTION_PROGRAM && (context->srr1 & (0x80000000 >> 11)) &&
__OSErrorTable[OS_ERROR_FPE] != 0) {
u32 fpscr;
u32 msr;
exception = OS_ERROR_FPE;
msr = PPCMfmsr();
PPCMtmsr(msr | MSR_FP);
if (__OSFPUContext) {
OSSaveFPUContext((OSContext*)__OSFPUContext);
}
fpscr = PPCMffpscr();
fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | FPSCR_VXSNAN |
FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | FPSCR_UX |
FPSCR_OX | FPSCR_FX | FPSCR_FI);
PPCMtfpscr(fpscr);
PPCMtmsr(msr);
if (__OSFPUContext == context) {
OSDisableScheduler();
__OSErrorTable[exception](exception, context, dsisr, dar);
context->srr1 &= ~MSR_FP;
__OSFPUContext = NULL;
context->fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
OSEnableScheduler();
__OSReschedule();
} else {
context->srr1 &= ~MSR_FP;
__OSFPUContext = NULL;
}
OSLoadContext(context);
}
if (__OSErrorTable[exception]) {
OSDisableScheduler();
__OSErrorTable[exception](exception, context, dsisr, dar);
OSEnableScheduler();
__OSReschedule();
OSLoadContext(context);
}
if (exception == OS_ERROR_DECREMENTER) {
OSLoadContext(context);
}
OSReport("Unhandled Exception %d", exception);
}
OSReport("\n");
OSDumpContext(context);
OSReport("\nDSISR = 0x%08x DAR = 0x%08x\n", dsisr, dar);
OSReport("TB = 0x%016llx\n", now);
switch (exception) {
case __OS_EXCEPTION_DSI:
OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access "
"invalid address 0x%x (read from DAR)\n",
context->srr0, dar);
break;
case __OS_EXCEPTION_ISI:
OSReport("\nAttempted to fetch instruction from invalid address 0x%x "
"(read from SRR0)\n",
context->srr0);
break;
case __OS_EXCEPTION_ALIGNMENT:
OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access "
"unaligned address 0x%x (read from DAR)\n",
context->srr0, dar);
break;
case __OS_EXCEPTION_PROGRAM:
OSReport("\nProgram exception : Possible illegal instruction/operation "
"at or around 0x%x (read from SRR0)\n",
context->srr0, dar);
break;
case OS_ERROR_PROTECTION:
OSReport("\n");
OSReport("AI DMA Address = 0x%04x%04x\n", __DSPRegs[0x00000018], __DSPRegs[0x00000018 + 1]);
OSReport("ARAM DMA Address = 0x%04x%04x\n", __DSPRegs[0x00000010], __DSPRegs[0x00000010 + 1]);
OSReport("DI DMA Address = 0x%08x\n", __DIRegs[0x00000005]);
break;
}
OSReport("\nLast interrupt (%d): SRR0 = 0x%08x TB = 0x%016llx\n", __OSLastInterrupt,
__OSLastInterruptSrr0, __OSLastInterruptTime);
PPCHalt();
}

View File

@ -0,0 +1,427 @@
#include <dolphin/os.h>
#include <dolphin/hw_regs.h>
static asm void ExternalInterruptHandler(register __OSException exception,
register OSContext* context);
extern void __RAS_OSDisableInterrupts_begin(void);
extern void __RAS_OSDisableInterrupts_end(void);
static __OSInterruptHandler* InterruptHandlerTable;
static OSInterruptMask InterruptPrioTable[] = {
OS_INTERRUPTMASK_PI_ERROR,
OS_INTERRUPTMASK_PI_DEBUG,
OS_INTERRUPTMASK_MEM,
OS_INTERRUPTMASK_PI_RSW,
OS_INTERRUPTMASK_PI_VI,
OS_INTERRUPTMASK_PI_PE,
OS_INTERRUPTMASK_PI_HSP,
OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP | OS_INTERRUPTMASK_AI |
OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI_SI | OS_INTERRUPTMASK_PI_DI,
OS_INTERRUPTMASK_DSP_AI,
OS_INTERRUPTMASK_PI_CP,
0xFFFFFFFF,
};
asm BOOL OSDisableInterrupts(void) {
// clang-format off
nofralloc
entry __RAS_OSDisableInterrupts_begin
mfmsr r3
rlwinm r4, r3, 0, 17, 15
mtmsr r4
entry __RAS_OSDisableInterrupts_end
rlwinm r3, r3, 17, 31, 31
blr
// clang-format on
}
asm BOOL OSEnableInterrupts(void) {
// clang-format off
nofralloc
mfmsr r3
ori r4, r3, 0x8000
mtmsr r4
rlwinm r3, r3, 17, 31, 31
blr
// clang-format on
}
asm BOOL OSRestoreInterrupts(register BOOL level){
// clang-format off
nofralloc
cmpwi level, 0
mfmsr r4
beq _disable
ori r5, r4, 0x8000
b _restore
_disable:
rlwinm r5, r4, 0, 17, 15
_restore:
mtmsr r5
rlwinm r3, r4, 17, 31, 31
blr
// clang-format on
}
__OSInterruptHandler
__OSSetInterruptHandler(__OSInterrupt interrupt, __OSInterruptHandler handler) {
__OSInterruptHandler oldHandler;
oldHandler = InterruptHandlerTable[interrupt];
InterruptHandlerTable[interrupt] = handler;
return oldHandler;
}
__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt) {
return InterruptHandlerTable[interrupt];
}
void __OSInterruptInit(void) {
InterruptHandlerTable = OSPhysicalToCached(0x3040);
memset(InterruptHandlerTable, 0, __OS_INTERRUPT_MAX * sizeof(__OSInterruptHandler));
*(OSInterruptMask*)OSPhysicalToCached(0x00C4) = 0;
*(OSInterruptMask*)OSPhysicalToCached(0x00C8) = 0;
__PIRegs[1] = 0xf0;
__OSMaskInterrupts(OS_INTERRUPTMASK_MEM | OS_INTERRUPTMASK_DSP | OS_INTERRUPTMASK_AI |
OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI);
__OSSetExceptionHandler(4, ExternalInterruptHandler);
}
u32 SetInterruptMask(OSInterruptMask mask, OSInterruptMask current) {
u32 reg;
switch (__cntlzw(mask)) {
case __OS_INTERRUPT_MEM_0:
case __OS_INTERRUPT_MEM_1:
case __OS_INTERRUPT_MEM_2:
case __OS_INTERRUPT_MEM_3:
case __OS_INTERRUPT_MEM_ADDRESS:
reg = 0;
if (!(current & OS_INTERRUPTMASK_MEM_0))
reg |= 0x1;
if (!(current & OS_INTERRUPTMASK_MEM_1))
reg |= 0x2;
if (!(current & OS_INTERRUPTMASK_MEM_2))
reg |= 0x4;
if (!(current & OS_INTERRUPTMASK_MEM_3))
reg |= 0x8;
if (!(current & OS_INTERRUPTMASK_MEM_ADDRESS))
reg |= 0x10;
__MEMRegs[0x0000000e] = (u16)reg;
mask &= ~OS_INTERRUPTMASK_MEM;
break;
case __OS_INTERRUPT_DSP_AI:
case __OS_INTERRUPT_DSP_ARAM:
case __OS_INTERRUPT_DSP_DSP:
reg = __DSPRegs[0x00000005];
reg &= ~0x1F8;
if (!(current & OS_INTERRUPTMASK_DSP_AI))
reg |= 0x10;
if (!(current & OS_INTERRUPTMASK_DSP_ARAM))
reg |= 0x40;
if (!(current & OS_INTERRUPTMASK_DSP_DSP))
reg |= 0x100;
__DSPRegs[0x00000005] = (u16)reg;
mask &= ~OS_INTERRUPTMASK_DSP;
break;
case __OS_INTERRUPT_AI_AI:
reg = __AIRegs[0];
reg &= ~0x2C;
if (!(current & OS_INTERRUPTMASK_AI_AI))
reg |= 0x4;
__AIRegs[0] = reg;
mask &= ~OS_INTERRUPTMASK_AI;
break;
case __OS_INTERRUPT_EXI_0_EXI:
case __OS_INTERRUPT_EXI_0_TC:
case __OS_INTERRUPT_EXI_0_EXT:
reg = __EXIRegs[0];
reg &= ~0x2C0F;
if (!(current & OS_INTERRUPTMASK_EXI_0_EXI))
reg |= 0x1;
if (!(current & OS_INTERRUPTMASK_EXI_0_TC))
reg |= 0x4;
if (!(current & OS_INTERRUPTMASK_EXI_0_EXT))
reg |= 0x400;
__EXIRegs[0] = reg;
mask &= ~OS_INTERRUPTMASK_EXI_0;
break;
case __OS_INTERRUPT_EXI_1_EXI:
case __OS_INTERRUPT_EXI_1_TC:
case __OS_INTERRUPT_EXI_1_EXT:
reg = __EXIRegs[5];
reg &= ~0xC0F;
if (!(current & OS_INTERRUPTMASK_EXI_1_EXI))
reg |= 0x1;
if (!(current & OS_INTERRUPTMASK_EXI_1_TC))
reg |= 0x4;
if (!(current & OS_INTERRUPTMASK_EXI_1_EXT))
reg |= 0x400;
__EXIRegs[5] = reg;
mask &= ~OS_INTERRUPTMASK_EXI_1;
break;
case __OS_INTERRUPT_EXI_2_EXI:
case __OS_INTERRUPT_EXI_2_TC:
reg = __EXIRegs[10];
reg &= ~0xF;
if (!(current & OS_INTERRUPTMASK_EXI_2_EXI))
reg |= 0x1;
if (!(current & OS_INTERRUPTMASK_EXI_2_TC))
reg |= 0x4;
__EXIRegs[10] = reg;
mask &= ~OS_INTERRUPTMASK_EXI_2;
break;
case __OS_INTERRUPT_PI_CP:
case __OS_INTERRUPT_PI_SI:
case __OS_INTERRUPT_PI_DI:
case __OS_INTERRUPT_PI_RSW:
case __OS_INTERRUPT_PI_ERROR:
case __OS_INTERRUPT_PI_VI:
case __OS_INTERRUPT_PI_DEBUG:
case __OS_INTERRUPT_PI_PE_TOKEN:
case __OS_INTERRUPT_PI_PE_FINISH:
case __OS_INTERRUPT_PI_HSP:
reg = 0xF0;
if (!(current & OS_INTERRUPTMASK_PI_CP)) {
reg |= 0x800;
}
if (!(current & OS_INTERRUPTMASK_PI_SI)) {
reg |= 0x8;
}
if (!(current & OS_INTERRUPTMASK_PI_DI)) {
reg |= 0x4;
}
if (!(current & OS_INTERRUPTMASK_PI_RSW)) {
reg |= 0x2;
}
if (!(current & OS_INTERRUPTMASK_PI_ERROR)) {
reg |= 0x1;
}
if (!(current & OS_INTERRUPTMASK_PI_VI)) {
reg |= 0x100;
}
if (!(current & OS_INTERRUPTMASK_PI_DEBUG)) {
reg |= 0x1000;
}
if (!(current & OS_INTERRUPTMASK_PI_PE_TOKEN)) {
reg |= 0x200;
}
if (!(current & OS_INTERRUPTMASK_PI_PE_FINISH)) {
reg |= 0x400;
}
if (!(current & OS_INTERRUPTMASK_PI_HSP)) {
reg |= 0x2000;
}
__PIRegs[1] = reg;
mask &= ~OS_INTERRUPTMASK_PI;
break;
default:
break;
}
return mask;
}
OSInterruptMask OSGetInterruptMask(void) { return *(OSInterruptMask*)OSPhysicalToCached(0x00C8); }
OSInterruptMask OSSetInterruptMask(OSInterruptMask local) {
BOOL enabled;
OSInterruptMask global;
OSInterruptMask prev;
OSInterruptMask mask;
enabled = OSDisableInterrupts();
global = *(OSInterruptMask*)OSPhysicalToCached(0x00C4);
prev = *(OSInterruptMask*)OSPhysicalToCached(0x00C8);
mask = (global | prev) ^ local;
*(OSInterruptMask*)OSPhysicalToCached(0x00C8) = local;
while (mask) {
mask = SetInterruptMask(mask, global | local);
}
OSRestoreInterrupts(enabled);
return prev;
}
OSInterruptMask __OSMaskInterrupts(OSInterruptMask global) {
BOOL enabled;
OSInterruptMask prev;
OSInterruptMask local;
OSInterruptMask mask;
enabled = OSDisableInterrupts();
prev = *(OSInterruptMask*)OSPhysicalToCached(0x00C4);
local = *(OSInterruptMask*)OSPhysicalToCached(0x00C8);
mask = ~(prev | local) & global;
global |= prev;
*(OSInterruptMask*)OSPhysicalToCached(0x00C4) = global;
while (mask) {
mask = SetInterruptMask(mask, global | local);
}
OSRestoreInterrupts(enabled);
return prev;
}
OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask global) {
BOOL enabled;
OSInterruptMask prev;
OSInterruptMask local;
OSInterruptMask mask;
enabled = OSDisableInterrupts();
prev = *(OSInterruptMask*)OSPhysicalToCached(0x00C4);
local = *(OSInterruptMask*)OSPhysicalToCached(0x00C8);
mask = (prev | local) & global;
global = prev & ~global;
*(OSInterruptMask*)OSPhysicalToCached(0x00C4) = global;
while (mask) {
mask = SetInterruptMask(mask, global | local);
}
OSRestoreInterrupts(enabled);
return prev;
}
volatile OSTime __OSLastInterruptTime;
volatile __OSInterrupt __OSLastInterrupt;
volatile u32 __OSLastInterruptSrr0;
void __OSDispatchInterrupt(__OSException exception, OSContext* context) {
u32 intsr;
u32 reg;
OSInterruptMask cause;
OSInterruptMask unmasked;
OSInterruptMask* prio;
__OSInterrupt interrupt;
__OSInterruptHandler handler;
intsr = __PIRegs[0];
intsr &= ~0x00010000;
if (intsr == 0 || (intsr & __PIRegs[1]) == 0) {
OSLoadContext(context);
}
cause = 0;
if (intsr & 0x00000080) {
reg = __MEMRegs[15];
if (reg & 0x1)
cause |= OS_INTERRUPTMASK_MEM_0;
if (reg & 0x2)
cause |= OS_INTERRUPTMASK_MEM_1;
if (reg & 0x4)
cause |= OS_INTERRUPTMASK_MEM_2;
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_MEM_3;
if (reg & 0x10)
cause |= OS_INTERRUPTMASK_MEM_ADDRESS;
}
if (intsr & 0x00000040) {
reg = __DSPRegs[5];
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_DSP_AI;
if (reg & 0x20)
cause |= OS_INTERRUPTMASK_DSP_ARAM;
if (reg & 0x80)
cause |= OS_INTERRUPTMASK_DSP_DSP;
}
if (intsr & 0x00000020) {
reg = __AIRegs[0];
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_AI_AI;
}
if (intsr & 0x00000010) {
reg = __EXIRegs[0];
if (reg & 0x2)
cause |= OS_INTERRUPTMASK_EXI_0_EXI;
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_EXI_0_TC;
if (reg & 0x800)
cause |= OS_INTERRUPTMASK_EXI_0_EXT;
reg = __EXIRegs[5];
if (reg & 0x2)
cause |= OS_INTERRUPTMASK_EXI_1_EXI;
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_EXI_1_TC;
if (reg & 0x800)
cause |= OS_INTERRUPTMASK_EXI_1_EXT;
reg = __EXIRegs[10];
if (reg & 0x2)
cause |= OS_INTERRUPTMASK_EXI_2_EXI;
if (reg & 0x8)
cause |= OS_INTERRUPTMASK_EXI_2_TC;
}
if (intsr & 0x00002000)
cause |= OS_INTERRUPTMASK_PI_HSP;
if (intsr & 0x00001000)
cause |= OS_INTERRUPTMASK_PI_DEBUG;
if (intsr & 0x00000400)
cause |= OS_INTERRUPTMASK_PI_PE_FINISH;
if (intsr & 0x00000200)
cause |= OS_INTERRUPTMASK_PI_PE_TOKEN;
if (intsr & 0x00000100)
cause |= OS_INTERRUPTMASK_PI_VI;
if (intsr & 0x00000008)
cause |= OS_INTERRUPTMASK_PI_SI;
if (intsr & 0x00000004)
cause |= OS_INTERRUPTMASK_PI_DI;
if (intsr & 0x00000002)
cause |= OS_INTERRUPTMASK_PI_RSW;
if (intsr & 0x00000800)
cause |= OS_INTERRUPTMASK_PI_CP;
if (intsr & 0x00000001)
cause |= OS_INTERRUPTMASK_PI_ERROR;
unmasked = cause & ~(*(OSInterruptMask*)OSPhysicalToCached(0x00C4) |
*(OSInterruptMask*)OSPhysicalToCached(0x00C8));
if (unmasked) {
for (prio = InterruptPrioTable;; ++prio) {
if (unmasked & *prio) {
interrupt = (__OSInterrupt)__cntlzw(unmasked & *prio);
break;
}
}
handler = __OSGetInterruptHandler(interrupt);
if (handler) {
if (__OS_INTERRUPT_MEM_ADDRESS < interrupt) {
__OSLastInterrupt = interrupt;
__OSLastInterruptTime = OSGetTime();
__OSLastInterruptSrr0 = context->srr0;
}
OSDisableScheduler();
handler(interrupt, context);
OSEnableScheduler();
__OSReschedule();
OSLoadContext(context);
}
}
OSLoadContext(context);
}
static asm void ExternalInterruptHandler(register __OSException exception,
register OSContext* context) {
#pragma unused(exception)
// clang-format off
nofralloc
OS_EXCEPTION_SAVE_GPRS(context)
stwu r1, -8(r1)
b __OSDispatchInterrupt
// clang-format on
}

View File

@ -2,11 +2,12 @@
#include "dolphin/__start.h"
#include "dolphin/ai.h"
#include "dolphin/dvd.h"
#include "dolphin/os/OSMemory.h"
#include "dolphin/os/OSReset.h"
#include "dolphin/pad.h"
#include "dolphin/vi.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@ -14,145 +15,155 @@
extern "C" void fn_803816B4(int);
extern "C" void fn_80362EC4(void*);
extern "C" void fn_80377118(int);
extern u32* fn_8033ED24(int);
static const char* buildTime = "Build v1.088 10/29/2002 2:21:25";
static char* rs_debugger_buffer;
static int lbl_80419820;
static bool lbl_80419818;
static int rs_debugger_size;
static bool SkipFatal = false;
static const GXColor bg = {128, 0, 0, 0};
static const GXColor fg = {255, 255, 255, 0};
static const uchar ExitButtons[4] = {PAD_BUTTON_RIGHT, PAD_BUTTON_LEFT, PAD_BUTTON_DOWN,
PAD_BUTTON_UP};
#define COMPARE_TIME(current, last) (current / last) > 1.0
static void hack() {
static const char* tmp1 = "%s\0\n";
static const char* tmp2 = "0x%08x: 0x%08x 0x%08x";
static const char* tmp3 = " 0x%08x: %s";
}
void ErrorHandler(OSError code, OSContext* context, int dsisr, uint dar) {
uint loopExitCriteria;
char buffer[1024];
OSContext newContext;
uint loopExitCriteria;
PADStatus pads[4];
uint local_60;
uchar local_60[4];
u32 iVar2;
u32* tmp;
u32* gpr;
uint i;
uint len;
if (code != OS_ERROR_PROTECTION || ((dsisr & 0x10) == 0 && (dar < 0x1800001))) {
OSProtectRange(3, 0, 0, 3);
memset((void*)0x81200000, 0, 0x280);
DCFlushRange((void*)0x81200000, 0x280);
fn_803816B4(0);
AIInitDMA(0x81200000, 0x280);
AIStartDMA();
fn_80362EC4(nullptr);
loopExitCriteria = 0;
PADControlMotor(0, 0);
VISetBlack(1);
VIFlush();
OSClearContext(&newContext);
OSSetCurrentContext(&newContext);
OSEnableInterrupts();
OSTime lastTime = OSGetTime();
OSTime currentTime;
if (code == 15 && ((dsisr & 0x10) != 0 || ((uint)dar > 0x1800000))) {
return;
}
while (loopExitCriteria < 4) {
OSProtectRange(3, 0, 0, 3);
memset((void*)0x81200000, 0, 0x280);
DCFlushRange((void*)0x81200000, 0x280);
AIRegisterDMACallback(NULL);
AIInitDMA(0x81200000, 0x280);
AIStartDMA();
DVDCancelAll(nullptr);
loopExitCriteria = 0;
PADControlMotor(0, 0);
VISetBlack(1);
VIFlush();
OSClearContext(&newContext);
OSSetCurrentContext(&newContext);
OSEnableInterrupts();
currentTime = OSGetTime();
if (COMPARE_TIME(currentTime, lastTime)) {
OSResetSystem(1, 0, 0);
}
OSTime lastTime = OSGetTime();
OSTime currentTime;
while (loopExitCriteria < 4) {
currentTime = OSGetTime();
if (OSTicksToSeconds(currentTime - lastTime) >= 10) {
OSResetSystem(1, 0, 0);
}
PADRead(pads);
while (pads[1].err == PAD_ERR_NO_CONTROLLER && OSTicksToSeconds(OSGetTime() - lastTime) < 10) {
PADReset(PAD_CHAN1_BIT);
PADRead(pads);
while (pads[1].err == -1) {
currentTime = OSGetTime();
if (COMPARE_TIME(currentTime, lastTime)) {
break;
}
fn_80377118(0x40000000);
PADRead(pads);
}
}
if (pads[1].err == 0) {
local_60 = 0x2010408;
if ((pads[1].button & 0xc10) == 0xc10) {
lastTime = OSGetTime();
if ((pads[1].button & 0xf) != 0) {
if ((pads[1].button & loopExitCriteria) ==
0) { // TODO: wrong logic with loopExitCriteria
if ((loopExitCriteria != 0) &&
pads[1].button == 0) { // TODO: wrong logic with pads[1].button
loopExitCriteria = 0;
}
} else {
loopExitCriteria += 1;
}
if (pads[1].err == PAD_ERR_NONE) {
*(uint*)local_60 = *(uint*)ExitButtons;
if ((pads[1].button & 0xc10) == 0xc10) {
lastTime = OSGetTime();
if ((pads[1].button & 0xf) != 0) {
if ((pads[1].button & local_60[loopExitCriteria]) != 0) {
loopExitCriteria += 1;
} else if ((loopExitCriteria != 0) &&
((pads[1].button & local_60[loopExitCriteria - 1]) == 0)) {
loopExitCriteria = 0;
}
} else {
loopExitCriteria = 0;
}
} else {
loopExitCriteria = 0;
}
}
}
VISetBlack(0);
VIFlush();
OSReport("Unhandled exception %d - Production\n", code);
OSReport("%s\n", BuildTime);
OSReport("------------------------- Context 0x%08x -------------------------\n", context);
for (i = 0; i < 16; ++i) {
OSReport("r%-2d = 0x%08x (%14d) r%-2d = 0x%08x (%14d)\n", i, context->gpr[i],
context->gpr[i], i + 0x10, context->gpr[i + 0x10], context->gpr[i + 0x10]);
}
OSReport("LR = 0x%08x CR = 0x%08x\n", context->lr, context->cr);
OSReport("SRR0 = 0x%08x SRR1 = 0x%08x\n", context->srr0, context->srr1);
OSReport("DSISR= 0x%08x DAR = 0x%08x\n", dsisr, dar);
if (rs_debugger_buffer != nullptr) {
strcpy(buffer, rs_debugger_buffer);
} else {
buffer[0] = 0;
}
len = strlen(buffer);
if (len != 0) {
len += sprintf(buffer + len, " - Production\n");
} else {
len += sprintf(buffer, "Exception %d - Production\n", code);
}
len += sprintf(buffer + len, "%s\n", BuildTime);
len += sprintf(buffer + len, "IP: 0x%8.8x Mem: 0x%8.8x", context->srr0, dar);
if (code == 0xf) {
len += sprintf(buffer + len, " - %d", dsisr);
}
len += sprintf(buffer + len, "\n\n");
OSReport("\nAddress: Back Chain LR Save\n");
gpr = (u32*)context->gpr[1];
for (i = 0; gpr != NULL && gpr != (void*)0xFFFFFFFF && i++ < rs_debugger_size + 16;) {
if (gpr > (void*)0x80000400 && gpr < (void*)0x81800000) {
if (i >= rs_debugger_size) {
OSReport("0x%08x: 0x%08x 0x%08x\n", gpr, *gpr, gpr[1]);
iVar2 = gpr[1];
tmp = fn_8033ED24(iVar2);
if (tmp == NULL) {
len += sprintf(buffer + len, "0x%08x: 0x%08x 0x%08x\n", gpr, *gpr, gpr[1]);
}
if (tmp != NULL) {
OSReport("RFO:0x%08x: %s\n", iVar2 - tmp[1], *tmp);
len += sprintf(buffer + len, "RFO:0x%08x: %s\n", iVar2 - tmp[1], *tmp);
}
}
}
VISetBlack(0);
VIFlush();
OSReport("Unhandled exception %d - Production\n", code);
OSReport("%s\n", buildTime);
OSReport("------------------------- Context 0x%08x -------------------------\n", context);
int i = 0;
do {
OSReport("r%-2d = 0x%08x (%14d) r%-2d = 0x%08x (%14d)\n", i, context->gpr[i],
context->gpr[i], i + 0x10, context->gpr[i + 0x10], context->gpr[i + 0x10]);
i += 1;
} while (i < 0x10);
OSReport("LR = 0x%08x CR = 0x%08x\n", context->lr, context->cr);
OSReport("SRR0 = 0x%08x SRR1 = 0x%08x\n", context->srr0, context->srr1);
OSReport("DSISR= 0x%08x DAR = 0x%08x\n", dsisr, dar);
char buffer[1024];
if (rs_debugger_buffer == nullptr) {
buffer[0] = 0;
} else {
strcpy(buffer, rs_debugger_buffer);
OSReport("0x%08x: BAD PTR\n", gpr);
sprintf(buffer + len, "0x%08x: BAD PTR\n", gpr);
break;
}
gpr = (u32*)*gpr;
}
int bufferSize = strlen(buffer);
if (bufferSize == 0) {
i = sprintf(buffer, "Exception %d - Production\n", code);
} else {
i = sprintf(buffer + bufferSize, " - Production\n");
}
int j = sprintf(buffer + bufferSize + i, "%s\n", buildTime);
int bufferIndex = bufferSize + i + j;
bufferIndex += sprintf(buffer + bufferIndex, "IP: 0x%8.8x Mem: 0x%8.8x", context->srr0, dar);
if (code == 0xf) {
bufferIndex += sprintf(buffer + bufferIndex, " - %d", dsisr);
}
bufferIndex += sprintf(buffer + bufferIndex, "\n\n");
OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access invalid address 0x%x "
"(read from DAR)\n",
context->srr0, dar);
OSReport("\nAddress: Back Chain LR Save\n");
uint stackPtr = context->gpr[1];
bool check;
i = 0;
while (true) {
if (((stackPtr == NULL) || (stackPtr == 0xffffffff)) || (check = 0xf < i, i += 1, check)) {
break;
}
if ((stackPtr < 0x80000401) || (0x817fffff < stackPtr)) {
OSReport("0x%08x: BAD PTR\n", stackPtr);
sprintf(buffer + j, "0x%08x: BAD PTR\n", stackPtr);
break;
}
uint* asPtr = (uint*)stackPtr;
OSReport("0x%08x: 0x%08x 0x%08x\n", stackPtr, *asPtr, asPtr[1]);
bufferIndex += sprintf(buffer + j, "0x%08x: 0x%08x 0x%08x\n", stackPtr, *asPtr, asPtr[1]);
stackPtr = *asPtr;
}
OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access invalid address 0x%x "
"(read from DAR)\n",
context->srr0, dar);
if (!lbl_80419818) {
GXColor fg; // = &DAT_80000000;
GXColor bg; // = 0xffffff00;
OSFatal(fg, bg, buffer);
}
if (!SkipFatal) {
OSFatal(fg, bg, buffer);
}
}
@ -167,11 +178,11 @@ void rs_debugger_printf(const char* format, ...) {
va_list arg;
OSProtectRange(3, 0, 0, 3);
lbl_80419820 = 0;
rs_debugger_size = 0;
if (strncmp(format, "SKIP", 4) == 0) {
const char* s = format + 4;
format += 5;
lbl_80419820 = *s - 0x30;
rs_debugger_size = *s - 0x30;
}
char buffer[0x400];

View File

@ -17,7 +17,10 @@ import re
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = os.path.abspath(os.path.join(script_dir, ".."))
src_dir = os.path.join(root_dir, "src")
include_dir = os.path.join(root_dir, "include")
include_dirs = [
os.path.join(root_dir, "include"),
os.path.join(root_dir, "libc"),
]
include_pattern = re.compile(r'^#include\s*[<"](.+?)[>"]$')
guard_pattern = re.compile(r'^#ifndef\s+(.*)$')
@ -26,14 +29,15 @@ defines = set()
def import_h_file(in_file: str, r_path: str) -> str:
rel_path = os.path.join(root_dir, r_path, in_file)
inc_path = os.path.join(include_dir, in_file)
if os.path.exists(rel_path):
return import_c_file(rel_path)
elif os.path.exists(inc_path):
return import_c_file(inc_path)
return import_c_file(rel_path)
for include_dir in include_dirs:
inc_path = os.path.join(include_dir, in_file)
if os.path.exists(inc_path):
return import_c_file(inc_path)
else:
print("Failed to locate", in_file)
exit(1)
print("Failed to locate", in_file)
return ""
def import_c_file(in_file) -> str:
in_file = os.path.relpath(in_file, root_dir)