📄 start08.c
字号:
/******************************************************************************
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().
******************************************************************************/
#include "hidef.h"
#include "start08.h"
/**********************************************************************/
#pragma DATA_SEG FAR _STARTUP
struct _tagStartup _startupData; /* read-only:
_startupData is allocated in ROM and
initialized by the linker */
#define USE_C_IMPL 0 /* for now, we are using the inline assembler implementation for the startup code */
#if !USE_C_IMPL
#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 */
#pragma NO_ENTRY
#pragma NO_EXIT
#pragma NO_FRAME
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
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
*/
int i;
int *far p;
#if USE_C_IMPL /* C implementation of ZERO OUT and COPY Down */
int j;
char *dst;
_Range *far r;
r = _startupData.pZeroOut;
/* zero out */
for (i=0; i != _startupData.nofZeroOuts; i++) {
dst = r->beg;
j = r->size;
do {
*dst = 0; /* zero out */
dst++;
j--;
} while(j != 0);
r++;
}
#else /* faster and smaller asm implementation for ZERO OUT */
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: ;
}
#endif
/* copy down */
/* _startupData.toCopyDownBeg ---> {nof(16) dstAddr(16) {bytes(8)}^nof} Zero(16) */
#if USE_C_IMPL /* (optimized) C implementation of COPY DOWN */
p = (int*far)_startupData.toCopyDownBeg;
for (;;) {
i = *p; /* nof */
if (i == 0) {
break;
}
dst = (char*far)p[1]; /* dstAddr */
p+=2;
do {
/* p points now into 'bytes' */
*dst = *((char*far)p); /* copy byte-wise */
((char*far)p)++;
dst++;
i--;
} while (i!= 0);
}
#elif 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 /* optimized asm version. Some bytes (ca 3) larger than C version (when considering the runtime routine too), but about 4 times faster */
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
/* FuncInits: for C++, this are the global constructors */
#ifdef __cplusplus
#ifdef __ELF_OBJECT_FILE_FORMAT__
i = _startupData.nofInitBodies - 1;
while ( i >= 0) {
(&_startupData.initBodies->initFunc)[i](); /* call C++ constructors */
i--;
}
#else
if (_startupData.mInits != NULL) {
_PFunc *fktPtr;
fktPtr = _startupData.mInits;
while(*fktPtr != NULL) {
(**fktPtr)(); /* call constructor */
fktPtr++;
}
}
#endif
#endif
/* LibInits: used only for ROM libraries */
}
#pragma NO_EXIT
#ifdef __cplusplus
extern "C"
#endif
void _Startup (void) { /* To set in the linker parameter file: '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
*/
#ifdef __ELF_OBJECT_FILE_FORMAT__
DisableInterrupts; /* in HIWARE format, this is done in the prestart code */
#endif
for (;;) { /* forever: initialize the program; call the root-procedure */
if (!(_startupData.flags&STARTUP_FLAGS_NOT_INIT_SP)) {
/* initialize the stack pointer */
INIT_SP_FROM_STARTUP_DESC();
}
Init();
(*_startupData.main)();
} /* end loop forever */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -