[Top][All Lists]
[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
- [avr-gcc-list] binutils/gas patch for ldi adiw ldd,
Klaus Rudolph <=