avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] binutils/gas patch for ldi adiw ldd


From: Klaus Rudolph
Subject: [avr-gcc-list] binutils/gas patch for ldi adiw ldd
Date: Sat, 20 Nov 2004 13:49:13 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040114

Hi Marek & Denis, hi list

I have made a patch for actual binutils (binutils-041119 CVS head) which enable some new features/improvements:

ldi:
the message "Warning: expression possibly out of 8-bit range" is removed, a real error checking is now activated. The error condition is now checked during linking/relocation. That makes ldi overruns impossible.

ldd/std:
ldd and std could now be used with offsets of labels. So you are able to write:

.lcomm table1 10
....
.lcomm table2 10

ldd r16, Y+(table2-table1)
or
std Y+(table2-table1), r16

which enables you to write some nice table copy functions which full error checking. Error checking is done during relocation/link time so no overrun could occure.

The same solution is implemented for adiw and sbiw instruction. So you also can
use it for index operation on assembler "structures".

sideeffects:
I introduced the features only with new BFD_RELOCS, older ones have not changed. So the patch is
a complete add-on and should not effect the c compiler.

Please do a deep test and if you find bugs send me a message. If no new bugs are in the patch it would be
nice if that features could be added to cvs head then for public usage.
Please give me a note if you add it to official binutils cvs HEAD.



Thanks
   Klaus

P.S. I have no idea why offsets could not be created from "unknown" sections. Here the gas is allways giveing a error message. that makes no sense I think because the relocation is done later.
Bug or feature? Any idea how to fix it?
diff -ur binutils-041119/bfd/bfd-in2.h binutils-041119_modified/bfd/bfd-in2.h
--- binutils-041119/bfd/bfd-in2.h       2004-11-08 14:17:32.000000000 +0100
+++ binutils-041119_modified/bfd/bfd-in2.h      2004-11-20 12:19:16.972675008 
+0100
@@ -3158,6 +3158,18 @@
 into 22 bits.  */
   BFD_RELOC_AVR_CALL,
 
+/* This is a 16 bit reloc for the AVR that stores all needed bits
+  for absolute addressing with ldi with overflow check to linktime*/
+  BFD_RELOC_AVR_LDI,
+
+/* This is a 6 bit reloc for the AVR that stores offset for ldd/std
+  instructions*/
+  BFD_RELOC_AVR_6,
+
+/* This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw
+  instructions*/
+  BFD_RELOC_AVR_6_ADIW,
+
 /* Direct 12 bit.  */
   BFD_RELOC_390_12,
 
diff -ur binutils-041119/bfd/elf32-avr.c 
binutils-041119_modified/bfd/elf32-avr.c
--- binutils-041119/bfd/elf32-avr.c     2004-10-21 17:28:20.000000000 +0200
+++ binutils-041119_modified/bfd/elf32-avr.c    2004-11-20 13:09:53.967981544 
+0100
@@ -329,7 +329,52 @@
         FALSE,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE)                 /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
+  /* A 16 bit absolute relocation of 16 bit address.
+     For LDI command.  */
+  HOWTO (R_AVR_LDI,            /* type */
+        0,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_AVR_LDI",   /* name */
+        FALSE,                 /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        FALSE),                /* pcrel_offset */
+  /* A 6 bit absolute relocation of 6 bit offset.
+     For ldd/sdd command.  */
+  HOWTO (R_AVR_6,              /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        6,                     /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_AVR_6",     /* name */
+        FALSE,                 /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        FALSE),                /* pcrel_offset */
+  /* A 6 bit absolute relocation of 6 bit offset.
+     For sbiw/adiw command.  */
+  HOWTO (R_AVR_6_ADIW,         /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        6,                     /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_AVR_6_ADIW",        /* name */
+        FALSE,                 /* partial_inplace */
+        0xffff,                /* src_mask */
+        0xffff,                /* dst_mask */
+        FALSE)         /* pcrel_offset */
 };
 
 /* Map BFD reloc types to AVR ELF reloc types.  */
@@ -360,7 +405,10 @@
   { BFD_RELOC_AVR_LO8_LDI_PM_NEG,   R_AVR_LO8_LDI_PM_NEG },
   { BFD_RELOC_AVR_HI8_LDI_PM_NEG,   R_AVR_HI8_LDI_PM_NEG },
   { BFD_RELOC_AVR_HH8_LDI_PM_NEG,   R_AVR_HH8_LDI_PM_NEG },
-  { BFD_RELOC_AVR_CALL,             R_AVR_CALL }
+  { BFD_RELOC_AVR_CALL,             R_AVR_CALL },
+  { BFD_RELOC_AVR_LDI,              R_AVR_LDI  },
+  { BFD_RELOC_AVR_6,                R_AVR_6    },
+  { BFD_RELOC_AVR_6_ADIW,           R_AVR_6_ADIW }
 };
 
 static reloc_howto_type *
@@ -561,6 +609,39 @@
       bfd_put_16 (input_bfd, x, contents);
       break;
 
