Bug 22049 - PowerPC VLE: Lower 16 bit address offset not calculated properly in some cases
Summary: PowerPC VLE: Lower 16 bit address offset not calculated properly in some cases
Status: RESOLVED INVALID
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.28
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-08-30 22:27 UTC by vincegeg83
Modified: 2017-08-31 21:07 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Assembly file to illustrate low 16 bit address problem (103 bytes, text/plain)
2017-08-31 19:59 UTC, vincegeg83
Details

Note You need to log in before you can comment on or make changes to this bug.
Description vincegeg83 2017-08-30 22:27:09 UTC
The following instruction sequence generates an invalid address offset:

    .org 0x100100

data0:
    .short 0x1234

    e_lis r4, data0@ha
    e_lhz r4, data0@l(r4)

... this will assemble to code that disassembles to:

    e_lis r4, word_0x100000@ha
    e_lhz r4, word_0x100000@l

In other words, it does not calculate the lower 16 bit offset correctly.  This also fails:

    e_lis r4, data0@ha
    e_addi16 r4, r4, data0@l
    e_lhz r4, 0(r4)

Again, this assembles to reference address 0x100000 for data0.  However, the following sequence WORKS correctly:

   e_lis r4, data0@ha
   e_ori r4, r4, data0@l
   e_lhz r4, 0(r4)
Comment 1 Alan Modra 2017-08-31 01:25:49 UTC
Seems to already be fixed, if this bug ever existed.  Disassembly of relocatable object files won't always show you what you might expect, since the instruction fields may have relocations.  It pays to use objdump -dr to see the relocs.

Note that this
   e_lis r4, data0@ha
   e_ori r4, r4, data0@l
is incorrect and *will* result in wrong addresses in the final linked object for half the possible addresses of data0.  You need to use @hi to set the high 16 bits when using ori to set the low 16 bits.
Comment 2 vincegeg83 2017-08-31 19:59:27 UTC
Created attachment 10381 [details]
Assembly file to illustrate low 16 bit address problem
Comment 3 vincegeg83 2017-08-31 20:00:22 UTC
Thanks, can you confirm whether this is correct?  It doesn't seem like it:

Original assembly (attached as test.s):

	.org	0x100100

	e_b	begin
data0:
	.short 0x1234

	.align 2, 0x44
begin:
	e_lis r4, data0@ha
	e_lhz r4, data0@l(r4)

_@photon ~/asm
$ powerpc-linux-as -many -mvle -mregnames test.s

_@photon ~/asm
$ powerpc-linux-objdump -dr a.out

a.out:     file format elf32-powerpc


Disassembly of section .text:

00000000 <data0-0x100104>:
        ...
  100100:       78 00 00 08     e_b     100108 <begin>

00100104 <data0>:
  100104:       12 34 44 44     .long 0x12344444

00100108 <begin>:
  100108:       70 80 e0 10     e_lis   r4,16
                        100108: R_PPC_VLE_HA16A .text+0x100104
  10010c:       58 84 00 00     e_lhz   r4,0(r4)
                        10010e: R_PPC_ADDR16_LO .text+0x100104


It seems to correctly set the symbol to 0x100104, but note the low 16 bit decoding is wrong, it's using 0 instead of 0x0104.
Comment 4 vincegeg83 2017-08-31 21:07:43 UTC
Ok, I think it's been sorted out.

I was converting the assembler objection file directly to binary, skipping the linker step.

I added this:


ld -melf32ppc --section-start=.text=0x100100 test.o -o test_vle.bin

...and it produces the correct machine code.