Contiki 2.6

cle_avr.c

00001 /*
00002  * Copyright (c) 2007, Swedish Institute of Computer Science
00003  * All rights reserved. 
00004  *
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions 
00007  * are met: 
00008  * 1. Redistributions of source code must retain the above copyright 
00009  *    notice, this list of conditions and the following disclaimer. 
00010  * 2. Redistributions in binary form must reproduce the above copyright 
00011  *    notice, this list of conditions and the following disclaimer in the 
00012  *    documentation and/or other materials provided with the distribution. 
00013  * 3. Neither the name of the Institute nor the names of its contributors 
00014  *    may be used to endorse or promote products derived from this software 
00015  *    without specific prior written permission. 
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
00027  * SUCH DAMAGE. 
00028  *
00029  * @(#)$Id: cle_avr.c,v 1.3 2007/06/04 17:50:25 bg- Exp $
00030  */
00031 
00032 /*
00033  * The Contiki dynamic Link Editor (CLE), ELF version.
00034  */
00035 
00036 #include <stdio.h>
00037 
00038 #include "contiki.h"
00039 
00040 #include "loader/elf32.h"
00041 #include "loader/cle.h"
00042 
00043 #define NDEBUG
00044 #include "lib/assert.h"
00045 
00046 #ifdef NDEBUG
00047 #define PRINTF(...) do {} while (0)
00048 #else
00049 #define PRINTF(...) printf(__VA_ARGS__)
00050 #endif
00051 
00052 #define R_AVR_NONE             0
00053 #define R_AVR_32               1
00054 #define R_AVR_7_PCREL          2
00055 #define R_AVR_13_PCREL         3
00056 #define R_AVR_16               4
00057 #define R_AVR_16_PM            5
00058 #define R_AVR_LO8_LDI          6
00059 #define R_AVR_HI8_LDI          7
00060 #define R_AVR_HH8_LDI          8
00061 #define R_AVR_LO8_LDI_NEG      9
00062 #define R_AVR_HI8_LDI_NEG     10
00063 #define R_AVR_HH8_LDI_NEG     11
00064 #define R_AVR_LO8_LDI_PM      12
00065 #define R_AVR_HI8_LDI_PM      13
00066 #define R_AVR_HH8_LDI_PM      14
00067 #define R_AVR_LO8_LDI_PM_NEG  15
00068 #define R_AVR_HI8_LDI_PM_NEG  16
00069 #define R_AVR_HH8_LDI_PM_NEG  17
00070 #define R_AVR_CALL            18
00071 
00072 /*
00073  * Writing relocs is machine dependent and this function is AVR
00074  * specific!
00075  */
00076 int
00077 cle_write_reloc(void *pos_,
00078                 const struct elf32_rela *rela,
00079                 cle_addr addr,
00080                 const struct cle_info *info)
00081 {
00082   unsigned char *pos = pos_;
00083   unsigned char byte;
00084 
00085   switch(ELF32_R_TYPE(rela->r_info)) {
00086   default:
00087     PRINTF("cle_upd_reloc: unsupported relocation type: %d\n",
00088            ELF32_R_TYPE(rela->r_info));
00089     return CLE_UNKNOWN_RELOC;
00090 
00091   case R_AVR_7_PCREL:           /* 2 */
00092     /* Reloc in bits 0x03f8 (0000 00kk kkkk k000). */
00093     byte = addr - (/* text */ + rela->r_offset + 2);
00094     byte = byte >> 1;
00095     pos[0] = (pos[0] & 0x07) | (byte << 3);     /* 0xf8 */
00096     pos[1] = (pos[1] & 0xfc) | (byte >> 5);     /* 0x03 */
00097     return CLE_OK;
00098 
00099   case R_AVR_13_PCREL:          /* 3 */
00100     /* Reloc in bits 0x0fff (0000 kkkk kkkk kkkk). */
00101     addr = addr - (info->text + rela->r_offset + 2);
00102     addr = addr >> 1;
00103     pos[0] = addr;
00104     pos[1] = (pos[1] & 0xf0) | ((addr >> 8) & 0x0f);
00105     return CLE_OK;
00106 
00107   case R_AVR_CALL:              /* 18 */
00108     addr = addr >> 1;
00109     pos[2] = addr;
00110     pos[3] = addr >> 8;
00111     return CLE_OK;
00112 
00113   case R_AVR_16:                /* 4 */
00114     pos[0] = addr;
00115     pos[1] = addr >> 8;
00116     return CLE_OK;
00117 
00118   case R_AVR_16_PM:             /* 5 */
00119     addr = addr >> 1;
00120     pos[0] = addr;
00121     pos[1] = addr >> 8;
00122     return CLE_OK;
00123 
00124     /*
00125      * Remaining relocs all have immediate value in bits 0x0f0f.
00126      */
00127   case R_AVR_LO8_LDI:           /* 6 */
00128     byte = addr;
00129     break;
00130     
00131   case R_AVR_HI8_LDI:           /* 7 */
00132     byte = addr >> 8;
00133     break;
00134 
00135   case R_AVR_HH8_LDI:           /* 8 */
00136     byte = addr >> 16;
00137     break;
00138 
00139   case R_AVR_LO8_LDI_NEG:       /* 9 */
00140     byte = (-addr);
00141     break;
00142 
00143   case R_AVR_HI8_LDI_NEG:       /* 10 */
00144     byte = (-addr) >> 8;
00145     break;
00146 
00147   case R_AVR_HH8_LDI_NEG:       /* 11 */
00148     byte = (-addr) >> 16;
00149     break;
00150 
00151   case R_AVR_LO8_LDI_PM:        /* 12 */
00152     byte = addr >> 1;
00153     break;
00154 
00155   case R_AVR_HI8_LDI_PM:        /* 13 */
00156     byte = addr >> 9;
00157     break;
00158 
00159   case R_AVR_HH8_LDI_PM:        /* 14 */
00160     byte = addr >> 17;
00161     break;
00162 
00163   case R_AVR_LO8_LDI_PM_NEG:    /* 15 */
00164     byte = (-addr) >> 1;
00165     break;
00166 
00167   case R_AVR_HI8_LDI_PM_NEG:    /* 16 */
00168     byte = (-addr) >> 9;
00169     break;
00170 
00171   case R_AVR_HH8_LDI_PM_NEG:    /* 17 */
00172     byte = (-addr) >> 17;
00173     break;
00174   }
00175   /* Relocation in bits 0x0f0f (0000 kkkk 0000 kkkk). */
00176   pos[0] = (pos[0] & 0xf0) | (byte & 0x0f);
00177   pos[1] = (pos[1] & 0xf0) | (byte >> 4);
00178 
00179   return CLE_OK;
00180 }