summaryrefslogtreecommitdiff
path: root/ldso/ldso/sh/ld_sysdep.h
blob: dc1b895b96cd846973e8fa5959e46981024c16cb (plain)
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
/*
 * Various assmbly language/system dependent  hacks that are required
 * so that we can minimize the amount of platform specific code.
 */

/* 
 * Define this if the system uses RELOCA.
 */
#define ELF_USES_RELOCA

/*
 * Get a pointer to the argv array.  On many platforms this can be just
 * the address if 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)

/*
 * Initialization sequence for a GOT.
 */
#define INIT_GOT(GOT_BASE,MODULE) \
{				\
  GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
  GOT_BASE[1] = (unsigned long) (MODULE); \
}

/*
 * 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)		\
	switch(ELF32_R_TYPE((RELP)->r_info)){			\
	case R_SH_REL32:					\
		*(REL) += (RELP)->r_addend - (LOAD);		\
		break;						\
	case R_SH_DIR32:					\
		*(REL) += (SYMBOL) + (RELP)->r_addend;		\
		break;						\
	case R_SH_RELATIVE:					\
		*(REL) += (LOAD);				\
		break;						\
	case R_SH_NONE:						\
		break;						\
	default:						\
		SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc type "); \
		SEND_NUMBER_STDERR(ELF32_R_TYPE((RELP)->r_info), 1); \
		SEND_STDERR("REL, SYMBOL, LOAD: ");		\
		SEND_ADDRESS_STDERR(REL, 0);			\
		SEND_STDERR(", ");				\
		SEND_ADDRESS_STDERR(SYMBOL, 0);			\
		SEND_STDERR(", ");				\
		SEND_ADDRESS_STDERR(LOAD, 1);			\
		_dl_exit(1);					\
	}


/*
 * Transfer control to the user's application, once the dynamic loader
 * is done.  This routine has to exit the current function, then 
 * call the _dl_elf_main function.
 */

#define START()   return _dl_elf_main;



/* Here we define the magic numbers that this dynamic loader should accept */

#define MAGIC1 EM_SH
#undef  MAGIC2
/* Used for error messages */
#define ELF_TARGET "sh"

struct elf_resolve;
extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);

static __inline__ unsigned int
_dl_urem(unsigned int n, unsigned int base)
{
register unsigned int __r0 __asm__ ("r0");
register unsigned int __r4 __asm__ ("r4") = n;
register unsigned int __r5 __asm__ ("r5") = base;

	__asm__ ("
		mov	#0, r0
		div0u

		! get one bit from the msb of the numerator into the T
		! bit and divide it by whats in %2.  Put the answer bit
		! into the T bit so it can come out again at the bottom

		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0

		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0

		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
 
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4 ; div1 r5, r0
		rotcl	r4
		mov  r4, r0
"
		: "=r" (__r0)
		: "r" (__r4), "r" (__r5)
		: "r4", "cc");

	return n - (base * __r0);
}

#define do_rem(result, n, base)		((result) = _dl_urem((n), (base)))

/* 4096 bytes alignment */
#define PAGE_ALIGN 0xfffff000
#define ADDR_ALIGN 0xfff
#define OFFS_ALIGN 0x7ffff000