Hi all

I would like to double-check something.

I am working on a or1k binutils port based on CGEN and I think I have
come across something that's currently wrong with our assembler, but
whether it's wrong or not isn't clear to me.

It's to do with the way that immediate values are encoded for branch
and jump instructions in the assembler.

For example, if we take the following OR1K assembly code:

        l.bf    1
        l.nop
        l.bf    4
        l.nop
        l.bf label1
        l.nop
        l.bf label1
        l.nop
label1:
        l.nop

Assembled with our current binutils port we get this when we disassemble:

Disassembly of section .text:

00000000 <label1-0x20>:
   0:   10 00 00 01     l.bf 4 <label1-0x1c>
   4:   15 00 00 00     l.nop 0x0
   8:   10 00 00 04     l.bf 18 <label1-0x8>
   c:   15 00 00 00     l.nop 0x0
  10:   10 00 00 04     l.bf 20 <label1>
  14:   15 00 00 00     l.nop 0x0
  18:   10 00 00 02     l.bf 20 <label1>
  1c:   15 00 00 00     l.nop 0x0

00000020 <label1>:
  20:   15 00 00 00     l.nop 0x0


But assembled and disassembled with the CGEN-derived binutils we get this:

Disassembly of section .text:

00000000 <label1-0x20>:
   0:   10 00 00 00     l.bf 0 <label1-0x20>
   4:   15 00 00 00     l.nop
   8:   10 00 00 01     l.bf c <label1-0x14>
   c:   15 00 00 00     l.nop
  10:   10 00 00 04     l.bf 20 <label1>
  14:   15 00 00 00     l.nop
  18:   10 00 00 02     l.bf 20 <label1>
  1c:   15 00 00 00     l.nop

00000020 <label1>:
  20:   15 00 00 00     l.nop


The differences are at 0 and 8, the immediates are _not_ right-shifted
by 2 in our existing toolchain, before being encoded into the
instruction, but they appear to be in the CGEN-based assembler.

I just thought this was a bug in our CGEN port, so I changed it so we
don't right-shift, but then we get this:

Disassembly of section .text:

00000000 <label1-0x20>:
   0:   10 00 00 01     l.bf 4 <label1-0x1c>
   4:   15 00 00 00     l.nop 0x0
   8:   10 00 00 04     l.bf 18 <label1-0x8>
   c:   15 00 00 00     l.nop 0x0
  10:   10 00 00 10     l.bf 50 <label1+0x30>
  14:   15 00 00 00     l.nop 0x0
  18:   10 00 00 08     l.bf 38 <label1+0x18>
  1c:   15 00 00 00     l.nop 0x0

00000020 <label1>:
  20:   15 00 00 00     l.nop 0x0

In this case, 0 and 8 appear like our current assembler, but now the
addresses for the label are not right-shifted by 2.

In our currently-used binutils port the assembler is handling the
special case of resolved label addresses in the md_apply_fix()
function in binutils-2.20.1/gas/config/tc-or32.c (line 413):

          insn |= (*val >> 2) & 0x03ffffff;

But I wonder if we should be leaving the immediate values in the
assembler un-shifted.

The or1k architecture spec has for l.j:

  Format:
    l.j N
  Description:
    The immediate value is shifted left two bits,
    sign-extended to program counter width, and
    then added to the address of the jump
    instruction. The result is the effective address of the
    jump. The program unconditionally jumps to EA with
    a delay of one instruction.

  32-bit Implementation:
    PC ← exts(Immediate << 2) + JumpInsnAddr

My interpretation of this is that we should _not_ be shifting the
immediate right by two (if it's a numerical immediate value, as
opposed to a label) and should be encoding that directly into the
instruction.

Does this sound right? I think it does, and would mean that any
existing assembler's encoding of l.j and l.b(n)f instructions with
numerical immediates is OK. In which case I need to get on the CGEN
list to ask about handling these two cases... :-(

But can anyone confirm this sounds sensible?

Thanks,

    Julius
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc

Reply via email to