+    case R_AVR_LDI:
+      contents += rel->r_offset;
+      srel = (bfd_signed_vma) relocation + rel->r_addend;
+      if ((srel&0xffff)>255) { //remove offset for data/eeprom section
+          return bfd_reloc_overflow;
+      }
+      x = bfd_get_16 (input_bfd, contents);
+      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
+      bfd_put_16 (input_bfd, x, contents);
+      break;
+
+    case R_AVR_6:
+      contents += rel->r_offset;
+      srel = (bfd_signed_vma) relocation + rel->r_addend;
+      if (((srel&0xffff)>63 ) || (srel <0 )) { //remove offset for data/eeprom 
section
+          return bfd_reloc_overflow;
+      }
+      x = bfd_get_16 (input_bfd, contents);
+      x = (x & 0xd3f8) | (( x  & 7) | (( x  & (3 << 3)) << 7) | (( x  & (1 << 
5)) << 8) );
+      bfd_put_16 (input_bfd, x, contents);
+      break;
+
+    case R_AVR_6_ADIW:
+      contents += rel->r_offset;
+      srel = (bfd_signed_vma) relocation + rel->r_addend;
+      if (((srel&0xffff)>63 ) || (srel <0 )) { //remove offset for data/eeprom 
section
+          return bfd_reloc_overflow;
+      }
+      x = bfd_get_16 (input_bfd, contents);
+      x = (x & 0xff30) | (x & 0xf) | (x & 0x30); 
+      bfd_put_16 (input_bfd, x, contents);
+      break;
+
     case R_AVR_HI8_LDI:
       contents += rel->r_offset;
       srel = (bfd_signed_vma) relocation + rel->r_addend;
diff -ur binutils-041119/gas/config/tc-avr.c 
binutils-041119_modified/gas/config/tc-avr.c
--- binutils-041119/gas/config/tc-avr.c 2004-09-11 15:15:04.000000000 +0200
+++ binutils-041119_modified/gas/config/tc-avr.c        2004-11-20 
13:00:07.496138816 +0100
@@ -150,6 +150,7 @@
 static unsigned int avr_get_constant PARAMS ((char *, int));
 static char *parse_exp PARAMS ((char *, expressionS *));
 static bfd_reloc_code_real_type avr_ldi_expression PARAMS ((expressionS *));
+static void avr_offset_expression PARAMS ((expressionS *));
 
 #define EXP_MOD_NAME(i) exp_mod[i].name
 #define EXP_MOD_RELOC(i) exp_mod[i].reloc
@@ -442,6 +443,8 @@
   bfd_set_arch_mach (stdoutput, TARGET_ARCH, avr_mcu->mach);
 }
 
+
+
 /* Resolve STR as a constant expression and return the result.
    If result greater than MAX then error.  */
 
@@ -464,6 +467,10 @@
   return ex.X_add_number;
 }
 
+/* Resolve STR as a constant expression and return the result.
+   If result greater than MAX then error.  */
+
+
 /* Parse instruction operands.
    Return binary opcode.  */
 
@@ -592,7 +599,7 @@
        }
       else
        {
-         op_mask = avr_get_constant (str, 31);
+         op_mask = avr_get_constant (str, 31 );
          str = input_line_pointer;
        }
 
@@ -689,12 +696,13 @@
          as_bad (_("pointer register (Y or Z) required"));
        str = skip_space (str);
        if (*str++ == '+')
-         {
-           unsigned int x;
-           x = avr_get_constant (str, 63);
-           str = input_line_pointer;
-           op_mask |= (x & 7) | ((x & (3 << 3)) << 7) | ((x & (1 << 5)) << 8);
-         }
+           {
+               input_line_pointer = str;
+               avr_offset_expression (&op_expr);
+               str = input_line_pointer;
+               fix_new_exp (frag_now, where, 3,
+                   &op_expr, FALSE, BFD_RELOC_AVR_6);
+           }
       }
       break;
 
@@ -746,11 +754,18 @@
 
     case 'K':
       {
+         input_line_pointer = str;
+         avr_offset_expression (&op_expr);
+         str = input_line_pointer;
+         fix_new_exp (frag_now, where, 3,
+         &op_expr, FALSE, BFD_RELOC_AVR_6_ADIW);
+            /*
        unsigned int x;
 
        x = avr_get_constant (str, 63);
        str = input_line_pointer;
        op_mask |= (x & 0xf) | ((x & 0x30) << 2);
+    */
       }
       break;
 
@@ -935,6 +950,27 @@
          bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where);
          break;
 
+       case BFD_RELOC_AVR_LDI:
+         if (value > 255)
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("operand out of range: %ld"), value);
+         bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where);
+         break;
+
+    case BFD_RELOC_AVR_6:
+         if ((value > 63) || (value<0) )
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("operand out of range: %ld"), value);
+      bfd_putl16 ((bfd_vma) insn | (( value  & 7) | (( value  & (3 << 3)) << 
7) | (( value  & (1 << 5)) << 8) ), where);
+      break;
+
+    case BFD_RELOC_AVR_6_ADIW:
+         if ((value > 63) || (value<0) )
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("operand out of range: %ld"), value);
+      bfd_putl16 ((bfd_vma) insn| (value & 0xf) | (value & 0x30), where);
+      break;
+
        case -BFD_RELOC_AVR_LO8_LDI:
          bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value >> 16), where);
          break;
