[Q] Go ABI0 assembler jump table

116 views
Skip to first unread message

Jan Mercl

unread,
Sep 25, 2025, 8:51:40 AM (4 days ago) Sep 25
to golang-nuts
Hello list,

Is it possible to write code in Go ABI0 assembler that implements a jump table? Motivation example: implement in Go ABI0 assembler this example C function:

int switch_func(int op) {
    int result;
    switch (op) {
        case 0:
            result = 100;
            break;
        case 1:
            result = 200;
            break;
        case 2:
            result = 300;
            break;
        default:
            result = -1;
            break;
    }
    return result;
}


I am now compiling this to a binary search, something like:

TEXT ·switch_func(SB),$32-20
        GO_ARGS
        NO_LOCAL_POINTERS
        MOVL op+8(FP), AX
        CMPL AX, $1
        JLT lbb5
        CMPL AX, $1
        JEQ lbb4
        CMPL AX, $2
        JNE lbb6
        MOVL $300, AX
        JMP lbb8
lbb4:
        MOVL $200, AX
        JMP lbb8
lbb5:
        CMPL AX, $0
        JEQ lbb7
lbb6:
        MOVL $4294967295, AX
        JMP lbb8
lbb7:
        MOVL $100, AX
lbb8:
        MOVL AX, ret+16(FP)
        RET

It works, but for a hot switch with many cases, like in the QuickJS VM loop, the overhead is still substantial. Hence I am looking into the options for compiling it instead as a jump table.
All my attempts so far failed. Does somebody know better and/or have a working example?

TIA for any information/links etc.

-j

Jan Mercl

unread,
Sep 26, 2025, 8:21:38 AM (3 days ago) Sep 26
to golang-nuts
On Thu, Sep 25, 2025 at 2:50 PM Jan Mercl <0xj...@gmail.com> wrote:

> Is it possible to write code in Go ABI0 assembler that implements a jump table?

For posterity, this proof of concept seems to work:

jnml@e5-1650:~/tmp/jumptable$ cat main.go
package main

// int switch_func(int op) {
// int result;
// switch (op) {
// case 0:
// result = 100;
// break;
// case 1:
// result = 200;
// break;
// case 2:
// result = 300;
// break;
// default:
// result = -1;
// break;
// }
// return result;
// }

func switch_func(op int64) int64

func main() {
for i := int64(0); i < 4; i++ {
println(i, switch_func(i))
}
}
jnml@e5-1650:~/tmp/jumptable$ cat main.s
#include "funcdata.h"
#include "textflag.h"

TEXT ·switch_func(SB), $0-16
GO_ARGS
NO_LOCAL_POINTERS
JMP over
JMP case0
JMP case1
JMP case2
over:
MOVQ op+0(FP), AX
CMPQ AX, $2
JA dflt
LEAQ ·switch_func+2(SB), CX
ADDQ AX, AX
ADDQ AX, CX
JMP CX

case0:
MOVQ $100, AX
JMP done

case1:
MOVQ $200, AX
JMP done

case2:
MOVQ $300, AX
JMP done

dflt:
MOVQ $-1, AX
done:
MOVQ AX, ret+8(FP)
RET
jnml@e5-1650:~/tmp/jumptable$ go run .
0 100
1 200
2 300
3 -1
jnml@e5-1650:~/tmp/jumptable$
Reply all
Reply to author
Forward
0 new messages