2 ; This file should only be included in the 78K0R_Kx3L demo. The 78K0R_Kx3 demo
\r
3 ; uses the standard startup file. This is work around a bug in the startup
\r
4 ; file provided with the IAR tools.
\r
8 ;------------------------------------------------------------------------------
\r
9 ; CSTARTUP source for 78K
\r
11 ; This module contains the code executed before the C/C++ "main"
\r
12 ; function is called.
\r
14 ; The code usually must be tailored to suit a specific hardware
\r
17 ; Assembler options:
\r
19 ; -D__STANDARD_MODEL__ To assemble for use with compiler standard
\r
22 ; -D__BANKED_MODEL__ To assemble for use with compiler banked
\r
25 ; -D__NEAR_MODEL__ To assemble for use with compiler near
\r
28 ; -D__FAR_MODEL__ To assemble for use with compiler far
\r
33 ; -D_CODEBANK_REG=0 To link for use with "standard" code model,
\r
34 ; no banked functions.
\r
36 ; -D_CODEBANK_REG='addr' To link for use with "banked" code model or
\r
37 ; "standard" code model with banked functions.
\r
38 ; 'addr' = bank switch register address.
\r
40 ;------------------------------------------------------------------------------
\r
41 ; Copyright (c) 2003-2008 IAR Systems AB.
\r
43 ;------------------------------------------------------------------------------
\r
45 #if !defined(__STANDARD_MODEL__) && !defined(__BANKED_MODEL__) && !defined(__NEAR_MODEL__) && !defined(__FAR_MODEL__)
\r
46 #error One of the macros __STANDARD_MODEL__, __BANKED_MODEL__, __NEAR_MODEL__ or __FAR_MODEL__ must be defined !
\r
49 ;------------------------------------------------------------------------------
\r
50 ; The stack segment.
\r
51 ; The stack size is defined in the linker command file
\r
52 ;------------------------------------------------------------------------------
\r
56 RSEG CSTACK:DATA:ROOT(1)
\r
59 ;------------------------------------------------------------------------------
\r
60 ; The interrupt vector segment.
\r
61 ; Interrupt functions with defined vectors will reserve
\r
62 ; space in this area as well as conformingly written assembly
\r
63 ; language interrupt handlers
\r
64 ;------------------------------------------------------------------------------
\r
66 COMMON INTVEC:CODE:ROOT(1)
\r
68 DC16 __program_start_fr ; Reset vector
\r
71 ;------------------------------------------------------------------------------
\r
72 ; The actual startup code
\r
74 ; Entry: __program_start
\r
75 ;------------------------------------------------------------------------------
\r
77 RSEG RCODE:CODE:ROOT(0)
\r
80 PUBLIC `@cstart` ; NEC debugger specific
\r
81 PUBLIC __program_start_fr
\r
83 EXTERN __low_level_init
\r
86 #if defined(__STANDARD_MODEL__) || defined(__BANKED_MODEL__)
\r
87 EXTERN _CODEBANK_REG
\r
89 EXTERN _NEAR_CONST_LOCATION
\r
92 #if defined(__BANKED_MODEL__)
\r
93 EXTERN ?FAR_CALL_L07
\r
95 SFRTYPE BANK_REG BYTE, READ, WRITE = _CODEBANK_REG
\r
101 ;------------------------------------------------------------------------------
\r
102 ; Perform the run-time initialization.
\r
103 ;------------------------------------------------------------------------------
\r
107 __program_start_fr:
\r
110 #if defined(__BANKED_MODEL__)
\r
111 MOV BANK_REG, #0 ; Banked, clear bank register
\r
112 #elif defined(__STANDARD_MODEL__)
\r
113 MOVW AX, #_CODEBANK_REG
\r
115 BZ nobank ; Standard, no banked functions, no bank register (=0)
\r
116 MOVW HL, #_CODEBANK_REG
\r
118 MOV [HL], A ; Standard with banked functions, clear bank register
\r
121 MOV A, #(_NEAR_CONST_LOCATION & 1) ; Near/Far, set mirror area
\r
126 #if __CORE__ != __78K0S__
\r
127 MOVW SP, #sfe(CSTACK)
\r
129 MOVW AX, #sfe(CSTACK)
\r
134 ; Init stack segment for 78K0R, as the generated code may sometimes
\r
135 ; access the 4th byte of a return address before it is initialized
\r
136 #if __CORE__ == __78K0R__
\r
137 MOVW HL, #sfb(CSTACK)
\r
138 MOVW BC, #LWRD(sizeof(CSTACK))
\r
152 #if __CORE__ == __78K0R__
\r
156 ;------------------------------------------------------------------------------
\r
157 ; Here is the place to put user initializations.
\r
158 ;------------------------------------------------------------------------------
\r
160 ; User initialization code
\r
162 ;------------------------------------------------------------------------------
\r
163 ; Call __low_level_init to perform initialization before initializing
\r
164 ; segments and calling main.
\r
165 ; If the function returns 0, no segment initialization should take place.
\r
167 ; Link with your own version of __low_level_init to override the
\r
168 ; default action: to do nothing but return 1.
\r
169 ;------------------------------------------------------------------------------
\r
171 #if defined(__FAR_MODEL__)
\r
172 CALL F:__low_level_init
\r
173 #elif defined(__BANKED_MODEL__)
\r
174 MOV E, #byte3(__low_level_init)
\r
175 MOVW HL, #lwrd(__low_level_init)
\r
178 CALL __low_level_init
\r
181 #if __CORE__ == __78K0R__
\r
189 #if defined(__NEAR_MODEL__) || defined(__FAR_MODEL__)
\r
190 ;------------------------------------------------------------------------------
\r
191 ; Segment initialization
\r
193 ; FAR_Z "uninitialized far data" are filled with zero
\r
194 ;------------------------------------------------------------------------------
\r
196 MODULE ?__INIT_FAR_Z
\r
199 RSEG RCODE:CODE:NOROOT(0)
\r
201 PUBLIC __INIT_FAR_Z
\r
204 MOV ES, #BYTE3(sfb(FAR_Z))
\r
205 MOVW HL, #LWRD(sfb(FAR_Z))
\r
206 MOV D, #BYTE3(sizeof(FAR_Z))
\r
207 MOVW BC, #LWRD(sizeof(FAR_Z))
\r
234 ;------------------------------------------------------------------------------
\r
235 ; Segment initialization
\r
237 ; NEAR_Z "uninitialized near data" are filled with zero
\r
238 ;------------------------------------------------------------------------------
\r
240 MODULE ?__INIT_NEAR_Z
\r
242 RSEG NEAR_Z:DATA(0)
\r
243 RSEG RCODE:CODE:NOROOT(0)
\r
245 PUBLIC __INIT_NEAR_Z
\r
248 #if __CORE__ == __78K0R__
\r
249 LIMIT sfb(NEAR_Z)>=0xF0000,1,1,"NEAR_I not placed in near memory"
\r
251 MOVW HL, #sfb(NEAR_Z)
\r
252 MOVW BC, #sizeof(NEAR_Z)
\r
253 #if __CORE__ == __78K0R__
\r
269 #if __CORE__ == __78K0R__
\r
282 ;------------------------------------------------------------------------------
\r
283 ; Segment initialization
\r
285 ; SADDR_Z "uninitialized saddr data" are filled with zero
\r
286 ;------------------------------------------------------------------------------
\r
288 MODULE ?__INIT_SADDR_Z
\r
290 RSEG SADDR_Z:DATA(0)
\r
291 RSEG RCODE:CODE:NOROOT(0)
\r
293 PUBLIC __INIT_SADDR_Z
\r
296 #if __CORE__ == __78K0R__
\r
297 LIMIT sfb(SADDR_Z),0xFFE20,0xFFF1F,"SADDR_Z not within saddr memory range"
\r
298 LIMIT sfe(SADDR_Z),0xFFE20,0xFFF1F,"SADDR_Z not within saddr memory range"
\r
300 LIMIT sfb(SADDR_Z),0xFE20,0xFF1F,"SADDR_Z not within saddr memory range"
\r
301 LIMIT sfe(SADDR_Z),0xFE20,0xFF1F,"SADDR_Z not within saddr memory range"
\r
303 MOVW HL, #sfb(SADDR_Z)
\r
304 MOV B, #sizeof(SADDR_Z)
\r
305 #if __CORE__ == __78K0R__
\r
313 #if __CORE__ == __78K0R__
\r
323 ;------------------------------------------------------------------------------
\r
324 ; Segment initialization
\r
326 ; WRKSEG short address work area is filled with zero
\r
327 ;------------------------------------------------------------------------------
\r
329 MODULE ?__INIT_WRKSEG
\r
331 RSEG WRKSEG:DATA(0)
\r
332 RSEG RCODE:CODE:NOROOT(0)
\r
334 PUBLIC __INIT_WRKSEG
\r
337 #if __CORE__ == __78K0R__
\r
338 LIMIT sfb(WRKSEG),0xFFE20,0xFFF1F,"WRKSEG not within saddr memory range"
\r
339 LIMIT sfe(WRKSEG),0xFFE20,0xFFF1F,"WRKSEG not within saddr memory range"
\r
341 LIMIT sfb(WRKSEG),0xFE20,0xFF1F,"WRKSEG not within saddr memory range"
\r
342 LIMIT sfe(WRKSEG),0xFE20,0xFF1F,"WRKSEG not within saddr memory range"
\r
344 MOVW HL, #sfb(WRKSEG)
\r
345 MOV B, #sizeof(WRKSEG)
\r
346 #if __CORE__ == __78K0R__
\r
354 #if __CORE__ == __78K0R__
\r
364 #if defined(__NEAR_MODEL__) || defined(__FAR_MODEL__)
\r
365 ;------------------------------------------------------------------------------
\r
366 ; Segment initialization
\r
368 ; FAR_ID is copied to FAR_I "initialized far data"
\r
369 ;------------------------------------------------------------------------------
\r
371 MODULE ?__INIT_FAR_I
\r
374 RSEG FAR_ID:DATA(0)
\r
375 RSEG RCODE:CODE:NOROOT(0)
\r
377 PUBLIC __INIT_FAR_I
\r
380 ; First make sure FAR_I and FAR_ID have the same size
\r
381 LIMIT sizeof(FAR_I)-sizeof(FAR_ID),0,0,"FAR_I and FAR_ID not same size"
\r
384 LIMIT (sfb(FAR_I)-sfb(FAR_ID))==0,0,0,"FAR_I and FAR_ID have same start address"
\r
386 ; FAR_I and FAR_ID must start at the same offset in a 64k page, unless sizeof
\r
387 ; FAR_I is less than 64k, then it's enugh if both segments reside within a 64k
\r
389 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"
\r
393 ; 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"
\r
394 MOV ES, #BYTE3(sfb(FAR_ID))
\r
395 MOVW HL, #LWRD(sfb(FAR_ID))
\r
396 MOV CS, #BYTE3(sizeof(FAR_ID)) ; CS is used as counter
\r
397 MOVW AX, #LWRD(sizeof(FAR_ID))
\r
405 MOV A, #BYTE3(sfb(FAR_I))
\r
406 MOVW DE, #LWRD(sfb(FAR_I))
\r
438 ;------------------------------------------------------------------------------
\r
439 ; Segment initialization
\r
441 ; NEAR_ID is copied to NEAR_I "initialized near data"
\r
442 ;------------------------------------------------------------------------------
\r
444 MODULE ?__INIT_NEAR_I
\r
446 RSEG NEAR_I:DATA(0)
\r
447 RSEG NEAR_ID:DATA(0)
\r
448 RSEG RCODE:CODE:NOROOT(0)
\r
450 PUBLIC __INIT_NEAR_I
\r
453 #if __CORE__ == __78K0R__
\r
454 LIMIT sfb(NEAR_I)>=0xF0000,1,1,"NEAR_I not placed in near memory"
\r
456 LIMIT sizeof(NEAR_I)-sizeof(NEAR_ID),0,0,"NEAR_I and NEAR_ID not same size"
\r
457 #if __CORE__ == __78K0R__
\r
458 MOV ES, #BYTE3(sfb(NEAR_ID))
\r
460 MOVW HL, #sfb(NEAR_ID)
\r
461 MOVW BC, #sizeof(NEAR_ID)
\r
462 #if __CORE__ == __78K0R__
\r
473 MOVW DE, #sfb(NEAR_I)
\r
475 #if __CORE__ != __78K0R__
\r
483 #if __CORE__ == __78K0R__
\r
496 ;------------------------------------------------------------------------------
\r
497 ; Segment initialization
\r
499 ; SADDR_ID is copied to SADDR_I "initialized saddr data"
\r
500 ;------------------------------------------------------------------------------
\r
502 MODULE ?__INIT_SADDR_I
\r
504 RSEG SADDR_I:DATA(0)
\r
505 RSEG SADDR_ID:DATA(0)
\r
506 RSEG RCODE:CODE:NOROOT(0)
\r
508 PUBLIC __INIT_SADDR_I
\r
511 #if __CORE__ == __78K0R__
\r
512 LIMIT sfb(SADDR_I),0xFFE20,0xFFF1F,"SADDR_I not within saddr memory range"
\r
513 LIMIT sfe(SADDR_I),0xFFE20,0xFFF1F,"SADDR_I not within saddr memory range"
\r
515 LIMIT sfb(SADDR_I),0xFE20,0xFF1F,"SADDR_I not within saddr memory range"
\r
516 LIMIT sfe(SADDR_I),0xFE20,0xFF1F,"SADDR_I not within saddr memory range"
\r
518 LIMIT sizeof(SADDR_I)-sizeof(SADDR_ID),0,0,"SADDR_I and SADDR_ID not same size"
\r
519 #if __CORE__ == __78K0R__
\r
520 MOV ES, #BYTE3(sfb(SADDR_ID))
\r
522 MOVW HL, #sfb(SADDR_ID)
\r
523 MOV B, #sizeof(SADDR_ID)
\r
524 MOVW DE, #sfb(SADDR_I)
\r
526 #if __CORE__ != __78K0R__
\r
534 #if __CORE__ == __78K0R__
\r
544 ;------------------------------------------------------------------------------
\r
545 ; Initialize constructors
\r
547 ; This segment part is required by the compiler when it is
\r
548 ; necessary to call constructors of global objects.
\r
549 ;------------------------------------------------------------------------------
\r
551 MODULE ?__INIT_CTORS
\r
554 RSEG RCODE:CODE:NOROOT(0)
\r
556 PUBLIC __INIT_CTORS
\r
558 EXTERN __call_ctors
\r
559 #if defined(__BANKED_MODEL__)
\r
560 EXTERN ?FAR_CALL_L07
\r
564 #if __CORE__ == __78K0R__
\r
565 MOV X, #byte3(sfe(DIFUNCT))
\r
567 MOVW AX, #lwrd(sfe(DIFUNCT))
\r
569 MOV X, #byte3(sfb(DIFUNCT))
\r
571 MOVW AX, #lwrd(sfb(DIFUNCT))
\r
573 CALL F:__call_ctors
\r
574 #elif defined(__BANKED_MODEL__)
\r
575 MOVW AX, #sfb(DIFUNCT)
\r
576 MOVW BC, #sfe(DIFUNCT)
\r
577 MOV E, #byte3(__call_ctors)
\r
578 MOVW HL, #lwrd(__call_ctors)
\r
581 MOVW AX, #sfb(DIFUNCT)
\r
582 MOVW BC, #sfe(DIFUNCT)
\r
589 ;------------------------------------------------------------------------------
\r
592 ; Call the actual "main" function
\r
593 ;------------------------------------------------------------------------------
\r
595 MODULE ?__MAIN_CALL
\r
597 RSEG RCODE:CODE:NOROOT(0)
\r
600 PUBLIC `@cend` ; NEC debugger specific
\r
604 #if defined(__BANKED_MODEL__)
\r
605 EXTERN ?FAR_CALL_L07
\r
609 #if defined(__FAR_MODEL__)
\r
612 #elif defined(__BANKED_MODEL__)
\r
613 MOV E, #byte3(main)
\r
614 MOVW HL, #lwrd(main)
\r
617 MOV E, #byte3(exit)
\r
618 MOVW HL, #lwrd(exit)
\r
627 ; STOP ; Should not return
\r
632 ;------------------------------------------------------------------------------
\r
633 ; Low level initialization function
\r
635 ; Entry: __low_level_init
\r
637 ; The only action of this default version of '__low_level_init' is to
\r
638 ; return 1. By doing so it signals that normal initialization of data
\r
639 ; segments should be done.
\r
641 ; A customized version of '__low_level_init' may be created in order to
\r
642 ; perform initialization before initializing segments and calling main
\r
643 ; and/or to skip initialization of data segments under certain
\r
645 ;------------------------------------------------------------------------------
\r
647 MODULE ?__low_level_init_stub
\r
649 RSEG RCODE:CODE:NOROOT(0)
\r
651 PUBLIC __low_level_init
\r
653 __low_level_init: ; By returning 1 this function
\r
654 MOVW AX, #1 ; indicates that the normal
\r
655 RET ; initialization should take place
\r