⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 __ppc_eabi_init.c

📁 mpc55**系列芯片的例程 包括SCI,SPI,TIMER,FIT,EDMA等几乎所有功能的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
1.  The MEMORY directive now supports 
addr_mode = external | internal // default is internal
addr_mode is ignored unless you have chosen the SDA PIC/PID ABI in the EPPC 
Target Pref panel.

2. New directives INTERNAL_SYMBOL and EXTERNAL_SYMBOL can be used to force
the addressing of global symbols.  These directives are of the 
form XXXL_SYMBOL { sym1, sym2, symN } where the symbols are the link time
symbol names (mangled for c++).

The auto-generated linker defined start and end symbols for loadable 
segments are internal if they are addresses into internal segments and 
external if they are for external segments.  All other linker defined 
symbols you create in a lcf are considered external unless you redefine
them with INTERNAL_SYMBOL.  The linker also defines some linker defined 
symbols for its own use and they have the following default settings:

_stack_addr [top of the stack - comes from pref panel settings] external
_stack_end [bottom of the stack - comes from pref panel settings] external
_heap_addr [bottom of the heap - comes from pref panel settings] external
_heap_end [top of the heap - comes from pref panel settings] external
// the next two need to be treated as internal to be EABI compliant so
// you may not redefine them.
_SDA_BASE_ [.sdata + 0x00008000] internal
_SDA2_BASE_ [.sdata2 + 0x00008000] internal
// The previous small data pointers rely on the small data registers being
// properly initialized before being accessible.  However, it is hard to
// initialize those pointers without accessing them as absolutes.
// The following two symbols are external versions of _SDA_BASE_ and
// _SDA2_BASE_ which can be used as absolutes.  You may not redefine them.
_ABS_SDA_BASE_ [.sdata + 0x00008000] external
_ABS_SDA2_BASE_ [.sdata2 + 0x00008000] external
// the following are numbers, not addresses and they must be treated
// as external.  You may not redefine them.
_nbfunctions [number of functions in program - deprecated] external
SIZEOF_HEADERS [size of the segment headers in a linux app] external

Especially note that the stack and heap linker generated symbols are
external.  It may be more practical in a SDA PIC/PID application to
make the heap and stack be contiguous with an internal segment and
define them as internal.

*** Uses for SDA PIC/PID ***

The runtime was developed for 3 different situations:

1. All code and data segments are internal.  The simplest case would be
for all segments to use the same MEMORY directive and to have all of the 
bss type segments at the end.  In such a simple case, the application could
be converted to a binary file and linked into another application which
could copy it to ram and jump to its entry point.

2. All of the essential segments are internal and therefore moveable but 
there may be some external segments which are absolute.  This situation is 
probably difficult to test but you can download the entire application
to the chip and at least debug it at its link time addresses.

3. Like 2, there are internal and external segments but the application is 
linked as a ROM image - the application does not need to be flashed to
ROM, however.  It is possible to change the ROM Image Address to be an
address into RAM and have the debugger download the image to the RAM 
address.  Alternatively, you could have the ROM image converted to a bin
file and link it into another application as in 1, above.  The structures 
used in __init_data(), _rom_copy_info and __bss_init_info, have been 
modified for SDA PIC/PID to have an extra field which tells the runtime 
where the segment is internal or external so that the internal segments 
will be copied to position relative addresses and the external segments 
will be copied to absolute addresses.

*** Compiler/Linker support for SDA Addressing ***
You build a SDA PIC/PID application by selecting SDA PIC/PID in the ABI
popup in the EPPC Target Preference panel.  When you chose that, the 
compiler will define a simple that you can use to guard PIC/PID source.

#if __option(sda_pic_pid) // is true if you have chosen SDA PIC/PID ABI

