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