From 8e98e3d9436b1a5b1fdc5cf6e14771cbe9eb6f3a Mon Sep 17 00:00:00 2001 From: KamelitoLoveless Date: Tue, 6 Oct 2026 20:34:56 +0200 Subject: [PATCH 1/5] exec: keep the scheduler flags where Kickstart has them, honour its hooks Programs that SetFunction() ExitIntr() and Schedule(), or replace ex_LaunchPoint, were never called on m68k (issue #1460). - SFF_SoftInt, SFF_QuantumOver and the pending-switch flag (now SFF_AttnSwitch, replacing ARF_AttnSwitch in AttnResched) are SysFlags bits 13, 14 and 15 on every target, as on Kickstart. Cause() updates SysFlags atomically unless AROS_NO_ATOMIC_OPERATIONS is set. - m68k interrupt handlers leave through the ExitIntr() vector with SysBase pushed, as Kickstart's level handlers do, and ExitIntr() pops it. - m68k Schedule() decides with interrupts masked, as on Kickstart, so the scheduler's non-atomic flag updates cannot lose a bit. - m68k Dispatch() enters the task through ex_LaunchPoint, publishing its own launch code there on first use. --- arch/m68k-all/exec/dispatch.S | 74 +++++++++++++++++--- arch/m68k-all/exec/exec_platform.h | 10 +-- arch/m68k-all/exec/exitintr.S | 9 ++- arch/m68k-all/exec/schedule.S | 9 ++- arch/m68k-all/exec/signal_fast.S | 109 +++++++++++++++++++++++++++++ arch/m68k-all/kernel/kernel_intr.c | 4 +- arch/m68k-amiga/kernel/amiga_irq.c | 9 ++- compiler/include/asm.c | 1 + compiler/include/exec/execbase.inc | 12 ++-- rom/exec/cause.c | 32 +++++++-- rom/exec/exec.conf | 2 +- rom/exec/exec_platform.h | 10 +-- 12 files changed, 244 insertions(+), 37 deletions(-) create mode 100644 arch/m68k-all/exec/signal_fast.S diff --git a/arch/m68k-all/exec/dispatch.S b/arch/m68k-all/exec/dispatch.S index c33929839cf..57393b32a82 100644 --- a/arch/m68k-all/exec/dispatch.S +++ b/arch/m68k-all/exec/dispatch.S @@ -20,12 +20,70 @@ AROS_SLIB_ENTRY(Dispatch,Exec,10): lea.l %sp@(-4*(8+8)),%sp /* %sp = regs_t */ move.l %sp,%sp@- /* Push regs_t * onto stack */ __Dispatch_this: - jsr cpu_Dispatch /* Call cpu_Dispatch */ - addq.l #4,%sp - movem.l %sp@+,%d0-%d7/%a0-%a5 /* Load task state */ - move.l %sp@(4),%a6 - move.l %a6,%usp /* Restore user stack pointer */ - move.l %sp@,%a6 /* Restore A6 */ - addq.l #8,%sp - rte /* SR, PC, etc are on the stack */ + /* A6 may still contain the caller's library base here. */ + move.l 4,%a6 + ori.w #0x0700,%sr + + /* Fast path for the ordinary head-of-ready-list dispatch. */ + lea.l TaskReady(%a6),%a0 + move.l %a0@,%a3 + move.l %a3@,%d0 + beq.s 1f + cmp.b #TS_READY,tc_State(%a3) + bne.s 1f + move.b tc_Flags(%a3),%d1 + and.b #TF_DISPATCH_SPECIAL,%d1 + bne.s 1f + move.w AttnFlags(%a6),%d1 + and.w #AFF_FPU,%d1 + bne.s 1f + + move.l %d0,%a0@ + move.l %d0,%a1 + move.l %a0,ln_Pred(%a1) + addq.l #1,DispCount(%a6) + move.l %a3,ThisTask(%a6) + move.w Quantum(%a6),Elapsed(%a6) + /* SFF_QuantumOver is bit 14 of SysFlags: bit 6 of its first byte */ + bclr.b #6,SysFlags(%a6) + move.b #TS_RUN,tc_State(%a3) + move.b tc_IDNestCnt(%a3),IDNestCnt(%a6) + move.l tc_SPReg(%a3),%a5 + bra.s 2f + +1: + jsr m68k_DispatchFrame + move.l %d0,%a5 + move.l ThisTask(%a6),%a3 + +2: + tst.b IDNestCnt(%a6) + bmi.s 3f + move.w #0x4000,0xdff09a + bra.s 4f +3: + move.w #0xc000,0xdff09a +4: + /* + * Enter the task through ex_LaunchPoint, as Kickstart's Dispatch() + * does: A3 is the task, A5 its saved frame and A6 SysBase. Programs + * hook the field to see each task being launched and chain to the + * address they found there, so the first dispatch publishes the + * default launch code below. + */ + move.l LaunchPoint(%a6),%d0 + bne.s 5f + lea.l %pc@(6f),%a4 + move.l %a4,LaunchPoint(%a6) + bra.s 6f +5: + move.l %d0,%a4 + jmp (%a4) +6: + lea.l %a5@(66),%a2 + move.l %a2,%usp + move.l %a5@+,%sp@- + move.w %a5@+,%sp@- + movem.l %a5@,%d0-%d7/%a0-%a6 + rte .endfunc diff --git a/arch/m68k-all/exec/exec_platform.h b/arch/m68k-all/exec/exec_platform.h index 10fdda4422b..ceb555815c7 100644 --- a/arch/m68k-all/exec/exec_platform.h +++ b/arch/m68k-all/exec/exec_platform.h @@ -22,8 +22,8 @@ struct Exec_PlatformData #define TDNESTCOUNT_DEC SysBase->TDNestCnt-- #define FLAG_SCHEDQUANTUM_CLEAR SysBase->SysFlags &= ~SFF_QuantumOver #define FLAG_SCHEDQUANTUM_SET SysBase->SysFlags |= SFF_QuantumOver -#define FLAG_SCHEDSWITCH_CLEAR SysBase->AttnResched &= ~ARF_AttnSwitch -#define FLAG_SCHEDSWITCH_SET SysBase->AttnResched |= ARF_AttnSwitch +#define FLAG_SCHEDSWITCH_CLEAR SysBase->SysFlags &= ~SFF_AttnSwitch +#define FLAG_SCHEDSWITCH_SET SysBase->SysFlags |= SFF_AttnSwitch #define FLAG_SCHEDDISPATCH_CLEAR SysBase->AttnResched &= ~ARF_AttnDispatch #define FLAG_SCHEDDISPATCH_SET SysBase->AttnResched |= ARF_AttnDispatch #else @@ -33,8 +33,8 @@ struct Exec_PlatformData #define TDNESTCOUNT_DEC AROS_ATOMIC_DEC(SysBase->TDNestCnt) #define FLAG_SCHEDQUANTUM_CLEAR AROS_ATOMIC_AND(SysBase->SysFlags, ~SFF_QuantumOver) #define FLAG_SCHEDQUANTUM_SET AROS_ATOMIC_OR(SysBase->SysFlags, SFF_QuantumOver) -#define FLAG_SCHEDSWITCH_CLEAR AROS_ATOMIC_AND(SysBase->AttnResched, ~ARF_AttnSwitch) -#define FLAG_SCHEDSWITCH_SET AROS_ATOMIC_OR(SysBase->AttnResched, ARF_AttnSwitch) +#define FLAG_SCHEDSWITCH_CLEAR AROS_ATOMIC_AND(SysBase->SysFlags, ~SFF_AttnSwitch) +#define FLAG_SCHEDSWITCH_SET AROS_ATOMIC_OR(SysBase->SysFlags, SFF_AttnSwitch) #define FLAG_SCHEDDISPATCH_CLEAR AROS_ATOMIC_AND(SysBase->AttnResched, ~ARF_AttnDispatch) #define FLAG_SCHEDDISPATCH_SET AROS_ATOMIC_OR(SysBase->AttnResched, ARF_AttnDispatch) #endif @@ -47,7 +47,7 @@ struct Exec_PlatformData #define TDNESTCOUNT_GET (SysBase->TDNestCnt) #define TDNESTCOUNT_SET(val) (SysBase->TDNestCnt=(val)) #define FLAG_SCHEDQUANTUM_ISSET (SysBase->SysFlags & SFF_QuantumOver) -#define FLAG_SCHEDSWITCH_ISSET (SysBase->AttnResched & ARF_AttnSwitch) +#define FLAG_SCHEDSWITCH_ISSET (SysBase->SysFlags & SFF_AttnSwitch) #define FLAG_SCHEDDISPATCH_ISSET (SysBase->AttnResched & ARF_AttnDispatch) #define GET_THIS_TASK (SysBase->ThisTask) diff --git a/arch/m68k-all/exec/exitintr.S b/arch/m68k-all/exec/exitintr.S index eaa2ba8f689..40d776a8472 100644 --- a/arch/m68k-all/exec/exitintr.S +++ b/arch/m68k-all/exec/exitintr.S @@ -1,5 +1,5 @@ /* - Copyright © 2012, The AROS Development Team. All rights reserved. + Copyright © 2012-2026, The AROS Development Team. All rights reserved. $Id$ Desc: ExitIntr() @@ -16,9 +16,12 @@ .func AROS_SLIB_ENTRY(ExitIntr,Exec,6) AROS_SLIB_ENTRY(ExitIntr,Exec,6): - /* At this point, %d0-%d1/%a0-%a1/%a5-%a6 are on - * the stack, followed by SR, PC, and an exception frame + /* Kickstart's entry contract: the interrupt handler jumped here + * through the library vector with SysBase pushed on the stack. + * Below it are %d0-%d1/%a0-%a1/%a5-%a6, followed by SR, PC, and + * an exception frame. */ + move.l %sp@+,%a6 /* If we are returning to supervisor mode, just do it. * %sp@(4*6) is the SR from the RTE. diff --git a/arch/m68k-all/exec/schedule.S b/arch/m68k-all/exec/schedule.S index d190180df51..dea023fffae 100644 --- a/arch/m68k-all/exec/schedule.S +++ b/arch/m68k-all/exec/schedule.S @@ -1,5 +1,5 @@ /* - Copyright © 2012, The AROS Development Team. All rights reserved. + Copyright © 2012-2026, The AROS Development Team. All rights reserved. $Id$ Desc: Schedule() @@ -19,6 +19,13 @@ AROS_SLIB_ENTRY(Schedule,Exec,7): movem.l %d0-%d1/%a0-%a1/%a5-%a6,%sp@- /* Save D0-D1/A0-A1 */ __Schedule_this: + /* + * Decide with interrupts masked, as Kickstart's Schedule() does: + * core_Schedule() clears SFF_AttnSwitch and looks at TaskReady, and + * an interrupt in between could set the flag or queue a task. Switch + * lowers the level again; otherwise the RTE restores it. + */ + or.w #0x0700,%sr jsr core_Schedule tst.w %d0 /* Something to do? */ movem.l %sp@+,%d0-%d1/%a0-%a1/%a5-%a6 /* Restore regs */ diff --git a/arch/m68k-all/exec/signal_fast.S b/arch/m68k-all/exec/signal_fast.S new file mode 100644 index 00000000000..5a9e85567e7 --- /dev/null +++ b/arch/m68k-all/exec/signal_fast.S @@ -0,0 +1,109 @@ +/* Fast common path for Signal() on a uniprocessor 68000. */ + +#include "aros/m68k/asm.h" + + .text + .balign 4 + .globl AROS_SLIB_ENTRY(Signal,Exec,54) + + .func AROS_SLIB_ENTRY(Signal,Exec,54) +AROS_SLIB_ENTRY(Signal,Exec,54): + /* + * A non-empty exception mask is common (input.device tasks have + * one). The generic path is needed only if a pending or newly + * delivered signal actually raises an exception. Classify the + * common waiting-task case before masking Paula; after taking the + * lock, validate the mutable fields before changing anything. + */ + move.l tc_SigRecvd(%a1),%a0 + move.l %a0,%d1 + or.l %d0,%d1 + and.l tc_SigExcept(%a1),%d1 + bne .slow_unlocked + cmp.b #TS_WAIT,tc_State(%a1) + bne .slow_unlocked + + move.l %d0,%d1 + and.l tc_SigWait(%a1),%d1 + + /* Protect signal fields and the scheduler lists. */ + move.w #0x4000,0xdff09a + addq.b #1,IDNestCnt(%a6) + cmp.l tc_SigRecvd(%a1),%a0 + bne .slow + cmp.b #TS_WAIT,tc_State(%a1) + bne .slow + + tst.l %d1 + beq.s .signal_only + + or.l %d0,tc_SigRecvd(%a1) + + /* Remove the task from TaskWait. */ + move.l %a2,%sp@- + move.l ln_Succ(%a1),%a0 + move.l ln_Pred(%a1),%a2 + move.l %a2,ln_Pred(%a0) + move.l %a0,ln_Succ(%a2) + move.b #TS_READY,tc_State(%a1) + + /* Enqueue by descending signed priority, preserving FIFO order. */ + move.l TaskReady(%a6),%a0 +.find: + tst.l ln_Succ(%a0) + beq.s .insert + move.b ln_Pri(%a1),%d1 + cmp.b ln_Pri(%a0),%d1 + bgt.s .insert + move.l ln_Succ(%a0),%a0 + bra.s .find + +.insert: + move.l ln_Pred(%a0),%a2 + move.l %a2,ln_Pred(%a1) + move.l %a0,ln_Succ(%a1) + move.l %a1,ln_Succ(%a2) + move.l %a1,ln_Pred(%a0) + move.l %sp@+,%a2 + + /* + * Match Reschedule() for a newly-ready higher-priority task without + * entering C or nesting another Disable(). Interrupt context keeps + * the actual switch deferred until ExitIntr(). + */ + move.l ThisTask(%a6),%a0 + cmp.b #TS_RUN,tc_State(%a0) + bne.s .done + move.b ln_Pri(%a1),%d1 + cmp.b ln_Pri(%a0),%d1 + ble.s .done + /* SFF_AttnSwitch is bit 15 of SysFlags: bit 7 of its first byte */ + bset.b #7,SysFlags(%a6) + bne.s .done + move.w #0x8004,0xdff09c + bra.s .done + +.signal_only: + or.l %d0,tc_SigRecvd(%a1) + +.done: + subq.b #1,IDNestCnt(%a6) + bpl.s .return + move.w #0xc000,0xdff09a +.return: + rts + +.slow: + /* Undo our Disable() nesting before entering the original C path. */ + subq.b #1,IDNestCnt(%a6) + bpl.s 1f + move.w #0xc000,0xdff09a +1: +.slow_unlocked: + move.l %a6,%sp@- + move.l %d0,%sp@- + move.l %a1,%sp@- + jsr Exec_SignalSlow + lea.l %sp@(12),%sp + rts + .endfunc diff --git a/arch/m68k-all/kernel/kernel_intr.c b/arch/m68k-all/kernel/kernel_intr.c index fb6deff4e8b..c1f3b3b06a9 100644 --- a/arch/m68k-all/kernel/kernel_intr.c +++ b/arch/m68k-all/kernel/kernel_intr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, The AROS Development Team + * Copyright (C) 2012-2026, The AROS Development Team * All right reserved. * Author: Jason S. McMullan * @@ -31,7 +31,7 @@ BOOL core_ExitIntr(VOID) * Do not disturb task if it's not necessary. * Reschedule only if switch pending flag is set. Exit otherwise. */ - if (SysBase->AttnResched & ARF_AttnSwitch) + if (FLAG_SCHEDSWITCH_ISSET) { /* Run task scheduling sequence */ return TRUE; diff --git a/arch/m68k-amiga/kernel/amiga_irq.c b/arch/m68k-amiga/kernel/amiga_irq.c index 801111acb93..d810f65d420 100644 --- a/arch/m68k-amiga/kernel/amiga_irq.c +++ b/arch/m68k-amiga/kernel/amiga_irq.c @@ -165,7 +165,14 @@ static inline UWORD custom_r(ULONG reg) " jsr " #handler "\n" \ " tst.w %d0\n" \ " beq 0f\n" \ - " jmp Exec_6_ExitIntr\n" \ + /* Leave through the ExitIntr() vector, the way Kickstart's \ + * level handlers do: SysBase is pushed above the saved \ + * registers and ExitIntr() pops it. A program that \ + * SetFunction()s ExitIntr() is then called on every \ + * interrupt exit, with the stack it expects. */ \ + " move.l (4).w,%a6\n" \ + " move.l %a6,%sp@-\n" \ + " jmp %a6@(-36)\n" \ "0:\n" \ " movem.l %sp@+,%d0/%d1/%a0/%a1/%a5/%a6\n" \ " rte\n" \ diff --git a/compiler/include/asm.c b/compiler/include/asm.c index 410e127dba6..191095436c3 100644 --- a/compiler/include/asm.c +++ b/compiler/include/asm.c @@ -61,6 +61,7 @@ int main(void) { DEFINE(SysFlags , offsetof (struct ExecBase, SysFlags)); DEFINE(IdleCount , offsetof (struct ExecBase, IdleCount)); DEFINE(DispCount , offsetof (struct ExecBase, DispCount)); + DEFINE(LaunchPoint , offsetof (struct ExecBase, ex_LaunchPoint)); #if !defined(__AROSEXEC_SMP__) DEFINE(Quantum , offsetof (struct ExecBase, Quantum)); DEFINE(Elapsed , offsetof (struct ExecBase, Elapsed)); diff --git a/compiler/include/exec/execbase.inc b/compiler/include/exec/execbase.inc index 88904fcf592..515153cc1e7 100644 --- a/compiler/include/exec/execbase.inc +++ b/compiler/include/exec/execbase.inc @@ -2,7 +2,7 @@ #define EXEC_EXECBASE_H /* - Copyright © 1995-2011, The AROS Development Team. All rights reserved. + Copyright � 1995-2026, The AROS Development Team. All rights reserved. $Id$ Desc: structure of exec.library @@ -146,12 +146,10 @@ struct ExecBase #define AFB_MMU AFB_PRIVATEB #define AFF_MMU AFF_PRIVATEB -/* SysFlags. Private and AROS-specific. */ -#define SFF_SoftInt (1L<<5) /* There is a software interrupt pending */ -#define SFF_QuantumOver (1L<<13) /* Task's time slice is over */ - -/* AttnResched. AmigaOS(tm)-compatible, but private. */ -#define ARF_AttnSwitch (1L<<7) /* Delayed task switch pending */ +/* SysFlags. Private; the bits are where Kickstart keeps them. */ +#define SFF_SoftInt (1L<<13) /* There is a software interrupt pending */ +#define SFF_QuantumOver (1L<<14) /* Task's time slice is over */ +#define SFF_AttnSwitch (1L<<15) /* Delayed task switch pending */ /* Cache */ #define CACRF_EnableI (1L<<0) diff --git a/rom/exec/cause.c b/rom/exec/cause.c index 42b44c9bce6..0c7230c0936 100644 --- a/rom/exec/cause.c +++ b/rom/exec/cause.c @@ -1,6 +1,5 @@ /* - Copyright © 1995-2018, The AROS Development Team. All rights reserved. - $Id$ + Copyright (C) 1995-2026, The AROS Development Team. All rights reserved. Desc: Cause() - Cause a software interrupt. Lang: english @@ -110,6 +109,25 @@ * looking at SFF_SoftInt flag. */ } + + /* Signal pending software interrupt condition */ +#ifndef AROS_NO_ATOMIC_OPERATIONS + __AROS_ATOMIC_OR_W(SysBase->SysFlags, SFF_SoftInt); +#else + SysBase->SysFlags |= SFF_SoftInt; +#endif + + /* + * Quick soft int request. For optimal performance m68k-amiga + * Enable() does not do any extra SFF_SoftInt checks + */ + CUSTOM_CAUSE(INTF_SOFTINT); + /* + * If we are in usermode the software interrupt will end up being triggered + * in Enable(). On Amiga hardware this happens because a hardware interrupt + * was queued. On other machines Enable() will simulate this behavior, + * looking at SFF_SoftInt flag. + */ Enable(); AROS_LIBFUNC_EXIT @@ -141,8 +159,14 @@ AROS_INTH0(SoftIntDispatch) /* Don't bother if there are no software ints queued. */ if( SysBase->SysFlags & SFF_SoftInt ) { - /* Clear Software interrupt pending flag. */ - SysBase->SysFlags &= ~(SFF_SoftInt); + /* Clear Software interrupt pending flag. The scheduler's attention + * flags share this word and can be set from higher interrupt levels, + * so the update should not be a load/modify/store sequence. */ +#ifndef AROS_NO_ATOMIC_OPERATIONS + __AROS_ATOMIC_AND_W(SysBase->SysFlags, ~SFF_SoftInt); +#else + SysBase->SysFlags &= ~(SFF_SoftInt); +#endif for(;;) { diff --git a/rom/exec/exec.conf b/rom/exec/exec.conf index 090d3708847..811db2593da 100644 --- a/rom/exec/exec.conf +++ b/rom/exec/exec.conf @@ -1,5 +1,5 @@ ##begin config -version 51.3 +version 51.10 libbase SysBase libbasetype struct IntExecBase libbasetypeextern struct ExecBase diff --git a/rom/exec/exec_platform.h b/rom/exec/exec_platform.h index e65095e69b8..c582cbe7a46 100644 --- a/rom/exec/exec_platform.h +++ b/rom/exec/exec_platform.h @@ -28,8 +28,8 @@ struct Exec_PlatformData #define TDNESTCOUNT_DEC SysBase->TDNestCnt-- #define FLAG_SCHEDQUANTUM_CLEAR SysBase->SysFlags &= ~SFF_QuantumOver #define FLAG_SCHEDQUANTUM_SET SysBase->SysFlags |= SFF_QuantumOver -#define FLAG_SCHEDSWITCH_CLEAR SysBase->AttnResched &= ~ARF_AttnSwitch -#define FLAG_SCHEDSWITCH_SET SysBase->AttnResched |= ARF_AttnSwitch +#define FLAG_SCHEDSWITCH_CLEAR SysBase->SysFlags &= ~SFF_AttnSwitch +#define FLAG_SCHEDSWITCH_SET SysBase->SysFlags |= SFF_AttnSwitch #define FLAG_SCHEDDISPATCH_CLEAR SysBase->AttnResched &= ~ARF_AttnDispatch #define FLAG_SCHEDDISPATCH_SET SysBase->AttnResched |= ARF_AttnDispatch #else @@ -39,8 +39,8 @@ struct Exec_PlatformData #define TDNESTCOUNT_DEC AROS_ATOMIC_DEC(SysBase->TDNestCnt) #define FLAG_SCHEDQUANTUM_CLEAR AROS_ATOMIC_AND(SysBase->SysFlags, ~SFF_QuantumOver) #define FLAG_SCHEDQUANTUM_SET AROS_ATOMIC_OR(SysBase->SysFlags, SFF_QuantumOver) -#define FLAG_SCHEDSWITCH_CLEAR AROS_ATOMIC_AND(SysBase->AttnResched, ~ARF_AttnSwitch) -#define FLAG_SCHEDSWITCH_SET AROS_ATOMIC_OR(SysBase->AttnResched, ARF_AttnSwitch) +#define FLAG_SCHEDSWITCH_CLEAR AROS_ATOMIC_AND(SysBase->SysFlags, ~SFF_AttnSwitch) +#define FLAG_SCHEDSWITCH_SET AROS_ATOMIC_OR(SysBase->SysFlags, SFF_AttnSwitch) #define FLAG_SCHEDDISPATCH_CLEAR AROS_ATOMIC_AND(SysBase->AttnResched, ~ARF_AttnDispatch) #define FLAG_SCHEDDISPATCH_SET AROS_ATOMIC_OR(SysBase->AttnResched, ARF_AttnDispatch) #endif @@ -53,7 +53,7 @@ struct Exec_PlatformData #define TDNESTCOUNT_GET (SysBase->TDNestCnt) #define TDNESTCOUNT_SET(val) (SysBase->TDNestCnt=(val)) #define FLAG_SCHEDQUANTUM_ISSET (SysBase->SysFlags & SFF_QuantumOver) -#define FLAG_SCHEDSWITCH_ISSET (SysBase->AttnResched & ARF_AttnSwitch) +#define FLAG_SCHEDSWITCH_ISSET (SysBase->SysFlags & SFF_AttnSwitch) #define FLAG_SCHEDDISPATCH_ISSET (SysBase->AttnResched & ARF_AttnDispatch) #define GET_THIS_TASK (SysBase->ThisTask) From 4606c2780d27cfb394a1f54f59ec733474114ef9 Mon Sep 17 00:00:00 2001 From: KamelitoLoveless Date: Tue, 6 Oct 2026 21:00:36 +0200 Subject: [PATCH 2/5] change to avoid rewritting kernel_cpu.c to fit Aros naming... --- arch/m68k-all/exec/dispatch.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/m68k-all/exec/dispatch.S b/arch/m68k-all/exec/dispatch.S index 57393b32a82..41ff38574a8 100644 --- a/arch/m68k-all/exec/dispatch.S +++ b/arch/m68k-all/exec/dispatch.S @@ -52,7 +52,8 @@ __Dispatch_this: bra.s 2f 1: - jsr m68k_DispatchFrame +// jsr m68k_DispatchFrame + jsr cpu_Dispatch move.l %d0,%a5 move.l ThisTask(%a6),%a3 From 5eae5bdc68a126c30d885ec689a6f5b838193390 Mon Sep 17 00:00:00 2001 From: KamelitoLoveless Date: Tue, 6 Oct 2026 22:14:30 +0200 Subject: [PATCH 3/5] sync aros --- arch/m68k-all/exec/switch.S | 97 +++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/arch/m68k-all/exec/switch.S b/arch/m68k-all/exec/switch.S index adbc59111bb..028a5d260a6 100644 --- a/arch/m68k-all/exec/switch.S +++ b/arch/m68k-all/exec/switch.S @@ -1,25 +1,92 @@ -/* - Copyright © 2012, The AROS Development Team. All rights reserved. - $Id$ - - Desc: Switch() - Lang: english - - These routines are the core of the m68k scheduling system -*/ +/* Save an m68k task context directly on its own user stack. */ #include "aros/m68k/asm.h" .text .balign 4 .globl AROS_SLIB_ENTRY(Switch,Exec,9) + .globl m68k_VoluntarySwitch .func AROS_SLIB_ENTRY(Switch,Exec,9) AROS_SLIB_ENTRY(Switch,Exec,9): - movem.l %d0-%d7/%a0-%a7,%sp@- - move.l %usp,%a0 - move.l %a0,%sp@(4*15) /* Fix up %a7 */ - move.l %sp,%sp@- /* Push regs_t * onto stack */ - jsr cpu_Switch /* Call cpu_Switch */ - jmp __Dispatch_this /* Skip ahead */ + move.w #0x2000,%sr + + /* + * Keep the caller's A5 temporarily on the supervisor stack. Build + * the persistent frame on the user stack in the Kickstart layout: + * PC(4), SR(2), D0-D7/A0-A6(60). The original USP is frame + 66. + */ + move.l %a5,%sp@- + move.l %usp,%a5 + movem.l %d0-%d7/%a0-%a6,%a5@- + move.l %sp@+,%a5@(13*4) + move.w %sp@+,%a5@- + move.l %sp@+,%a5@- + + move.l %a5,%sp@- + jsr m68k_SwitchTail + addq.l #4,%sp + jmp __Dispatch_this + .endfunc + + /* + * KrnSwitch() is used only by Exec/Wait(), after Wait has linked the + * current task into TaskWait. Keep this entry distinct from the + * general Switch vector: no scheduler-policy call is required for + * the outgoing task, and Paula interrupts can be reopened as soon as + * its persistent frame and nesting state have been published. + */ + .func m68k_VoluntarySwitch +m68k_VoluntarySwitch: + move.w #0x2000,%sr + move.l %a5,%sp@- + move.l %usp,%a5 + movem.l %d0-%d7/%a0-%a6,%a5@- + move.l %sp@+,%a5@(13*4) + move.w %sp@+,%a5@- + move.l %sp@+,%a5@- + + /* + * The expensive trap and context save above run with interrupts + * enabled. Only the signal recheck and scheduler-list commit below + * form the critical section. + */ + move.w #0x4000,0xdff09a + move.l ThisTask(%a6),%a0 + move.b %d3,%d1 + addq.b #1,%d1 + move.b %d1,IDNestCnt(%a6) + + move.l tc_SigRecvd(%a0),%d0 + and.l tc_SigWait(%a0),%d0 + bne.s 1f + + move.b #-1,TDNestCnt(%a6) + move.b #4,tc_State(%a0) /* TS_WAIT */ + + /* AddTail(&SysBase->TaskWait, &task->tc_Node). */ + lea.l TaskWait(%a6),%a1 + move.l lh_TailPred(%a1),%a2 + lea.l ln_Pred(%a1),%a3 + move.l %a3,ln_Succ(%a0) + move.l %a2,ln_Pred(%a0) + move.l %a0,ln_Succ(%a2) + move.l %a0,lh_TailPred(%a1) + + move.l %a5,tc_SPReg(%a0) + move.b %d1,tc_IDNestCnt(%a0) + move.b #-1,IDNestCnt(%a6) + move.w #0xc000,0xdff09a + jmp __Dispatch_this + +1: + /* + * A signal arrived while the prospective frame was being built. + * Recreate Supervisor()'s exception frame, restore the registers + * from that frame, and return to Wait() without switching tasks. + */ + move.l %a5@,%sp@- + move.w %a5@(4),%sp@- + movem.l %a5@(6),%d0-%d7/%a0-%a6 + rte .endfunc From 1c905fc80c30d1830ec35459b40da92ab0472564 Mon Sep 17 00:00:00 2001 From: KamelitoLoveless Date: Tue, 6 Oct 2026 23:34:55 +0200 Subject: [PATCH 4/5] fixes --- arch/m68k-all/exec/dispatch.S | 15 +-- arch/m68k-all/exec/preparecontext.c | 109 ++++++++----------- arch/m68k-all/kernel/kernel_cpu.c | 157 +++++++++------------------- compiler/include/asm.c | 21 +++- 4 files changed, 116 insertions(+), 186 deletions(-) diff --git a/arch/m68k-all/exec/dispatch.S b/arch/m68k-all/exec/dispatch.S index 41ff38574a8..b9bf6b3a74d 100644 --- a/arch/m68k-all/exec/dispatch.S +++ b/arch/m68k-all/exec/dispatch.S @@ -1,12 +1,4 @@ -/* - Copyright © 2012, The AROS Development Team. All rights reserved. - $Id$ - - Desc: Dispatch() - Lang: english - - These routines are the core of the m68k scheduling system -*/ +/* Restore an m68k task context directly from its saved user-stack frame. */ #include "aros/m68k/asm.h" @@ -17,8 +9,6 @@ .func AROS_SLIB_ENTRY(Dispatch,Exec,10) AROS_SLIB_ENTRY(Dispatch,Exec,10): - lea.l %sp@(-4*(8+8)),%sp /* %sp = regs_t */ - move.l %sp,%sp@- /* Push regs_t * onto stack */ __Dispatch_this: /* A6 may still contain the caller's library base here. */ move.l 4,%a6 @@ -52,8 +42,7 @@ __Dispatch_this: bra.s 2f 1: -// jsr m68k_DispatchFrame - jsr cpu_Dispatch + jsr m68k_DispatchFrame move.l %d0,%a5 move.l ThisTask(%a6),%a3 diff --git a/arch/m68k-all/exec/preparecontext.c b/arch/m68k-all/exec/preparecontext.c index 4df5abe1a0b..1a6184eaced 100644 --- a/arch/m68k-all/exec/preparecontext.c +++ b/arch/m68k-all/exec/preparecontext.c @@ -1,21 +1,17 @@ -/* - Copyright © 1995-2011, The AROS Development Team. All rights reserved. - $Id$ - - Desc: PrepareContext() - Prepare a task context for dispatch, m68k version - Lang: english -*/ +/* Prepare the initial task frame in the format used by Switch/Dispatch. */ #include #include #include #include #include +#include #include "exec_intern.h" #include "exec_util.h" -#define _PUSH(sp, val) *--sp = (IPTR)val +#define _PUSH(sp, val) *--sp = (IPTR)(val) +#define M68K_TASK_FRAME_SIZE 66 BOOL PrepareContext(struct Task *task, APTR entryPoint, APTR fallBack, const struct TagItem *tagList, struct ExecBase *SysBase) @@ -24,74 +20,59 @@ BOOL PrepareContext(struct Task *task, APTR entryPoint, APTR fallBack, WORD numargs = 0; IPTR *sp = task->tc_SPReg; struct ExceptionContext *ctx; + UBYTE *frame; if (!(task->tc_Flags & TF_ETASK)) return FALSE; - + ctx = KrnCreateContext(); task->tc_UnionETask.tc_ETask->et_RegFrame = ctx; if (!ctx) return FALSE; - while(tagList) - { - switch(tagList->ti_Tag) - { - case TAG_MORE: - tagList = (const struct TagItem *)tagList->ti_Data; - continue; - - case TAG_SKIP: - tagList += tagList->ti_Data; - break; - - case TAG_DONE: - tagList = NULL; - break; - -#define HANDLEARG(x) \ - case TASKTAG_ARG ## x: \ - args[x - 1] = (IPTR)tagList->ti_Data; \ - if (x > numargs) numargs = x; \ - break; - - HANDLEARG(1) - HANDLEARG(2) - HANDLEARG(3) - HANDLEARG(4) - HANDLEARG(5) - HANDLEARG(6) - HANDLEARG(7) - HANDLEARG(8) + while (tagList) { + switch (tagList->ti_Tag) { + case TAG_MORE: + tagList = (const struct TagItem *)tagList->ti_Data; + continue; + case TAG_SKIP: + tagList += tagList->ti_Data; + break; + case TAG_DONE: + tagList = NULL; + break; +#define HANDLEARG(x) \ + case TASKTAG_ARG ## x: \ + args[x - 1] = (IPTR)tagList->ti_Data; \ + if (x > numargs) numargs = x; \ + break; + HANDLEARG(1) + HANDLEARG(2) + HANDLEARG(3) + HANDLEARG(4) + HANDLEARG(5) + HANDLEARG(6) + HANDLEARG(7) + HANDLEARG(8) } - - if (tagList) tagList++; + if (tagList) + tagList++; } - - /* - There is not much to do here, or at least that is how it - appears. Most of the work is done in the kernel_cpu.h macros. - */ - if (numargs) - { - /* On m68k C function gets all param on stack */ - while(numargs--) - { - _PUSH(sp, args[numargs]); - } - } - - /* First we push the return address */ + while (numargs--) + _PUSH(sp, args[numargs]); _PUSH(sp, fallBack); - - /* Then set up the frame to be used by Dispatch() */ - ctx->pc = (IPTR)entryPoint; - ctx->a[7] = (IPTR)sp; - ctx->sr = 0x0000; - /* We return the new stack pointer back to the caller. */ - task->tc_SPReg = sp; + frame = (UBYTE *)sp - M68K_TASK_FRAME_SIZE; + memset(frame, 0, M68K_TASK_FRAME_SIZE); + *(IPTR *)(frame + 0) = (IPTR)entryPoint; + *(UWORD *)(frame + 4) = 0; + + /* Retain a conventional context for FPU/AMMX storage and diagnostics. */ + ctx->pc = (IPTR)entryPoint; + ctx->a[7] = (IPTR)sp; + ctx->sr = 0; + task->tc_SPReg = frame; return TRUE; -} /* PrepareContext() */ +} diff --git a/arch/m68k-all/kernel/kernel_cpu.c b/arch/m68k-all/kernel/kernel_cpu.c index cb045746ff2..d91c1208738 100644 --- a/arch/m68k-all/kernel/kernel_cpu.c +++ b/arch/m68k-all/kernel/kernel_cpu.c @@ -1,11 +1,10 @@ /* - Copyright © 1995-2014, The AROS Development Team. All rights reserved. - $Id$ -*/ + Copyright (C) 1995-2026, The AROS Development Team. All rights reserved. -/* - * M68K Schedule functions - */ + The assembly scheduler entry saves and restores the integer context + directly on the task's user stack; this file retains the common scheduler + policy and optional CPU-context handling. +*/ #include #include @@ -13,17 +12,8 @@ #include #include -#include #include -#ifndef D -# ifdef DEBUG -# define D(x) x -# else -# define D(x) -# endif -#endif - extern void cpu_Exception(void); asm ( " .text\n" @@ -37,129 +27,84 @@ asm ( " rts\n" ); -void cpu_Switch(regs_t *regs) +void m68k_SwitchTail(APTR frame) { struct Task *task = SysBase->ThisTask; struct AROSCPUContext *ctx = task->tc_UnionETask.tc_ETask->et_RegFrame; - D(bug("[Kernel] %s: Switching ThisTask=0x%p '%s'\n", __func__, task, task->tc_Node.ln_Name);) - - /* Actually save the context */ - CopyMem(regs, &ctx->cpu, sizeof(regs_t)); - - /* If we have an FPU, save the FPU context */ if (SysBase->AttnFlags & AFF_FPU) - AROS_UFC2NR(void, FpuSaveContext, - AROS_UFCA(struct FpuContext *, &ctx->fpu, A0), - AROS_UFCA(UWORD, (SysBase->AttnFlags & AFF_68060) ? 2 : 0, D0)); - -#ifdef NONVAMPIRE - /* IF we have AMMX (68080) *and* if AMMX bit in SR is set, save AMMX context */ - if (SysBase->AttnFlags & AFF_68080) // && (ctx->cpu.sr & 0x800)) -#endif - AROS_UFC1NR(void, AMMXSaveContext,AROS_UFCA(struct AMMXContext *, &ctx->ammx, A0)); + AROS_UFC2NR(void, FpuSaveContext, + AROS_UFCA(struct FpuContext *, &ctx->fpu, A0), + AROS_UFCA(UWORD, (SysBase->AttnFlags & AFF_68060) ? 2 : 0, D0)); - /* Update tc_SPReg */ - task->tc_SPReg = (APTR)regs->a[7]; + if (SysBase->AttnFlags & AFF_68080) + AROS_UFC1NR(void, AMMXSaveContext, + AROS_UFCA(struct AMMXContext *, &ctx->ammx, A0)); + task->tc_SPReg = frame; core_Switch(); } -void cpu_Dispatch(regs_t *regs) +APTR m68k_DispatchFrame(void) { struct Task *task; struct AROSCPUContext *ctx; + UBYTE *frame; for (;;) { - asm volatile ("ori #0x0700, %sr\n"); // Disable CPU interrupts + asm volatile ("ori #0x0700, %sr\n"); task = core_Dispatch(); if (task != NULL) break; - D( - bug("[Kernel] %s: TASK QUEUE EMPTY!!\n", __func__); - - // Dump tasks ... - if (SysBase->ThisTask) - { - bug("[Kernel] %s: ThisTask=0x%p '%s'\n", __func__, SysBase->ThisTask, SysBase->ThisTask->tc_Node.ln_Name); - bug("[Kernel] %s: tc_Flags = %x\n", __func__, SysBase->ThisTask->tc_Flags); - bug("[Kernel] %s: tc_State = %x\n", __func__, SysBase->ThisTask->tc_State); - bug("[Kernel] %s: tc_SigAlloc = %x\n", __func__, SysBase->ThisTask->tc_SigAlloc); - bug("[Kernel] %s: tc_SigWait = %x\n", __func__, SysBase->ThisTask->tc_SigWait); - bug("[Kernel] %s: tc_SigRecv = %x\n", __func__, SysBase->ThisTask->tc_SigRecv); - bug("[Kernel] %s: tc_IDNestCnt = %d\n", __func__, SysBase->ThisTask->tc_IDNestCnt); - bug("[Kernel] %s: tc_TDNestCnt = %d\n", __func__, SysBase->ThisTask->tc_TDNestCnt); - } - - ForeachNode(&SysBase->TaskReady, task) - { - bug("[Kernel] %s: Ready Task @ 0x%p '%s'\n", __func__, task, task->tc_Node.ln_Name); - bug("[Kernel] %s: tc_Flags = %x\n", __func__, task->tc_Flags); - bug("[Kernel] %s: tc_State = %x\n", __func__, task->tc_State); - bug("[Kernel] %s: tc_SigAlloc = %x\n", __func__, task->tc_SigAlloc); - bug("[Kernel] %s: tc_SigWait = %x\n", __func__, task->tc_SigWait); - bug("[Kernel] %s: tc_SigRecv = %x\n", __func__, task->tc_SigRecv); - bug("[Kernel] %s: tc_IDNestCnt = %d\n", __func__, task->tc_IDNestCnt); - bug("[Kernel] %s: tc_TDNestCnt = %d\n", __func__, task->tc_TDNestCnt); - } - ForeachNode(&SysBase->TaskWait, task) - { - bug("[Kernel] %s: Waiting Task @ 0x%p '%s'\n", __func__, task, task->tc_Node.ln_Name); - bug("[Kernel] %s: tc_Flags = %x\n", __func__, task->tc_Flags); - bug("[Kernel] %s: tc_State = %x\n", __func__, task->tc_State); - bug("[Kernel] %s: tc_SigAlloc = %x\n", __func__, task->tc_SigAlloc); - bug("[Kernel] %s: tc_SigWait = %x\n", __func__, task->tc_SigWait); - bug("[Kernel] %s: tc_SigRecv = %x\n", __func__, task->tc_SigRecv); - bug("[Kernel] %s: tc_IDNestCnt = %d\n", __func__, task->tc_IDNestCnt); - bug("[Kernel] %s: tc_TDNestCnt = %d\n", __func__, task->tc_TDNestCnt); - } - ) - /* Break IDNestCnt */ + if (SysBase->IDNestCnt >= 0) { - SysBase->IDNestCnt=-1; + SysBase->IDNestCnt = -1; asm volatile ("move.w #0xc000,0xdff09a\n"); } - asm volatile ("stop #0x2000\n"); // Wait for an interrupt + asm volatile ("stop #0x2000\n"); } - D(bug("[Kernel] %s: Dispatching Task @ 0x%p '%s'\n", __func__, task, task->tc_Node.ln_Name);) - ctx = task->tc_UnionETask.tc_ETask->et_RegFrame; - CopyMem(&ctx->cpu, regs, sizeof(regs_t)); - regs->a[7] = (IPTR)task->tc_SPReg; - - /* If we have an FPU, restore the FPU context */ if (SysBase->AttnFlags & AFF_FPU) - AROS_UFC2NR(void, FpuRestoreContext, - AROS_UFCA(struct FpuContext *, &ctx->fpu, A0), - AROS_UFCA(UWORD, (SysBase->AttnFlags & AFF_68060) ? 2 : 0, D0)); -#ifdef NONVAMPIRE - /* IF we have AMMX (68080) *and* if AMMX bit in SR is set, save AMMX context */ - if (SysBase->AttnFlags & AFF_68080) // && (ctx->cpu.sr & 0x800)) -#endif - AROS_UFC1NR(void, AMMXRestoreContext, AROS_UFCA(struct AMMXContext *, &ctx->ammx, A0)); - - /* Re-enable interrupts if needed */ - if (SysBase->IDNestCnt < 0) { + AROS_UFC2NR(void, FpuRestoreContext, + AROS_UFCA(struct FpuContext *, &ctx->fpu, A0), + AROS_UFCA(UWORD, (SysBase->AttnFlags & AFF_68060) ? 2 : 0, D0)); + + if (SysBase->AttnFlags & AFF_68080) + AROS_UFC1NR(void, AMMXRestoreContext, + AROS_UFCA(struct AMMXContext *, &ctx->ammx, A0)); + + if (SysBase->IDNestCnt < 0) asm volatile ("move.w #0xc000,0xdff09a\n"); - } else { + else asm volatile ("move.w #0x4000,0xdff09a\n"); - } + frame = task->tc_SPReg; if (task->tc_Flags & TF_EXCEPT) { - /* Exec_Exception() will Enable() */ + ULONG originalPC = *(ULONG *)frame; + UBYTE *exceptionFrame = frame - sizeof(ULONG); + unsigned int i; + + /* Exec_Exception() balances this Disable() when it returns. */ Disable(); - /* Manipulate the current CPU context so Exec_Exception gets - * executed after we leave Supervisor mode. - */ - task->tc_SPReg -= sizeof(ULONG); /* RTS to original PC */ - if (task->tc_SPReg <= task->tc_SPLower) - Alert(AT_DeadEnd|AN_StackProbe); - *(ULONG *)(task->tc_SPReg) = regs->pc; + if (exceptionFrame <= (UBYTE *)task->tc_SPLower) + Alert(AT_DeadEnd | AN_StackProbe); - regs->a[7] = (IPTR)task->tc_SPReg; - regs->pc = (IPTR)cpu_Exception; + /* + * Make room below the 66-byte task-stack frame. The destination is + * lower than the source, so a forward byte copy is overlap-safe. + * Restoring this shifted frame sets USP to the word immediately after + * it; place the interrupted PC there for cpu_Exception's final RTS. + */ + for (i = 0; i < 66; i++) + exceptionFrame[i] = frame[i]; + *(ULONG *)(exceptionFrame + 66) = originalPC; + *(ULONG *)exceptionFrame = (ULONG)cpu_Exception; + task->tc_SPReg = exceptionFrame; + frame = exceptionFrame; } + + return frame; } diff --git a/compiler/include/asm.c b/compiler/include/asm.c index 191095436c3..af11b0d7141 100644 --- a/compiler/include/asm.c +++ b/compiler/include/asm.c @@ -1,6 +1,5 @@ /* - Copyright © 1995-2017, The AROS Development Team. All rights reserved. - $Id$ + Copyright (C) 1995-2026, The AROS Development Team. All rights reserved. */ #include @@ -53,6 +52,7 @@ int main(void) { DEFINE(SMPPrivate5 , offsetof (struct ExecBase, SMPPrivate5)); #endif DEFINE(TaskReady , offsetof (struct ExecBase, TaskReady)); + DEFINE(TaskWait , offsetof (struct ExecBase, TaskWait)); #if !defined(__AROSEXEC_SMP__) DEFINE(ThisTask , offsetof (struct ExecBase, ThisTask)); #else @@ -77,6 +77,7 @@ int main(void) { DEFINE(tc_ExceptCode , offsetof (struct Task, tc_ExceptCode)); DEFINE(tc_ExceptData , offsetof (struct Task, tc_ExceptData)); DEFINE(tc_SigExcept , offsetof (struct Task, tc_SigExcept)); + DEFINE(tc_SigWait , offsetof (struct Task, tc_SigWait)); DEFINE(tc_SigRecvd , offsetof (struct Task, tc_SigRecvd)); DEFINE(tc_Launch , offsetof (struct Task, tc_Launch)); DEFINE(tc_Switch , offsetof (struct Task, tc_Switch)); @@ -84,10 +85,20 @@ int main(void) { DEFINE(tc_SPLower , offsetof (struct Task, tc_SPLower)); DEFINE(tc_SPUpper , offsetof (struct Task, tc_SPUpper)); DEFINE(tc_IDNestCnt , offsetof (struct Task, tc_IDNestCnt)); + DEFINE(tc_TDNestCnt , offsetof (struct Task, tc_TDNestCnt)); DEFINE(tc_ETask , offsetof (struct Task, tc_UnionETask.tc_ETask)); asm volatile("\n.asciz \"/* struct ETask */\"" ::); - DEFINE(et_TaskStorage, offsetof (struct ETask, et_TaskStorage)); + DEFINE(et_Reserved, offsetof (struct ETask, et_Reserved)); + DEFINE(et_RegFrame, offsetof (struct ETask, et_RegFrame)); + +#ifdef __mc68000 + asm volatile("\n.asciz \"/* m68k ExceptionContext */\"" ::); + DEFINE(ec_D, offsetof (struct ExceptionContext, d)); + DEFINE(ec_A, offsetof (struct ExceptionContext, a)); + DEFINE(ec_SR, offsetof (struct ExceptionContext, sr)); + DEFINE(ec_PC, offsetof (struct ExceptionContext, pc)); +#endif asm volatile("\n.asciz \"/* struct Process */\"" ::); DEFINE(pr_CES , offsetof (struct Process, pr_CES)); @@ -99,6 +110,7 @@ int main(void) { DEFINE(pr_FileSystemTask, offsetof (struct Process, pr_FileSystemTask)); DEFINE(pr_MsgPort , offsetof (struct Process, pr_MsgPort)); DEFINE(pr_Result2 , offsetof (struct Process, pr_Result2)); + DEFINE(pr_GlobVec , offsetof (struct Process, pr_GlobVec)); DEFINE(pr_ReturnAddr , offsetof (struct Process, pr_ReturnAddr)); DEFINE(pr_SegList , offsetof (struct Process, pr_SegList)); DEFINE(pr_WindowPtr , offsetof (struct Process, pr_WindowPtr)); @@ -156,13 +168,16 @@ int main(void) { asm volatile("\n.asciz \"/* Task Flags */\"" ::); DEFINE(TS_RUN , TS_RUN); DEFINE(TS_READY , TS_READY); + DEFINE(TS_WAIT , TS_WAIT); DEFINE(TF_STACKCHK , TF_STACKCHK); DEFINE(TF_EXCEPT , TF_EXCEPT); DEFINE(TF_SWITCH , TF_SWITCH); DEFINE(TF_LAUNCH , TF_LAUNCH); + DEFINE(TF_DISPATCH_SPECIAL, TF_LAUNCH | TF_EXCEPT); asm volatile("\n.asciz \"/* Exec Flags */\"" ::); DEFINE(AFF_FPU , AFF_FPU); + DEFINE(SFF_QuantumClear, (UWORD)~SFF_QuantumOver); asm volatile("\n.asciz \"/* Exec functions */\"" ::); DEFINE(Supervisor , FuncOffset (5)); From a7c9493f7c28383be063bef8adadbead84d0f3e8 Mon Sep 17 00:00:00 2001 From: KamelitoLoveless Date: Wed, 7 Oct 2026 00:24:01 +0200 Subject: [PATCH 5/5] forgot to commit --- rom/exec/cause.c | 1 + rom/exec/signal.c | 1 + rom/exec/wait.c | 1 + 3 files changed, 3 insertions(+) diff --git a/rom/exec/cause.c b/rom/exec/cause.c index 0c7230c0936..e3f71342a1c 100644 --- a/rom/exec/cause.c +++ b/rom/exec/cause.c @@ -6,6 +6,7 @@ */ #include +#include #include #include diff --git a/rom/exec/signal.c b/rom/exec/signal.c index a295fcfddee..199e589a319 100644 --- a/rom/exec/signal.c +++ b/rom/exec/signal.c @@ -7,6 +7,7 @@ */ #define DEBUG 0 +#include #include #include diff --git a/rom/exec/wait.c b/rom/exec/wait.c index 70d317fbadd..ffe4132f208 100644 --- a/rom/exec/wait.c +++ b/rom/exec/wait.c @@ -7,6 +7,7 @@ */ #define DEBUG 0 +#include #include #include