If you then link, the linker will generate a table for the runtime files
__ppc_eabi_init.cpp/__ppc_eabi_init.c to use.  If your application has
absolute addressing relocations (which it would by default) you will
probably get linker warnings telling you that those relocations may
cause a problem.  If that happens, you have two choices.  You can change
the Code Model popup in the EPPC Target Preference panel to be
SDA Based PIC/PID Addressing for all of your sources and libraries, and/or
check the Tune Relocations checkbox in the EPPC Target Preference panel.
This new option is only available for the EABI and SDA PIC/PID ABIs.  For
EABI it changes 14 bit branch relocations to 24 bit branch relocations
only if they can not reach the calling site from the original relocation.
For SDA PIC/PID, it changes absolute addressed references of data from
code to use a small data register instead of r0 and changes absolute
code to code refernces to use the pc relative relocations.  In general,
this will work well for normnal compiled code.  It is always possible
to link in an assembly file that does not behave in a standard way.

Whether you use the Code Model SDA Based PIC/PID Addressing or not,
#pragma section has been modified to accept far_sda_rel for the data_mode
and code_mode options.  If you leave those options out, the compiler
will you the Code Model to determine the appropriate modes.

Absolute Addressing defaults to data_mode = far_abs and code_mode = pc_rel.
SDA Based PIC/PID Addressing defaults to data_mode = far_sda_rel and
code_mode = pc_rel.

***************************************************************************/

/***************************************************************************/
/*
 *	__get_runtime_linktime_delta
 *
 *	Assumes that r13 and r2 are initialized correctly and that they always
 *	stay in the same relationship to each other.
 *
 *	Utility function to get difference between runtime and linktime addresses.
 *
 */
/***************************************************************************/
static asm int __get_runtime_linktime_delta(void)
{
	nofralloc
    /* _ABS_SDA_BASE_, generated by the linker, is the same value as 		 	*/
	/* _SDA_BASE_ but forces the linker to treat it as absolutetly addressed 	*/
	/* and not to substitute r13 for r0.  We therefore end up with r3 exactly 	*/
	/* as calculated at linktime. 												*/
	addis	r3, r0, _ABS_SDA_BASE_@ha
	addi	r3, r3, _ABS_SDA_BASE_@l
   	/* Subtract the runtime from the linktime address.							*/
   	sub		r3,r13,r3
	blr
}

/***************************************************************************/
/*
 *	__mwerks_fixup_relocations
 *
 *	Modify initialized pointers in the data sections to reflect correct
 *	runtime addresses.  The linker created a table, _f_mwerks_fixup, of 
 *	offsets into the data sections that need modification.  This function
 *	loads the pointer at that offset and applies the runtime/linktime
 *	delta.  We wait to call this function until after __init_data.
 *
 */
/***************************************************************************/
static asm void __mwerks_fixup_relocations(void)
{
	nofralloc
	
	/* r13, r2, and r1 have their correct runtime values.						*/

    mflr    r0

   	/* If runtime and linktime addresses are the same, no fixup is necessary.	*/
   	bl		__get_runtime_linktime_delta
    cmpli   cr0,r3,0
    beq     no_fixup

	/* Initialize runtime addresses of the fixup table.  _f_mwerks_fixup is the	*/
	/* beginning of the table and _e_mwerks_fixup is the end.  Note that r0 	*/
	/* will get converted to r13 or r2 by the linker. 							*/
    addis   r5,r0,_f_mwerks_fixup@ha
    addis   r4,r0,_e_mwerks_fixup@ha
    addi    r5,r5,_f_mwerks_fixup@l
    addi    r4,r4,_e_mwerks_fixup@l

    /* Compute number of entries ((_e_mwerks_fixup - _f_mwerks_fixup) / 4).		*/
    subf    r6,r5,r4			
    /* If there are no entries, bail.											*/
    cmpli   cr0,r6,0
    beq     no_fixup
    srwi    r6,r6,2
    mtctr   r6
	/* We use pre-increment, so move to first real entry - 4.					*/
    subi    r5,r5,4
fixup_loop:
	/* Load address of relocation.												*/
    lwzu    r6,4(r5)
    /* Update address using SDA delta.											*/
    add     r6,r6,r3
    /* Load value at relocation.												*/
    lwz	    r7,0(r6)
    /* Update value using SDA delta.											*/
    add     r7,r7,r3
    /* Store updated value.														*/
    stw	    r7,0(r6)
    bdnz    fixup_loop
no_fixup:
    mtlr    r0
    blr
}

