Skip to content

Instantly share code, notes, and snippets.

@momvart
Last active January 29, 2019 06:53
Show Gist options
  • Save momvart/a75205f954733bda2bc2a79f7e91940d to your computer and use it in GitHub Desktop.
Save momvart/a75205f954733bda2bc2a79f7e91940d to your computer and use it in GitHub Desktop.
MIPS assembly code that converts epoch to date and time parts
#MIPS equivalent of .NET DateTime.GetDatePart
#https://referencesource.microsoft.com/mscorlib/R/ff06f271f088f1a8.html
.macro push(%value)
addi $sp, $sp, -4
sw %value, 0($sp)
.end_macro
.macro pop(%storeTo)
lw %storeTo, 0($sp)
addi $sp ,$sp, 4
.end_macro
.macro lwmem(%reg, %label)
la $t7, %label
lw %reg, 0($t7)
.end_macro
.macro swmem(%reg, %label)
la $t7, %label
sw %reg, 0($t7)
.end_macro
.data
#Date Constants
DaysPerYear: .word 365
DaysPer4Year: .word 1461
DaysPer100Year: .word 36524
DaysPer400Year: .word 146097
DaysTo1970: .word 719162
SecondsPerDay: .word 86400
SecondsPerHour: .word 3600
SecondsPerMinute: .word 60
DaysTillMonths365: .word 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
DaysTillMonths366: .word 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
#Date Parts
curDateYear: .word 0
curDateMonth: .word 0
curDateDay: .word 0
curDateHour: .word 0
curDateMin: .word 0
curDateSec: .word 0
convertEpoch: #Extracts date parts from epoch timestamp. $a0: epoch
push($ra)
push($s0)
push($s1)
push($s2)
push($s3)
push($s4)
push($s5)
push($s6)
lwmem($t0, SecondsPerDay)
div $a0, $t0
mfhi $s0 #remaining seconds for time of day
mflo $s1 #days in $s1
bgez $s0, posPart1
add $s0, $s0, $t0
subi $s1, $s1, 1
posPart1:
lwmem($t0, SecondsPerHour)
div $s0, $t0 #count of hours
mfhi $s0
mflo $t0
swmem($t0, curDateHour)
lwmem($t0, SecondsPerMinute)
div $s0, $t0 #count of minutes
mfhi $s0
mflo $t0
swmem($t0, curDateMin)
swmem($s0, curDateSec) #now $s0 is free
lwmem($t0, DaysTo1970)
add $s1, $t0, $s1 #moving to 0001/01/01
lwmem($t0, DaysPer400Year)
div $s1, $t0
mfhi $s1
mflo $s2 #count of 400 years in y400 = $s2
mul $s0, $s2, 400 #total years count will be stored in $s0
posPart2:
lwmem($t0, DaysPer100Year)
div $s1, $t0
mflo $s3 #count of 100 years in y100 = $s3
bne $s3, 4, continue100 #if(y100 == 4)
li $s3, 3 #y100 = 3
continue100:
mul $t0, $s3, $t0 #n -= y100 * DaysPer100Year
sub $s1, $s1, $t0
mul $t0, $s3, 100 #years += y100 * 100
add $s0, $t0, $s0
lwmem($t0, DaysPer4Year)
div $s1, $t0
mflo $s4 #count of 4 years in y4 = $s2
continue4:
mul $t0, $s4, $t0 #n -= y4 * DaysPer4Year
sub $s1, $s1, $t0
mul $t0, $s4, 4
add $s0, $t0, $s0 #years += y4 * 4
lwmem($t0, DaysPerYear)
div $s1, $t0
mflo $s5 #count of years in y1 = $s5
bne $s5, 4, continue1 #if(y1 == 4)
li $s5, 3 #y1 = 3
continue1:
mul $t0, $s5, $t0 #n -= y1 * DaysPerYear
sub $s1, $s1, $t0
add $s0, $s5, $s0 #years += y1
addi $s0, $s0, 1
swmem($s0, curDateYear)
#leapYear = y1 == 3 && (y4 != 24 || y100 == 3)
beq $s5, 3, leapYear1
li $s6, 0
j leapYear5
leapYear1:
beq $s4, 24, leapYear2
li $s6, 1
j leapYear5
leapYear2:
bne $s3, 3, leapYear3
li $s6, 1
j leapYear5
leapYear3:
li $s6, 0 #leapYear is stored at $s6
leapYear5:
beqz $s6, nonLeapCalc #if(leapYear)
la $s3, DaysTillMonths366 #$s3 = &DaysTillMonth366
nonLeapCalc: #else
la $s3, DaysTillMonths365 #$s3 = &DaysTillMonth365
sra $s2, $s1, 5 #m = n >> 5 + 1
addi $s2, $s2, 1
findMonthLoop: #while(n >= $s3[m])
sll $t0, $s2, 2
add $t0, $s3, $t0
lw $t0, 0($t0)
blt $s1, $t0, findMonthLoopEnd
inc($s2) #m++
j findMonthLoop
findMonthLoopEnd:
swmem($s2, curDateMonth)
subi $t1, $s2, 1 #days(in month) = n - $s3[m - 1] + 1
sll $t1, $t1, 2
add $t0, $t1, $s3
lw $t0, 0($t0)
sub $t0, $s1, $t0
addi $t0, $t0, 1
swmem($t0, curDateDay)
pop($s6)
pop($s5)
pop($s4)
pop($s3)
pop($s2)
pop($s1)
pop($s0)
pop($ra)
jr $ra
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment