Checkpoint

This commit is contained in:
Scott Duensing 2026-05-04 01:28:27 -05:00
parent dc2505c4af
commit 05fc37d323
9 changed files with 239 additions and 392 deletions

View file

@ -26,13 +26,20 @@ double difftime(time_t end, time_t start);
// Calendar conversions. gmtime and localtime are identical here — // Calendar conversions. gmtime and localtime are identical here —
// no timezone support; "local" is treated as UTC. // no timezone support; "local" is treated as UTC.
// //
// ⚠ gmtime/localtime are CURRENTLY KNOWN-BROKEN: the year-decomposition // ⚠ gmtime/localtime are KNOWN-BROKEN under the GS/OS Loader. The
// loop hits a W65816 backend codegen issue that mis-iterates and // interface returns a pointer to a static global; user code reads
// returns year=1970 regardless of input. Workaround: build the // `r->tm_field` via [dp],Y bank=0 but the global lives in the user's
// struct tm by hand and call mktime/asctime/strftime, all of which // bank (cRELOC patches its IMM16 reference for the user bank, not
// work correctly on a user-supplied struct tm. // bank 0). Use gmtime_r / localtime_r below — they take a caller-
// supplied buffer (a stack local works) which is reachable
// consistently in either environment.
//
// Under runInMame (DBR=0) plain gmtime/localtime work for sec/min/hour
// only; date fields stay at the 1970-01-01 sentinel.
struct tm *gmtime (const time_t *t); struct tm *gmtime (const time_t *t);
struct tm *localtime(const time_t *t); struct tm *localtime(const time_t *t);
struct tm *gmtime_r (const time_t *t, struct tm *out);
struct tm *localtime_r(const time_t *t, struct tm *out);
time_t mktime (struct tm *tm); time_t mktime (struct tm *tm);
// Text formatting. asctime returns "Sun Jan 1 00:00:00 1970\n" form. // Text formatting. asctime returns "Sun Jan 1 00:00:00 1970\n" form.

View file

