|
| 1 | +/****************************************************************************** |
| 2 | + FILE : start08.c |
| 3 | + PURPOSE : 68HC08 standard startup code |
| 4 | + LANGUAGE : ANSI-C / INLINE ASSEMBLER |
| 5 | + ---------------------------------------------------------------------------- |
| 6 | + HISTORY |
| 7 | + 22 oct 93 Created. |
| 8 | + 04/17/97 Also C++ constructors called in Init(). |
| 9 | + ******************************************************************************/ |
| 10 | + |
| 11 | +/**********************************************************************/ |
| 12 | +/* NOTE: */ |
| 13 | +/* This version of the startup code assumes that main */ |
| 14 | +/* does never return (saving the 2 byte return address of _Startup on */ |
| 15 | +/* the stack). */ |
| 16 | +/**********************************************************************/ |
| 17 | + |
| 18 | +#define __NO_FLAGS_OFFSET /* we do not need the flags field in the startup data descriptor */ |
| 19 | +#define __NO_MAIN_OFFSET /* we do not need the main field in the startup data descriptor */ |
| 20 | + |
| 21 | +#include <start08.h> |
| 22 | + |
| 23 | +#ifdef __cplusplus |
| 24 | +#define __EXTERN_C extern "C" |
| 25 | +#else |
| 26 | +#define __EXTERN_C |
| 27 | +#endif |
| 28 | + |
| 29 | +__EXTERN_C extern void main(void); /* prototype of main function */ |
| 30 | + |
| 31 | +#include "non_bank.sgm" |
| 32 | + |
| 33 | + |
| 34 | +/***************************************************************************/ |
| 35 | +/* Macros to control how the startup code handles the COP: */ |
| 36 | +/* #define _DO_FEED_COP_ : do feed the COP */ |
| 37 | +/* Without defining any of these, the startup code does NOT handle the COP */ |
| 38 | +/***************************************************************************/ |
| 39 | +/* __ONLY_INIT_SP define: */ |
| 40 | +/* This define selects an shorter version of the startup code */ |
| 41 | +/* which only loads the stack pointer and directly afterwards calls */ |
| 42 | +/* main. This version does however NOT initialize global variables */ |
| 43 | +/* (so this version is not ANSI compliant!). */ |
| 44 | +/***************************************************************************/ |
| 45 | + |
| 46 | +#if defined(_DO_FEED_COP_) |
| 47 | +#define __FEED_COP_IN_HLI() } _FEED_COP(); __asm { |
| 48 | +#else |
| 49 | +#define __FEED_COP_IN_HLI() /* do nothing */ |
| 50 | +#endif |
| 51 | + |
| 52 | +#ifndef __ONLY_INIT_SP |
| 53 | + |
| 54 | +#pragma DATA_SEG FAR _STARTUP |
| 55 | +struct _tagStartup _startupData; /* read-only: |
| 56 | + _startupData is allocated in ROM and |
| 57 | + initialized by the linker */ |
| 58 | + |
| 59 | +#pragma MESSAGE DISABLE C20001 /* Warning C20001: Different value of stack pointer depending on control-flow */ |
| 60 | +/* the function _COPY_L releases some bytes from the stack internally */ |
| 61 | + |
| 62 | +#if defined(__OPTIMIZE_FOR_SIZE__) || defined(_DO_FEED_COP_) |
| 63 | +#pragma NO_ENTRY |
| 64 | +#pragma NO_EXIT |
| 65 | +#pragma NO_FRAME |
| 66 | +/*lint -esym(528, loadByte) inhibit warning about unreferenced loadByte function */ |
| 67 | +static void near loadByte(void) { |
| 68 | + asm { |
| 69 | + PSHH |
| 70 | + PSHX |
| 71 | +#ifdef __HCS08__ |
| 72 | + LDHX 5,SP |
| 73 | + LDA 0,X |
| 74 | + AIX #1 |
| 75 | + STHX 5,SP |
| 76 | +#else |
| 77 | + LDA 5,SP |
| 78 | + PSHA |
| 79 | + LDX 7,SP |
| 80 | + PULH |
| 81 | + LDA 0,X |
| 82 | + AIX #1 |
| 83 | + STX 6,SP |
| 84 | + PSHH |
| 85 | + PULX |
| 86 | + STX 5,SP |
| 87 | +#endif |
| 88 | + PULX |
| 89 | + PULH |
| 90 | + RTS |
| 91 | + } |
| 92 | +} |
| 93 | +#endif /* defined(__OPTIMIZE_FOR_SIZE__) || defined(_DO_FEED_COP_) */ |
| 94 | + |
| 95 | + |
| 96 | +#ifdef __cplusplus |
| 97 | +static void Call_Constructors(void) { |
| 98 | + int i; |
| 99 | +#ifdef __ELF_OBJECT_FILE_FORMAT__ |
| 100 | + i = (int)(_startupData.nofInitBodies - 1); |
| 101 | + while (i >= 0) { |
| 102 | + (&_startupData.initBodies->initFunc)[i](); /* call C++ constructors */ |
| 103 | + i--; |
| 104 | + } |
| 105 | +#else /* __ELF_OBJECT_FILE_FORMAT__ */ |
| 106 | + /* HIWARE object file format */ |
| 107 | + if (_startupData.mInits != NULL) { |
| 108 | + _PFunc *fktPtr; |
| 109 | + fktPtr = _startupData.mInits; |
| 110 | + while(*fktPtr != NULL) { |
| 111 | + (**fktPtr)(); /* call constructor */ |
| 112 | + fktPtr++; |
| 113 | + } |
| 114 | + } |
| 115 | +#endif /* __ELF_OBJECT_FILE_FORMAT__ */ |
| 116 | +} |
| 117 | +#endif |
| 118 | + |
| 119 | +/*lint -esym(752,_COPY_L) inhibit message on function declared, but not used (it is used in HLI) */ |
| 120 | +__EXTERN_C extern void _COPY_L(void); |
| 121 | +/* DESC: copy very large structures (>= 256 bytes) in 16-bit address space (stack incl.) |
| 122 | + IN: TOS count, TOS(2) @dest, H:X @src |
| 123 | + OUT: |
| 124 | + WRITTEN: X,H */ |
| 125 | +#ifdef __ELF_OBJECT_FILE_FORMAT__ |
| 126 | + #define toCopyDownBegOffs 0 |
| 127 | +#else |
| 128 | + #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 */ |
| 129 | +#endif |
| 130 | +static void Init(void) { |
| 131 | +/* purpose: 1) zero out RAM-areas where data is allocated |
| 132 | + 2) init run-time data |
| 133 | + 3) copy initialization data from ROM to RAM |
| 134 | + */ |
| 135 | + /*lint -esym(529,p,i) inhibit warning about symbols not used: it is used in HLI below */ |
| 136 | + int i; |
| 137 | + int *far p; |
| 138 | + |
| 139 | + asm { |
| 140 | +ZeroOut: |
| 141 | + LDA _startupData.nofZeroOuts:1 ; // nofZeroOuts |
| 142 | + INCA |
| 143 | + STA i:1 ; // i is counter for number of zero outs |
| 144 | + LDA _startupData.nofZeroOuts:0 ; // nofZeroOuts |
| 145 | + INCA |
| 146 | + STA i:0 |
| 147 | + LDHX _startupData.pZeroOut ; // *pZeroOut |
| 148 | + BRA Zero_5 |
| 149 | +Zero_3: |
| 150 | + ; // CLR i:1 is already 0 |
| 151 | +Zero_4: |
| 152 | + ; // { HX == _pZeroOut } |
| 153 | + PSHX |
| 154 | + PSHH |
| 155 | + ; // { nof bytes in (int)2,X } |
| 156 | + ; // { address in (int)0,X } |
| 157 | + LDA 0,X |
| 158 | + PSHA |
| 159 | + LDA 2,X |
| 160 | + INCA |
| 161 | + STA p ; // p:0 is used for high byte of byte counter |
| 162 | + LDA 3,X |
| 163 | + LDX 1,X |
| 164 | + PULH |
| 165 | + INCA |
| 166 | + BRA Zero_0 |
| 167 | +Zero_1: |
| 168 | + ; // CLRA A is already 0, so we do not have to clear it |
| 169 | +Zero_2: |
| 170 | + CLR 0,X |
| 171 | + AIX #1 |
| 172 | + __FEED_COP_IN_HLI() ; // it's necessary to feed the COP in the inner loop for the fast COP timeout of some derivatives |
| 173 | +Zero_0: |
| 174 | + DBNZA Zero_2 |
| 175 | +Zero_6: |
| 176 | + DBNZ p, Zero_1 |
| 177 | + PULH |
| 178 | + PULX ; // restore *pZeroOut |
| 179 | + AIX #4 ; // advance *pZeroOut |
| 180 | +Zero_5: |
| 181 | + DBNZ i:1, Zero_4 |
| 182 | + DBNZ i:0, Zero_3 |
| 183 | + |
| 184 | +CopyDown: |
| 185 | + |
| 186 | + } |
| 187 | + |
| 188 | + /* copy down */ |
| 189 | + /* _startupData.toCopyDownBeg ---> {nof(16) dstAddr(16) {bytes(8)}^nof} Zero(16) */ |
| 190 | +#if defined(__OPTIMIZE_FOR_SIZE__) || defined(_DO_FEED_COP_) /* for now: only -os version supports _DO_FEED_COP_ */ |
| 191 | + asm { |
| 192 | +#ifdef __HCS08__ |
| 193 | + LDHX _startupData.toCopyDownBeg:toCopyDownBegOffs |
| 194 | + PSHX |
| 195 | + PSHH |
| 196 | +#else |
| 197 | + LDA _startupData.toCopyDownBeg:(1+toCopyDownBegOffs) |
| 198 | + PSHA |
| 199 | + LDA _startupData.toCopyDownBeg:(0+toCopyDownBegOffs) |
| 200 | + PSHA |
| 201 | +#endif |
| 202 | +Loop0: |
| 203 | + JSR loadByte ; // load high byte counter |
| 204 | + TAX ; // save for compare |
| 205 | + INCA |
| 206 | + STA i |
| 207 | + JSR loadByte ; // load low byte counter |
| 208 | + INCA |
| 209 | + STA i:1 |
| 210 | + DECA |
| 211 | + BNE notfinished |
| 212 | + CBEQX #0, finished |
| 213 | +notfinished: |
| 214 | + |
| 215 | + JSR loadByte ; // load high byte ptr |
| 216 | + PSHA |
| 217 | + PULH |
| 218 | + JSR loadByte ; // load low byte ptr |
| 219 | + TAX ; // HX is now destination pointer |
| 220 | + BRA Loop1 |
| 221 | +Loop3: |
| 222 | +Loop2: |
| 223 | + __FEED_COP_IN_HLI() |
| 224 | + JSR loadByte ; // load data byte |
| 225 | + STA 0,X |
| 226 | + AIX #1 |
| 227 | +Loop1: |
| 228 | + DBNZ i:1, Loop2 |
| 229 | + DBNZ i:0, Loop3 |
| 230 | + BRA Loop0 |
| 231 | + |
| 232 | +finished: |
| 233 | + AIS #2 |
| 234 | + } |
| 235 | +#else /*defined(__OPTIMIZE_FOR_SIZE__) || defined(_DO_FEED_COP_) */ |
| 236 | + /* time optimized asm version. */ |
| 237 | + asm { |
| 238 | +#ifdef __HCS08__ |
| 239 | + LDHX _startupData.toCopyDownBeg:toCopyDownBegOffs |
| 240 | +#else |
| 241 | + LDX _startupData.toCopyDownBeg:(0+toCopyDownBegOffs) |
| 242 | + PSHX |
| 243 | + PULH |
| 244 | + LDX _startupData.toCopyDownBeg:(1+toCopyDownBegOffs) |
| 245 | +#endif |
| 246 | +next: |
| 247 | + LDA 0,X ; // list is terminated by 2 zero bytes |
| 248 | + ORA 1,X |
| 249 | + BEQ copydone |
| 250 | + PSHX ; // store current position |
| 251 | + PSHH |
| 252 | + LDA 3,X ; // psh dest low |
| 253 | + PSHA |
| 254 | + LDA 2,X ; // psh dest high |
| 255 | + PSHA |
| 256 | + LDA 1,X ; // psh cnt low |
| 257 | + PSHA |
| 258 | + LDA 0,X ; // psh cnt high |
| 259 | + PSHA |
| 260 | + AIX #4 |
| 261 | + JSR _COPY_L ; // copy one block |
| 262 | + PULH |
| 263 | + PULX |
| 264 | + TXA |
| 265 | + ADD 1,X ; // add low |
| 266 | + PSHA |
| 267 | + PSHH |
| 268 | + PULA |
| 269 | + ADC 0,X ; // add high |
| 270 | + PSHA |
| 271 | + PULH |
| 272 | + PULX |
| 273 | + AIX #4 |
| 274 | + BRA next |
| 275 | +copydone: |
| 276 | + } |
| 277 | +#endif /* defined(__OPTIMIZE_FOR_SIZE__) || defined(_DO_FEED_COP_) */ |
| 278 | + |
| 279 | + /* FuncInits: for C++, this are the global constructors */ |
| 280 | +#ifdef __cplusplus |
| 281 | + Call_Constructors(); |
| 282 | +#endif /* __cplusplus */ |
| 283 | + |
| 284 | + /* implement ROM libraries initialization here (see startup.c) */ |
| 285 | +} |
| 286 | +#endif /* __ONLY_INIT_SP */ |
| 287 | + |
| 288 | + |
| 289 | +#pragma NO_EXIT |
| 290 | +__EXTERN_C void _Startup(void) { |
| 291 | +/* set the reset vector to _Startup in the linker parameter file (*.prm): |
| 292 | + 'VECTOR 0 _Startup' |
| 293 | +
|
| 294 | + purpose: 1) initialize the stack |
| 295 | + 2) initialize run-time, ... |
| 296 | + initialize the RAM, copy down init data, etc (Init) |
| 297 | + 3) call main; |
| 298 | + called from: _PRESTART-code generated by the Linker |
| 299 | +*/ |
| 300 | + INIT_SP_FROM_STARTUP_DESC(); |
| 301 | +#ifndef __ONLY_INIT_SP |
| 302 | + Init(); |
| 303 | +#endif |
| 304 | +#ifndef __BANKED__ |
| 305 | + __asm JMP main; /* with a C style main(); we would push the return address on the stack wasting 2 RAM bytes */ |
| 306 | +#else |
| 307 | + __asm CALL main; |
| 308 | +#endif |
| 309 | +} |
0 commit comments