Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * include/asm-m32r/flat.h | |
3 | * | |
4 | * uClinux flat-format executables | |
5 | * | |
6 | * Copyright (C) 2004 Kazuhiro Inaoka | |
7 | * | |
8 | * This file is subject to the terms and conditions of the GNU General Public | |
9 | * License. See the file "COPYING" in the main directory of this archive for | |
10 | * more details. | |
11 | */ | |
12 | #ifndef __ASM_M32R_FLAT_H | |
13 | #define __ASM_M32R_FLAT_H | |
14 | ||
15 | #define flat_stack_align(sp) (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0)) | |
16 | #define flat_argvp_envp_on_stack() 0 | |
17 | #define flat_old_ram_flag(flags) (flags) | |
f9720205 | 18 | #define flat_set_persistent(relval, p) 0 |
1da177e4 LT |
19 | #define flat_reloc_valid(reloc, size) \ |
20 | (((reloc) - textlen_for_m32r_lo16_data) <= (size)) | |
f9720205 | 21 | #define flat_get_addr_from_rp(rp, relval, flags, persistent) \ |
1da177e4 LT |
22 | m32r_flat_get_addr_from_rp(rp, relval, (text_len) ) |
23 | ||
24 | #define flat_put_addr_at_rp(rp, addr, relval) \ | |
25 | m32r_flat_put_addr_at_rp(rp, addr, relval) | |
26 | ||
27 | /* Convert a relocation entry into an address. */ | |
28 | static inline unsigned long | |
29 | flat_get_relocate_addr (unsigned long relval) | |
30 | { | |
31 | return relval & 0x00ffffff; /* Mask out top 8-bits */ | |
32 | } | |
33 | ||
34 | #define flat_m32r_get_reloc_type(relval) ((relval) >> 24) | |
35 | ||
36 | #define M32R_SETH_OPCODE 0xd0c00000 /* SETH instruction code */ | |
37 | ||
38 | #define FLAT_M32R_32 0x00 /* 32bits reloc */ | |
39 | #define FLAT_M32R_24 0x01 /* unsigned 24bits reloc */ | |
40 | #define FLAT_M32R_16 0x02 /* 16bits reloc */ | |
41 | #define FLAT_M32R_LO16 0x03 /* signed low 16bits reloc (low()) */ | |
42 | #define FLAT_M32R_LO16_DATA 0x04 /* signed low 16bits reloc (low()) | |
43 | for a symbol in .data section */ | |
44 | /* High 16bits of an address used | |
45 | when the lower 16bbits are treated | |
46 | as unsigned. | |
47 | To create SETH instruction only. | |
48 | 0x1X: X means a number of register. | |
49 | 0x10 - 0x3F are reserved. */ | |
50 | #define FLAT_M32R_HI16_ULO 0x10 /* reloc for SETH Rn,#high(imm16) */ | |
51 | /* High 16bits of an address used | |
52 | when the lower 16bbits are treated | |
53 | as signed. | |
54 | To create SETH instruction only. | |
55 | 0x2X: X means a number of register. | |
56 | 0x20 - 0x4F are reserved. */ | |
57 | #define FLAT_M32R_HI16_SLO 0x20 /* reloc for SETH Rn,#shigh(imm16) */ | |
58 | ||
59 | static unsigned long textlen_for_m32r_lo16_data = 0; | |
60 | ||
61 | static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp, | |
62 | unsigned long relval, | |
63 | unsigned long textlen) | |
64 | { | |
65 | unsigned int reloc = flat_m32r_get_reloc_type (relval); | |
66 | textlen_for_m32r_lo16_data = 0; | |
67 | if (reloc & 0xf0) { | |
68 | unsigned long addr = htonl(*rp); | |
69 | switch (reloc & 0xf0) | |
70 | { | |
71 | case FLAT_M32R_HI16_ULO: | |
72 | case FLAT_M32R_HI16_SLO: | |
73 | if (addr == 0) { | |
74 | /* put "seth Rn,#0x0" instead of 0 (addr). */ | |
75 | *rp = (M32R_SETH_OPCODE | ((reloc & 0x0f)<<24)); | |
76 | } | |
77 | return addr; | |
78 | default: | |
79 | break; | |
80 | } | |
81 | } else { | |
82 | switch (reloc) | |
83 | { | |
84 | case FLAT_M32R_LO16: | |
85 | return htonl(*rp) & 0xFFFF; | |
86 | case FLAT_M32R_LO16_DATA: | |
87 | /* FIXME: The return value will decrease by textlen | |
88 | at m32r_flat_put_addr_at_rp () */ | |
89 | textlen_for_m32r_lo16_data = textlen; | |
90 | return (htonl(*rp) & 0xFFFF) + textlen; | |
91 | case FLAT_M32R_16: | |
92 | return htons(*(unsigned short *)rp) & 0xFFFF; | |
93 | case FLAT_M32R_24: | |
94 | return htonl(*rp) & 0xFFFFFF; | |
95 | case FLAT_M32R_32: | |
96 | return htonl(*rp); | |
97 | default: | |
98 | break; | |
99 | } | |
100 | } | |
101 | return ~0; /* bogus value */ | |
102 | } | |
103 | ||
104 | static inline void m32r_flat_put_addr_at_rp (unsigned long *rp, | |
105 | unsigned long addr, | |
106 | unsigned long relval) | |
107 | { | |
108 | unsigned int reloc = flat_m32r_get_reloc_type (relval); | |
109 | if (reloc & 0xf0) { | |
110 | unsigned long Rn = reloc & 0x0f; /* get a number of register */ | |
111 | Rn <<= 24; /* 0x0R000000 */ | |
112 | reloc &= 0xf0; | |
113 | switch (reloc) | |
114 | { | |
115 | case FLAT_M32R_HI16_ULO: /* To create SETH Rn,#high(imm16) */ | |
116 | *rp = (M32R_SETH_OPCODE | Rn | |
117 | | ((addr >> 16) & 0xFFFF)); | |
118 | break; | |
119 | case FLAT_M32R_HI16_SLO: /* To create SETH Rn,#shigh(imm16) */ | |
120 | *rp = (M32R_SETH_OPCODE | Rn | |
121 | | (((addr >> 16) + ((addr & 0x8000) ? 1 : 0)) | |
122 | & 0xFFFF)); | |
123 | break; | |
124 | } | |
125 | } else { | |
126 | switch (reloc) { | |
127 | case FLAT_M32R_LO16_DATA: | |
128 | addr -= textlen_for_m32r_lo16_data; | |
129 | textlen_for_m32r_lo16_data = 0; | |
130 | case FLAT_M32R_LO16: | |
131 | *rp = (htonl(*rp) & 0xFFFF0000) | (addr & 0xFFFF); | |
132 | break; | |
133 | case FLAT_M32R_16: | |
134 | *(unsigned short *)rp = addr & 0xFFFF; | |
135 | break; | |
136 | case FLAT_M32R_24: | |
137 | *rp = (htonl(*rp) & 0xFF000000) | (addr & 0xFFFFFF); | |
138 | break; | |
139 | case FLAT_M32R_32: | |
140 | *rp = addr; | |
141 | break; | |
142 | } | |
143 | } | |
144 | } | |
145 | ||
146 | #endif /* __ASM_M32R_FLAT_H */ |