This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Patch for avr port of binutils [adiw, sbiw, ldd with more functionality]
- From: Klaus Rudolph <lts-rudolph at gmx dot de>
- To: binutils <binutils at sources dot redhat dot com>
- Date: Thu, 16 Dec 2004 22:42:50 +0100
- Subject: Patch for avr port of binutils [adiw, sbiw, ldd with more functionality]
- References: <41C1B44B.3030803@gmx.de> <m34qim6x4z.fsf@gossamer.airs.com>
Sorry if you got this mail again, but I send that mail 20:44 local time
to <binutils@sources.redhat.com> but got this message not back again???
So I tried it again.
If you got also the first message I think something is going wrong with
my email system :-(
>Ian Lance Taylor schrieb:
Klaus Rudolph <lts-rudolph@gmx.de> writes:
What procedure in general is needed to provide some more work :-)
Submit the patches for approval, breaking them up into relevant chunks
so that they can be understood and approved by the maintainers.
Here is the patch for approval.
Additional functionality:
in older Versions from gas only constants are wroking in connection
with ldd, sbiw, adiw
now you also could write:
table1:
...
table2:
....
ldd r16, Y+(table2-table1)
adiw r16, (table2-table1)
sbiw r16, (table2-table1)
The patch is going only to avr related files.
Bye
Klaus
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-25 08:04:36.000000000 +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-25 08:08:55.000000000 +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) | (( srel & 7) | (( srel & (3 << 3)) << 7) | (( srel & (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) | (srel & 0xf) | ((srel & 0x30)<<2);
+ 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-25 08:09:58.000000000 +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,11 @@
case 'K':
{
- unsigned int x;
-
- x = avr_get_constant (str, 63);
- str = input_line_pointer;
- op_mask |= (x & 0xf) | ((x & 0x30) << 2);
+ 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);
}
break;
@@ -935,6 +943,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)<<2), where);
+ break;
+
case -BFD_RELOC_AVR_LO8_LDI:
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value >> 16), where);
break;
@@ -1129,6 +1158,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 +1201,6 @@
char op[8];
int mod;
tmp = str;
-
str = extract_word (str, op, sizeof (op));
if (op[0])
@@ -1218,14 +1273,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-25 08:04:36.000000000 +0100
@@ -128,7 +128,7 @@
.\" ========================================================================
.\"
.IX Title "AS 1"
-.TH AS 1 "2004-11-19" "binutils-041119" "GNU Development Tools"
+.TH AS 1 "2004-11-23" "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-25 08:04:36.000000000 +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 */
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-25 08:04:36.000000000 +0100
@@ -128,7 +128,7 @@
.\" ========================================================================
.\"
.IX Title "LD 1"
-.TH LD 1 "2004-11-19" "binutils-041119" "GNU Development Tools"
+.TH LD 1 "2004-11-23" "binutils-041119" "GNU Development Tools"
.SH "NAME"
ld \- Using LD, the GNU linker
.SH "SYNOPSIS"