Fix verilog output when the width is > 1.

PR 25202
bfd	* bfd.c (VerilogDataEndianness): New variable.
	(verilog_write_record): Use VerilogDataEndianness, if set, to
	choose the endianness of the output.
	(verilog_write_section): Adjust the address by the data width.

binutils* objcopy.c (copy_object): Set VerilogDataEndianness to the
	endianness of the input file.
	(copy_main): Verifiy the value set by the --verilog-data-width
	option.
	* testsuite/binutils-all/objcopy.exp: Add tests of the new behaviour.
	* testsuite/binutils-all/verilog-I4.hex: New file.
This commit is contained in:
Nick Clifton
2022-12-01 13:09:26 +00:00
parent 7505bb034c
commit 6ef35c04df
6 changed files with 102 additions and 8 deletions

View File

@ -1,3 +1,11 @@
2022-12-01 Nick Clifton <nickc@redhat.com>
PR 25202
* bfd.c (VerilogDataEndianness): New variable.
(verilog_write_record): Use VerilogDataEndianness, if set, to
choose the endianness of the output.
(verilog_write_section): Adjust the address by the data width.
2022-11-21 Nick Clifton <nickc@redhat.com>
PR 29764

View File

@ -62,6 +62,10 @@
Data width in bytes. */
unsigned int VerilogDataWidth = 1;
/* Modified by obcopy.c
Data endianness. */
enum bfd_endian VerilogDataEndianness = BFD_ENDIAN_UNKNOWN;
/* Macros for converting between hex and binary. */
static const char digs[] = "0123456789ABCDEF";
@ -105,7 +109,7 @@ verilog_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach
return true;
}
/* We have to save up all the outpu for a splurge before output. */
/* We have to save up all the output for a splurge before output. */
static bool
verilog_set_section_contents (bfd *abfd,
@ -238,7 +242,8 @@ verilog_write_record (bfd *abfd,
*dst++ = ' ';
}
}
else if (bfd_little_endian (abfd))
else if ((VerilogDataEndianness == BFD_ENDIAN_UNKNOWN && bfd_little_endian (abfd)) /* FIXME: Can this happen ? */
|| (VerilogDataEndianness == BFD_ENDIAN_LITTLE))
{
/* If the input byte stream contains:
05 04 03 02 01 00
@ -263,8 +268,10 @@ verilog_write_record (bfd *abfd,
TOHEX (dst, *end);
dst += 2;
}
/* FIXME: Should padding bytes be inserted here ? */
}
else
else /* Big endian output. */
{
for (src = data; src < end;)
{
@ -274,6 +281,7 @@ verilog_write_record (bfd *abfd,
if ((src - data) % VerilogDataWidth == 0)
*dst++ = ' ';
}
/* FIXME: Should padding bytes be inserted here ? */
}
*dst++ = '\r';
@ -291,7 +299,14 @@ verilog_write_section (bfd *abfd,
unsigned int octets_written = 0;
bfd_byte *location = list->data;
verilog_write_address (abfd, list->where);
/* Insist that the starting address is a multiple of the data width. */
if (list->where % VerilogDataWidth)
{
bfd_set_error (bfd_error_invalid_operation);
return false;
}
verilog_write_address (abfd, list->where / VerilogDataWidth);
while (octets_written < list->size)
{
unsigned int octets_this_chunk = list->size - octets_written;

View File

@ -1,3 +1,13 @@
2022-12-01 Nick Clifton <nickc@redhat.com>
PR 25202
* objcopy.c (copy_object): Set VerilogDataEndianness to the
endianness of the input file.
(copy_main): Verifiy the value set by the --verilog-data-width
option.
* testsuite/binutils-all/objcopy.exp: Add tests of the new behaviour.
* testsuite/binutils-all/verilog-I4.hex: New file.
2022-11-21 Nick Clifton <nickc@redhat.com>
PR 29764

View File

@ -546,6 +546,11 @@ extern bool _bfd_srec_forceS3;
the --verilog-data-width parameter. */
extern unsigned int VerilogDataWidth;
/* Endianness of data for verilog output.
This variable is declared in bfd/verilog.c and is set in the
copy_object() function. */
extern enum bfd_endian VerilogDataEndianness;
/* Forward declarations. */
static void setup_section (bfd *, asection *, void *);
static void setup_bfd_headers (bfd *, bfd *);
@ -2655,6 +2660,12 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
return false;
}
/* Set the Verilog output endianness based upon the input file's
endianness. We may not be producing verilog format output,
but testing this just adds extra code this is not really
necessary. */
VerilogDataEndianness = ibfd->xvec->byteorder;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
{
if ((do_debug_sections & compress) != 0
@ -5847,8 +5858,18 @@ copy_main (int argc, char *argv[])
case OPTION_VERILOG_DATA_WIDTH:
VerilogDataWidth = parse_vma (optarg, "--verilog-data-width");
if (VerilogDataWidth < 1)
fatal (_("verilog data width must be at least 1 byte"));
switch (VerilogDataWidth)
{
case 1:
case 2:
case 4:
case 8:
case 16: /* We do not support widths > 16 because the verilog
data is handled internally in 16 byte wide packets. */
break;
default:
fatal (_("error: verilog data width must be 1, 2, 4, 8 or 16"));
}
break;
case 0:

View File

@ -155,13 +155,13 @@ proc objcopy_test_verilog {testname} {
}
set got [binutils_run $OBJCOPY "-O verilog --verilog-data-width 0 $binfile $verilog-0.hex"]
if ![regexp "verilog data width must be at least 1 byte" $got] then {
if ![regexp "error: verilog data width must be 1, 2, 4, 8 or 16" $got] then {
fail "objcopy ($testname 0) {$got}"
} else {
pass "objcopy ($testname 0)"
}
foreach width {1 2 4 8} {
foreach width {1 2} {
set got [binutils_run $OBJCOPY "-O verilog --verilog-data-width $width $binfile $verilog-$width.hex"]
if ![string equal "" $got] then {
fail "objcopy ($testname $width)"
@ -173,6 +173,40 @@ proc objcopy_test_verilog {testname} {
fail "objcopy ($testname $width)"
}
}
# 16-bit little-endian targets fail the following tests because the
# verilog backend does not convert from 16-bits to 32-bits before it
# converts from internal format to little endian format.
if { [istarget tic54*-*-*] || [istarget pdp11-*-*] } {
untested "verilog width-4 and width-8 tests"
return
}
foreach width {4 8} {
set got [binutils_run $OBJCOPY "-O verilog --verilog-data-width $width $binfile $verilog-$width.hex"]
if ![string equal "" $got] then {
fail "objcopy ($testname $width)"
}
send_log "regexp_diff $verilog-$width.hex $srcdir/$subdir/verilog-$width.hex\n"
if {! [regexp_diff "$verilog-$width.hex" "$srcdir/$subdir/verilog-$width.hex"]} {
pass "objcopy ($testname $width)"
} else {
fail "objcopy ($testname $width)"
}
}
# Test generating endian correct output.
set testname "objcopy (verilog output endian-ness == input endian-ness)"
set got [binutils_run $OBJCOPY "-O verilog --verilog-data-width 4 $binfile $verilog-I4.hex"]
if ![string equal "" $got] then {
fail $testname
}
send_log "regexp_diff $verilog-I4.hex $srcdir/$subdir/verilog-I4.hex\n"
if {! [regexp_diff "$verilog-I4.hex" "$srcdir/$subdir/verilog-I4.hex"]} {
pass $testname
} else {
fail $testname
}
}
objcopy_test_verilog "verilog data width"

View File

@ -0,0 +1,6 @@
@00000000
(01020304|04030201) 00000000.*
@000000..
(02000000|00000002).*
#pass