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. */ 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 textlen_for_m32r_lo16_data = textlen; 87 return (htonl(*rp) & 0xFFFF) + textlen; 88 case FLAT_M32R_16: 89 return htons(*(unsigned short *)rp) & 0xFFFF; 90 case FLAT_M32R_24: 91 return htonl(*rp) & 0xFFFFFF; 92 case FLAT_M32R_32: 93 return htonl(*rp); 94 default: 95 break; 96 } 97 } 98 return ~0; /* bogus value */ 99} 100 101static inline void m32r_flat_put_addr_at_rp (unsigned long *rp, 102 unsigned long addr, 103 unsigned long relval) 104{ 105 unsigned int reloc = flat_m32r_get_reloc_type (relval); 106 if (reloc & 0xf0) { 107 unsigned long Rn = reloc & 0x0f; /* get a number of register */ 108 Rn <<= 24; /* 0x0R000000 */ 109 reloc &= 0xf0; 110 switch (reloc) 111 { 112 case FLAT_M32R_HI16_ULO: /* To create SETH Rn,#high(imm16) */ 113 *rp = (M32R_SETH_OPCODE | Rn 114 | ((addr >> 16) & 0xFFFF)); 115 break; 116 case FLAT_M32R_HI16_SLO: /* To create SETH Rn,#shigh(imm16) */ 117 *rp = (M32R_SETH_OPCODE | Rn 118 | (((addr >> 16) + ((addr & 0x8000) ? 1 : 0)) 119 & 0xFFFF)); 120 break; 121 } 122 } else { 123 switch (reloc) { 124 case FLAT_M32R_LO16_DATA: 125 addr -= textlen_for_m32r_lo16_data; 126 textlen_for_m32r_lo16_data = 0; 127 case FLAT_M32R_LO16: 128 *rp = (htonl(*rp) & 0xFFFF0000) | (addr & 0xFFFF); 129 break; 130 case FLAT_M32R_16: 131 *(unsigned short *)rp = addr & 0xFFFF; 132 break; 133 case FLAT_M32R_24: 134 *rp = (htonl(*rp) & 0xFF000000) | (addr & 0xFFFFFF); 135 break; 136 case FLAT_M32R_32: 137 *rp = addr; 138 break; 139 } 140 } 141} 142 143#endif /* __ASM_M32R_FLAT_H */ 144