/* Copyright (C) 2010 Texas Instruments Incorporated * Contributed by Mark Salter * * Borrowed heavily from frv arch: * Copyright (C) 2003 Red Hat, Inc. * * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ #undef DL_START #define DL_START(X) \ int \ _dl_start (unsigned placeholder, \ struct elf32_dsbt_loadmap *dl_boot_progmap, \ struct elf32_dsbt_loadmap *dl_boot_ldsomap, \ Elf32_Dyn *dl_boot_ldso_dyn_pointer, \ X) /* * On entry, the kernel has set up the stack thusly: * * 0(sp) pad0 * 4(sp) pad1 * 8(sp) argc * 12(sp) argv[0] * ... * (4*(argc+3))(sp) NULL * (4*(argc+4))(sp) envp[0] * ... * NULL * * Register values are unspecified, except: * * B4 --> executable loadmap address * A6 --> interpreter loadmap address * B6 --> dynamic section address * B14 --> our DP setup by kernel * * NB: DSBT index is always 0 for the executable * and 1 for the interpreter */ __asm__(" .text\n" ".globl _start\n" "_start:\n" " B .S2 _dl_start\n" " STW .D2T2 B14, *+B14[1]\n" " ADD .D1X B15,8,A8\n" " ADDKPC .S2 ret_from_dl,B3,2\n" "ret_from_dl:\n" " B .S2X A4\n" " || LDW .D2T2 *+B14[0],B14\n" " ADDKPC .S2 __dl_fini,B0,0\n" " MV .S1X B0,A4\n" " NOP\n" " NOP\n" " NOP\n" "__dl_fini:\n" " LDW .D2T2 *+B14[1],B14\n" " NOP 4\n" " LDW .D2T1 *+B14($GOT(_dl_fini)), A0\n" " NOP 4\n" " BNOP .S2X A0, 5\n"); __asm__(" .text\n" "__c6x_cache_sync:\n" " MVK .S2 330,B0\n" " SWE\n" " NOP\n" " BNOP .S2 B3,5\n" " NOP\n" " NOP\n" " NOP\n" " NOP\n" "\n" ); /* * Get a pointer to the argv array. On many platforms this can be just * the address of the first argument, on other platforms we need to * do something a little more subtle here. */ #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1) struct elf32_dsbt_loadmap; /* * Here is a macro to perform a relocation. This is only used when * bootstrapping the dynamic loader. RELP is the relocation that we * are performing, REL is the pointer to the address we are relocating. * SYMBOL is the symbol involved in the relocation, and LOAD is the * load address. */ #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ switch(ELF32_R_TYPE((RELP)->r_info)){ \ case R_C6000_ABS_L16: \ { \ unsigned int opcode = *(REL); \ unsigned int v = (SYMBOL) + (RELP)->r_addend; \ opcode &= ~0x7fff80; \ opcode |= ((v & 0xffff) << 7); \ *(REL) = opcode; \ } \ break; \ case R_C6000_ABS_H16: \ { \ unsigned int opcode = *(REL); \ unsigned int v = (SYMBOL) + (RELP)->r_addend; \ opcode &= ~0x7fff80; \ opcode |= ((v >> 9) & 0x7fff80); \ *(REL) = opcode; \ } \ break; \ case R_C6000_ABS32: \ *(REL) = (SYMBOL) + (RELP)->r_addend; \ break; \ default: \ _dl_exit(1); \ } extern void __c6x_cache_sync(unsigned long start, unsigned long end) attribute_hidden;