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