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