mirror of
https://github.com/PrimeDecomp/echoes.git
synced 2024-11-23 05:10:06 +00:00
RAssertDolphin fixes
This commit is contained in:
parent
f03293a9f9
commit
67cc8b5cc7
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@ orig/*/*
|
||||
tools/mwcc_compiler/*
|
||||
!tools/mwcc_compiler/.gitkeep
|
||||
/*.txt
|
||||
ctx.c
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, ...);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
13
libc/stdbool.h
Normal 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
550
src/Dolphin/os/OSContext.c
Normal 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
205
src/Dolphin/os/OSError.c
Normal 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();
|
||||
}
|
427
src/Dolphin/os/OSInterrupt.c
Normal file
427
src/Dolphin/os/OSInterrupt.c
Normal 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
|
||||
}
|
@ -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];
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user