/* Any assembly language/system dependent hacks needed to setup boot1.c so it * will work as expected and cope with whatever platform specific wierdness is * needed for this architecture. * Copyright (C) 2005 by Joakim Tjernlund * Copyright (C) 2005 by Erik Andersen */ #include __asm__("" " .text\n" " .globl _start\n" " .ent _start\n" " .type _start,@function\n" " .hidden _start\n" "_start:\n" " .set noreorder\n" " move $25, $31\n" " bal 0f\n" " nop\n" "0:\n" #if _MIPS_SIM == _MIPS_SIM_ABI32 " .cpload $31\n" #else /* N32 || N64 */ " .cpsetup $31, $2, 0b\n" #endif /* N32 || N64 */ " move $31, $25\n" " .set reorder\n" #if _MIPS_SIM == _MIPS_SIM_ABI64 " dla $4, _DYNAMIC\n" " sd $4, -0x7ff0($28)\n" #else /* O32 || N32 */ " la $4, _DYNAMIC\n" " sw $4, -0x7ff0($28)\n" #endif /* O32 || N32 */ " move $4, $29\n" #if _MIPS_SIM == _MIPS_SIM_ABI32 " subu $29, 16\n" #endif # if !defined __mips_isa_rev || __mips_isa_rev < 6 #if _MIPS_SIM == _MIPS_SIM_ABI64 " dla $8, .coff\n" #else /* O32 || N32 */ " la $8, .coff\n" #endif /* O32 || N32 */ " bltzal $8, .coff\n" ".coff:\n" # else ".coff:\n" " lapc $31, .coff\n" # endif #if _MIPS_SIM == _MIPS_SIM_ABI64 " dsubu $8, $31, $8\n" " dla $25, _dl_start\n" " daddu $25, $8\n" #else /* O32 || N32 */ " subu $8, $31, $8\n" " la $25, _dl_start\n" " addu $25, $8\n" #endif /* O32 || N32 */ " jalr $25\n" #if _MIPS_SIM == _MIPS_SIM_ABI32 " addiu $29, 16\n" #endif " move $16, $28\n" " move $17, $2\n" #if _MIPS_SIM == _MIPS_SIM_ABI64 " ld $2, _dl_skip_args\n" " beq $2, $0, 1f\n" " ld $4, 0($29)\n" " dsubu $4, $2\n" " dsll $2, 2\n" " daddu $29, $2\n" " sd $4, 0($29)\n" "1:\n" " ld $5, 0($29)\n" " dla $6, 8 ($29)\n" " dsll $7, $5, 2\n" " daddu $7, $7, $6\n" " daddu $7, $7, 4\n" " and $2, $29, -4 * 4\n" " sd $29, -8($2)\n" " dsubu $29, $2, 32\n" " ld $29, 24($29)\n" " dla $2, _dl_fini\n" #else /* O32 || N32 */ " lw $2, _dl_skip_args\n" " beq $2, $0, 1f\n" " lw $4, 0($29)\n" " subu $4, $2\n" " sll $2, 2\n" " addu $29, $2\n" " sw $4, 0($29)\n" "1:\n" " lw $5, 0($29)\n" " la $6, 4 ($29)\n" " sll $7, $5, 2\n" " addu $7, $7, $6\n" " addu $7, $7, 4\n" " and $2, $29, -2 * 4\n" " sw $29, -4($2)\n" " subu $29, $2, 32\n" #if _MIPS_SIM == _MIPS_SIM_ABI32 " .cprestore 16\n" #endif " lw $29, 28($29)\n" " la $2, _dl_fini\n" #endif /* O32 || N32 */ " move $25, $17\n" " jr $25\n" ".end _start\n" ".size _start, . -_start\n" "\n\n" "\n\n" ".previous\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) /* We can't call functions earlier in the dl startup process */ #define NO_FUNCS_BEFORE_BOOTSTRAP /* * Here is a macro to perform the GOT relocation. This is only * used when bootstrapping the dynamic loader. */ #define PERFORM_BOOTSTRAP_GOT(tpnt) \ do { \ ElfW(Sym) *sym; \ ElfW(Addr) i; \ register ElfW(Addr) gp __asm__ ("$28"); \ ElfW(Addr) *mipsgot = elf_mips_got_from_gpreg (gp); \ \ /* Add load address displacement to all local GOT entries */ \ i = 2; \ while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ mipsgot[i++] += tpnt->loadaddr; \ \ /* Handle global GOT entries */ \ mipsgot += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; \ sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] + \ tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; \ i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\ \ while (i--) { \ if (sym->st_shndx == SHN_UNDEF || \ sym->st_shndx == SHN_COMMON) \ *mipsgot = tpnt->loadaddr + sym->st_value; \ else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && \ *mipsgot != sym->st_value) \ *mipsgot += tpnt->loadaddr; \ else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { \ if (sym->st_other == 0) \ *mipsgot += tpnt->loadaddr; \ } \ else \ *mipsgot = tpnt->loadaddr + sym->st_value; \ \ mipsgot++; \ sym++; \ } \ } while (0) /* * Here is a macro to perform a relocation. This is only used when * bootstrapping the dynamic loader. */ #if _MIPS_SIM == _MIPS_SIM_ABI64 /* consult with glibc sysdeps/mips/dl-machine.h 1.69 */ #define R_MIPS_BOOTSTRAP_RELOC ((R_MIPS_64 << 8) | R_MIPS_REL32) #else /* N32 || O32 */ #define R_MIPS_BOOTSTRAP_RELOC R_MIPS_REL32 #endif #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ switch(ELF_R_TYPE((RELP)->r_info)) { \ case R_MIPS_BOOTSTRAP_RELOC: \ if (SYMTAB) { \ if (symtab_indexdynamic_info[DT_MIPS_GOTSYM_IDX])\ *REL += SYMBOL; \ } \ else { \ *REL += LOAD; \ } \ break; \ case R_MIPS_NONE: \ break; \ default: \ SEND_STDERR("Aiieeee!"); \ _dl_exit(1); \ }