adrianmcmenamin
adrianmcmenamin

Reputation: 1129

RISC V assembly alignment errors

I am trying to build a Forth-like threaded interpretive language (TIL) using the Spike RISC-V emulator and the pk kernel. I am using riscv64-unknown-elf-gcc to build the ELFs.

I am having a lot of issues with alignment - I believe the code should be eight-byte aligned and for a while I got that by sticking a nop in the header generating macro (for those that don't know TILs, the commands are generally built out of blocks of assembly which have a standard structure - I am using a macro to generate the structure.

I have just extended the code alot - adding more keywords etc - and the alignment issue is back again. Eg:

riscv64-unknown-elf-gcc -o riscyforth riscyforth.S
...... /../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/bin/ld: /tmp/ccpobhjr.o(.text+0x679): 7 bytes required for alignment to 8-byte boundary, but only 6 present
..... /../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/bin/ld: can't relax section: bad value
collect2: error: ld returned 1 exit status

This is the macro generating the function headers:

.macro CODEHEADER Name, PrevName, flags
.balign 8
TIL_\Name:
        .4byte  \flags
        .4byte  \Name
ptr_\PrevName:
        .4byte TIL_\PrevName
length_ASCII_\Name:
        .4byte end_\Name - beg_\Name
beg_\Name:
        .ascii "\Name" 
end_\Name:
        .balign 8
\Name:
.endm

The executable code begins at \Name and this is where I am trying to guarantee 8 byte alignment - eg a typical function might look like (this one puts a 1 on the stack):

           CODEHEADER 1, DOT
            li t0, 1
            PUSH t0
            tail NEXT

and the li t0, 1 would be the found at \Name where Name was 1.

Is there a way to guarantee this alignment? I cannot find anything in online documentation but wondered if any users had heuristics here?

Upvotes: 0

Views: 1920

Answers (3)

teeh
teeh

Reputation: 9

Use pad as .p2align 4, 0x20 the cell size in RISCV must be 4 bytes

Upvotes: -1

teeh
teeh

Reputation: 9

I'm using

// set start reverse linked list
// trick adapted from amforth-6.9
99:
.word 0

.macro header name, label, flags=0x0
is_\label:
    .p2align 1, 0x00
    .word 99b
99:
    .byte \flags
    .byte (3f - 2f) 
2:
    .ascii "\name"
3:
    .p2align 2, 0x20    
\label:
.endm

Could reorder it :)

Upvotes: 1

adrianmcmenamin
adrianmcmenamin

Reputation: 1129

Here's how I solved this problem:

.balign 8

Does appear to be working correctly but it didn't guarantee that all the instructions in my FORTH were properly aligned because (if you are familiar with FORTH/TILs this make more sense than if you are not) the function headers had variable size function names and so were followed by actual code that would not necessarily be in alignment.

I fixed this by setting aside a fixed size for function names and - ensuring code started again on an aligned address. I also issue a nop at the start of every function to ensure each function starts at an aligned address to begin with. Here's the macro:

.macro CODEHEADER Name, PrevName, flags
nop
TIL_\Name:
        .4byte  \flags
        .4byte  \Name
ptr_\PrevName:
        .4byte TIL_\PrevName
length_ASCII_\Name:
        .4byte (end_\Name - beg_\Name) + 1
beg_\Name:
        .ascii "\Name"
end_\Name:
        .fill (24 - (end_\Name - beg_\Name)), 1, 0xFF
\Name:
.endm

Upvotes: 1

Related Questions