Bug 15649 - ARM - Invalid constant after fixup with shifted immediate values
Summary: ARM - Invalid constant after fixup with shifted immediate values
Status: WAITING
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.23
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-06-19 14:32 UTC by Michał Leśniewski
Modified: 2013-06-26 09:52 UTC (History)
2 users (show)

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


Attachments
Use A1 encoding when A2 encoding of negative PC+offset fails (931 bytes, patch)
2013-06-26 09:52 UTC, Nick Clifton
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michał Leśniewski 2013-06-19 14:32:00 UTC
The ARM data processing instructions (e.g. add, mov, and, etc.) accept immediate operators. The immediate values can be 8-bit values rotated by any even number of bits in the range 0-30. For example, it is possible to use immediate values like 0xab, 0xab000000 and 0x00ab, but not 0xa000b000.

gas accepts immediate operands in two forms: 
   insn rd, rm, imm, rot          @ rd := insn(rm, rot32(imm8, rot4))
   insn rd, rm, imm               @ rd := insn(rm, imm)

In the first case, the base value (imm) and the rotation are given explicitly. In the second case, these values are calculated by gas. 

I found out that when using the second syntax, gas reports an error saying "invalid constant (...) after fixup" when some valid immediate values are given. 

Example instruction:
  add	r0, r1, #0xf000000f

Equivalent instruction (which is handled correctly): 
  add	r0, r1, #0xff, #4
Comment 1 Nick Clifton 2013-06-24 14:01:09 UTC
Hi Michal,

  Please could you provide a test case to reproduce this problem ?

  I tried the following:

  % cat pr15649.s
       .text
        .global foo
    foo: 
        add     r0, r1, #0xf000000f
        add     r0, r1, #0xff, 4

  But was able to assemble it without any problems:

  % as pr15649.s
  % objdump -d a.out
  a.out:     file format elf32-littlearm

  Disassembly of section .text:

  00000000 <foo>:
     0:   e28102ff        add     r0, r1, #-268435441     ; 0xf000000f
     4:   e28102ff        add     r0, r1, #-268435441     ; 0xf000000f


This was using GAS built from the 2.23 branch, but the same thing happens with the current mainline sources as well.

Cheers
  Nick
Comment 2 Michał Leśniewski 2013-06-25 07:36:56 UTC
Hi Nick,

I run a few tests to see which values actually cause the problem. 

Here are is a small source file which demonstrates the problem:
       .text
       .global foo
       .syntax unified
       .arm

    foo: 
        add r0, pc, #0x7d, 4
        add r0, pc, #0xd0000007

        add r0, pc, #0xe8, 4
        add r0, pc, #0x8000000e

        add r0, pc, #0x53, 2
        add r0, pc, #0xc0000014

Output:
test.S: Assembler messages:
test.S:8: Error: invalid constant (ffffffffd0000007) after fixup
test.S:11: Error: invalid constant (ffffffff8000000e) after fixup
test.S:14: Error: invalid constant (ffffffffc0000014) after fixup

I also checked with other operand registers (rn != pc) -- the assembler did not report any errors.
Comment 3 Nick Clifton 2013-06-26 09:52:29 UTC
Created attachment 7094 [details]
Use A1 encoding when A2 encoding of negative PC+offset fails

Here is a possible patch.  I am not sure that it is 100% correct however - I need an opinion from an ARM assembler expert...