# XSTORMY16 startup code
|
# XSTORMY16 startup code
|
|
|
# Interrupt vectors at 0x8000.
|
# Interrupt vectors at 0x8000.
|
.section .int_vec,"ax"
|
.section .int_vec,"ax"
|
.global _start
|
.global _start
|
.align 1
|
.align 1
|
_start:
|
_start:
|
;; Reset, watchdog timer interrupt
|
;; Reset, watchdog timer interrupt
|
jmpf _int_reset
|
jmpf _int_reset
|
;; base timer interrupt
|
;; base timer interrupt
|
jmpf _int_basetimer
|
jmpf _int_basetimer
|
;; timer 0
|
;; timer 0
|
jmpf _int_timer0
|
jmpf _int_timer0
|
;; timer 1
|
;; timer 1
|
jmpf _int_timer1
|
jmpf _int_timer1
|
;; SIO0 interrupt
|
;; SIO0 interrupt
|
jmpf _int_sio0
|
jmpf _int_sio0
|
;; SIO1 interrupt
|
;; SIO1 interrupt
|
jmpf _int_sio1
|
jmpf _int_sio1
|
;; port0 interrupt
|
;; port0 interrupt
|
jmpf _int_port0
|
jmpf _int_port0
|
;; port1 interrupt
|
;; port1 interrupt
|
jmpf _int_port1
|
jmpf _int_port1
|
|
|
# Reset code, set up memory and call main.
|
# Reset code, set up memory and call main.
|
.section .rodata
|
.section .rodata
|
2: .word __rdata
|
2: .word __rdata
|
.text
|
.text
|
_int_reset:
|
_int_reset:
|
;; Set up the stack pointer.
|
;; Set up the stack pointer.
|
mov r0,#__stack
|
mov r0,#__stack
|
bz r0,#0,0f
|
bz r0,#0,0f
|
mov sp,r0
|
mov sp,r0
|
0:
|
0:
|
;; Zero the data space
|
;; Zero the data space
|
mov r0,#_edata
|
mov r0,#_edata
|
mov r1,#_end
|
mov r1,#_end
|
mov r2,#0
|
mov r2,#0
|
0: mov.w (r0++),r2
|
0: mov.w (r0++),r2
|
blt r0,r1,0b
|
blt r0,r1,0b
|
|
|
;; Copy data from ROM into RAM. ROM area may be above 64k,
|
;; Copy data from ROM into RAM. ROM area may be above 64k,
|
;; but RAM may not.
|
;; but RAM may not.
|
mov r1,#__data
|
mov r1,#__data
|
mov r3,#_edata
|
mov r3,#_edata
|
mov r4,#2b
|
mov r4,#2b
|
mov.w r0,(r4++)
|
mov.w r0,(r4++)
|
mov.w r2,(r4)
|
mov.w r2,(r4)
|
mov r8,r2
|
mov r8,r2
|
;; If _data == _rdata there's no need to copy anything.
|
;; If _data == _rdata there's no need to copy anything.
|
bnz r0,r1,0f
|
bnz r0,r1,0f
|
bz r2,#0,1f
|
bz r2,#0,1f
|
0: movf.w r2,(r0++)
|
0: movf.w r2,(r0++)
|
bnz r0,#0,2f
|
bnz r0,#0,2f
|
add r8,#1
|
add r8,#1
|
2: mov.w (r1++),r2
|
2: mov.w (r1++),r2
|
blt r1,r3,0b
|
blt r1,r3,0b
|
1:
|
1:
|
;; Call hardware init routine
|
;; Call hardware init routine
|
callf _hwinit
|
callf _hwinit
|
;; Call initialization routines
|
;; Call initialization routines
|
callf _init
|
callf _init
|
;; Set up fini routines to be called from exit
|
;; Set up fini routines to be called from exit
|
mov r2,#@fptr(_fini)
|
mov r2,#@fptr(_fini)
|
callf atexit
|
callf atexit
|
;; Call main() with empty argc/argv/envp
|
;; Call main() with empty argc/argv/envp
|
mov r2,#0
|
mov r2,#0
|
mov r3,#0
|
mov r3,#0
|
mov r4,#0
|
mov r4,#0
|
callf main
|
callf main
|
;; Exit.
|
;; Exit.
|
callf exit
|
callf exit
|
;; Should never reach this code.
|
;; Should never reach this code.
|
halt
|
halt
|
1: .size _int_reset,1b-_int_reset
|
1: .size _int_reset,1b-_int_reset
|
|
|
# Stub interrupt routines.
|
# Stub interrupt routines.
|
.globl _int_timer0
|
.globl _int_timer0
|
.weak _int_timer0
|
.weak _int_timer0
|
.globl _int_timer1
|
.globl _int_timer1
|
.weak _int_timer1
|
.weak _int_timer1
|
.globl _int_sio0
|
.globl _int_sio0
|
.weak _int_sio0
|
.weak _int_sio0
|
.globl _int_sio1
|
.globl _int_sio1
|
.weak _int_sio1
|
.weak _int_sio1
|
.globl _int_port0
|
.globl _int_port0
|
.weak _int_port0
|
.weak _int_port0
|
.globl _int_port1
|
.globl _int_port1
|
.weak _int_port1
|
.weak _int_port1
|
.globl _int_basetimer
|
.globl _int_basetimer
|
.weak _int_basetimer
|
.weak _int_basetimer
|
_int_timer0:
|
_int_timer0:
|
_int_timer1:
|
_int_timer1:
|
_int_sio0:
|
_int_sio0:
|
_int_sio1:
|
_int_sio1:
|
_int_port0:
|
_int_port0:
|
_int_port1:
|
_int_port1:
|
_int_basetimer:
|
_int_basetimer:
|
iret
|
iret
|
1: .size _int_timer0,1b-_int_timer0
|
1: .size _int_timer0,1b-_int_timer0
|
|
|
# Stub hardware init
|
# Stub hardware init
|
.globl _hwinit
|
.globl _hwinit
|
.weak _hwinit
|
.weak _hwinit
|
_hwinit:
|
_hwinit:
|
ret
|
ret
|
1: .size _int_hwinit,1b-_int_hwinit
|
1: .size _int_hwinit,1b-_int_hwinit
|
|
|
# The first word in .data has address 0, so it's not a good
|
# The first word in .data has address 0, so it's not a good
|
# idea to use it as its address conflicts with NULL.
|
# idea to use it as its address conflicts with NULL.
|
# Place a HALT instruction there to try to catch NULL pointer
|
# Place a HALT instruction there to try to catch NULL pointer
|
# dereferences.
|
# dereferences.
|
.data
|
.data
|
halt
|
halt
|
|
|