mirror of
https://github.com/cc65/cc65.git
synced 2025-02-11 15:30:52 +00:00
Convert _time_t_to_tm to asm
46 bytes size gain, -8% cycles on the unit tests
This commit is contained in:
parent
8aa59e4af3
commit
348a9048b7
@ -1,64 +0,0 @@
|
|||||||
/*****************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* gmtime.c */
|
|
||||||
/* */
|
|
||||||
/* Convert calendar time into broken down time in UTC */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* (C) 2002 Ullrich von Bassewitz */
|
|
||||||
/* Wacholderweg 14 */
|
|
||||||
/* D-70597 Stuttgart */
|
|
||||||
/* EMail: uz@musoftware.de */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
|
||||||
/* warranty. In no event will the authors be held liable for any damages */
|
|
||||||
/* arising from the use of this software. */
|
|
||||||
/* */
|
|
||||||
/* Permission is granted to anyone to use this software for any purpose, */
|
|
||||||
/* including commercial applications, and to alter it and redistribute it */
|
|
||||||
/* freely, subject to the following restrictions: */
|
|
||||||
/* */
|
|
||||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
|
||||||
/* claim that you wrote the original software. If you use this software */
|
|
||||||
/* in a product, an acknowledgment in the product documentation would be */
|
|
||||||
/* appreciated but is not required. */
|
|
||||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
|
||||||
/* be misrepresented as being the original software. */
|
|
||||||
/* 3. This notice may not be removed or altered from any source */
|
|
||||||
/* distribution. */
|
|
||||||
/* */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
struct tm* __fastcall__ _time_t_to_tm (const time_t t)
|
|
||||||
{
|
|
||||||
static struct tm timebuf;
|
|
||||||
/* Since our ints are just 16 bits, split the given time into seconds,
|
|
||||||
** hours and days. Each of the values will fit in a 16 bit variable.
|
|
||||||
** The mktime routine will then do the rest.
|
|
||||||
*/
|
|
||||||
timebuf.tm_sec = t % 3600;
|
|
||||||
timebuf.tm_min = 0;
|
|
||||||
timebuf.tm_hour = (t / 3600) % 24;
|
|
||||||
timebuf.tm_mday = (t / (3600UL * 24UL)) + 1;
|
|
||||||
timebuf.tm_mon = 0;
|
|
||||||
timebuf.tm_year = 70; /* Base value is 1/1/1970 */
|
|
||||||
|
|
||||||
/* Call mktime to do the final conversion */
|
|
||||||
mktime (&timebuf);
|
|
||||||
|
|
||||||
/* Return the result */
|
|
||||||
return &timebuf;
|
|
||||||
}
|
|
129
libsrc/common/_time_t_to_tm.s
Normal file
129
libsrc/common/_time_t_to_tm.s
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
;
|
||||||
|
; 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
|
@ -65,7 +65,8 @@ static const unsigned MonthDays [] = {
|
|||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/* use statics for size optimisation (~34 bytes) */
|
||||||
|
#pragma static-locals(push, on)
|
||||||
|
|
||||||
time_t __fastcall__ mktime (register struct tm* TM)
|
time_t __fastcall__ mktime (register struct tm* TM)
|
||||||
/* Make a time in seconds since 1/1/1970 from the broken down time in TM.
|
/* Make a time in seconds since 1/1/1970 from the broken down time in TM.
|
||||||
@ -74,8 +75,8 @@ time_t __fastcall__ mktime (register struct tm* TM)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
register div_t D;
|
register div_t D;
|
||||||
static int Max;
|
int Max;
|
||||||
static unsigned DayCount;
|
unsigned DayCount;
|
||||||
|
|
||||||
/* Check if TM is valid */
|
/* Check if TM is valid */
|
||||||
if (TM == 0) {
|
if (TM == 0) {
|
||||||
@ -182,3 +183,5 @@ time_t __fastcall__ mktime (register struct tm* TM)
|
|||||||
((unsigned) TM->tm_sec) -
|
((unsigned) TM->tm_sec) -
|
||||||
_tz.timezone;
|
_tz.timezone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma static-locals(pop)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user