@ -594,14 +594,9 @@ GetCtlValue:
; tool 0x1E10, set 0x10 (ControlManager) ; tool 0x1E10, set 0x10 (ControlManager)
.globl GrowSize .globl GrowSize
GrowSize: GrowSize:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1E10 ldx #0x1E10
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -1003,14 +998,9 @@ CMReleaseResource:
; tool 0x2610, set 0x10 (ControlManager) ; tool 0x2610, set 0x10 (ControlManager)
.globl FindTargetCtl .globl FindTargetCtl
FindTargetCtl: FindTargetCtl:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2610 ldx #0x2610
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -1087,14 +1077,9 @@ GetCtlMoreFlags:
; tool 0x3510, set 0x10 (ControlManager) ; tool 0x3510, set 0x10 (ControlManager)
.globl GetCtlParamPtr .globl GetCtlParamPtr
GetCtlParamPtr: GetCtlParamPtr:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x3510 ldx #0x3510
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -1121,14 +1106,9 @@ InvalCtls:
; tool 0x2710, set 0x10 (ControlManager) ; tool 0x2710, set 0x10 (ControlManager)
.globl MakeNextCtlTarget .globl MakeNextCtlTarget
MakeNextCtlTarget: MakeNextCtlTarget:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2710 ldx #0x2710
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -1514,14 +1494,9 @@ CloseNDAByWinPtr:
; tool 0x1405, set 0x05 (DeskManager) ; tool 0x1405, set 0x05 (DeskManager)
.globl GetDAStrPtr .globl GetDAStrPtr
GetDAStrPtr: GetDAStrPtr:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1405 ldx #0x1405
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -2876,14 +2851,9 @@ FlushEvents:
; tool 0x1206, set 0x06 (EventManager) ; tool 0x1206, set 0x06 (EventManager)
.globl GetCaretTime .globl GetCaretTime
GetCaretTime: GetCaretTime:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1206 ldx #0x1206
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -2894,14 +2864,9 @@ GetCaretTime:
; tool 0x1106, set 0x06 (EventManager) ; tool 0x1106, set 0x06 (EventManager)
.globl GetDblTime .globl GetDblTime
GetDblTime: GetDblTime:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1106 ldx #0x1106
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -3012,14 +2977,9 @@ PostEvent:
; tool 0x1006, set 0x06 (EventManager) ; tool 0x1006, set 0x06 (EventManager)
.globl TickCount .globl TickCount
TickCount: TickCount:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1006 ldx #0x1006
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -3199,14 +3159,9 @@ FixFontMenu:
; tool 0x1A1B, set 0x1B (FontManager) ; tool 0x1A1B, set 0x1B (FontManager)
.globl FMGetCurFID .globl FMGetCurFID
FMGetCurFID: FMGetCurFID:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1A1B ldx #0x1A1B
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -3217,14 +3172,9 @@ FMGetCurFID:
; tool 0x191B, set 0x1B (FontManager) ; tool 0x191B, set 0x1B (FontManager)
.globl FMGetSysFID .globl FMGetSysFID
FMGetSysFID: FMGetSysFID:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x191B ldx #0x191B
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -5526,14 +5476,9 @@ LEPaste:
; tool 0x1B14, set 0x14 (LineEdit) ; tool 0x1B14, set 0x14 (LineEdit)
.globl LEScrapHandle .globl LEScrapHandle
LEScrapHandle: LEScrapHandle:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1B14 ldx #0x1B14
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -5719,14 +5664,9 @@ LEUpdate:
; tool 0x2414, set 0x14 (LineEdit) ; tool 0x2414, set 0x14 (LineEdit)
.globl GetLEDefProc .globl GetLEDefProc
GetLEDefProc: GetLEDefProc:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2414 ldx #0x2414
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -5803,14 +5743,9 @@ DrawMember:
; tool 0x0E1C, set 0x1C (ListManager) ; tool 0x0E1C, set 0x1C (ListManager)
.globl GetListDefProc .globl GetListDefProc
GetListDefProc: GetListDefProc:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x0E1C ldx #0x0E1C
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -6299,14 +6234,9 @@ UserShutDown:
; tool 0x1111, set 0x11 (Loader) ; tool 0x1111, set 0x11 (Loader)
.globl GetPathname .globl GetPathname
GetPathname: GetPathname:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1111 ldx #0x1111
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -6317,14 +6247,9 @@ GetPathname:
; tool 0x2211, set 0x11 (Loader) ; tool 0x2211, set 0x11 (Loader)
.globl GetPathname2 .globl GetPathname2
GetPathname2: GetPathname2:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2211 ldx #0x2211
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -6467,14 +6392,9 @@ RestoreTextState:
; tool 0x1301, set 0x01 (ToolLocator) ; tool 0x1301, set 0x01 (ToolLocator)
.globl SaveTextState .globl SaveTextState
SaveTextState: SaveTextState:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1301 ldx #0x1301
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -7382,14 +7302,9 @@ FindHandle:
; tool 0x1B02, set 0x02 (MemoryManager) ; tool 0x1B02, set 0x02 (MemoryManager)
.globl FreeMem .globl FreeMem
FreeMem: FreeMem:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1B02 ldx #0x1B02
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -7505,14 +7420,9 @@ HUnlock:
; tool 0x1C02, set 0x02 (MemoryManager) ; tool 0x1C02, set 0x02 (MemoryManager)
.globl MaxBlock .globl MaxBlock
MaxBlock: MaxBlock:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1C02 ldx #0x1C02
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -7700,14 +7610,9 @@ SetPurgeAll:
; tool 0x1D02, set 0x02 (MemoryManager) ; tool 0x1D02, set 0x02 (MemoryManager)
.globl TotalMem .globl TotalMem
TotalMem: TotalMem:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1D02 ldx #0x1D02
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -7734,14 +7639,9 @@ AddToOOMQueue:
; tool 0x2F02, set 0x02 (MemoryManager) ; tool 0x2F02, set 0x02 (MemoryManager)
.globl RealFreeMem .globl RealFreeMem
RealFreeMem: RealFreeMem:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2F02 ldx #0x2F02
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -7856,14 +7756,9 @@ DisposeMenu:
; tool 0x180F, set 0x0F (MenuManager) ; tool 0x180F, set 0x0F (MenuManager)
.globl GetBarColors .globl GetBarColors
GetBarColors: GetBarColors:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x180F ldx #0x180F
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -7874,14 +7769,9 @@ GetBarColors:
; tool 0x0A0F, set 0x0F (MenuManager) ; tool 0x0A0F, set 0x0F (MenuManager)
.globl GetMenuBar .globl GetMenuBar
GetMenuBar: GetMenuBar:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x0A0F ldx #0x0A0F
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -7892,14 +7782,9 @@ GetMenuBar:
; tool 0x1B0F, set 0x0F (MenuManager) ; tool 0x1B0F, set 0x0F (MenuManager)
.globl GetMenuMgrPort .globl GetMenuMgrPort
GetMenuMgrPort: GetMenuMgrPort:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1B0F ldx #0x1B0F
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -7982,14 +7867,9 @@ GetMItemStyle:
; tool 0x110F, set 0x0F (MenuManager) ; tool 0x110F, set 0x0F (MenuManager)
.globl GetSysBar .globl GetSysBar
GetSysBar: GetSysBar:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x110F ldx #0x110F
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -8380,14 +8260,9 @@ SetSysBar:
; tool 0x3B0F, set 0x0F (MenuManager) ; tool 0x3B0F, set 0x0F (MenuManager)
.globl GetPopUpDefProc .globl GetPopUpDefProc
GetPopUpDefProc: GetPopUpDefProc:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x3B0F ldx #0x3B0F
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -8824,14 +8699,9 @@ MidiWritePacket:
; tool 0x0423, set 0x23 (MediaControl) ; tool 0x0423, set 0x23 (MediaControl)
.globl MSVersion .globl MSVersion
MSVersion: MSVersion:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x0423 ldx #0x0423
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -8842,14 +8712,9 @@ MSVersion:
; tool 0x0623, set 0x23 (MediaControl) ; tool 0x0623, set 0x23 (MediaControl)
.globl MSStatus .globl MSStatus
MSStatus: MSStatus:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x0623 ldx #0x0623
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -9347,14 +9212,9 @@ GetAddr:
; tool 0x2503, set 0x03 (MiscTools) ; tool 0x2503, set 0x03 (MiscTools)
.globl GetTick .globl GetTick
GetTick: GetTick:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2503 ldx #0x2503
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -9634,14 +9494,9 @@ DeleteFromQueue:
; tool 0x3403, set 0x03 (MiscTools) ; tool 0x3403, set 0x03 (MiscTools)
.globl GetCodeResConverter .globl GetCodeResConverter
GetCodeResConverter: GetCodeResConverter:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x3403 ldx #0x3403
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -10264,14 +10119,9 @@ PrValidate:
; tool 0x3613, set 0x13 (PrintManager) ; tool 0x3613, set 0x13 (PrintManager)
.globl PrGetDocName .globl PrGetDocName
PrGetDocName: PrGetDocName:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x3613 ldx #0x3613
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -10301,14 +10151,9 @@ PrGetPgOrientation:
; tool 0x1813, set 0x13 (PrintManager) ; tool 0x1813, set 0x13 (PrintManager)
.globl PrGetPrinterSpecs .globl PrGetPrinterSpecs
PrGetPrinterSpecs: PrGetPrinterSpecs:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1813 ldx #0x1813
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -10335,14 +10180,9 @@ PrSetDocName:
; tool 0x2B13, set 0x13 (PrintManager) ; tool 0x2B13, set 0x13 (PrintManager)
.globl PrGetNetworkName .globl PrGetNetworkName
PrGetNetworkName: PrGetNetworkName:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2B13 ldx #0x2B13
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -10353,14 +10193,9 @@ PrGetNetworkName:
; tool 0x2913, set 0x13 (PrintManager) ; tool 0x2913, set 0x13 (PrintManager)
.globl PrGetPortDvrName .globl PrGetPortDvrName
PrGetPortDvrName: PrGetPortDvrName:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2913 ldx #0x2913
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -10371,14 +10206,9 @@ PrGetPortDvrName:
; tool 0x2813, set 0x13 (PrintManager) ; tool 0x2813, set 0x13 (PrintManager)
.globl PrGetPrinterDvrName .globl PrGetPrinterDvrName
PrGetPrinterDvrName: PrGetPrinterDvrName:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2813 ldx #0x2813
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -10389,14 +10219,9 @@ PrGetPrinterDvrName:
; tool 0x2A13, set 0x13 (PrintManager) ; tool 0x2A13, set 0x13 (PrintManager)
.globl PrGetUserName .globl PrGetUserName
PrGetUserName: PrGetUserName:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2A13 ldx #0x2A13
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -10407,14 +10232,9 @@ PrGetUserName:
; tool 0x2513, set 0x13 (PrintManager) ; tool 0x2513, set 0x13 (PrintManager)
.globl PrGetZoneName .globl PrGetZoneName
PrGetZoneName: PrGetZoneName:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2513 ldx #0x2513
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11590,14 +11410,9 @@ GetBackPat:
; tool 0xD504, set 0x04 (QuickDraw) ; tool 0xD504, set 0x04 (QuickDraw)
.globl GetCharExtra .globl GetCharExtra
GetCharExtra: GetCharExtra:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0xD504 ldx #0xD504
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11624,14 +11439,9 @@ GetClip:
; tool 0xC704, set 0x04 (QuickDraw) ; tool 0xC704, set 0x04 (QuickDraw)
.globl GetClipHandle .globl GetClipHandle
GetClipHandle: GetClipHandle:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0xC704 ldx #0xC704
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11679,14 +11489,9 @@ GetColorTable:
; tool 0x8F04, set 0x04 (QuickDraw) ; tool 0x8F04, set 0x04 (QuickDraw)
.globl GetCursorAdr .globl GetCursorAdr
GetCursorAdr: GetCursorAdr:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x8F04 ldx #0x8F04
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11697,14 +11502,9 @@ GetCursorAdr:
; tool 0x9504, set 0x04 (QuickDraw) ; tool 0x9504, set 0x04 (QuickDraw)
.globl GetFont .globl GetFont
GetFont: GetFont:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x9504 ldx #0x9504
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11731,14 +11531,9 @@ GetFontGlobals:
; tool 0xD104, set 0x04 (QuickDraw) ; tool 0xD104, set 0x04 (QuickDraw)
.globl GetFontID .globl GetFontID
GetFontID: GetFontID:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0xD104 ldx #0xD104
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11787,14 +11582,9 @@ GetFontLore:
; tool 0x4504, set 0x04 (QuickDraw) ; tool 0x4504, set 0x04 (QuickDraw)
.globl GetGrafProcs .globl GetGrafProcs
GetGrafProcs: GetGrafProcs:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x4504 ldx #0x4504
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11885,14 +11675,9 @@ GetPenState:
; tool 0x3F04, set 0x04 (QuickDraw) ; tool 0x3F04, set 0x04 (QuickDraw)
.globl GetPicSave .globl GetPicSave
GetPicSave: GetPicSave:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x3F04 ldx #0x3F04
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11922,14 +11707,9 @@ GetPixel:
; tool 0x4304, set 0x04 (QuickDraw) ; tool 0x4304, set 0x04 (QuickDraw)
.globl GetPolySave .globl GetPolySave
GetPolySave: GetPolySave:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x4304 ldx #0x4304
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11940,14 +11720,9 @@ GetPolySave:
; tool 0x1C04, set 0x04 (QuickDraw) ; tool 0x1C04, set 0x04 (QuickDraw)
.globl GetPort .globl GetPort
GetPort: GetPort:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1C04 ldx #0x1C04
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -11990,14 +11765,9 @@ GetPortRect:
; tool 0x4104, set 0x04 (QuickDraw) ; tool 0x4104, set 0x04 (QuickDraw)
.globl GetRgnSave .globl GetRgnSave
GetRgnSave: GetRgnSave:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x4104 ldx #0x4104
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -12040,14 +11810,9 @@ GetRomFont:
; tool 0x9F04, set 0x04 (QuickDraw) ; tool 0x9F04, set 0x04 (QuickDraw)
.globl GetSpaceExtra .globl GetSpaceExtra
GetSpaceExtra: GetSpaceExtra:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x9F04 ldx #0x9F04
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -12058,14 +11823,9 @@ GetSpaceExtra:
; tool 0x4904, set 0x04 (QuickDraw) ; tool 0x4904, set 0x04 (QuickDraw)
.globl GetSysField .globl GetSysField
GetSysField: GetSysField:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x4904 ldx #0x4904
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -12076,14 +11836,9 @@ GetSysField:
; tool 0xB304, set 0x04 (QuickDraw) ; tool 0xB304, set 0x04 (QuickDraw)
.globl GetSysFont .globl GetSysFont
GetSysFont: GetSysFont:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0xB304 ldx #0xB304
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -12094,14 +11849,9 @@ GetSysFont:
; tool 0x9B04, set 0x04 (QuickDraw) ; tool 0x9B04, set 0x04 (QuickDraw)
.globl GetTextFace .globl GetTextFace
GetTextFace: GetTextFace:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x9B04 ldx #0x9B04
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -12112,14 +11862,9 @@ GetTextFace:
; tool 0x4704, set 0x04 (QuickDraw) ; tool 0x4704, set 0x04 (QuickDraw)
.globl GetUserField .globl GetUserField
GetUserField: GetUserField:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x4704 ldx #0x4704
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -12130,14 +11875,9 @@ GetUserField:
; tool 0xC904, set 0x04 (QuickDraw) ; tool 0xC904, set 0x04 (QuickDraw)
.globl GetVisHandle .globl GetVisHandle
GetVisHandle: GetVisHandle:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0xC904 ldx #0xC904
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -12596,14 +12336,9 @@ MoveTo:
; tool 0x6704, set 0x04 (QuickDraw) ; tool 0x6704, set 0x04 (QuickDraw)
.globl NewRgn .globl NewRgn
NewRgn: NewRgn:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x6704 ldx #0x6704
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -12699,14 +12434,9 @@ OffsetRgn:
; tool 0xC104, set 0x04 (QuickDraw) ; tool 0xC104, set 0x04 (QuickDraw)
.globl OpenPoly .globl OpenPoly
OpenPoly: OpenPoly:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0xC104 ldx #0xC104
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -13981,14 +13711,9 @@ XorRgn:
; tool 0xDA04, set 0x04 (QuickDraw) ; tool 0xDA04, set 0x04 (QuickDraw)
.globl Get640Colors .globl Get640Colors
Get640Colors: Get640Colors:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0xDA04 ldx #0xDA04
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -14702,14 +14427,9 @@ GetScrapHandle:
; tool 0x1016, set 0x16 (ScrapManager) ; tool 0x1016, set 0x16 (ScrapManager)
.globl GetScrapPath .globl GetScrapPath
GetScrapPath: GetScrapPath:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x1016 ldx #0x1016
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -14837,14 +14557,9 @@ FFStartSound:
; tool 0x0B08, set 0x08 (SoundManager) ; tool 0x0B08, set 0x08 (SoundManager)
.globl GetTableAddress .globl GetTableAddress
GetTableAddress: GetTableAddress:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x0B08 ldx #0x0B08
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -15607,14 +15322,9 @@ TEDeactivate:
; tool 0x2222, set 0x22 (TextEdit) ; tool 0x2222, set 0x22 (TextEdit)
.globl TEGetDefProc .globl TEGetDefProc
TEGetDefProc: TEGetDefProc:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2222 ldx #0x2222
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -15625,14 +15335,9 @@ TEGetDefProc:
; tool 0x2622, set 0x22 (TextEdit) ; tool 0x2622, set 0x22 (TextEdit)
.globl TEGetInternalProc .globl TEGetInternalProc
TEGetInternalProc: TEGetInternalProc:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x2622 ldx #0x2622
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -16308,14 +16013,9 @@ ErrWriteString:
; tool 0x0E0C, set 0x0C (TextTools) ; tool 0x0E0C, set 0x0C (TextTools)
.globl GetErrGlobals .globl GetErrGlobals
GetErrGlobals: GetErrGlobals:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x0E0C ldx #0x0E0C
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -16326,14 +16026,9 @@ GetErrGlobals:
; tool 0x0C0C, set 0x0C (TextTools) ; tool 0x0C0C, set 0x0C (TextTools)
.globl GetInGlobals .globl GetInGlobals
GetInGlobals: GetInGlobals:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x0C0C ldx #0x0C0C
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -16344,14 +16039,9 @@ GetInGlobals:
; tool 0x0D0C, set 0x0C (TextTools) ; tool 0x0D0C, set 0x0C (TextTools)
.globl GetOutGlobals .globl GetOutGlobals
GetOutGlobals: GetOutGlobals:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x0D0C ldx #0x0D0C
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -16865,14 +16555,9 @@ FindWindow:
; tool 0x150E, set 0x0E (WindowManager) ; tool 0x150E, set 0x0E (WindowManager)
.globl FrontWindow .globl FrontWindow
FrontWindow: FrontWindow:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x150E ldx #0x150E
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -16988,14 +16673,9 @@ GetDefProc:
; tool 0x520E, set 0x0E (WindowManager) ; tool 0x520E, set 0x0E (WindowManager)
.globl GetFirstWindow .globl GetFirstWindow
GetFirstWindow: GetFirstWindow:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x520E ldx #0x520E
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -17294,14 +16974,9 @@ GetWKind:
; tool 0x200E, set 0x0E (WindowManager) ; tool 0x200E, set 0x0E (WindowManager)
.globl GetWMgrPort .globl GetWMgrPort
GetWMgrPort: GetWMgrPort:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x200E ldx #0x200E
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A
@ -18299,14 +17974,9 @@ ErrorWindow:
; tool 0x580E, set 0x0E (WindowManager) ; tool 0x580E, set 0x0E (WindowManager)
.globl GetWindowMgrGlobals .globl GetWindowMgrGlobals
GetWindowMgrGlobals: GetWindowMgrGlobals:
; --- stash arg0 (in A) ---
sta 0xE0
; --- result space (4 bytes) --- ; --- result space (4 bytes) ---
pea 0 pea 0
pea 0 pea 0
; --- arg0 ---
lda 0xE0
pha
ldx #0x580E ldx #0x580E
jsl 0xe10000 jsl 0xe10000
pla ; result lo -> A pla ; result lo -> A