@@ -1129,6 +1165,33 @@
   return input_line_pointer;
 }
 
+/* Parse for ldd/std offset */
+
+static void
+avr_offset_expression (exp)
+     expressionS *exp;
+{
+  char *str = input_line_pointer;
+  char *tmp;
+  char op[8];
+  tmp = str;
+  str = extract_word (str, op, sizeof (op));
+
+  input_line_pointer = tmp;
+  expression (exp);
+
+  /* Warn about expressions that fail to use lo8 ().  */
+  if (exp->X_op == O_constant)
+    {
+        
+      int x = exp->X_add_number;
+      
+      if (x < -255 || x > 255)
+       as_warn (_("constant out of 8-bit range: %d"), x);
+    }
+
+}
+
 /* Parse special expressions (needed for LDI command):
    xx8 (address)
    xx8 (-address)
@@ -1145,7 +1208,6 @@
   char op[8];
   int mod;
   tmp = str;
-
   str = extract_word (str, op, sizeof (op));
 
   if (op[0])
@@ -1218,14 +1280,14 @@
   /* Warn about expressions that fail to use lo8 ().  */
   if (exp->X_op == O_constant)
     {
+        
       int x = exp->X_add_number;
+      
       if (x < -255 || x > 255)
        as_warn (_("constant out of 8-bit range: %d"), x);
     }
-  else
-    as_warn (_("expression possibly out of 8-bit range"));
 
-  return BFD_RELOC_AVR_LO8_LDI;
+  return BFD_RELOC_AVR_LDI;
 }
 
 /* Flag to pass `pm' mode between `avr_parse_cons_expression' and
diff -ur binutils-041119/gas/doc/as.1 binutils-041119_modified/gas/doc/as.1
--- binutils-041119/gas/doc/as.1        2004-11-19 06:41:48.000000000 +0100
+++ binutils-041119_modified/gas/doc/as.1       2004-11-20 12:06:41.396540040 
+0100
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13
+.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14
 .\"
 .\" Standard preamble:
 .\" ========================================================================
@@ -128,7 +128,7 @@
 .\" ========================================================================
 .\"
 .IX Title "AS 1"
-.TH AS 1 "2004-11-19" "binutils-041119" "GNU Development Tools"
+.TH AS 1 "2004-11-20" "binutils-041119" "GNU Development Tools"
 .SH "NAME"
 AS \- the portable GNU assembler.
 .SH "SYNOPSIS"
diff -ur binutils-041119/include/elf/avr.h 
binutils-041119_modified/include/elf/avr.h
--- binutils-041119/include/elf/avr.h   2001-03-14 03:27:44.000000000 +0100
+++ binutils-041119_modified/include/elf/avr.h  2004-11-20 12:45:43.298516824 
+0100
@@ -53,6 +53,9 @@
      RELOC_NUMBER (R_AVR_HI8_LDI_PM_NEG,       16)
      RELOC_NUMBER (R_AVR_HH8_LDI_PM_NEG,       17)
      RELOC_NUMBER (R_AVR_CALL,                18)
+     RELOC_NUMBER (R_AVR_LDI,              19)
+     RELOC_NUMBER (R_AVR_6,                20)
+     RELOC_NUMBER (R_AVR_6_ADIW,           21)
 END_RELOC_NUMBERS (R_AVR_max)
 
 #endif /* _ELF_AVR_H */
Nur in binutils-041119_modified/intl: config.cache.
Nur in binutils-041119_modified/intl: config.h.
Nur in binutils-041119_modified/intl: config.status.
Nur in binutils-041119_modified/intl: stamp-h.
diff -ur binutils-041119/ld/ld.1 binutils-041119_modified/ld/ld.1
--- binutils-041119/ld/ld.1     2004-11-19 06:41:51.000000000 +0100
+++ binutils-041119_modified/ld/ld.1    2004-11-20 12:07:49.404201304 +0100
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13
+.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14
 .\"
 .\" Standard preamble:
 .\" ========================================================================
@@ -128,7 +128,7 @@
 .\" ========================================================================
 .\"
 .IX Title "LD 1"
-.TH LD 1 "2004-11-19" "binutils-041119" "GNU Development Tools"
+.TH LD 1 "2004-11-20" "binutils-041119" "GNU Development Tools"
 .SH "NAME"
 ld \- Using LD, the GNU linker
 .SH "SYNOPSIS"
@@ -538,11 +538,11 @@
 Print a link map to the standard output.  A link map provides
 information about the link, including the following:
 .RS 4
-.IP "\(bu" 4
+.IP "*" 4
 Where object files and symbols are mapped into memory.
-.IP "\(bu" 4
+.IP "*" 4
 How common symbols are allocated.
-.IP "\(bu" 4
+.IP "*" 4
 All archive members included in the link, with a mention of the symbol
 which caused the archive member to be brought in.
 .RE

reply via email to

[Prev in Thread] Current Thread [Next in Thread]