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