Skip to content

Different JUMP with global / not-global symbol #22

Open
@wnienhaus

Description

@wnienhaus

Overview

For JUMP instructions using an absolute/constant symbol as an argument, binutils-esp32ulp produces a different output depending on whether that symbol is exported with .global or not. This appears to be a bug.

The following example code can be used to reproduce the issue:

 .set const, 12
 .global const

entry:
 jump const

Assemble and link the example as follows:

base=global_bug  # given the source is called "global_bug.s"
esp32ulp-elf-as -o ${base}.o ${base}.s
esp32ulp-elf-ld -T esp32.ulp.ld -o ${base}.elf ${base}.o
esp32ulp-elf-objcopy -O binary ${base}.elf ${base}.bin

Inspect the binary output as follows:

xxd global_bug.bin

Current behaviour

When building the example code as is, the binary result is:

0000000: 756c 7000 0c00 0400 0000 0000 3000 0080  ulp.........0...

However, when commenting out (or removing) the line .global const - in other words const is NOT exported, then the binary result becomes:

0000000: 756c 7000 0c00 0400 0000 0000 0c00 0080  ulp.............

Notice the last (JUMP) instruction is different: 3000 0080 vs 0c00 0080.

Decoding those two, I get

# global
3000 0080:
  dreg       =   0  # 0
  addr       =  12  # Target PC
  unused     =   0  # Unused
  reg        =   0  # Immediate mode
  type       =   0  # BX_JUMP_TYPE_DIRECT
  opcode     =   8  # OPCODE_BRANCH
  sub_opcode =   0  # SUB_OPCODE_BX

# NOT global
0c00 0080:
  dreg       =   0  # 0
  addr       =   3  # Target PC
  unused     =   0  # Unused
  reg        =   0  # Immediate mode
  type       =   0  # BX_JUMP_TYPE_DIRECT
  opcode     =   8  # OPCODE_BRANCH
  sub_opcode =   0  # SUB_OPCODE_BX

Notice how the addr field is different. In fact in the second case (not global) the symbol value has been divided by 4.

I assume this is related to address translation from bytes to words, however the behaviour should at least be consistent, no matter whether a symbol is marked global or not.

Expected behaviour

I would expect the correct behaviour to be, that the JUMP instruction uses the symbol value as is (ie. addr == 12 - not divided by 4).

This would match how the ESP32 ULP coprocessor instruction set documentation describes that arguments, which are constants rather than labels, are used without conversion.

Furthermore, the JUMPR and JUMPS instructions behave that way too (i.e. they use those symbol values without conversion), irrespective of whether the symbol is marked global or not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions