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#define flat_get_addr_from_rp(rp, relval, flags, persistent) \ 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. */ 27static inline unsigned long 28flat_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 58static unsigned long textlen_for_m32r_lo16_data = 0; 59 60static 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 103static 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 */ 146