;-----------------------------------------------------------------------
;
; This file contains the M16C C startup routine and must usually
; be tailored to suit customer's hardware.
;
; Copyright 2002 IAR Systems. All rights reserved.
;
; $Revision: 1.16 $
;
;-----------------------------------------------------------------------

        MODULE  ?cstart

        PUBLIC  __program_start
        PUBLIC  __data16_init
        PUBLIC  __data16_zero
        PUBLIC  ?cstart_call_ctors

        EXTERN  main
        EXTERN  exit
        EXTERN  __call_ctors
        EXTERN  __low_level_init
        EXTERN  ?GENERIC_MOVE_LONG_L08
        EXTERN  RelocatableVectTbl

        ;------------------------------------------------------
        ; Useful macros
        ;------------------------------------------------------

        ; Load 24-bit constant value to (high,low)
LD24    MACRO   value,high,low
        MOV.B   #BYTE3(value),high
        MOV.W   #LWRD(value),low
        ENDM

        ; Load 32-bit constant value to (high,low)
LD32    MACRO   value,high,low
        MOV.W   #HWRD(value),high
        MOV.W   #LWRD(value),low
        ENDM

        ; Load a stack-pointer with last even address of segment
LDSTACK MACRO   segment,reg
        LDC     #sfe(segment), reg
        ENDM


        ;------------------------------------------------------
        ; __program_start - Reset vector should point to here.
        ;
        ; Calls __low_level_init to perform initialization
        ; before initializing segments and calling main.
        ; If the function returns 0 no segment initialization
        ; should take place.
        ;
        ; Link with your own version of __low_level_init to
        ; override the default action: do nothing but return 1.
        ;------------------------------------------------------

        RSEG    CSTACK
        RSEG    ISTACK
        RSEG    CSTART:CODE:NOROOT
	REQUIRE	call_main

__program_start:
        LDC     #sfe(ISTACK),   ISP                             ; Set up interrupt stack
        FCLR    U                                               ; Select interrupt stack
        LDC     #sfe(CSTACK),   SP                              ; Set up C         stack
        LDINTB  #RelocatableVectTbl                             ; Set up INTB register
        JSR.A   __low_level_init                                ; Call __low_level_init

        ;-----------------------------------------------------------
        ; Run-time test whether we should do segment initialization
        ;-----------------------------------------------------------
        TST.B   R0L,            R0L
        JNE     do_segment_init
        JMP     skip_segment_init

do_segment_init:

        ;------------------------------------------------------
        ; Perform segment initialization of DATA16 memory.
        ;------------------------------------------------------

        RSEG    DATA16_Z
        RSEG    CSTART:CODE:NOROOT

__data16_zero:
        MOV.W   #sizeof(DATA16_Z), R3
        MOV.W   #sfb(DATA16_Z),    A1
        MOV.B   #0, R0L
        SSTR.B

        RSEG    DATA16_I
        RSEG    DATA16_ID
        RSEG    CSTART:CODE:NOROOT

__data16_init:
        MOV.W   #sizeof(DATA16_ID), R3
        MOV.W   #sfb(DATA16_I),     A1
        LD24    sfb(DATA16_ID),     R1H, A0
        SMOVF.B



        RSEG    CSTART:CODE:NOROOT
skip_segment_init:
        ; Fall through to next required CSTART segment part


        ;------------------------------------------------------
        ; Call constructors
        ;------------------------------------------------------

        RSEG    DIFUNCT
        RSEG    CSTART:CODE:NOROOT

        PUBLIC  ?cstart_call_ctors
        EXTERN  __call_ctors

?cstart_call_ctors:
        PUSH.W  #HWRD(sfe(DIFUNCT))
        PUSH.W  #LWRD(sfe(DIFUNCT))
        LD32    sfb(DIFUNCT),R2,R0
        JSR.A   __call_ctors


        ; Fall through to next required CSTART segment part


        ;------------------------------------------------------
        ; Call main and exit
        ;------------------------------------------------------

        ; This segment part is marked as ROOT, since it must
        ; be preserved by the linker.
        ;
        RSEG    CSTART:CODE:NOROOT

call_main:
        MOV.W   #0, R0  ; Call main with argc = 0
        JSR.A   main
        JMP.A   exit    ; Argument to exit is return value of main

        ;------------------------------------------------------
        ; Fixed interrupt table.
        ;
        ; We install all fixed interrupts in a segment called
        ; INTVEC1. All fixed interrupts have a hard coded name.
        ; Write an interrupt handler in C using this name, with
        ; no vector specification, and it will replace the
        ; default handler.
        ;------------------------------------------------------

        EXTERN  __undefined_instruction_handler
        EXTERN  __overflow_handler
        EXTERN  __break_instruction_handler
        EXTERN  __address_match_handler
        EXTERN  __single_step_handler
        EXTERN  __watchdog_timer_handler
        EXTERN  __DBC_handler
        EXTERN  __NMI_handler

        ; Labels for the ID Code Check Function.
        ; (To be initialized in the linker file)
        EXTERN  _ID_CODE_1
        EXTERN  _ID_CODE_2
        EXTERN  _ID_CODE_3
        EXTERN  _ID_CODE_4
        EXTERN  _ID_CODE_5
        EXTERN  _ID_CODE_6
        EXTERN  _ID_CODE_7
        EXTERN  _OFS_VALUE

	PUBLIC ??intvec_start

        COMMON INTVEC1:NOROOT