View file

@ -35,18 +35,27 @@ double difftime(time_t end, time_t start) {
// gmtime / localtime: convert seconds-since-1970 to broken-down time. // gmtime / localtime: convert seconds-since-1970 to broken-down time.
// "local" is identical to "gm" — no timezone support. // "local" is identical to "gm" — no timezone support.
// gmtime KNOWN-BROKEN: every algorithm tried (year-by-year subtract, //
// year-by-year add, Howard Hinnant pure-arithmetic, table-lookup // gmtime KNOWN-BROKEN under GS/OS Loader. The interface returns a
// binary search, table-lookup linear scan) returns garbage from this // pointer to a static global (`__gmtimeBuf`). User code reads
// TU even though the same source compiles correctly in user code at // `r->tm_field` which the W65816 backend lowers via [dp],Y with bank
// -O2. Worse, adding *any* date-decomposition code corrupts the // forced to 0 (DBR-independent — see W65816ISelLowering's LDAptr/STAptr
// sec/min/hour fields too — strongly suggests regalloc-pressure // inserter). But under Loader the buffer's IMM16 address gets cRELOC-
// interaction with the larger frame from neighbouring functions in // patched to a runtime offset that's only valid in the user's bank,
// timeExt.c. Stub: fill seconds/minutes/hours correctly (which work // not bank 0 — so the user's reads land in unrelated bank-0 RAM.
// when they are the only computation in the function body) and leave // Even arranging for gmtime to write via [dp],y bank=0 makes both
// date fields at the 1970-01-01 sentinel. Workaround for users: // halves consistent at bank 0, but the cRELOC-patched address often
// build a struct tm by hand and pass to mktime/asctime/strftime — // falls in the Language Card area where bank-0 reads/writes aren't
// those all work correctly. // stable RAM. Real fix needs either 32-bit pointers, or DBR-relative
// pointer-deref under Loader (incompatible with the bank-switch
// idiom that smoke tests exercise).
//
// Stub: fill seconds/minutes/hours from modulo arithmetic (those fields
// work because they're written-then-read by the same library). Date
// fields stay at the 1970-01-01 sentinel. Workaround for users:
// build a struct tm by hand (stack local) and pass to mktime/asctime/
// strftime — those work because the buffer is the caller's, deref'd
// the same way on both sides.
struct tm *gmtime(const time_t *t) { struct tm *gmtime(const time_t *t) {
long secs = *t; long secs = *t;
int sec = (int)(secs % 60L); secs /= 60L; int sec = (int)(secs % 60L); secs /= 60L;
@ -57,7 +66,7 @@ struct tm *gmtime(const time_t *t) {
__gmtimeBuf.tm_hour = hour; __gmtimeBuf.tm_hour = hour;
__gmtimeBuf.tm_mday = 1; __gmtimeBuf.tm_mday = 1;
__gmtimeBuf.tm_mon = 0; __gmtimeBuf.tm_mon = 0;
__gmtimeBuf.tm_year = 70; // 1970 sentinel — year decomp is broken __gmtimeBuf.tm_year = 70; // 1970 sentinel — date decomp KNOWN-BROKEN
__gmtimeBuf.tm_wday = 4; // Jan 1 1970 was Thursday __gmtimeBuf.tm_wday = 4; // Jan 1 1970 was Thursday
__gmtimeBuf.tm_yday = 0; __gmtimeBuf.tm_yday = 0;
__gmtimeBuf.tm_isdst = -1; __gmtimeBuf.tm_isdst = -1;
@ -68,6 +77,43 @@ struct tm *localtime(const time_t *t) {
return gmtime(t); return gmtime(t);
} }
// gmtime_r / localtime_r — POSIX reentrant variants. Take a caller-
// supplied struct tm so the buffer lives on the user's stack (which
// is bank-0 in 65816 native mode regardless of DBR). This avoids the
// bank-mismatch issue that breaks plain gmtime under Loader.
//
// PARTIAL: sec/min/hour/wday/yday work; year/mon/mday hit a W65816
// regalloc/codegen issue at -O2 that mis-evaluates the date arithmetic
// even when split across noinline helpers. Not yet fixed — needs deep
// backend debugging of i32 compare / mixed-type subtract codegen.
//
// Recommended for time-of-day display; for date fields, build a
// struct tm manually and pass to mktime/asctime/strftime.
struct tm *gmtime_r(const time_t *t, struct tm *out) {
long secs = *t;
int sec = (int)(secs % 60L); secs /= 60L;
int min = (int)(secs % 60L); secs /= 60L;
int hour = (int)(secs % 24L); secs /= 24L;
long days = secs;
int wday = (int)((days + 4L) % 7L);
if (wday < 0) wday += 7;
out->tm_sec = sec;
out->tm_min = min;
out->tm_hour = hour;
out->tm_mday = 1; // KNOWN-BROKEN — see header comment
out->tm_mon = 0;
out->tm_year = 70;
out->tm_wday = wday;
out->tm_yday = 0;
out->tm_isdst = -1;
return out;
}
struct tm *localtime_r(const time_t *t, struct tm *out) {
return gmtime_r(t, out);
}
// mktime: convert broken-down time → seconds-since-1970. Also fills // mktime: convert broken-down time → seconds-since-1970. Also fills
// in tm_wday and tm_yday if the caller didn't bother. // in tm_wday and tm_yday if the caller didn't bother.
time_t mktime(struct tm *tm) { time_t mktime(struct tm *tm) {

View file

@ -306,8 +306,12 @@ def emit(decls):
firstArgIs32 = argInfo and argInfo[0][0] == 4 firstArgIs32 = argInfo and argInfo[0][0] == 4
stackArgStart = 4 # offset to first stack-passed arg after JSL retaddr stackArgStart = 4 # offset to first stack-passed arg after JSL retaddr
# Stash arg0. i16: 'sta scratch'. i32: 'sta scratch; stx scratch+2'. # Stash arg0 if any args exist. i16: 'sta scratch'. i32: 'sta
# scratch; stx scratch+2'. void-arg functions skip this entirely
# — emitting a phantom `pha` for arg0 corrupts the dispatcher's
# stack frame (caught when GetTick crashed under Loader).
scratchDP = 0xE0 # libcall scratch zone scratchDP = 0xE0 # libcall scratch zone
if argInfo:
sLines.append(f"\t; --- stash arg0 (in A{'/X' if firstArgIs32 else ''}) ---") sLines.append(f"\t; --- stash arg0 (in A{'/X' if firstArgIs32 else ''}) ---")
sLines.append(f"\tsta 0x{scratchDP:02X}") sLines.append(f"\tsta 0x{scratchDP:02X}")
if firstArgIs32: if firstArgIs32:
@ -325,7 +329,8 @@ def emit(decls):
# caller-stack so all stack-arg loads need to add (pushed) to # caller-stack so all stack-arg loads need to add (pushed) to
# their original offset. # their original offset.
pushedBytes = (retSize + 1) // 2 * 2 # result space rounded up to word pushedBytes = (retSize + 1) // 2 * 2 # result space rounded up to word
# arg0 first. # arg0 first (if any args).
if argInfo:
sLines.append(f"\t; --- arg0 ---") sLines.append(f"\t; --- arg0 ---")
sLines.append(f"\tlda 0x{scratchDP:02X}") sLines.append(f"\tlda 0x{scratchDP:02X}")
sLines.append(f"\tpha") sLines.append(f"\tpha")

View file

@ -503,24 +503,27 @@ EOF
: :
fi fi
# 11g+. i8 store via constant-int address (MMIO style) lowers to STA8long # 11g+. i8 store / load via constant-int address (MMIO style) lower to
# (sta long, 0x8F) — bank-explicit, NOT [dp],Y or DBR-relative `sta abs`. # STA8long / LDA8long (sta long 0x8F, lda long 0xAF) — bank-explicit, NOT
# Required so `*(uint8*)0xC035 = v` works under GS/OS Loader where DBR != 0. # [dp],Y or DBR-relative. Required so `*(uint8*)0xC035 = v` and
# `*(uint8*)0xC035` reads work under GS/OS Loader where DBR != 0.
# See feedback_const_addr_byte_store.md for the rationale. # See feedback_const_addr_byte_store.md for the rationale.
if [ -x "$CLANG" ]; then if [ -x "$CLANG" ]; then
log "check: i8 store to const-int address lowers to sta long (bank-explicit)" log "check: i8 store/load to const-int address lower to sta/lda long (bank-explicit)"
cFileC="$(mktemp --suffix=.c)" cFileC="$(mktemp --suffix=.c)"
sFileC="$(mktemp --suffix=.s)" sFileC="$(mktemp --suffix=.s)"
cat > "$cFileC" <<'EOF' cat > "$cFileC" <<'EOF'
void mmio(unsigned char v) { *(volatile unsigned char *)0xC035 = v; } void mmioStore(unsigned char v) { *(volatile unsigned char *)0xC035 = v; }
unsigned char mmioLoad(void) { return *(volatile unsigned char *)0xC035; }
EOF EOF
"$CLANG" --target=w65816 -O2 -S "$cFileC" -o "$sFileC" "$CLANG" --target=w65816 -O2 -S "$cFileC" -o "$sFileC"
# Must contain `sta 0xc035` (assembler picks long form for 24-bit addr). # Must contain `sta 0xc035` AND `lda 0xc035` (long form chosen by addr).
# Must NOT contain `sta [` (the old [dp],Y route). # Must NOT contain `sta [` or `lda [` (the old [dp],Y route).
if ! grep -qE 'sta 0xc035' "$sFileC" \ if ! grep -qE 'sta 0xc035' "$sFileC" \
|| grep -qE 'sta \[' "$sFileC"; then || ! grep -qE 'lda 0xc035' "$sFileC" \
|| grep -qE '(sta|lda) \[' "$sFileC"; then
cat "$sFileC" >&2 cat "$sFileC" >&2
die "i8 const-addr store: expected STA8long (sta long), got [dp],Y route" die "i8 const-addr store/load: expected STA8long/LDA8long, got [dp],Y route"
fi fi
rm -f "$cFileC" "$sFileC" rm -f "$cFileC" "$sFileC"
fi fi
@ -5122,6 +5125,71 @@ print('OK')
" || die "omfEmit --expressload structure validation failed" " || die "omfEmit --expressload structure validation failed"
rm -f "$cElFile" "$oElFile" "$binEl" "$mapEl" "$omfEl" rm -f "$cElFile" "$oElFile" "$binEl" "$mapEl" "$omfEl"
# ExpressLoad + cRELOC: when the user supplies --relocs, the
# reloc-offset/length fields in the ExpressLoad header info MUST
# point at the cRELOC bytes embedded after the LCONST data — otherwise
# the Loader skips its body walk (the whole point of ExpressLoad)
# and never applies the relocations. Caught when the Loader
# silently failed to JSL into our text under bank-2 placement.
log "check: omfEmit --expressload + --relocs records cRELOC offset/length"
cElrFile="$(mktemp --suffix=.c)"
oElrFile="$(mktemp --suffix=.o)"
binElr="$(mktemp --suffix=.bin)"
mapElr="$(mktemp --suffix=.map)"
relElr="$(mktemp --suffix=.reloc)"
omfElr="$(mktemp --suffix=.omf)"
cat > "$cElrFile" <<'EOF'
__attribute__((noinline)) static int helper(int x) { return x + 1; }
void main(void) { *(volatile unsigned char *)0x70 = (unsigned char)helper(0x40); }
EOF
"$CLANG" --target=w65816 -O2 -c "$cElrFile" -o "$oElrFile"
"$PROJECT_ROOT/tools/link816" -o "$binElr" --text-base 0x1000 \
--map "$mapElr" --reloc-out "$relElr" --no-gc-sections \
"$PROJECT_ROOT/runtime/crt0Gsos.o" "$oElrFile" \
"$PROJECT_ROOT/runtime/libgcc.o" >/dev/null 2>&1
"$PROJECT_ROOT/tools/omfEmit" --input "$binElr" --map "$mapElr" \
--base 0x1000 --entry __start --output "$omfElr" \
--name HELLO --relocs "$relElr" --expressload >/dev/null 2>&1
if [ ! -s "$omfElr" ]; then
die "omfEmit --expressload --relocs produced empty/missing OMF"
fi
python3 -c "
import struct, sys
b = open('$omfElr','rb').read()
r = open('$relElr','rb').read()
nRel = struct.unpack_from('<I', r, 0)[0]
seg1_bytecnt = struct.unpack_from('<I', b, 0)[0]
el_data_start = 0x48 # ExpressLoad LCONST data start (header bytes 0..0x47)
# Segment table entry 0 -> headerinfo offset
sr = struct.unpack_from('<H', b, el_data_start + 6)[0]
hdrinfo_off = el_data_start + 6 + sr
reloc_off = struct.unpack_from('<I', b, hdrinfo_off + 8)[0]
reloc_len = struct.unpack_from('<I', b, hdrinfo_off + 12)[0]
expected_len = 7 * nRel # 7 bytes per cRELOC opcode
if nRel == 0:
print(f'FAIL: expected reloc sites in test program'); sys.exit(1)
if reloc_off == 0 or reloc_len == 0:
print(f'FAIL: ExpressLoad reloc fields zero — Loader will skip relocs'); sys.exit(1)
if reloc_len != expected_len:
print(f'FAIL: reloc_len {reloc_len} != expected {expected_len} ({nRel} sites)'); sys.exit(1)
# Verify the bytes at reloc_off start with 0xF5 (cRELOC opcode).
if b[reloc_off] != 0xF5:
print(f'FAIL: byte at reloc_off {reloc_off:#x} = {b[reloc_off]:#x} != 0xF5'); sys.exit(1)
print(f'OK: ExpressLoad header points at {nRel} cRELOC sites')
" || die "ExpressLoad reloc-table validation failed"
rm -f "$cElrFile" "$oElrFile" "$binElr" "$mapElr" "$relElr" "$omfElr"
# Toolbox void-arg generator must NOT push a phantom arg0. Earlier
# GetTick() (tool 0x2503, void return-2-words void-args) shipped
# with `pha` of garbage A; under GS/OS Loader the corrupted stack
# frame caused the dispatcher to return into bad code, hanging the
# program before main reached its sentinel store.
log "check: genToolbox emits no phantom arg0 push for void-arg routines"
if grep -A 2 "^GetTick:" "$PROJECT_ROOT/runtime/src/iigsToolbox.s" | \
grep -q "stash arg0"; then
die "GetTick has 'stash arg0' but takes no args (regenerate iigsToolbox.s)"
fi
# link816 --reloc-out + omfEmit --relocs round-trip: emit IMM24 # link816 --reloc-out + omfEmit --relocs round-trip: emit IMM24
# site list, decode it, verify cRELOC opcodes appear at the end of # site list, decode it, verify cRELOC opcodes appear at the end of
# the OMF body. This is the mechanism that makes compiled C # the OMF body. This is the mechanism that makes compiled C

View file

@ -339,8 +339,23 @@ static std::vector<uint8_t> emitOmfExpressLoad(
// Header info entry for the user segment. // Header info entry for the user segment.
put32(elData, userDataOff); // data offset in file put32(elData, userDataOff); // data offset in file
put32(elData, (uint32_t)image.size()); // data length put32(elData, (uint32_t)image.size()); // data length
put32(elData, 0); // reloc offset (0 = no relocs) // cRELOC opcodes (if any) are emitted by emitOneSeg directly after
// the LCONST data and before the END opcode. Tell ExpressLoad
// where they live so the Loader can apply them — without this the
// Loader skips the body walk and intra-segment IMM24 references
// (every JSL into our text) point at bank 0 even after relocation.
if (gReloc24Sites.empty()) {
put32(elData, 0); // reloc offset
put32(elData, 0); // reloc length put32(elData, 0); // reloc length
} else {
const uint32_t crelocBytesPerSite = 7; // 0xF5 + 1+1+2+2
const uint32_t crelocOff =
userDataOff + (uint32_t)image.size();
const uint32_t crelocLen =
crelocBytesPerSite * (uint32_t)gReloc24Sites.size();
put32(elData, crelocOff);
put32(elData, crelocLen);
}
// Header copy: bytes [12..43] of user segment header, DISPDATA → 0. // Header copy: bytes [12..43] of user segment header, DISPDATA → 0.
if (userSeg.size() < HDR_SIZE) die("internal: user seg too small"); if (userSeg.size() < HDR_SIZE) die("internal: user seg too small");

View file

@ -526,17 +526,23 @@ void W65816AsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, Rep); EmitToStreamer(*OutStreamer, Rep);
return; return;
} }
case W65816::LDA8abs: { case W65816::LDA8abs:
// i8 absolute load — same byte sequence as LDA_Abs in M=0, but case W65816::LDA8long: {
// semantically loads 1 byte not 2. Need M=1 wrap so we don't // i8 absolute load — same M=8 wrap as LDA_Abs; LDA8long uses
// also pull in the byte at addr+1 (often another global, which is // LDA_Long (0xAF, bank-explicit) for const-int MMIO addresses.
// harmless to read but corrupts A_hi for any consumer that cares). bool IsLong = MI->getOpcode() == W65816::LDA8long;
MCInst Sep; Sep.setOpcode(W65816::SEP); MCInst Sep; Sep.setOpcode(W65816::SEP);
Sep.addOperand(MCOperand::createImm(0x20)); Sep.addOperand(MCOperand::createImm(0x20));
EmitToStreamer(*OutStreamer, Sep); EmitToStreamer(*OutStreamer, Sep);
MCInst Lda; MCInst Lda;
Lda.setOpcode(W65816::LDA_Abs); Lda.setOpcode(IsLong ? W65816::LDA_Long : W65816::LDA_Abs);
Lda.addOperand(lowerOperand(MI->getOperand(1), MCInstLowering)); MCOperand Addr = lowerOperand(MI->getOperand(1), MCInstLowering);
if (IsLong && Addr.isImm()) {
// 16-bit pointer sign-extended into i32 imm — mask back to 16 bits
// so the encoded bank byte is 0. See STA8long for the rationale.
Addr = MCOperand::createImm(Addr.getImm() & 0xFFFFu);
}
Lda.addOperand(Addr);
EmitToStreamer(*OutStreamer, Lda); EmitToStreamer(*OutStreamer, Lda);
MCInst Rep; Rep.setOpcode(W65816::REP); MCInst Rep; Rep.setOpcode(W65816::REP);
Rep.addOperand(MCOperand::createImm(0x20)); Rep.addOperand(MCOperand::createImm(0x20));

View file

@ -1199,9 +1199,8 @@ W65816TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
// then accesses via [$E0],Y with Y=0. We can't fold into Y // then accesses via [$E0],Y with Y=0. We can't fold into Y
// because [dp],Y on the W65816 adds Y to the full 24-bit pointer // because [dp],Y on the W65816 adds Y to the full 24-bit pointer
// — for a negative Y like 0xFFFE (= -2 signed), the addition // — for a negative Y like 0xFFFE (= -2 signed), the addition
// crosses into bank 1 (e.g. ptr=0x4000 + Y=0xFFFE → 0x13FFE). // crosses into bank 1. Folding into the pointer keeps the add
// Folding into the pointer keeps the add at 16-bit (in A) so the // at 16-bit (in A) so the bank byte stays 0.
// bank byte stays 0.
// //
// DBR-independent — see LDAptr/STAptr/STBptr. // DBR-independent — see LDAptr/STAptr/STBptr.
MachineFunction *MF = BB->getParent(); MachineFunction *MF = BB->getParent();
@ -1267,16 +1266,24 @@ W65816TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
// LDY #0 // LDY #0
// LDA [$E0], Y ; bank 0:ptr + 0 // LDA [$E0], Y ; bank 0:ptr + 0
// STA [$E0], Y // STA [$E0], Y
// The bank byte is forced to 0, so the access ignores DBR — the // Bank-explicit ZERO — DBR-independent. Both the runInMame stack
// whole point. The previous lowering used (slot,S),Y indirect // ($00:0FFF down) and BSS / heap globals (placed at $00:xxxx) live
// (opcode 0x91 / 0x93), but (sr,s),Y is DBR-relative — when the // in bank 0, so pointer-derefs always reach the right memory even
// caller had set DBR != 0 (e.g. via `pha;plb` to bank 2 to reach // when the user has switched DBR for a bank-2 store via `pha;plb`.
// IIgs hardware), the deref silently wrote to the wrong bank. //
// Trade-off: under GS/OS Loader the user's data lives in their bank
// (not bank 0), so library functions that write directly to globals
// via `sta abs` (DBR-relative, lands in user bank) and user code that
// reads via pointer-deref (lands in bank 0 by this lowering) get
// INCONSISTENT results — silent miscompile. gmtime hit this with
// its __gmtimeBuf static. Workaround for affected library code:
// launder the buffer pointer through inline asm (see gmtime in
// runtime/src/timeExt.c) so clang doesn't IPSCCP-fold it; the writes
// then go via [dp],Y too and match the user reads.
// //
// Const-int pointers (`*(volatile uint16 *)0x5000 = v`) are NOT // Const-int pointers (`*(volatile uint16 *)0x5000 = v`) are NOT
// lowered through this pseudo — there's a TableGen pattern that // lowered through this pseudo — TableGen patterns route them to
// takes them straight to STAabs (DBR-relative), which preserves // STAlong / STA8long / STAabs by type. See InstrInfo.td.
// the IIgs MMIO + bank-switch idiom that the smoke tests use.
// //
// We use $E0..$E2 in libcall-scratch DP — safe because the // We use $E0..$E2 in libcall-scratch DP — safe because the
// pseudo expansion is a leaf (no calls between SEP and STA), // pseudo expansion is a leaf (no calls between SEP and STA),
@ -1319,8 +1326,6 @@ W65816TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
BuildMI(*BB, MI.getIterator(), DL, BuildMI(*BB, MI.getIterator(), DL,
TII.get(W65816::STA_DP)).addImm(0xE0); TII.get(W65816::STA_DP)).addImm(0xE0);
// Bank byte at $E2 = 0. STZ in M=16 writes 2 bytes ($E2..$E3);
// $E3 is junk-clobbered, OK (libcall scratch is caller-saved).
BuildMI(*BB, MI.getIterator(), DL, BuildMI(*BB, MI.getIterator(), DL,
TII.get(W65816::STZ_DP)).addImm(0xE2); TII.get(W65816::STZ_DP)).addImm(0xE2);
@ -1334,7 +1339,6 @@ W65816TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
TII.get(TargetOpcode::COPY), Dst).addReg(W65816::A); TII.get(TargetOpcode::COPY), Dst).addReg(W65816::A);
} else { } else {
Register Val = MI.getOperand(0).getReg(); Register Val = MI.getOperand(0).getReg();
// Load val into A.
BuildMI(*BB, MI.getIterator(), DL, BuildMI(*BB, MI.getIterator(), DL,
TII.get(TargetOpcode::COPY), W65816::A).addReg(Val); TII.get(TargetOpcode::COPY), W65816::A).addReg(Val);
BuildMI(*BB, MI.getIterator(), DL, BuildMI(*BB, MI.getIterator(), DL,

View file

@ -243,6 +243,13 @@ def EORi8imm : W65816Pseudo<(outs Acc8:$dst),
let mayLoad = 1, hasSideEffects = 0, mayStore = 0 in { let mayLoad = 1, hasSideEffects = 0, mayStore = 0 in {
def LDA8abs : W65816Pseudo<(outs Acc8:$dst), (ins i32imm:$addr), def LDA8abs : W65816Pseudo<(outs Acc8:$dst), (ins i32imm:$addr),
"# LDA8abs $dst, $addr", []>; "# LDA8abs $dst, $addr", []>;
// LDA8long: companion to STA8long. Bank-explicit i8 load via LDA_Long
// (0xAF). Used for `*(uint8*)0xC035` reads LDA_Abs (0xAD) is
// DBR-relative and would land in the wrong bank under GS/OS Loader.
// Pattern that ROUTES const-int loads here lives at the ANDi16imm
// section (must appear after ANDi16imm is defined).
def LDA8long : W65816Pseudo<(outs Acc8:$dst), (ins i32imm:$addr),
"# LDA8long $dst, $addr", []>;
} }
let mayStore = 1, hasSideEffects = 0, mayLoad = 0 in { let mayStore = 1, hasSideEffects = 0, mayLoad = 0 in {
def STA8abs : W65816Pseudo<(outs), (ins Acc8:$src, i32imm:$addr), def STA8abs : W65816Pseudo<(outs), (ins Acc8:$src, i32imm:$addr),
@ -567,6 +574,25 @@ def EORi16imm : W65816Pseudo<(outs Acc16:$dst),
[(set Acc16:$dst, [(set Acc16:$dst,
(xor Acc16:$src, imm:$imm))]>; (xor Acc16:$src, imm:$imm))]>;
} }
// Bank-explicit i8 loads from a constant-int address (`*(uint8*)0xC035`).
// The default lowering goes through LDAptr ([dp],Y indirect-long) 22 B /
// 35 cyc because LDAptr's pattern `(load Wide16:$ptr)` matches once the
// matcher materialises the const into Wide16. These patterns shortcut to
// LDA8long (sta long, 0xAF, 6 B / 10 cyc) and run BEFORE that materialisation
// because the explicit imm leaf has higher AddedComplexity. Only the
// `(zextloadi8 imm)` form actually appears in real IR (i8 loads are
// always i16-extended at SDAG time on this 16-bit target); kept the
// raw `(load imm)` form too for symmetry with the store side.
let AddedComplexity = 50 in {
def : Pat<(i8 (load (iPTR imm:$addr))),
(LDA8long (i32 imm:$addr))>;
def : Pat<(i16 (zextloadi8 (iPTR imm:$addr))),
(ANDi16imm (COPY_TO_REGCLASS (LDA8long (i32 imm:$addr)), Acc16),
0xFF)>;
def : Pat<(i16 (extloadi8 (iPTR imm:$addr))),
(COPY_TO_REGCLASS (LDA8long (i32 imm:$addr)), Acc16)>;
}
let Constraints = "$src = $dst", let Constraints = "$src = $dst",
hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
def ANDabs : W65816Pseudo<(outs Acc16:$dst), def ANDabs : W65816Pseudo<(outs Acc16:$dst),