/****************************************************************************** FILE : start08.c PURPOSE : 68HC08 standard startup code LANGUAGE : ANSI-C / INLINE ASSEMBLER ---------------------------------------------------------------------------- HISTORY 22 oct 93 Created. 04/17/97 Also C++ constructors called in Init(). ******************************************************************************/ /**********************************************************************/ /* NOTE: */ /* This version of the startup code does assumes that main */ /* does never return (saving the 2 byte return address of _Startup on */ /* the stack). */ /**********************************************************************/ #define __NO_FLAGS_OFFSET /* we do not need the flags field in the startup data descriptor */ #define __NO_MAIN_OFFSET /* we do not need the main field in the startup data descriptor */ #include #ifdef __cplusplus #define __EXTERN_C extern "C" #else #define __EXTERN_C #endif /**********************************************************************/ /* __ONLY_INIT_SP define: */ /* This define selects an shorter version of the startup code */ /* which only loads the stack pointer and directly afterwards calls */ /* main. This version does however NOT initialized global variables */ /* (So this version is not ANSI compliant!) */ /**********************************************************************/ #ifndef __ONLY_INIT_SP #pragma DATA_SEG FAR _STARTUP struct _tagStartup _startupData; /* read-only: _startupData is allocated in ROM and initialized by the linker */ #pragma MESSAGE DISABLE C20001 /* Warning C20001: Different value of stackpointer depending on control-flow */ /* the function _COPY_L releases some bytes from the stack internally */ #ifdef __OPTIMIZE_FOR_SIZE__ #pragma NO_ENTRY #pragma NO_EXIT #pragma NO_FRAME /*lint -esym(528, loadByte) inhibit warning about not referenced loadByte function */ static void near loadByte(void) { asm { PSHH PSHX #ifdef __HCS08__ LDHX 5,SP LDA 0,X AIX #1 STHX 5,SP #else LDA 5,SP PSHA LDX 7,SP PULH LDA 0,X AIX #1 STX 6,SP PSHH PULX STX 5,SP #endif PULX PULH RTS } } #endif /* __OPTIMIZE_FOR_SIZE__ */ /*lint -esym(752,_COPY_L) inhibit message on dunction declared, but not used (it is used in HLI) */ __EXTERN_C extern void _COPY_L(void); /* DESC: copy very large structures (>= 256 bytes) in 16 bit address space (stack incl.) IN: TOS count, TOS(2) @dest, H:X @src OUT: WRITTEN: X,H */ #ifdef __ELF_OBJECT_FILE_FORMAT__ #define toCopyDownBegOffs 0 #else #define toCopyDownBegOffs 2 /* for the hiware format, the toCopyDownBeg field is a long. Because the HC08 is big endian, we have to use an offset of 2 */ #endif static void Init(void) { /* purpose: 1) zero out RAM-areas where data is allocated 2) init run-time data 3) copy initialization data from ROM to RAM */ /*lint -esym(529,p,i) inhibit warning about symbols not used: it is used in HLI below */ int i; int *far p; asm { ZeroOut: ; LDA _startupData.nofZeroOuts:1 ; nofZeroOuts INCA STA i:1 ; i is counter for number of zero outs LDA _startupData.nofZeroOuts:0 ; nofZeroOuts INCA STA i:0 LDHX _startupData.pZeroOut ; *pZeroOut BRA Zero_5 Zero_3: ; ; CLR i:1 is already 0 Zero_4: ; ; { HX == _pZeroOut } PSHX PSHH ; { nof bytes in (int)2,X } ; { address in (int)0,X } LDA 0,X PSHA LDA 2,X INCA STA p ; p:0 is used for high byte of byte counter LDA 3,X LDX 1,X PULH INCA BRA Zero_0 Zero_1: ; ; CLRA A is already 0, so we do not have to clear it Zero_2: ; CLR 0,X AIX #1 Zero_0: ; DBNZA Zero_2 Zero_6: DBNZ p, Zero_1 PULH PULX ; restore *pZeroOut AIX #4 ; advance *pZeroOut Zero_5: ; DBNZ i:1, Zero_4 DBNZ i:0, Zero_3 ; CopyDown: ; } /* copy down */ /* _startupData.toCopyDownBeg ---> {nof(16) dstAddr(16) {bytes(8)}^nof} Zero(16) */ #if defined(__OPTIMIZE_FOR_SIZE__) asm { #ifdef __HCS08__ LDHX _startupData.toCopyDownBeg:toCopyDownBegOffs PSHX PSHH #else LDA _startupData.toCopyDownBeg:(1+toCopyDownBegOffs) PSHA LDA _startupData.toCopyDownBeg:(0+toCopyDownBegOffs) PSHA #endif Loop0: JSR loadByte ; load high byte counter TAX ; save for compare INCA STA i JSR loadByte ; load low byte counter INCA STA i:1 DECA BNE notfinished CBEQX #0, finished notfinished: JSR loadByte ; load high byte ptr PSHA PULH JSR loadByte ; load low byte ptr TAX ; HX is now destination pointer BRA Loop1 Loop3: Loop2: JSR loadByte ; load data byte STA 0,X AIX #1 Loop1: DBNZ i:1, Loop2 DBNZ i:0, Loop3 BRA Loop0 finished: AIS #2 }; #else /* defined(__OPTIMIZE_FOR_SIZE__) time optimized asm version. */ asm { #ifdef __HCS08__ LDHX _startupData.toCopyDownBeg:toCopyDownBegOffs #else LDX _startupData.toCopyDownBeg:(0+toCopyDownBegOffs) PSHX PULH LDX _startupData.toCopyDownBeg:(1+toCopyDownBegOffs) #endif next: LDA 0,X ; list is terminated by 2 zero bytes ORA 1,X BEQ copydone PSHX ; store current position PSHH LDA 3,X ; psh dest low PSHA LDA 2,X ; psh dest high PSHA LDA 1,X ; psh cnt low PSHA LDA 0,X ; psh cnt high PSHA AIX #4 JSR _COPY_L ; copy one block PULH PULX TXA ADD 1,X ; add low PSHA PSHH PULA ADC 0,X ; add high PSHA PULH PULX AIX #4 BRA next copydone: }; #endif /* defined(__OPTIMIZE_FOR_SIZE__) */ /* FuncInits: for C++, this are the global constructors */ #ifdef __cplusplus #ifdef __ELF_OBJECT_FILE_FORMAT__ i = (int)(_startupData.nofInitBodies - 1); while (i >= 0) { (&_startupData.initBodies->initFunc)[i](); /* call C++ constructors */ i--; } #else /* __ELF_OBJECT_FILE_FORMAT__ */ /* HIWARE object file format */ if (_startupData.mInits != NULL) { _PFunc *fktPtr; fktPtr = _startupData.mInits; while(*fktPtr != NULL) { (**fktPtr)(); /* call constructor */ fktPtr++; } } #endif /* __ELF_OBJECT_FILE_FORMAT__ */ #endif /* __cplusplus */ /* implement ROM libraries initialization here (see startup.c) */ } #endif /* __ONLY_INIT_SP */ __EXTERN_C extern void main(void); /* prototype of main function */ #pragma NO_EXIT __EXTERN_C void _Startup(void) { /* set the reset vector to _Startup in the linker parameter file (*.prm): 'VECTOR 0 _Startup' purpose: 1) initialize the stack 2) initialize run-time, ... initialize the RAM, copy down init dat etc (Init) 3) call main; called from: _PRESTART-code generated by the Linker */ INIT_SP_FROM_STARTUP_DESC(); #ifndef __ONLY_INIT_SP Init(); #endif __asm JMP main; /* with a C style main(); we would push the return address on the stack wasting 2 RAM bytes */ }