??intvec_start:
        DC24    __undefined_instruction_handler
        DC8     _ID_CODE_1
        DC24    __overflow_handler
        DC8     _ID_CODE_2
        DC24    __break_instruction_handler
        DC8     0
        DC24    __address_match_handler
        DC8     _ID_CODE_3
        DC24    __single_step_handler
        DC8     _ID_CODE_4
        DC24    __watchdog_timer_handler
        DC8     _ID_CODE_5
        DC24    __DBC_handler
        DC8     _ID_CODE_6
        DC24    __NMI_handler
        DC8     _ID_CODE_7
        DC24    __program_start              ; Reset vector
        DC8     _OFS_VALUE                                 

        ENDMOD


        ;------------------------------------------------------
        ; Default handlers for fixed interrupts
        ;------------------------------------------------------

        MODULE  __undefined_instruction
        EXTERN  ??reit
        REQUIRE ??reit
        PUBLIC  __undefined_instruction_handler
        RSEG    CSTART:CODE:NOROOT(1)
__undefined_instruction_handler:
        ; Fall through to ??reit
        ENDMOD

        MODULE  __overflow
        EXTERN  ??reit
        REQUIRE ??reit
        PUBLIC  __overflow_handler
        RSEG    CSTART:CODE:NOROOT(1)
__overflow_handler:
        ; Fall through to ??reit
        ENDMOD

        MODULE  __break_instruction
        EXTERN  ??reit
        REQUIRE ??reit
        PUBLIC  __break_instruction_handler
        RSEG    CSTART:CODE:NOROOT(1)
__break_instruction_handler:
        ; Fall through to ??reit
        ENDMOD

        MODULE  __address_match
        EXTERN  ??reit
        REQUIRE ??reit
        PUBLIC  __address_match_handler
        RSEG    CSTART:CODE:NOROOT(1)
__address_match_handler:
        ; Fall through to ??reit
        ENDMOD

        MODULE  __single_step
        EXTERN  ??reit
        REQUIRE ??reit
        PUBLIC  __single_step_handler
        RSEG    CSTART:CODE:NOROOT(1)
__single_step_handler:
        ; Fall through to ??reit
        ENDMOD

        MODULE  __watchdog_timer
        EXTERN  ??reit
        REQUIRE ??reit
        PUBLIC  __watchdog_timer_handler
        RSEG    CSTART:CODE:NOROOT(1)
__watchdog_timer_handler:
        ; Fall through to ??reit
        ENDMOD

        MODULE  __DBC
        EXTERN  ??reit
        REQUIRE ??reit
        PUBLIC  __DBC_handler
        RSEG    CSTART:CODE:NOROOT(1)
__DBC_handler:
        ; Fall through to ??reit
        ENDMOD

        MODULE  __NMI
        EXTERN  ??reit
        REQUIRE ??reit
        PUBLIC  __NMI_handler
        RSEG    CSTART:CODE:NOROOT(1)
__NMI_handler:
        ; Fall through to ??reit
        ENDMOD

        ;------------------------------------------------------
        ; Return from interrupt
        ;------------------------------------------------------
        MODULE    __reit
        PUBLIC  ??reit
        RSEG    CSTART:CODE:NOROOT(1)
	EXTERN ??intvec_start
	REQUIRE ??intvec_start
??reit:
        REIT

        ENDMOD


        ;------------------------------------------------------
        ; FUNCTION: __low_level_init
        ;
        ; You can replace this routine by linking with your
        ; own version.
        ;
        ; The default action is to do nothing and return 1.
        ;------------------------------------------------------

        MODULE  __low_level_init
        PUBLIC  __low_level_init
        RSEG    CSTART:CODE:NOROOT

__low_level_init:
        MOV.B   #1,R0L
        RTS

        ENDMOD


        ;------------------------------------------------------
        ;  __overflow - This variable is used by the intrinsic
        ;               functions __RMPA_W_overflow and
        ;               __RMPA_B_overflow.
        ;------------------------------------------------------

        MODULE  __overflow
        PUBLIC  __overflow
        EXTERN  __data13_zero

        RSEG    DATA13_Z:NEAR:NOROOT

__overflow:
        DC8     0
        REQUIRE __data13_zero

        END