/***************************************************************************/
/*
 *	__init_registers
 *
 *	Initialize PowerPC EABI Registers
 *
 *	Note: this function is guaranteed to not reference any memory; the memory
 *	controller may not be initialized.
 *
 *	we now overload the function in the event that the user wants pic pid
 *
 */
/***************************************************************************/
asm extern void __init_registers(void)
{
	nofralloc						/* see above on usage of nofralloc */

    mflr    r0

	/* _ABS_SDA_BASE_, generated by the linker, is the same value as 		 	*/
	/* _SDA_BASE_ but forces the linker to treat it as absolutetly addressed 	*/
	/* and not to substitute r13 for r0.  We therefore end up with r13 exactly 	*/
	/* as calculated at linktime. 												*/
	addis	r13, r0, _ABS_SDA_BASE_@ha
	addi	r13, r13, _ABS_SDA_BASE_@l

	/* _ABS_SDA2_BASE_, generated by the linker, is the same value as 		 	*/
	/* _SDA2_BASE_ but forces the linker to treat it as absolutetly addressed 	*/
	/* and not to substitute r2 for r0.  We therefore end up with r2 exactly 	*/
	/* as calculated at linktime. 												*/
	addis	r2, r0, _ABS_SDA2_BASE_@ha
	addi	r2, r2, _ABS_SDA2_BASE_@l
   
	/* Grab the runtime address of __get_linktime_address.  The bcl will put	*/
	/* __get_linktime_address into LR. */
	bcl 	20,31,__get_linktime_address
entry __get_linktime_address
	/* Move runtime address of __get_linktime_address from LR to r4. */
	mflr	r4

	/* Grab the linktime address of __get_linktime_address.  Note that r0 will	*/
	/* get converted to r13 or r2 by the linker but because r13 and r2 may not	*/
	/* reflect the their runtime values yet, r3 might not equal r4.				*/
    addis   r3,r0,__get_linktime_address@ha
    addi    r3,r3,__get_linktime_address@l
    
   	/* Subtract the runtime from the linktime address.							*/
   	sub		r3,r4,r3
   	/* If runtime and linktime addresses are the same, no fixup is necessary.	*/
    cmpli   cr0,r3,0
    beq     no_fixup

   	/* Add the delta into small data pointers so they will reflect the current 	*/
   	/* position of code and data.												*/
   	add		r13,r13,r3
   	add		r2,r2,r3
no_fixup:

	/* Initialize runtime address of _stack_addr.  Note that r0 will			*/
	/* get converted to r13 or r2 by the linker if _stack_addr is 				*/
	/* treated as an internal symbol (default is external).						*/
	addis	r1, r0, _stack_addr@ha
	addi	r1, r1, _stack_addr@l
    mtlr    r0

	blr
}

/***************************************************************************/
/*
 *	__init_data
 *
 *	Initialize all (RAM) data sections, copying ROM sections as necessary.
 *
 *	dst			destination RAM address
 *	size		number of bytes to zero
 *
 *	we now overload the function in the event that the user wants pic pid
 *
 */
