2 * include/asm-nios2nommu/flat.h -- uClinux bFLT relocations
4 * Copyright (C) 2004,05 Microtronix Datacom Ltd
6 * This file is subject to the terms and conditions of the GNU General
7 * Public License. See the file COPYING in the main directory of this
8 * archive for more details.
10 * Written by Wentao Xu <wentao@microtronix.com>
13 #ifndef __NIOS2_FLAT_H__
14 #define __NIOS2_FLAT_H__
16 #define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000))
18 /* The stack is 64-bit aligned for Nios II, so (sp - 1) shall
19 * be 64-bit aligned, where -1 is for argc
21 #define flat_stack_align(sp) (sp = (unsigned long *)(((unsigned long)sp - 1) & (-8)))
23 /* The uClibc port for Nios II expects the argc is followed by argv and envp */
24 #define flat_argvp_envp_on_stack() 1
26 #define flat_old_ram_flag(flags) (flags)
28 /* We store the type of relocation in the top 4 bits of the `relval.' */
30 /* Convert a relocation entry into an address. */
31 static inline unsigned long
32 flat_get_relocate_addr (unsigned long relval
)
34 return relval
& 0x0fffffff; /* Mask out top 4-bits */
37 #define FLAT_NIOS2_RELOC_TYPE(relval) ((relval) >> 28)
39 #define FLAT_NIOS2_R_32 0 /* Normal 32-bit reloc */
40 #define FLAT_NIOS2_R_HI_LO 1 /* High 16-bits + low 16-bits field */
41 #define FLAT_NIOS2_R_HIADJ_LO 2 /* High 16-bits adjust + low 16-bits field */
42 #define FLAT_NIOS2_R_CALL26 4 /* Call imm26 */
44 /* Extract the address to be relocated from the symbol reference at rp;
45 * relval is the raw relocation-table entry from which RP is derived.
46 * rp shall always be 32-bit aligned
48 static inline unsigned long flat_get_addr_from_rp (unsigned long *rp
,
52 switch (FLAT_NIOS2_RELOC_TYPE(relval
))
55 /* Simple 32-bit address. The loader expect it in bigger endian */
58 case FLAT_NIOS2_R_HI_LO
:
59 /* get the two 16-bit immediate value from instructions, then
60 * construct a 32-bit value. Again the loader expect bigger endian
62 return htonl ((((rp
[0] >> 6) & 0xFFFF) << 16 ) |
63 ((rp
[1] >> 6) & 0xFFFF));
65 case FLAT_NIOS2_R_HIADJ_LO
:
67 /* get the two 16-bit immediate value from instructions, then
68 * construct a 32-bit value. Again the loader expect bigger endian
70 unsigned int low
, high
;
71 high
= (rp
[0] >> 6) & 0xFFFF;
72 low
= (rp
[1] >> 6) & 0xFFFF;
74 if ((low
>> 15) & 1) high
--;
76 return htonl ((high
<< 16 ) | low
);
78 case FLAT_NIOS2_R_CALL26
:
79 /* the 26-bit immediate value is actually 28-bit */
80 return htonl(((*rp
) >> 6) << 2);
83 return ~0; /* bogus value */
87 /* Insert the address addr into the symbol reference at rp;
88 * relval is the raw relocation-table entry from which rp is derived.
89 * rp shall always be 32-bit aligned
91 static inline void flat_put_addr_at_rp (unsigned long *rp
, unsigned long addr
,
94 unsigned long exist_val
;
95 switch (FLAT_NIOS2_RELOC_TYPE (relval
)) {
97 /* Simple 32-bit address. */
101 case FLAT_NIOS2_R_HI_LO
:
103 rp
[0] = ((((exist_val
>> 22) << 16) | (addr
>> 16)) << 6) | (exist_val
& 0x3F);
105 rp
[1] = ((((exist_val
>> 22) << 16) | (addr
& 0xFFFF)) << 6) | (exist_val
& 0x3F);
108 case FLAT_NIOS2_R_HIADJ_LO
:
110 unsigned int high
= (addr
>> 16);
111 if ((addr
>> 15) & 1)
112 high
= (high
+ 1) & 0xFFFF;
114 rp
[0] = ((((exist_val
>> 22) << 16) | high
) << 6) | (exist_val
& 0x3F);
116 rp
[1] = ((((exist_val
>> 22) << 16) | (addr
& 0xFFFF)) << 6) | (exist_val
& 0x3F);
119 case FLAT_NIOS2_R_CALL26
:
120 /* the opcode of CALL is 0, so just store the value */
121 *rp
= ((addr
>> 2) << 6);
126 #endif /* __NIOS2_FLAT_H__ */