-
Notifications
You must be signed in to change notification settings - Fork 0
/
Start08.c
309 lines (282 loc) · 9.79 KB
/
Start08.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/******************************************************************************
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 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 <start08.h>
#ifdef __cplusplus
#define __EXTERN_C extern "C"
#else
#define __EXTERN_C
#endif
__EXTERN_C extern void main(void); /* prototype of main function */
#include "non_bank.sgm"
/***************************************************************************/
/* Macros to control how the startup code handles the COP: */
/* #define _DO_FEED_COP_ : do feed the COP */
/* Without defining any of these, the startup code does NOT handle the COP */
/***************************************************************************/
/* __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 initialize global variables */
/* (so this version is not ANSI compliant!). */
/***************************************************************************/
#if defined(_DO_FEED_COP_)
#define __FEED_COP_IN_HLI() } _FEED_COP(); __asm {
#else
#define __FEED_COP_IN_HLI() /* do nothing */
#endif
#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 stack pointer depending on control-flow */
/* the function _COPY_L releases some bytes from the stack internally */
#if defined(__OPTIMIZE_FOR_SIZE__) || defined(_DO_FEED_COP_)
#pragma NO_ENTRY
#pragma NO_EXIT
#pragma NO_FRAME
/*lint -esym(528, loadByte) inhibit warning about unreferenced 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 /* defined(__OPTIMIZE_FOR_SIZE__) || defined(_DO_FEED_COP_) */
#ifdef __cplusplus
static void Call_Constructors(void) {
int i;
#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
/*lint -esym(752,_COPY_L) inhibit message on function 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
__FEED_COP_IN_HLI() ; // it's necessary to feed the COP in the inner loop for the fast COP timeout of some derivatives
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__) || defined(_DO_FEED_COP_) /* for now: only -os version supports _DO_FEED_COP_ */
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:
__FEED_COP_IN_HLI()
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__) || defined(_DO_FEED_COP_) */
/* 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__) || defined(_DO_FEED_COP_) */
/* FuncInits: for C++, this are the global constructors */
#ifdef __cplusplus
Call_Constructors();
#endif /* __cplusplus */
/* implement ROM libraries initialization here (see startup.c) */
}
#endif /* __ONLY_INIT_SP */
#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 data, etc (Init)
3) call main;
called from: _PRESTART-code generated by the Linker
*/
INIT_SP_FROM_STARTUP_DESC();
#ifndef __ONLY_INIT_SP
Init();
#endif
#ifndef __BANKED__
__asm JMP main; /* with a C style main(); we would push the return address on the stack wasting 2 RAM bytes */
#else
__asm CALL main;
#endif
}