/***************************************************************************/
extern void __init_data(void)
{
	__pic_rom_copy_info *dci;
	__pic_bss_init_info *bii;
	int					delta = __get_runtime_linktime_delta();
	unsigned int		size;
	unsigned char 		*ram_addr;		/* address in ram (executing address) */
	unsigned char 		*ram_end;		/* end address in ram (executing address) */
	unsigned char 		*rom_addr;		/* address in rom */
	unsigned char 		*rom_end;		/* end address in rom */
	int					internal;
		
	/* for sda pic pid, if ram_end and ram_addr are swapped so that ram_end < ram_addr, 		*/
	/* then segment is internal, otherwise it is external.  for eabi, addresses are external 	*/

	dci = _pic_rom_copy_info;
	while (1) {
		if (dci->rom_addr == 0 && dci->ram_addr == 0 && dci->ram_end == 0) break;
		internal = (dci->rom_end < dci->rom_addr);
		if (internal) {
			rom_addr = dci->rom_end + delta;
			rom_end = dci->rom_addr + delta;
		} else {
			rom_addr = dci->rom_addr;
			rom_end = dci->rom_end;
		}
		internal = (dci->ram_end < dci->ram_addr);
		if (internal) {
			ram_addr = dci->ram_end + delta;
			ram_end = dci->ram_addr + delta;
		} else {
			ram_addr = dci->ram_addr;
			ram_end = dci->ram_end;
		}
		size = (unsigned int) (ram_end - ram_addr);
 		__copy_rom_section(ram_addr, rom_addr, size);
 		dci++;
	}
 
 	/* Initialize with zeros: */

	bii = _pic_bss_init_info;
	while (1) {
		if (bii->ram_addr == 0 && bii->ram_end == 0) break;
		internal = (bii->ram_end < bii->ram_addr);
		if (internal) {
			ram_addr = bii->ram_end + delta;
			ram_end = bii->ram_addr + delta;
		} else {
			ram_addr = bii->ram_addr;
			ram_end = bii->ram_end;
		}
		size = (unsigned int) (ram_end - ram_addr);
 		__init_bss_section(ram_addr, size);
 		bii++;
	}
	
	/* now that data is copied to ram, we can fix up initialized pointers */
	__mwerks_fixup_relocations();	
}

/***************************************************************************/
/*
 *	__exception_info_constants
 *
 *	Called from __init_cpp_exceptions.cpp
 *
 *	info		address of linker generated exception table info
 *	R2			address of variable to hold the value in r2
 *
 *	we now overload the function in the event that the user wants pic pid
 *
 */
/***************************************************************************/
extern void __exception_info_constants(void **info, char **R2)
{
	register char *temp;				/* r2 register contents								*/

	asm {
		mr      temp,r2
	}
	*R2 = temp;
	
	*info = _pic_eti_init_info;
}

/***************************************************************************/
/*
 *	__find_exception_addresses
 *
 *	Called from ExceptionPPC.cp
 *
 *	info		address of linker generated exception table info
 *	returnaddr	address within a code segment
 *	returnaddr	address within a code segment
 *	ex_start	address of variable to hold address of exception table info
 *	ex_end		address of variable to hold end address of exception table info
 *
 *	we now overload the function in the event that the user wants pic pid
 *
 */
/***************************************************************************/
extern int __find_exception_addresses(void *info, char *returnaddr, void **ex_start, void **ex_end)
{
	__pic_eti_init_info	*eti_info = (__pic_eti_init_info*)info;
	unsigned char		*start;			/* address */
	unsigned char		*end;			/* end address */
	int					internal;
	int					delta = __get_runtime_linktime_delta();
	
	while (1) {
		if (eti_info->code_end - eti_info->code_start == 0) break;
		internal = (eti_info->code_end < eti_info->code_start);
		if (internal) {
			start = eti_info->code_end + delta;
			end = eti_info->code_start + delta;
		} else {
			start = eti_info->code_start;
			end = eti_info->code_end;
		}
		if((unsigned char*)returnaddr>=start && (unsigned char*)returnaddr<end) {
			internal = (eti_info->eti_end < eti_info->eti_start);
			if (internal) {
				start = eti_info->eti_end + delta;
				end = eti_info->eti_start + delta;
			} else {
				start = eti_info->eti_start;
				end = eti_info->eti_end;
			}
			*ex_start = start;
			*ex_end = end;
			return(1);
		}
 		eti_info++;
	}
	
	return(0);
}


#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -