; ; This file should only be included in the 78K0R_Kx3L demo. The 78K0R_Kx3 demo ; uses the standard startup file. This is work around a bug in the startup ; file provided with the IAR tools. ; ;------------------------------------------------------------------------------ ; CSTARTUP source for 78K ; ; This module contains the code executed before the C/C++ "main" ; function is called. ; ; The code usually must be tailored to suit a specific hardware ; configuration. ; ; Assembler options: ; ; -D__STANDARD_MODEL__ To assemble for use with compiler standard ; code model. ; ; -D__BANKED_MODEL__ To assemble for use with compiler banked ; code model. ; ; -D__NEAR_MODEL__ To assemble for use with compiler near ; code model. ; ; -D__FAR_MODEL__ To assemble for use with compiler far ; code model. ; ; Linker options: ; ; -D_CODEBANK_REG=0 To link for use with "standard" code model, ; no banked functions. ; ; -D_CODEBANK_REG='addr' To link for use with "banked" code model or ; "standard" code model with banked functions. ; 'addr' = bank switch register address. ; ;------------------------------------------------------------------------------ ; Copyright (c) 2003-2008 IAR Systems AB. ; $Revision: 3577 $ ;------------------------------------------------------------------------------ #if !defined(__STANDARD_MODEL__) && !defined(__BANKED_MODEL__) && !defined(__NEAR_MODEL__) && !defined(__FAR_MODEL__) #error One of the macros __STANDARD_MODEL__, __BANKED_MODEL__, __NEAR_MODEL__ or __FAR_MODEL__ must be defined ! #endif ;------------------------------------------------------------------------------ ; The stack segment. ; The stack size is defined in the linker command file ;------------------------------------------------------------------------------ MODULE ?CSTARTUP RSEG CSTACK:DATA:ROOT(1) ;------------------------------------------------------------------------------ ; The interrupt vector segment. ; Interrupt functions with defined vectors will reserve ; space in this area as well as conformingly written assembly ; language interrupt handlers ;------------------------------------------------------------------------------ COMMON INTVEC:CODE:ROOT(1) DC16 __program_start_fr ; Reset vector ;------------------------------------------------------------------------------ ; The actual startup code ; ; Entry: __program_start ;------------------------------------------------------------------------------ RSEG RCODE:CODE:ROOT(0) PUBLIC ?C_STARTUP PUBLIC `@cstart` ; NEC debugger specific PUBLIC __program_start_fr EXTERN __low_level_init EXTERN __MAIN_CALL #if defined(__STANDARD_MODEL__) || defined(__BANKED_MODEL__) EXTERN _CODEBANK_REG #else EXTERN _NEAR_CONST_LOCATION PMC DEFINE 0xFFFFE #endif #if defined(__BANKED_MODEL__) EXTERN ?FAR_CALL_L07 SFRTYPE BANK_REG BYTE, READ, WRITE = _CODEBANK_REG #endif REQUIRE __MAIN_CALL ;------------------------------------------------------------------------------ ; Perform the run-time initialization. ;------------------------------------------------------------------------------ ?C_STARTUP: `@cstart`: __program_start_fr: DI #if defined(__BANKED_MODEL__) MOV BANK_REG, #0 ; Banked, clear bank register #elif defined(__STANDARD_MODEL__) MOVW AX, #_CODEBANK_REG OR A, X BZ nobank ; Standard, no banked functions, no bank register (=0) MOVW HL, #_CODEBANK_REG XOR A, A MOV [HL], A ; Standard with banked functions, clear bank register nobank: #else MOV A, #(_NEAR_CONST_LOCATION & 1) ; Near/Far, set mirror area MOV1 CY, A.0 MOV1 PMC.0, CY #endif #if __CORE__ != __78K0S__ MOVW SP, #sfe(CSTACK) #else MOVW AX, #sfe(CSTACK) MOVW SP, AX #endif ; Init stack segment for 78K0R, as the generated code may sometimes ; access the 4th byte of a return address before it is initialized #if __CORE__ == __78K0R__ MOVW HL, #sfb(CSTACK) MOVW BC, #LWRD(sizeof(CSTACK)) CMP0 C SKZ INC B MOV A, #0xCD loop_s: MOV [HL], A INCW HL DEC C BNZ loop_s DEC B BNZ loop_s #endif #if __CORE__ == __78K0R__ MOV CS, #0 #endif ;------------------------------------------------------------------------------ ; Here is the place to put user initializations. ;------------------------------------------------------------------------------ ; User initialization code ;------------------------------------------------------------------------------ ; Call __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: to do nothing but return 1. ;------------------------------------------------------------------------------ #if defined(__FAR_MODEL__) CALL F:__low_level_init #elif defined(__BANKED_MODEL__) MOV E, #byte3(__low_level_init) MOVW HL, #lwrd(__low_level_init) CALL ?FAR_CALL_L07 #else CALL __low_level_init #endif OR A, X #if __CORE__ == __78K0R__ SKNZ BR N:__MAIN_CALL #else BZ __MAIN_CALL #endif ENDMOD #if defined(__NEAR_MODEL__) || defined(__FAR_MODEL__) ;------------------------------------------------------------------------------ ; Segment initialization ; ; FAR_Z "uninitialized far data" are filled with zero ;------------------------------------------------------------------------------ MODULE ?__INIT_FAR_Z RSEG FAR_Z:DATA(0) RSEG RCODE:CODE:NOROOT(0) PUBLIC __INIT_FAR_Z __INIT_FAR_Z: MOV ES, #BYTE3(sfb(FAR_Z)) MOVW HL, #LWRD(sfb(FAR_Z)) MOV D, #BYTE3(sizeof(FAR_Z)) MOVW BC, #LWRD(sizeof(FAR_Z)) CMP0 C SKZ INC B CMP0 B SKZ INC D CLRB A loop: MOV ES:[HL], A INCW HL MOV A, H OR A, L CLRB A SKNZ INC ES DEC C BNZ loop DEC B BNZ loop DEC D BNZ loop ENDMOD #endif ;------------------------------------------------------------------------------ ; Segment initialization ; ; NEAR_Z "uninitialized near data" are filled with zero ;------------------------------------------------------------------------------ MODULE ?__INIT_NEAR_Z RSEG NEAR_Z:DATA(0) RSEG RCODE:CODE:NOROOT(0) PUBLIC __INIT_NEAR_Z __INIT_NEAR_Z: #if __CORE__ == __78K0R__ LIMIT sfb(NEAR_Z)>=0xF0000,1,1,"NEAR_I not placed in near memory" #endif MOVW HL, #sfb(NEAR_Z) MOVW BC, #sizeof(NEAR_Z) #if __CORE__ == __78K0R__ CMP0 C SKZ INC B CLRB A #else MOV A, C OR A, A BZ cont INC B XOR A, A cont: #endif loop: MOV [HL], A INCW HL #if __CORE__ == __78K0R__ DEC C BNZ loop DEC B BNZ loop #else DBNZ C, loop DBNZ B, loop #endif ENDMOD ;------------------------------------------------------------------------------ ; Segment initialization ; ; SADDR_Z "uninitialized saddr data" are filled with zero ;------------------------------------------------------------------------------ MODULE ?__INIT_SADDR_Z RSEG SADDR_Z:DATA(0) RSEG RCODE:CODE:NOROOT(0) PUBLIC __INIT_SADDR_Z __INIT_SADDR_Z: #if __CORE__ == __78K0R__ LIMIT sfb(SADDR_Z),0xFFE20,0xFFF1F,"SADDR_Z not within saddr memory range" LIMIT sfe(SADDR_Z),0xFFE20,0xFFF1F,"SADDR_Z not within saddr memory range" #else LIMIT sfb(SADDR_Z),0xFE20,0xFF1F,"SADDR_Z not within saddr memory range" LIMIT sfe(SADDR_Z),0xFE20,0xFF1F,"SADDR_Z not within saddr memory range" #endif MOVW HL, #sfb(SADDR_Z) MOV B, #sizeof(SADDR_Z) #if __CORE__ == __78K0R__ CLRB A #else XOR A, A #endif loop: MOV [HL], A INCW HL #if __CORE__ == __78K0R__ DEC B BNZ loop #else DBNZ B, loop #endif ENDMOD ;------------------------------------------------------------------------------ ; Segment initialization ; ; WRKSEG short address work area is filled with zero ;------------------------------------------------------------------------------ MODULE ?__INIT_WRKSEG RSEG WRKSEG:DATA(0) RSEG RCODE:CODE:NOROOT(0) PUBLIC __INIT_WRKSEG __INIT_WRKSEG: #if __CORE__ == __78K0R__ LIMIT sfb(WRKSEG),0xFFE20,0xFFF1F,"WRKSEG not within saddr memory range" LIMIT sfe(WRKSEG),0xFFE20,0xFFF1F,"WRKSEG not within saddr memory range" #else LIMIT sfb(WRKSEG),0xFE20,0xFF1F,"WRKSEG not within saddr memory range" LIMIT sfe(WRKSEG),0xFE20,0xFF1F,"WRKSEG not within saddr memory range" #endif MOVW HL, #sfb(WRKSEG) MOV B, #sizeof(WRKSEG) #if __CORE__ == __78K0R__ CLRB A #else XOR A, A #endif loop: MOV [HL], A INCW HL #if __CORE__ == __78K0R__ DEC B BNZ loop #else DBNZ B, loop #endif ENDMOD #if defined(__NEAR_MODEL__) || defined(__FAR_MODEL__) ;------------------------------------------------------------------------------ ; Segment initialization ; ; FAR_ID is copied to FAR_I "initialized far data" ;------------------------------------------------------------------------------ MODULE ?__INIT_FAR_I RSEG FAR_I:DATA(0) RSEG FAR_ID:DATA(0) RSEG RCODE:CODE:NOROOT(0) PUBLIC __INIT_FAR_I __INIT_FAR_I: ; First make sure FAR_I and FAR_ID have the same size LIMIT sizeof(FAR_I)-sizeof(FAR_ID),0,0,"FAR_I and FAR_ID not same size" ; Sanity check LIMIT (sfb(FAR_I)-sfb(FAR_ID))==0,0,0,"FAR_I and FAR_ID have same start address" ; FAR_I and FAR_ID must start at the same offset in a 64k page, unless sizeof ; FAR_I is less than 64k, then it's enugh if both segments reside within a 64k ; boundary LIMIT (((sfb(FAR_I)^sfb(FAR_ID)) & 0xFFFF) == 0) || ( (sizeof(FAR_I)< 0x10000) && (((sfb(FAR_I)^sfe(FAR_I)) & 0xF0000) == 0) && (((sfb(FAR_I)^sfe(FAR_I)) & 0xF0000) == 0) ),1,1,"FAR_I and FAR_ID have same start address" ; LIMIT (sfb(FAR_I)^sfb(FAR_ID)) & 0xFFFF,0,0,"FAR_I and FAR_ID must start at the same offset into a 64k page" MOV ES, #BYTE3(sfb(FAR_ID)) MOVW HL, #LWRD(sfb(FAR_ID)) MOV CS, #BYTE3(sizeof(FAR_ID)) ; CS is used as counter MOVW AX, #LWRD(sizeof(FAR_ID)) MOVW BC, AX CMP0 C SKZ INC B CMP0 B SKZ INC CS ; counter MOV A, #BYTE3(sfb(FAR_I)) MOVW DE, #LWRD(sfb(FAR_I)) MOV X, A loop: MOV A, ES:[HL] XCH A, X XCH A, ES XCH A, X MOV ES:[DE], A XCH A, X XCH A, ES XCH A, X INCW HL MOV A, H OR A, L SKNZ INC ES INCW DE MOV A, D OR A, E SKNZ INC X DEC C BNZ loop DEC B BNZ loop DEC CS ; counter BNZ loop ENDMOD #endif ;------------------------------------------------------------------------------ ; Segment initialization ; ; NEAR_ID is copied to NEAR_I "initialized near data" ;------------------------------------------------------------------------------ MODULE ?__INIT_NEAR_I RSEG NEAR_I:DATA(0) RSEG NEAR_ID:DATA(0) RSEG RCODE:CODE:NOROOT(0) PUBLIC __INIT_NEAR_I __INIT_NEAR_I: #if __CORE__ == __78K0R__ LIMIT sfb(NEAR_I)>=0xF0000,1,1,"NEAR_I not placed in near memory" #endif LIMIT sizeof(NEAR_I)-sizeof(NEAR_ID),0,0,"NEAR_I and NEAR_ID not same size" #if __CORE__ == __78K0R__ MOV ES, #BYTE3(sfb(NEAR_ID)) #endif MOVW HL, #sfb(NEAR_ID) MOVW BC, #sizeof(NEAR_ID) #if __CORE__ == __78K0R__ CMP0 C SKZ INC B #else MOV A, C OR A, A BZ cont INC B cont: #endif MOVW DE, #sfb(NEAR_I) loop: #if __CORE__ != __78K0R__ MOV A, [HL] #else MOV A, ES:[HL] #endif MOV [DE], A INCW HL INCW DE #if __CORE__ == __78K0R__ DEC C BNZ loop DEC B BNZ loop #else DBNZ C, loop DBNZ B, loop #endif ENDMOD ;------------------------------------------------------------------------------ ; Segment initialization ; ; SADDR_ID is copied to SADDR_I "initialized saddr data" ;------------------------------------------------------------------------------ MODULE ?__INIT_SADDR_I RSEG SADDR_I:DATA(0) RSEG SADDR_ID:DATA(0) RSEG RCODE:CODE:NOROOT(0) PUBLIC __INIT_SADDR_I __INIT_SADDR_I: #if __CORE__ == __78K0R__ LIMIT sfb(SADDR_I),0xFFE20,0xFFF1F,"SADDR_I not within saddr memory range" LIMIT sfe(SADDR_I),0xFFE20,0xFFF1F,"SADDR_I not within saddr memory range" #else LIMIT sfb(SADDR_I),0xFE20,0xFF1F,"SADDR_I not within saddr memory range" LIMIT sfe(SADDR_I),0xFE20,0xFF1F,"SADDR_I not within saddr memory range" #endif LIMIT sizeof(SADDR_I)-sizeof(SADDR_ID),0,0,"SADDR_I and SADDR_ID not same size" #if __CORE__ == __78K0R__ MOV ES, #BYTE3(sfb(SADDR_ID)) #endif MOVW HL, #sfb(SADDR_ID) MOV B, #sizeof(SADDR_ID) MOVW DE, #sfb(SADDR_I) loop: #if __CORE__ != __78K0R__ MOV A, [HL] #else MOV A, ES:[HL] #endif MOV [DE], A INCW HL INCW DE #if __CORE__ == __78K0R__ DEC B BNZ loop #else DBNZ B, loop #endif ENDMOD ;------------------------------------------------------------------------------ ; Initialize constructors ; ; This segment part is required by the compiler when it is ; necessary to call constructors of global objects. ;------------------------------------------------------------------------------ MODULE ?__INIT_CTORS RSEG DIFUNCT(0) RSEG RCODE:CODE:NOROOT(0) PUBLIC __INIT_CTORS EXTERN __call_ctors #if defined(__BANKED_MODEL__) EXTERN ?FAR_CALL_L07 #endif __INIT_CTORS: #if __CORE__ == __78K0R__ MOV X, #byte3(sfe(DIFUNCT)) PUSH AX MOVW AX, #lwrd(sfe(DIFUNCT)) PUSH AX MOV X, #byte3(sfb(DIFUNCT)) PUSH AX MOVW AX, #lwrd(sfb(DIFUNCT)) PUSH AX CALL F:__call_ctors #elif defined(__BANKED_MODEL__) MOVW AX, #sfb(DIFUNCT) MOVW BC, #sfe(DIFUNCT) MOV E, #byte3(__call_ctors) MOVW HL, #lwrd(__call_ctors) CALL ?FAR_CALL_L07 #else MOVW AX, #sfb(DIFUNCT) MOVW BC, #sfe(DIFUNCT) CALL __call_ctors #endif ENDMOD ;------------------------------------------------------------------------------ ; Enter main ; ; Call the actual "main" function ;------------------------------------------------------------------------------ MODULE ?__MAIN_CALL RSEG RCODE:CODE:NOROOT(0) PUBLIC __MAIN_CALL PUBLIC `@cend` ; NEC debugger specific EXTERN main EXTERN exit #if defined(__BANKED_MODEL__) EXTERN ?FAR_CALL_L07 #endif __MAIN_CALL: #if defined(__FAR_MODEL__) CALL F:main CALL F:exit #elif defined(__BANKED_MODEL__) MOV E, #byte3(main) MOVW HL, #lwrd(main) CALL ?FAR_CALL_L07 MOV E, #byte3(exit) MOVW HL, #lwrd(exit) CALL ?FAR_CALL_L07 #else CALL main CALL exit #endif `@cend`: ; STOP ; Should not return ENDMOD ;------------------------------------------------------------------------------ ; Low level initialization function ; ; Entry: __low_level_init ; ; The only action of this default version of '__low_level_init' is to ; return 1. By doing so it signals that normal initialization of data ; segments should be done. ; ; A customized version of '__low_level_init' may be created in order to ; perform initialization before initializing segments and calling main ; and/or to skip initialization of data segments under certain ; circumstances. ;------------------------------------------------------------------------------ MODULE ?__low_level_init_stub RSEG RCODE:CODE:NOROOT(0) PUBLIC __low_level_init __low_level_init: ; By returning 1 this function MOVW AX, #1 ; indicates that the normal RET ; initialization should take place ENDMOD END