mirror of
https://github.com/cc65/cc65.git
synced 2024-09-11 22:55:11 +00:00
130 lines
3.3 KiB
ArmAsm
130 lines
3.3 KiB
ArmAsm
;
|
|
; Colin Leroy-Mira, 2024
|
|
;
|
|
; struct tm* __fastcall__ _time_t_to_tm (const time_t t)
|
|
;
|
|
; Helper to gmtime and localtime. Breaks down a number of
|
|
; seconds since Jan 1, 1970 into days, hours and seconds,
|
|
; so that each of them fits in 16 bits; passes the
|
|
; result to _mktime which fixes all values in the struct,
|
|
; and returns a pointer to the struct to callers.
|
|
;
|
|
|
|
.export __time_t_to_tm
|
|
.import udiv32, _mktime
|
|
.importzp sreg, tmp3, ptr1, ptr2, ptr3, ptr4
|
|
|
|
.include "time.inc"
|
|
|
|
.macpack cpu
|
|
|
|
__time_t_to_tm:
|
|
; Divide number of seconds since epoch, in ptr1:sreg,
|
|
; by 86400 to get the number of days since epoch, and
|
|
; the number of seconds today in the remainder.
|
|
|
|
; Load t as dividend (sreg is already set by the caller)
|
|
sta ptr1
|
|
stx ptr1+1
|
|
|
|
; Load 86400 as divisor
|
|
lda #$80
|
|
sta ptr3
|
|
lda #$51
|
|
sta ptr3+1
|
|
lda #$01
|
|
sta ptr4
|
|
lda #$00
|
|
sta ptr4+1
|
|
|
|
; Clear TM buf while we have zero in A
|
|
ldx #.sizeof(tm)-1
|
|
: sta TM,x
|
|
dex
|
|
bne :-
|
|
|
|
; Divide t/86400
|
|
jsr udiv32
|
|
|
|
; Store the quotient (the number of full days), and increment
|
|
; by one as epoch starts at day 1.
|
|
clc
|
|
lda ptr1
|
|
adc #1
|
|
sta TM + tm::tm_mday
|
|
lda ptr1+1
|
|
adc #0
|
|
sta TM + tm::tm_mday+1
|
|
|
|
; Now divide the number of remaining seconds by 3600,
|
|
; to get the number of hours, and the seconds in the
|
|
; current hour, in neat 16-bit integers.
|
|
|
|
; Load the previous division's remainder (in ptr2:tmp3:tmp4)
|
|
; as dividend
|
|
lda ptr2
|
|
sta ptr1
|
|
lda ptr2+1
|
|
sta ptr1+1
|
|
lda tmp3
|
|
sta sreg
|
|
; We ignore the high byte stored in tmp4 because it will be
|
|
; zero. We'll zero sreg+1 right below, when we'll have
|
|
; a convenient zero already in A.
|
|
|
|
; Load divisor
|
|
lda #<3600
|
|
sta ptr3
|
|
lda #>3600
|
|
sta ptr3+1
|
|
|
|
; Zero the two high bytes of the divisor and the high byte
|
|
; of the dividend.
|
|
.if .cpu .bitand CPU_ISET_65SC02
|
|
stz ptr4
|
|
stz ptr4+1
|
|
stz sreg+1
|
|
.else
|
|
lda #$00
|
|
sta ptr4
|
|
sta ptr4+1
|
|
sta sreg+1
|
|
.endif
|
|
|
|
; Do the division
|
|
jsr udiv32
|
|
|
|
; Store year
|
|
lda #70
|
|
sta TM + tm::tm_year
|
|
|
|
; Store hours (the quotient of the last division)
|
|
lda ptr1
|
|
sta TM + tm::tm_hour
|
|
lda ptr1+1
|
|
sta TM + tm::tm_hour+1
|
|
|
|
; Store seconds (the remainder of the last division)
|
|
lda ptr2
|
|
sta TM + tm::tm_sec
|
|
lda ptr2+1
|
|
sta TM + tm::tm_sec+1
|
|
|
|
; The rest of the struct tm fields are zero. mktime
|
|
; will take care of shifting extra seconds to minutes,
|
|
; and extra days to months and years.
|
|
|
|
; Call mktime
|
|
lda #<TM
|
|
ldx #>TM
|
|
jsr _mktime
|
|
|
|
; And return our pointer
|
|
lda #<TM
|
|
ldx #>TM
|
|
rts
|
|
|
|
.bss
|
|
|
|
TM: .tag tm
|