diff --git a/.vscode/settings.json b/.vscode/settings.json index 20606a87..06904809 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -27,7 +27,15 @@ "db.h": "c", "ppcarch.h": "c", "osalarm.h": "c", - "ospriv.h": "c" + "ospriv.h": "c", + "gx.h": "c", + "osthread.h": "c", + "osserial.h": "c", + "osmutex.h": "c", + "osexception.h": "c", + "oserror.h": "c", + "oscontext.h": "c", + "oscache.h": "c" }, "files.autoSave": "onFocusChange", "files.insertFinalNewline": true, diff --git a/asm/Dolphin/os/OSThread.s b/asm/Dolphin/os/OSThread.s index 7922a199..64892931 100644 --- a/asm/Dolphin/os/OSThread.s +++ b/asm/Dolphin/os/OSThread.s @@ -2,16 +2,16 @@ .section .bss .balign 8 -lbl_805415F8: +RunQueue: .skip 0x9F8 .section .sbss .balign 8 -lbl_805A9920: +RunQueueBits: .skip 0x4 -lbl_805A9924: +RunQueueHint: .skip 0x4 -lbl_805A9928: +Reschedule: .skip 0x8 .section .sdata @@ -33,7 +33,7 @@ DefaultSwitchThreadCallback: .global __OSThreadInit __OSThreadInit: /* 8038446C 003813CC 7C 08 02 A6 */ mflr r0 -/* 80384470 003813D0 3C 60 80 54 */ lis r3, lbl_805415F8@ha +/* 80384470 003813D0 3C 60 80 54 */ lis r3, RunQueue@ha /* 80384474 003813D4 90 01 00 04 */ stw r0, 4(r1) /* 80384478 003813D8 38 00 00 02 */ li r0, 2 /* 8038447C 003813DC 38 80 00 10 */ li r4, 0x10 @@ -43,7 +43,7 @@ __OSThreadInit: /* 8038448C 003813EC 93 A1 00 0C */ stw r29, 0xc(r1) /* 80384490 003813F0 3B A0 00 00 */ li r29, 0 /* 80384494 003813F4 93 81 00 08 */ stw r28, 8(r1) -/* 80384498 003813F8 3B 83 15 F8 */ addi r28, r3, lbl_805415F8@l +/* 80384498 003813F8 3B 83 15 F8 */ addi r28, r3, RunQueue@l /* 8038449C 003813FC 3B FC 04 18 */ addi r31, r28, 0x418 /* 803844A0 00381400 B0 1C 06 E0 */ sth r0, 0x6e0(r28) /* 803844A4 00381404 38 00 00 01 */ li r0, 1 @@ -82,10 +82,10 @@ __OSThreadInit: /* 80384528 00381488 93 FE 00 E4 */ stw r31, 0xe4(r30) /* 8038452C 0038148C 38 60 00 00 */ li r3, 0 /* 80384530 00381490 48 00 0D CD */ bl OSClearStack -/* 80384534 00381494 93 AD AD 60 */ stw r29, lbl_805A9920@sda21(r13) +/* 80384534 00381494 93 AD AD 60 */ stw r29, RunQueueBits@sda21(r13) /* 80384538 00381498 3B C0 00 00 */ li r30, 0 /* 8038453C 0038149C 57 C0 18 38 */ slwi r0, r30, 3 -/* 80384540 003814A0 93 AD AD 64 */ stw r29, lbl_805A9924@sda21(r13) +/* 80384540 003814A0 93 AD AD 64 */ stw r29, RunQueueHint@sda21(r13) /* 80384544 003814A4 7F BC 02 14 */ add r29, r28, r0 lbl_80384548: /* 80384548 003814A8 7F A3 EB 78 */ mr r3, r29 @@ -112,7 +112,7 @@ lbl_80384588: /* 80384594 003814F4 93 DF 02 FC */ stw r30, 0x2fc(r31) /* 80384598 003814F8 93 E4 00 00 */ stw r31, 0(r4) /* 8038459C 003814FC 4B FF B0 79 */ bl OSClearContext -/* 803845A0 00381500 93 CD AD 68 */ stw r30, lbl_805A9928@sda21(r13) +/* 803845A0 00381500 93 CD AD 68 */ stw r30, Reschedule@sda21(r13) /* 803845A4 00381504 80 01 00 1C */ lwz r0, 0x1c(r1) /* 803845A8 00381508 83 E1 00 14 */ lwz r31, 0x14(r1) /* 803845AC 0038150C 83 C1 00 10 */ lwz r30, 0x10(r1) @@ -142,9 +142,9 @@ OSDisableScheduler: /* 803845E8 00381548 94 21 FF F0 */ stwu r1, -0x10(r1) /* 803845EC 0038154C 93 E1 00 0C */ stw r31, 0xc(r1) /* 803845F0 00381550 4B FF D0 71 */ bl OSDisableInterrupts -/* 803845F4 00381554 80 8D AD 68 */ lwz r4, lbl_805A9928@sda21(r13) +/* 803845F4 00381554 80 8D AD 68 */ lwz r4, Reschedule@sda21(r13) /* 803845F8 00381558 38 04 00 01 */ addi r0, r4, 1 -/* 803845FC 0038155C 90 0D AD 68 */ stw r0, lbl_805A9928@sda21(r13) +/* 803845FC 0038155C 90 0D AD 68 */ stw r0, Reschedule@sda21(r13) /* 80384600 00381560 7C 9F 23 78 */ mr r31, r4 /* 80384604 00381564 4B FF D0 85 */ bl OSRestoreInterrupts /* 80384608 00381568 7F E3 FB 78 */ mr r3, r31 @@ -161,9 +161,9 @@ OSEnableScheduler: /* 80384628 00381588 94 21 FF F0 */ stwu r1, -0x10(r1) /* 8038462C 0038158C 93 E1 00 0C */ stw r31, 0xc(r1) /* 80384630 00381590 4B FF D0 31 */ bl OSDisableInterrupts -/* 80384634 00381594 80 8D AD 68 */ lwz r4, lbl_805A9928@sda21(r13) +/* 80384634 00381594 80 8D AD 68 */ lwz r4, Reschedule@sda21(r13) /* 80384638 00381598 38 04 FF FF */ addi r0, r4, -1 -/* 8038463C 0038159C 90 0D AD 68 */ stw r0, lbl_805A9928@sda21(r13) +/* 8038463C 0038159C 90 0D AD 68 */ stw r0, Reschedule@sda21(r13) /* 80384640 003815A0 7C 9F 23 78 */ mr r31, r4 /* 80384644 003815A4 4B FF D0 45 */ bl OSRestoreInterrupts /* 80384648 003815A8 7F E3 FB 78 */ mr r3, r31 @@ -197,11 +197,11 @@ lbl_80384694: /* 8038469C 003815FC 40 82 00 20 */ bne lbl_803846BC /* 803846A0 00381600 80 03 02 D0 */ lwz r0, 0x2d0(r3) /* 803846A4 00381604 38 80 00 01 */ li r4, 1 -/* 803846A8 00381608 80 AD AD 60 */ lwz r5, lbl_805A9920@sda21(r13) +/* 803846A8 00381608 80 AD AD 60 */ lwz r5, RunQueueBits@sda21(r13) /* 803846AC 0038160C 20 00 00 1F */ subfic r0, r0, 0x1f /* 803846B0 00381610 7C 80 00 30 */ slw r0, r4, r0 /* 803846B4 00381614 7C A0 00 78 */ andc r0, r5, r0 -/* 803846B8 00381618 90 0D AD 60 */ stw r0, lbl_805A9920@sda21(r13) +/* 803846B8 00381618 90 0D AD 60 */ stw r0, RunQueueBits@sda21(r13) lbl_803846BC: /* 803846BC 0038161C 38 00 00 00 */ li r0, 0 /* 803846C0 00381620 90 03 02 DC */ stw r0, 0x2dc(r3) @@ -253,8 +253,8 @@ lbl_8038474C: /* 8038474C 003816AC 7F E3 FB 78 */ mr r3, r31 /* 80384750 003816B0 4B FF FF 11 */ bl UnsetRun /* 80384754 003816B4 93 DF 02 D0 */ stw r30, 0x2d0(r31) -/* 80384758 003816B8 3C 60 80 54 */ lis r3, lbl_805415F8@ha -/* 8038475C 003816BC 38 03 15 F8 */ addi r0, r3, lbl_805415F8@l +/* 80384758 003816B8 3C 60 80 54 */ lis r3, RunQueue@ha +/* 8038475C 003816BC 38 03 15 F8 */ addi r0, r3, RunQueue@l /* 80384760 003816C0 80 7F 02 D0 */ lwz r3, 0x2d0(r31) /* 80384764 003816C4 54 63 18 38 */ slwi r3, r3, 3 /* 80384768 003816C8 7C 00 1A 14 */ add r0, r0, r3 @@ -275,12 +275,12 @@ lbl_8038478C: /* 8038479C 003816FC 80 9F 02 DC */ lwz r4, 0x2dc(r31) /* 803847A0 00381700 93 E4 00 04 */ stw r31, 4(r4) /* 803847A4 00381704 80 1F 02 D0 */ lwz r0, 0x2d0(r31) -/* 803847A8 00381708 80 8D AD 60 */ lwz r4, lbl_805A9920@sda21(r13) +/* 803847A8 00381708 80 8D AD 60 */ lwz r4, RunQueueBits@sda21(r13) /* 803847AC 0038170C 20 00 00 1F */ subfic r0, r0, 0x1f /* 803847B0 00381710 7C 60 00 30 */ slw r0, r3, r0 /* 803847B4 00381714 7C 80 03 78 */ or r0, r4, r0 -/* 803847B8 00381718 90 0D AD 60 */ stw r0, lbl_805A9920@sda21(r13) -/* 803847BC 0038171C 90 6D AD 64 */ stw r3, lbl_805A9924@sda21(r13) +/* 803847B8 00381718 90 0D AD 60 */ stw r0, RunQueueBits@sda21(r13) +/* 803847BC 0038171C 90 6D AD 64 */ stw r3, RunQueueHint@sda21(r13) /* 803847C0 00381720 48 00 00 E8 */ b lbl_803848A8 lbl_803847C4: /* 803847C4 00381724 80 9F 02 E0 */ lwz r4, 0x2e0(r31) @@ -351,7 +351,7 @@ lbl_80384888: /* 80384898 003817F8 48 00 00 14 */ b lbl_803848AC lbl_8038489C: /* 8038489C 003817FC 38 00 00 01 */ li r0, 1 -/* 803848A0 00381800 90 0D AD 64 */ stw r0, lbl_805A9924@sda21(r13) +/* 803848A0 00381800 90 0D AD 64 */ stw r0, RunQueueHint@sda21(r13) /* 803848A4 00381804 93 DF 02 D0 */ stw r30, 0x2d0(r31) lbl_803848A8: /* 803848A8 00381808 38 60 00 00 */ li r3, 0 @@ -366,14 +366,14 @@ lbl_803848AC: .global SelectThread SelectThread: /* 803848C4 00381824 7C 08 02 A6 */ mflr r0 -/* 803848C8 00381828 3C 80 80 54 */ lis r4, lbl_805415F8@ha +/* 803848C8 00381828 3C 80 80 54 */ lis r4, RunQueue@ha /* 803848CC 0038182C 90 01 00 04 */ stw r0, 4(r1) /* 803848D0 00381830 94 21 FF E8 */ stwu r1, -0x18(r1) /* 803848D4 00381834 93 E1 00 14 */ stw r31, 0x14(r1) -/* 803848D8 00381838 3B E4 15 F8 */ addi r31, r4, lbl_805415F8@l +/* 803848D8 00381838 3B E4 15 F8 */ addi r31, r4, RunQueue@l /* 803848DC 0038183C 93 C1 00 10 */ stw r30, 0x10(r1) /* 803848E0 00381840 3B C3 00 00 */ addi r30, r3, 0 -/* 803848E4 00381844 80 0D AD 68 */ lwz r0, lbl_805A9928@sda21(r13) +/* 803848E4 00381844 80 0D AD 68 */ lwz r0, Reschedule@sda21(r13) /* 803848E8 00381848 2C 00 00 00 */ cmpwi r0, 0 /* 803848EC 0038184C 40 81 00 0C */ ble lbl_803848F8 /* 803848F0 00381850 38 60 00 00 */ li r3, 0 @@ -395,7 +395,7 @@ lbl_80384918: /* 80384928 00381888 40 82 00 90 */ bne lbl_803849B8 /* 8038492C 0038188C 2C 1E 00 00 */ cmpwi r30, 0 /* 80384930 00381890 40 82 00 20 */ bne lbl_80384950 -/* 80384934 00381894 80 8D AD 60 */ lwz r4, lbl_805A9920@sda21(r13) +/* 80384934 00381894 80 8D AD 60 */ lwz r4, RunQueueBits@sda21(r13) /* 80384938 00381898 80 06 02 D0 */ lwz r0, 0x2d0(r6) /* 8038493C 0038189C 7C 84 00 34 */ cntlzw r4, r4 /* 80384940 003818A0 7C 00 20 00 */ cmpw r0, r4 @@ -425,12 +425,12 @@ lbl_80384984: /* 80384994 003818F4 80 A6 02 DC */ lwz r5, 0x2dc(r6) /* 80384998 003818F8 90 C5 00 04 */ stw r6, 4(r5) /* 8038499C 003818FC 80 06 02 D0 */ lwz r0, 0x2d0(r6) -/* 803849A0 00381900 80 AD AD 60 */ lwz r5, lbl_805A9920@sda21(r13) +/* 803849A0 00381900 80 AD AD 60 */ lwz r5, RunQueueBits@sda21(r13) /* 803849A4 00381904 20 00 00 1F */ subfic r0, r0, 0x1f /* 803849A8 00381908 7C 80 00 30 */ slw r0, r4, r0 /* 803849AC 0038190C 7C A0 03 78 */ or r0, r5, r0 -/* 803849B0 00381910 90 0D AD 60 */ stw r0, lbl_805A9920@sda21(r13) -/* 803849B4 00381914 90 8D AD 64 */ stw r4, lbl_805A9924@sda21(r13) +/* 803849B0 00381910 90 0D AD 60 */ stw r0, RunQueueBits@sda21(r13) +/* 803849B4 00381914 90 8D AD 64 */ stw r4, RunQueueHint@sda21(r13) lbl_803849B8: /* 803849B8 00381918 A0 06 01 A2 */ lhz r0, 0x1a2(r6) /* 803849BC 0038191C 54 00 07 BD */ rlwinm. r0, r0, 0, 0x1e, 0x1e @@ -447,7 +447,7 @@ lbl_803849D8: /* 803849E4 00381944 38 80 00 00 */ li r4, 0 /* 803849E8 00381948 7D 88 03 A6 */ mtlr r12 /* 803849EC 0038194C 4E 80 00 21 */ blrl -/* 803849F0 00381950 80 0D AD 60 */ lwz r0, lbl_805A9920@sda21(r13) +/* 803849F0 00381950 80 0D AD 60 */ lwz r0, RunQueueBits@sda21(r13) /* 803849F4 00381954 38 60 00 00 */ li r3, 0 /* 803849F8 00381958 90 7E 00 E4 */ stw r3, 0xe4(r30) /* 803849FC 0038195C 28 00 00 00 */ cmplwi r0, 0 @@ -457,19 +457,19 @@ lbl_803849D8: lbl_80384A0C: /* 80384A0C 0038196C 4B FF CC 69 */ bl OSEnableInterrupts lbl_80384A10: -/* 80384A10 00381970 80 0D AD 60 */ lwz r0, lbl_805A9920@sda21(r13) +/* 80384A10 00381970 80 0D AD 60 */ lwz r0, RunQueueBits@sda21(r13) /* 80384A14 00381974 28 00 00 00 */ cmplwi r0, 0 /* 80384A18 00381978 41 82 FF F8 */ beq lbl_80384A10 /* 80384A1C 0038197C 4B FF CC 45 */ bl OSDisableInterrupts -/* 80384A20 00381980 80 0D AD 60 */ lwz r0, lbl_805A9920@sda21(r13) +/* 80384A20 00381980 80 0D AD 60 */ lwz r0, RunQueueBits@sda21(r13) /* 80384A24 00381984 28 00 00 00 */ cmplwi r0, 0 /* 80384A28 00381988 41 82 FF E4 */ beq lbl_80384A0C /* 80384A2C 0038198C 38 7F 07 30 */ addi r3, r31, 0x730 /* 80384A30 00381990 4B FF AB E5 */ bl OSClearContext lbl_80384A34: /* 80384A34 00381994 38 60 00 00 */ li r3, 0 -/* 80384A38 00381998 90 6D AD 64 */ stw r3, lbl_805A9924@sda21(r13) -/* 80384A3C 0038199C 80 0D AD 60 */ lwz r0, lbl_805A9920@sda21(r13) +/* 80384A38 00381998 90 6D AD 64 */ stw r3, RunQueueHint@sda21(r13) +/* 80384A3C 0038199C 80 0D AD 60 */ lwz r0, RunQueueBits@sda21(r13) /* 80384A40 003819A0 7C 07 00 34 */ cntlzw r7, r0 /* 80384A44 003819A4 54 E0 18 38 */ slwi r0, r7, 3 /* 80384A48 003819A8 7C 9F 02 14 */ add r4, r31, r0 @@ -488,11 +488,11 @@ lbl_80384A6C: /* 80384A74 003819D4 28 00 00 00 */ cmplwi r0, 0 /* 80384A78 003819D8 40 82 00 1C */ bne lbl_80384A94 /* 80384A7C 003819DC 20 07 00 1F */ subfic r0, r7, 0x1f -/* 80384A80 003819E0 80 8D AD 60 */ lwz r4, lbl_805A9920@sda21(r13) +/* 80384A80 003819E0 80 8D AD 60 */ lwz r4, RunQueueBits@sda21(r13) /* 80384A84 003819E4 38 60 00 01 */ li r3, 1 /* 80384A88 003819E8 7C 60 00 30 */ slw r0, r3, r0 /* 80384A8C 003819EC 7C 80 00 78 */ andc r0, r4, r0 -/* 80384A90 003819F0 90 0D AD 60 */ stw r0, lbl_805A9920@sda21(r13) +/* 80384A90 003819F0 90 0D AD 60 */ stw r0, RunQueueBits@sda21(r13) lbl_80384A94: /* 80384A94 003819F4 38 00 00 00 */ li r0, 0 /* 80384A98 003819F8 90 1E 02 DC */ stw r0, 0x2dc(r30) @@ -523,7 +523,7 @@ __OSReschedule: /* 80384AEC 00381A4C 7C 08 02 A6 */ mflr r0 /* 80384AF0 00381A50 90 01 00 04 */ stw r0, 4(r1) /* 80384AF4 00381A54 94 21 FF F8 */ stwu r1, -8(r1) -/* 80384AF8 00381A58 80 0D AD 64 */ lwz r0, lbl_805A9924@sda21(r13) +/* 80384AF8 00381A58 80 0D AD 64 */ lwz r0, RunQueueHint@sda21(r13) /* 80384AFC 00381A5C 2C 00 00 00 */ cmpwi r0, 0 /* 80384B00 00381A60 41 82 00 0C */ beq lbl_80384B0C /* 80384B04 00381A64 38 60 00 00 */ li r3, 0 @@ -584,7 +584,7 @@ lbl_80384BA8: /* 80384BBC 00381B1C 48 00 00 B0 */ b lbl_80384C6C lbl_80384BC0: /* 80384BC0 00381B20 38 00 00 01 */ li r0, 1 -/* 80384BC4 00381B24 90 0D AD 64 */ stw r0, lbl_805A9924@sda21(r13) +/* 80384BC4 00381B24 90 0D AD 64 */ stw r0, RunQueueHint@sda21(r13) /* 80384BC8 00381B28 48 00 00 A4 */ b lbl_80384C6C lbl_80384BCC: /* 80384BCC 00381B2C 80 9E 02 E0 */ lwz r4, 0x2e0(r30) @@ -668,7 +668,7 @@ lbl_80384CCC: /* 80384CD0 00381C30 4B FF E0 E9 */ bl __OSUnlockAllMutex /* 80384CD4 00381C34 38 7E 02 E8 */ addi r3, r30, 0x2e8 /* 80384CD8 00381C38 48 00 05 21 */ bl OSWakeupThread -/* 80384CDC 00381C3C 80 0D AD 64 */ lwz r0, lbl_805A9924@sda21(r13) +/* 80384CDC 00381C3C 80 0D AD 64 */ lwz r0, RunQueueHint@sda21(r13) /* 80384CE0 00381C40 2C 00 00 00 */ cmpwi r0, 0 /* 80384CE4 00381C44 41 82 00 0C */ beq lbl_80384CF0 /* 80384CE8 00381C48 38 60 00 00 */ li r3, 0 @@ -733,8 +733,8 @@ lbl_80384DAC: /* 80384DAC 00381D0C 28 03 00 00 */ cmplwi r3, 0 /* 80384DB0 00381D10 40 82 FF DC */ bne lbl_80384D8C /* 80384DB4 00381D14 90 1D 02 D0 */ stw r0, 0x2d0(r29) -/* 80384DB8 00381D18 3C 60 80 54 */ lis r3, lbl_805415F8@ha -/* 80384DBC 00381D1C 38 03 15 F8 */ addi r0, r3, lbl_805415F8@l +/* 80384DB8 00381D18 3C 60 80 54 */ lis r3, RunQueue@ha +/* 80384DBC 00381D1C 38 03 15 F8 */ addi r0, r3, RunQueue@l /* 80384DC0 00381D20 80 7D 02 D0 */ lwz r3, 0x2d0(r29) /* 80384DC4 00381D24 54 63 18 38 */ slwi r3, r3, 3 /* 80384DC8 00381D28 7C 00 1A 14 */ add r0, r0, r3 @@ -755,12 +755,12 @@ lbl_80384DEC: /* 80384DFC 00381D5C 80 9D 02 DC */ lwz r4, 0x2dc(r29) /* 80384E00 00381D60 93 A4 00 04 */ stw r29, 4(r4) /* 80384E04 00381D64 80 1D 02 D0 */ lwz r0, 0x2d0(r29) -/* 80384E08 00381D68 80 8D AD 60 */ lwz r4, lbl_805A9920@sda21(r13) +/* 80384E08 00381D68 80 8D AD 60 */ lwz r4, RunQueueBits@sda21(r13) /* 80384E0C 00381D6C 20 00 00 1F */ subfic r0, r0, 0x1f /* 80384E10 00381D70 7C 60 00 30 */ slw r0, r3, r0 /* 80384E14 00381D74 7C 80 03 78 */ or r0, r4, r0 -/* 80384E18 00381D78 90 0D AD 60 */ stw r0, lbl_805A9920@sda21(r13) -/* 80384E1C 00381D7C 90 6D AD 64 */ stw r3, lbl_805A9924@sda21(r13) +/* 80384E18 00381D78 90 0D AD 60 */ stw r0, RunQueueBits@sda21(r13) +/* 80384E1C 00381D7C 90 6D AD 64 */ stw r3, RunQueueHint@sda21(r13) /* 80384E20 00381D80 48 00 01 40 */ b lbl_80384F60 lbl_80384E24: /* 80384E24 00381D84 80 9D 02 E0 */ lwz r4, 0x2e0(r29) @@ -859,7 +859,7 @@ lbl_80384F2C: /* 80384F58 00381EB8 7C 7D 1B 79 */ or. r29, r3, r3 /* 80384F5C 00381EBC 40 82 FF D0 */ bne lbl_80384F2C lbl_80384F60: -/* 80384F60 00381EC0 80 0D AD 64 */ lwz r0, lbl_805A9924@sda21(r13) +/* 80384F60 00381EC0 80 0D AD 64 */ lwz r0, RunQueueHint@sda21(r13) /* 80384F64 00381EC4 2C 00 00 00 */ cmpwi r0, 0 /* 80384F68 00381EC8 41 82 00 0C */ beq lbl_80384F74 /* 80384F6C 00381ECC 38 60 00 00 */ li r3, 0 @@ -906,7 +906,7 @@ lbl_80384FF4: /* 80384FFC 00381F5C 48 00 00 20 */ b lbl_8038501C lbl_80385000: /* 80385000 00381F60 38 00 00 01 */ li r0, 1 -/* 80385004 00381F64 90 0D AD 64 */ stw r0, lbl_805A9924@sda21(r13) +/* 80385004 00381F64 90 0D AD 64 */ stw r0, RunQueueHint@sda21(r13) /* 80385008 00381F68 B0 1D 02 C8 */ sth r0, 0x2c8(r29) /* 8038500C 00381F6C 48 00 00 C4 */ b lbl_803850D0 lbl_80385010: @@ -967,7 +967,7 @@ lbl_8038509C: /* 803850C8 00382028 7C 7D 1B 79 */ or. r29, r3, r3 /* 803850CC 0038202C 40 82 FF D0 */ bne lbl_8038509C lbl_803850D0: -/* 803850D0 00382030 80 0D AD 64 */ lwz r0, lbl_805A9924@sda21(r13) +/* 803850D0 00382030 80 0D AD 64 */ lwz r0, RunQueueHint@sda21(r13) /* 803850D4 00382034 2C 00 00 00 */ cmpwi r0, 0 /* 803850D8 00382038 41 82 00 0C */ beq lbl_803850E4 /* 803850DC 0038203C 38 60 00 00 */ li r3, 0 @@ -1039,8 +1039,8 @@ lbl_803851B8: /* 803851B8 00382118 90 83 02 E0 */ stw r4, 0x2e0(r3) lbl_803851BC: /* 803851BC 0038211C 38 00 00 01 */ li r0, 1 -/* 803851C0 00382120 90 0D AD 64 */ stw r0, lbl_805A9924@sda21(r13) -/* 803851C4 00382124 80 0D AD 64 */ lwz r0, lbl_805A9924@sda21(r13) +/* 803851C0 00382120 90 0D AD 64 */ stw r0, RunQueueHint@sda21(r13) +/* 803851C4 00382124 80 0D AD 64 */ lwz r0, RunQueueHint@sda21(r13) /* 803851C8 00382128 2C 00 00 00 */ cmpwi r0, 0 /* 803851CC 0038212C 41 82 00 0C */ beq lbl_803851D8 /* 803851D0 00382130 38 60 00 00 */ li r3, 0 @@ -1064,9 +1064,9 @@ OSWakeupThread: /* 80385208 00382168 93 C1 00 10 */ stw r30, 0x10(r1) /* 8038520C 0038216C 7C 7E 1B 78 */ mr r30, r3 /* 80385210 00382170 4B FF C4 51 */ bl OSDisableInterrupts -/* 80385214 00382174 3C 80 80 54 */ lis r4, lbl_805415F8@ha +/* 80385214 00382174 3C 80 80 54 */ lis r4, RunQueue@ha /* 80385218 00382178 3B E3 00 00 */ addi r31, r3, 0 -/* 8038521C 0038217C 38 A4 15 F8 */ addi r5, r4, lbl_805415F8@l +/* 8038521C 0038217C 38 A4 15 F8 */ addi r5, r4, RunQueue@l /* 80385220 00382180 48 00 00 9C */ b lbl_803852BC lbl_80385224: /* 80385224 00382184 80 66 02 E0 */ lwz r3, 0x2e0(r6) @@ -1105,17 +1105,17 @@ lbl_80385288: /* 80385298 003821F8 80 86 02 DC */ lwz r4, 0x2dc(r6) /* 8038529C 003821FC 90 C4 00 04 */ stw r6, 4(r4) /* 803852A0 00382200 80 06 02 D0 */ lwz r0, 0x2d0(r6) -/* 803852A4 00382204 80 8D AD 60 */ lwz r4, lbl_805A9920@sda21(r13) +/* 803852A4 00382204 80 8D AD 60 */ lwz r4, RunQueueBits@sda21(r13) /* 803852A8 00382208 20 00 00 1F */ subfic r0, r0, 0x1f /* 803852AC 0038220C 7C 60 00 30 */ slw r0, r3, r0 /* 803852B0 00382210 7C 80 03 78 */ or r0, r4, r0 -/* 803852B4 00382214 90 0D AD 60 */ stw r0, lbl_805A9920@sda21(r13) -/* 803852B8 00382218 90 6D AD 64 */ stw r3, lbl_805A9924@sda21(r13) +/* 803852B4 00382214 90 0D AD 60 */ stw r0, RunQueueBits@sda21(r13) +/* 803852B8 00382218 90 6D AD 64 */ stw r3, RunQueueHint@sda21(r13) lbl_803852BC: /* 803852BC 0038221C 80 DE 00 00 */ lwz r6, 0(r30) /* 803852C0 00382220 28 06 00 00 */ cmplwi r6, 0 /* 803852C4 00382224 40 82 FF 60 */ bne lbl_80385224 -/* 803852C8 00382228 80 0D AD 64 */ lwz r0, lbl_805A9924@sda21(r13) +/* 803852C8 00382228 80 0D AD 64 */ lwz r0, RunQueueHint@sda21(r13) /* 803852CC 0038222C 2C 00 00 00 */ cmpwi r0, 0 /* 803852D0 00382230 41 82 00 0C */ beq lbl_803852DC /* 803852D4 00382234 38 60 00 00 */ li r3, 0 diff --git a/configure.py b/configure.py index fcebb5e9..b805d215 100755 --- a/configure.py +++ b/configure.py @@ -841,7 +841,7 @@ LIBS = [ "Dolphin/os/OSResetSW", ["Dolphin/os/OSRtc", False], ["Dolphin/os/OSSync", True], - "Dolphin/os/OSThread", + ["Dolphin/os/OSThread", True], ["Dolphin/os/OSTime", True], ["Dolphin/os/__ppc_eabi_init", True], ], diff --git a/include/dolphin/os.h b/include/dolphin/os.h index 5a5ffdae..e28f43f7 100644 --- a/include/dolphin/os.h +++ b/include/dolphin/os.h @@ -67,10 +67,10 @@ OSTime OSGetTime(); OSTick OSGetTick(); typedef struct OSCalendarTime { - int sec; // seconds after the minute [0, 61] - int min; // minutes after the hour [0, 59] - int hour; // hours since midnight [0, 23] - int mday; // day of the month [1, 31] + int sec; // seconds after the minute [0, 61] + int min; // minutes after the hour [0, 59] + int hour; // hours since midnight [0, 23] + int mday; // day of the month [1, 31] int mon; // month since January [0, 11] int year; // years in AD [1, ...] int wday; // days since Sunday [0, 6] @@ -80,9 +80,8 @@ typedef struct OSCalendarTime { int usec; // microseconds after the millisecond [0,999] } OSCalendarTime; -OSTime OSCalendarTimeToTicks( OSCalendarTime* td ); -void OSTicksToCalendarTime( OSTime ticks, OSCalendarTime* td ); - +OSTime OSCalendarTimeToTicks(OSCalendarTime* td); +void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime* td); #define OS_CONSOLE_MASK 0xf0000000 #define OS_CONSOLE_RETAIL 0x00000000 @@ -157,6 +156,7 @@ void OSFatal(GXColor fg, GXColor bg, const char* msg); #include #include #include +#include #include #include #include diff --git a/include/dolphin/os/OSContext.h b/include/dolphin/os/OSContext.h index ecc09a81..e5544aba 100644 --- a/include/dolphin/os/OSContext.h +++ b/include/dolphin/os/OSContext.h @@ -80,7 +80,7 @@ extern "C" { #define OS_CONTEXT_FPR30 384 #define OS_CONTEXT_FPR31 392 -#define OS_CONTEXT_FPSCR 400 +#define OS_CONTEXT_FPSCR 400 #define OS_CONTEXT_SRR0 408 #define OS_CONTEXT_SRR1 412 @@ -130,6 +130,7 @@ extern "C" { #define OS_CONTEXT_PSF29 688 #define OS_CONTEXT_PSF30 696 #define OS_CONTEXT_PSF31 704 +#define OS_CONTEXT_STATE_EXC 0x02u typedef struct OSContext { u32 gpr[32]; @@ -155,7 +156,7 @@ typedef struct OSContext { } OSContext; -void OSSaveContext(OSContext* context); +u32 OSSaveContext(OSContext* context); void OSClearContext(OSContext* context); OSContext* OSGetCurrentContext(); void OSSetCurrentContext(OSContext* context); diff --git a/include/dolphin/os/OSThread.h b/include/dolphin/os/OSThread.h index 0dcef9ad..7464e685 100644 --- a/include/dolphin/os/OSThread.h +++ b/include/dolphin/os/OSThread.h @@ -62,7 +62,49 @@ struct OSThread { void* specific[OS_THREAD_SPECIFIC_MAX]; }; +enum OS_THREAD_STATE { + OS_THREAD_STATE_READY = 1, + OS_THREAD_STATE_RUNNING = 2, + OS_THREAD_STATE_WAITING = 4, + OS_THREAD_STATE_MORIBUND = 8 +}; + +#define OS_THREAD_ATTR_DETACH 0x0001u + +#define OS_THREAD_STACK_MAGIC 0xDEADBABE + +#define OS_PRIORITY_MIN 0 // highest +#define OS_PRIORITY_MAX 31 // lowest +#define OS_PRIORITY_IDLE OS_PRIORITY_MAX + + +void OSInitThreadQueue(OSThreadQueue* queue); OSThread* OSGetCurrentThread(void); +BOOL OSIsThreadSuspended(OSThread* thread); +BOOL OSIsThreadTerminated(OSThread* thread); +s32 OSDisableScheduler(void); +s32 OSEnableScheduler(void); +void OSYieldThread(void); +BOOL OSCreateThread(OSThread* thread, void* (*func)(void*), void* param, void* stack, u32 stackSize, + OSPriority priority, u16 attr); +void OSExitThread(void* val); +void OSCancelThread(OSThread* thread); +BOOL OSJoinThread(OSThread* thread, void** val); +void OSDetachThread(OSThread* thread); +s32 OSResumeThread(OSThread* thread); +s32 OSSuspendThread(OSThread* thread); +BOOL OSSetThreadPriority(OSThread* thread, OSPriority priority); +OSPriority OSGetThreadPriority(OSThread* thread); +void OSSleepThread(OSThreadQueue* queue); +void OSWakeupThread(OSThreadQueue* queue); + +void* OSGetThreadSpecific(s32 index); +void OSSetThreadSpecific(s32 index, void* ptr); + +OSThread* OSSetIdleFunction(OSIdleFunction idleFunction, void* param, void* stack, u32 stackSize); +OSThread* OSGetIdleFunction(void); +void OSClearStack(u8 val); +long OSCheckActiveThreads(void); #ifdef __cplusplus } diff --git a/obj_files.mk b/obj_files.mk index 953953a0..ee5da86b 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -706,7 +706,7 @@ OS_FILES :=\ $(BUILD_DIR)/asm/Dolphin/os/OSResetSW.o\ $(BUILD_DIR)/asm/Dolphin/os/OSRtc.o\ $(BUILD_DIR)/src/Dolphin/os/OSSync.o\ - $(BUILD_DIR)/asm/Dolphin/os/OSThread.o\ + $(BUILD_DIR)/src/Dolphin/os/OSThread.ep.o\ $(BUILD_DIR)/src/Dolphin/os/OSTime.ep.o\ $(BUILD_DIR)/src/Dolphin/os/__ppc_eabi_init.ep.o\ diff --git a/src/Dolphin/os/OSThread.c b/src/Dolphin/os/OSThread.c new file mode 100644 index 00000000..dfb392f1 --- /dev/null +++ b/src/Dolphin/os/OSThread.c @@ -0,0 +1,829 @@ +#include "dolphin/os/OSPriv.h" + +static vu32 RunQueueBits; +static volatile BOOL RunQueueHint; +static vs32 Reschedule; + +static OSThreadQueue RunQueue[32]; +static OSThread IdleThread; +static OSThread DefaultThread; +static OSContext IdleContext; +static void DefaultSwitchThreadCallback(OSThread* from, OSThread* to); +static OSSwitchThreadCallback SwitchThreadCallback = DefaultSwitchThreadCallback; + +OSThread* __OSCurrentThread : OS_BASE_CACHED + 0x00E4; +OSThreadQueue __OSActiveThreadQueue : OS_BASE_CACHED + 0x00DC; +volatile OSContext __OSCurrentContext : OS_BASE_CACHED + 0x00D4; +volatile OSContext* __OSFPUContext : OS_BASE_CACHED + 0x00D8; + +static void DefaultSwitchThreadCallback(OSThread* from, OSThread* to) {} + +extern u8 _stack_addr[]; +extern u8 _stack_end[]; + +#define AddTail(queue, thread, link) \ + do { \ + OSThread* prev; \ + \ + prev = (queue)->tail; \ + if (prev == NULL) \ + (queue)->head = (thread); \ + else \ + prev->link.next = (thread); \ + (thread)->link.prev = prev; \ + (thread)->link.next = NULL; \ + (queue)->tail = (thread); \ + } while (0) + +#define AddPrio(queue, thread, link) \ + do { \ + OSThread *prev, *next; \ + \ + for (next = (queue)->head; next && next->priority <= thread->priority; next = next->link.next) \ + ; \ + if (next == NULL) \ + AddTail(queue, thread, link); \ + else { \ + (thread)->link.next = next; \ + prev = next->link.prev; \ + next->link.prev = (thread); \ + (thread)->link.prev = prev; \ + if (prev == NULL) \ + (queue)->head = (thread); \ + else \ + prev->link.next = (thread); \ + } \ + } while (0) + +#define RemoveItem(queue, thread, link) \ + do { \ + OSThread *next, *prev; \ + next = (thread)->link.next; \ + prev = (thread)->link.prev; \ + if (next == NULL) \ + (queue)->tail = prev; \ + else \ + next->link.prev = prev; \ + if (prev == NULL) \ + (queue)->head = next; \ + else \ + prev->link.next = next; \ + } while (0) + +#define RemoveHead(queue, thread, link) \ + do { \ + OSThread* __next; \ + (thread) = (queue)->head; \ + __next = (thread)->link.next; \ + if (__next == NULL) \ + (queue)->tail = NULL; \ + else \ + __next->link.prev = NULL; \ + (queue)->head = __next; \ + } while (0) + +static inline void OSInitMutexQueue(OSMutexQueue* queue) { queue->head = queue->tail = NULL; } + +static inline void OSSetCurrentThread(OSThread* thread) { + SwitchThreadCallback(__OSCurrentThread, thread); + __OSCurrentThread = thread; +} + +void __OSThreadInit() { + OSThread* thread = &DefaultThread; + int prio; + + thread->state = OS_THREAD_STATE_RUNNING; + thread->attr = OS_THREAD_ATTR_DETACH; + thread->priority = thread->base = 16; + thread->suspend = 0; + thread->val = (void*)-1; + thread->mutex = NULL; + OSInitThreadQueue(&thread->queueJoin); + OSInitMutexQueue(&thread->queueMutex); + + __OSFPUContext = &thread->context; + + OSClearContext(&thread->context); + OSSetCurrentContext(&thread->context); + thread->stackBase = (void*)_stack_addr; + thread->stackEnd = (void*)_stack_end; + *(thread->stackEnd) = OS_THREAD_STACK_MAGIC; + + OSSetCurrentThread(thread); + OSClearStack(0); + + RunQueueBits = 0; + RunQueueHint = FALSE; + for (prio = OS_PRIORITY_MIN; prio <= OS_PRIORITY_MAX; ++prio) { + OSInitThreadQueue(&RunQueue[prio]); + } + + OSInitThreadQueue(&__OSActiveThreadQueue); + AddTail(&__OSActiveThreadQueue, thread, linkActive); + OSClearContext(&IdleContext); + Reschedule = 0; +} + +void OSInitThreadQueue(OSThreadQueue* queue) { queue->head = queue->tail = NULL; } + +OSThread* OSGetCurrentThread() { return __OSCurrentThread; } + +#if NONMATCHING +/* Code matches, stack epilogue bug*/ +s32 OSDisableScheduler() { + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + count = Reschedule++; + OSRestoreInterrupts(enabled); + return count; +} +#else +/* clang-format off */ +#pragma push +#pragma optimization_level +#pragma optimizewithasm off +asm s32 OSDisableScheduler() { + nofralloc + mflr r0 + stw r0, 4(r1) + stwu r1, -0x10(r1) + stw r31, 0xc(r1) + bl OSDisableInterrupts + lwz r4, Reschedule + addi r0, r4, 1 + stw r0, Reschedule + mr r31, r4 + bl OSRestoreInterrupts + mr r3, r31 + lwz r0, 0x14(r1) + lwz r31, 0xc(r1) + addi r1, r1, 0x10 + mtlr r0 + blr +} +/* clang-format on */ +#pragma pop +#endif + +#if NONMATCHING +/* Code matches, stack epilogue bug*/ +s32 OSEnableScheduler() { + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + count = Reschedule--; + OSRestoreInterrupts(enabled); + return count; +} +#else +/* clang-format off */ +#pragma push +#pragma optimization_level +#pragma optimizewithasm off +asm s32 OSEnableScheduler() { + nofralloc + mflr r0 + stw r0, 4(r1) + stwu r1, -0x10(r1) + stw r31, 0xc(r1) + bl OSDisableInterrupts + lwz r4, Reschedule + subi r0, r4, 1 + stw r0, Reschedule + mr r31, r4 + bl OSRestoreInterrupts + mr r3, r31 + lwz r0, 0x14(r1) + lwz r31, 0xc(r1) + addi r1, r1, 0x10 + mtlr r0 + blr +} +/* clang-format on */ +#pragma pop +#endif + +static void SetRun(OSThread* thread) { + thread->queue = &RunQueue[thread->priority]; + AddTail(thread->queue, thread, link); + RunQueueBits |= 1u << (OS_PRIORITY_MAX - thread->priority); + RunQueueHint = TRUE; +} +#pragma dont_inline on +static void UnsetRun(OSThread* thread) { + OSThreadQueue* queue; + queue = thread->queue; + RemoveItem(queue, thread, link); + if (queue->head == 0) + RunQueueBits &= ~(1u << (OS_PRIORITY_MAX - thread->priority)); + thread->queue = NULL; +} +#pragma dont_inline reset + +OSPriority __OSGetEffectivePriority(OSThread* thread) { + OSPriority priority; + OSMutex* mutex; + OSThread* blocked; + + priority = thread->base; + for (mutex = thread->queueMutex.head; mutex; mutex = mutex->link.next) { + blocked = mutex->queue.head; + if (blocked && blocked->priority < priority) { + priority = blocked->priority; + } + } + return priority; +} + +static OSThread* SetEffectivePriority(OSThread* thread, OSPriority priority) { + switch (thread->state) { + case OS_THREAD_STATE_READY: + UnsetRun(thread); + thread->priority = priority; + SetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + RemoveItem(thread->queue, thread, link); + thread->priority = priority; + AddPrio(thread->queue, thread, link); + if (thread->mutex) { + return thread->mutex->thread; + } + break; + case OS_THREAD_STATE_RUNNING: + RunQueueHint = TRUE; + thread->priority = priority; + break; + } + return NULL; +} + +static void UpdatePriority(OSThread* thread) { + OSPriority priority; + + do { + if (0 < thread->suspend) { + break; + } + priority = __OSGetEffectivePriority(thread); + if (thread->priority == priority) { + break; + } + thread = SetEffectivePriority(thread, priority); + } while (thread); +} + +static void __OSSwitchThread(OSThread* nextThread) { + OSSetCurrentThread(nextThread); + OSSetCurrentContext(&nextThread->context); + OSLoadContext(&nextThread->context); +} + +static OSThread* SelectThread(BOOL yield) { + OSContext* currentContext; + OSThread* currentThread; + OSThread* nextThread; + OSPriority priority; + OSThreadQueue* queue; + + if (0 < Reschedule) { + return 0; + } + + currentContext = OSGetCurrentContext(); + currentThread = OSGetCurrentThread(); + if (currentContext != ¤tThread->context) { + return 0; + } + + if (currentThread) { + if (currentThread->state == OS_THREAD_STATE_RUNNING) { + if (!yield) { + priority = __cntlzw(RunQueueBits); + if (currentThread->priority <= priority) { + return 0; + } + } + currentThread->state = OS_THREAD_STATE_READY; + SetRun(currentThread); + } + + if (!(currentThread->context.state & OS_CONTEXT_STATE_EXC) && + OSSaveContext(¤tThread->context)) { + return 0; + } + } + + OSSetCurrentThread(NULL); + if (RunQueueBits == 0) { + OSSetCurrentContext(&IdleContext); + do { + OSEnableInterrupts(); + while (RunQueueBits == 0) + ; + OSDisableInterrupts(); + } while (RunQueueBits == 0); + + OSClearContext(&IdleContext); + } + + RunQueueHint = FALSE; + + priority = __cntlzw(RunQueueBits); + queue = &RunQueue[priority]; + RemoveHead(queue, nextThread, link); + if (queue->head == 0) { + RunQueueBits &= ~(1u << (OS_PRIORITY_MAX - priority)); + } + nextThread->queue = NULL; + nextThread->state = OS_THREAD_STATE_RUNNING; + __OSSwitchThread(nextThread); + return nextThread; +} + +void __OSReschedule() { + if (!RunQueueHint) { + return; + } + + SelectThread(FALSE); +} + +void OSYieldThread(void) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + SelectThread(TRUE); + OSRestoreInterrupts(enabled); +} + +void OSCancelThread(OSThread* thread) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + + switch (thread->state) { + case OS_THREAD_STATE_READY: + if (!(0 < thread->suspend)) { + UnsetRun(thread); + } + break; + case OS_THREAD_STATE_RUNNING: + RunQueueHint = TRUE; + break; + case OS_THREAD_STATE_WAITING: + RemoveItem(thread->queue, thread, link); + thread->queue = NULL; + if (!(0 < thread->suspend) && thread->mutex) { + UpdatePriority(thread->mutex->thread); + } + break; + default: + OSRestoreInterrupts(enabled); + return; + } + + OSClearContext(&thread->context); + if (thread->attr & OS_THREAD_ATTR_DETACH) { + RemoveItem(&__OSActiveThreadQueue, thread, linkActive); + thread->state = 0; + } else { + thread->state = OS_THREAD_STATE_MORIBUND; + } + + __OSUnlockAllMutex(thread); + + OSWakeupThread(&thread->queueJoin); + + __OSReschedule(); + OSRestoreInterrupts(enabled); + + return; +} + +#if NONMATCHING +/* Code matches, stack epilogue bug*/ +s32 OSResumeThread(OSThread* thread) { + BOOL enabled; + s32 suspendCount; + + enabled = OSDisableInterrupts(); + suspendCount = thread->suspend--; + if (thread->suspend < 0) { + thread->suspend = 0; + } else if (thread->suspend == 0) { + switch (thread->state) { + case OS_THREAD_STATE_READY: + thread->priority = __OSGetEffectivePriority(thread); + SetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + RemoveItem(thread->queue, thread, link); + thread->priority = __OSGetEffectivePriority(thread); + AddPrio(thread->queue, thread, link); + if (thread->mutex) { + UpdatePriority(thread->mutex->thread); + } + break; + } + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return suspendCount; +} +#else +/* clang-format off */ +#pragma push +#pragma optimization_level 0 +#pragma optimizewithasm off +asm s32 OSResumeThread(OSThread* thread) { + nofralloc + mflr r0 + stw r0, 4(r1) + stwu r1, -0x28(r1) + stw r31, 0x24(r1) + stw r30, 0x20(r1) + stw r29, 0x1c(r1) + mr r29, r3 + bl OSDisableInterrupts + lwz r4, 0x2cc(r29) + addi r31, r3, 0 + addi r0, r4, -1 + stw r0, 0x2cc(r29) + mr r30, r4 + lwz r0, 0x2cc(r29) + cmpwi r0, 0 + bge lbl_80384D60 + li r0, 0 + stw r0, 0x2cc(r29) + b lbl_80384F74 +lbl_80384D60: + bne lbl_80384F74 + lhz r0, 0x2c8(r29) + cmpwi r0, 4 + beq lbl_80384E24 + bge lbl_80384F60 + cmpwi r0, 1 + beq lbl_80384D80 + b lbl_80384F60 +lbl_80384D80: + lwz r0, 0x2d4(r29) + lwz r3, 0x2f4(r29) + b lbl_80384DAC +lbl_80384D8C: + lwz r4, 0(r3) + cmplwi r4, 0 + beq lbl_80384DA8 + lwz r4, 0x2d0(r4) + cmpw r4, r0 + bge lbl_80384DA8 + mr r0, r4 +lbl_80384DA8: + lwz r3, 0x10(r3) +lbl_80384DAC: + cmplwi r3, 0 + bne lbl_80384D8C + stw r0, 0x2d0(r29) + lis r3, RunQueue@ha + addi r0, r3, RunQueue@l + lwz r3, 0x2d0(r29) + slwi r3, r3, 3 + add r0, r0, r3 + stw r0, 0x2dc(r29) + lwz r4, 0x2dc(r29) + lwz r3, 4(r4) + cmplwi r3, 0 + bne lbl_80384DE8 + stw r29, 0(r4) + b lbl_80384DEC +lbl_80384DE8: + stw r29, 0x2e0(r3) +lbl_80384DEC: + stw r3, 0x2e4(r29) + li r0, 0 + li r3, 1 + stw r0, 0x2e0(r29) + lwz r4, 0x2dc(r29) + stw r29, 4(r4) + lwz r0, 0x2d0(r29) + lwz r4, RunQueueBits + subfic r0, r0, 0x1f + slw r0, r3, r0 + or r0, r4, r0 + stw r0, RunQueueBits + stw r3, RunQueueHint + b lbl_80384F60 +lbl_80384E24: + lwz r4, 0x2e0(r29) + lwz r5, 0x2e4(r29) + cmplwi r4, 0 + bne lbl_80384E40 + lwz r3, 0x2dc(r29) + stw r5, 4(r3) + b lbl_80384E44 +lbl_80384E40: + stw r5, 0x2e4(r4) +lbl_80384E44: + cmplwi r5, 0 + bne lbl_80384E58 + lwz r3, 0x2dc(r29) + stw r4, 0(r3) + b lbl_80384E5C +lbl_80384E58: + stw r4, 0x2e0(r5) +lbl_80384E5C: + lwz r0, 0x2d4(r29) + lwz r3, 0x2f4(r29) + b lbl_80384E88 +lbl_80384E68: + lwz r4, 0(r3) + cmplwi r4, 0 + beq lbl_80384E84 + lwz r4, 0x2d0(r4) + cmpw r4, r0 + bge lbl_80384E84 + mr r0, r4 +lbl_80384E84: + lwz r3, 0x10(r3) +lbl_80384E88: + cmplwi r3, 0 + bne lbl_80384E68 + stw r0, 0x2d0(r29) + lwz r4, 0x2dc(r29) + lwz r5, 0(r4) + b lbl_80384EA4 +lbl_80384EA0: + lwz r5, 0x2e0(r5) +lbl_80384EA4: + cmplwi r5, 0 + beq lbl_80384EBC + lwz r3, 0x2d0(r5) + lwz r0, 0x2d0(r29) + cmpw r3, r0 + ble lbl_80384EA0 +lbl_80384EBC: + cmplwi r5, 0 + bne lbl_80384EF4 + lwz r3, 4(r4) + cmplwi r3, 0 + bne lbl_80384ED8 + stw r29, 0(r4) + b lbl_80384EDC +lbl_80384ED8: + stw r29, 0x2e0(r3) +lbl_80384EDC: + stw r3, 0x2e4(r29) + li r0, 0 + stw r0, 0x2e0(r29) + lwz r3, 0x2dc(r29) + stw r29, 4(r3) + b lbl_80384F1C +lbl_80384EF4: + stw r5, 0x2e0(r29) + lwz r3, 0x2e4(r5) + stw r29, 0x2e4(r5) + cmplwi r3, 0 + stw r3, 0x2e4(r29) + bne lbl_80384F18 + lwz r3, 0x2dc(r29) + stw r29, 0(r3) + b lbl_80384F1C +lbl_80384F18: + stw r29, 0x2e0(r3) +lbl_80384F1C: + lwz r3, 0x2f0(r29) + cmplwi r3, 0 + beq lbl_80384F60 + lwz r29, 8(r3) +lbl_80384F2C: + lwz r0, 0x2cc(r29) + cmpwi r0, 0 + bgt lbl_80384F60 + mr r3, r29 + bl __OSGetEffectivePriority + lwz r0, 0x2d0(r29) + addi r4, r3, 0 + cmpw r0, r4 + beq lbl_80384F60 + mr r3, r29 + bl SetEffectivePriority + or. r29, r3, r3 + bne lbl_80384F2C +lbl_80384F60: + lwz r0, RunQueueHint + cmpwi r0, 0 + beq lbl_80384F74 + li r3, 0 + bl SelectThread +lbl_80384F74: + mr r3, r31 + bl OSRestoreInterrupts + mr r3, r30 + lwz r0, 0x2c(r1) + lwz r31, 0x24(r1) + lwz r30, 0x20(r1) + lwz r29, 0x1c(r1) + addi r1, r1, 0x28 + mtlr r0 + blr +} +#pragma pop +/* clang-format on */ + +#endif + +#if NONMATCHING +/* Code matches, stack epilogue bug*/ +s32 OSSuspendThread(OSThread* thread) { + BOOL enabled; + s32 suspendCount; + + enabled = OSDisableInterrupts(); + suspendCount = thread->suspend++; + if (suspendCount == 0) { + switch (thread->state) { + case OS_THREAD_STATE_RUNNING: + RunQueueHint = TRUE; + thread->state = OS_THREAD_STATE_READY; + break; + case OS_THREAD_STATE_READY: + UnsetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + RemoveItem(thread->queue, thread, link); + thread->priority = 32; + AddTail(thread->queue, thread, link); + if (thread->mutex) { + UpdatePriority(thread->mutex->thread); + } + break; + } + + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return suspendCount; +} +#else +/* clang-format off */ +#pragma push +#pragma optimization_level 0 +#pragma optimizewithasm off +asm s32 OSSuspendThread(OSThread* thread) { + nofralloc + mflr r0 + stw r0, 4(r1) + stwu r1, -0x20(r1) + stw r31, 0x1c(r1) + stw r30, 0x18(r1) + stw r29, 0x14(r1) + mr r29, r3 + bl OSDisableInterrupts + lwz r4, 0x2cc(r29) + addi r31, r3, 0 + addi r0, r4, 1 + or. r30, r4, r4 + stw r0, 0x2cc(r29) + bne lbl_803850E4 + lhz r0, 0x2c8(r29) + cmpwi r0, 3 + beq lbl_803850D0 + bge lbl_80384FF4 + cmpwi r0, 1 + beq lbl_80385010 + bge lbl_80385000 + b lbl_803850D0 +lbl_80384FF4: + cmpwi r0, 5 + bge lbl_803850D0 + b lbl_8038501C +lbl_80385000: + li r0, 1 + stw r0, RunQueueHint + sth r0, 0x2c8(r29) + b lbl_803850D0 +lbl_80385010: + mr r3, r29 + bl UnsetRun + b lbl_803850D0 +lbl_8038501C: + lwz r4, 0x2e0(r29) + lwz r5, 0x2e4(r29) + cmplwi r4, 0 + bne lbl_80385038 + lwz r3, 0x2dc(r29) + stw r5, 4(r3) + b lbl_8038503C +lbl_80385038: + stw r5, 0x2e4(r4) +lbl_8038503C: + cmplwi r5, 0 + bne lbl_80385050 + lwz r3, 0x2dc(r29) + stw r4, 0(r3) + b lbl_80385054 +lbl_80385050: + stw r4, 0x2e0(r5) +lbl_80385054: + li r0, 0x20 + stw r0, 0x2d0(r29) + lwz r4, 0x2dc(r29) + lwz r3, 4(r4) + cmplwi r3, 0 + bne lbl_80385074 + stw r29, 0(r4) + b lbl_80385078 +lbl_80385074: + stw r29, 0x2e0(r3) +lbl_80385078: + stw r3, 0x2e4(r29) + li r0, 0 + stw r0, 0x2e0(r29) + lwz r3, 0x2dc(r29) + stw r29, 4(r3) + lwz r3, 0x2f0(r29) + cmplwi r3, 0 + beq lbl_803850D0 + lwz r29, 8(r3) +lbl_8038509C: + lwz r0, 0x2cc(r29) + cmpwi r0, 0 + bgt lbl_803850D0 + mr r3, r29 + bl __OSGetEffectivePriority + lwz r0, 0x2d0(r29) + addi r4, r3, 0 + cmpw r0, r4 + beq lbl_803850D0 + mr r3, r29 + bl SetEffectivePriority + or. r29, r3, r3 + bne lbl_8038509C +lbl_803850D0: + lwz r0, RunQueueHint + cmpwi r0, 0 + beq lbl_803850E4 + li r3, 0 + bl SelectThread +lbl_803850E4: + mr r3, r31 + bl OSRestoreInterrupts + mr r3, r30 + lwz r0, 0x24(r1) + lwz r31, 0x1c(r1) + lwz r30, 0x18(r1) + lwz r29, 0x14(r1) + addi r1, r1, 0x20 + mtlr r0 + blr +} +#pragma pop +/* clang-format on */ +#endif + +void OSSleepThread(OSThreadQueue* queue) { + BOOL enabled; + OSThread* currentThread; + + enabled = OSDisableInterrupts(); + currentThread = OSGetCurrentThread(); + + currentThread->state = OS_THREAD_STATE_WAITING; + currentThread->queue = queue; + AddPrio(queue, currentThread, link); + RunQueueHint = TRUE; + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +void OSWakeupThread(OSThreadQueue* queue) { + BOOL enabled; + OSThread* thread; + + enabled = OSDisableInterrupts(); + while (queue->head) { + RemoveHead(queue, thread, link); + thread->state = OS_THREAD_STATE_READY; + if (!(0 < thread->suspend)) { + SetRun(thread); + } + } + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +void OSClearStack(u8 val) { + register u32 sp; + register u32* p; + register u32 pattern; + + pattern = ((u32)val << 24) | ((u32)val << 16) | ((u32)val << 8) | (u32)val; + sp = OSGetStackPointer(); + for (p = __OSCurrentThread->stackEnd + 1; p < (u32*)sp; ++p) { + *p = pattern; + } +}