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