Please help to make inline ASM jumptable

General FreeBASIC programming questions.
Post Reply
Emulog
Posts: 24
Joined: Jan 12, 2023 0:44

Please help to make inline ASM jumptable

Post by Emulog »

I have a select/case of 30 more cases and growing as a main loop.
With -RR option i saw in asm that code is done via JNE sequence.
I am new to FB and x64 asm, how should i write something like jmp [eax+ebx] and somehow put offsets in sequence to this jump.
Or must it be a relative jump to a sequence of jump opcodes, like in Z80 asm ?
Also i read that inline ASM do some push/pops on entry/exit , is this true ? How to overcome this ? I saw that gcc have a "volatile" word to keep code at -O2/3 stages, where add this ?
I need a 64-entry jumptable with linear case value of 0..63 to put instead of select/case/end.
SARG
Posts: 1756
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Please help to make inline ASM jumptable

Post by SARG »

Using 'as const' with select case creates a jump table.

Try this code compiled with -gen gas64 to see (asm code) the jump table.

Code: Select all

dim as integer myselect

select case as const myselect
	Case 4
	print "4"
	case 5
	print "5"
	case 6
	print "6"
End Select
Emulog
Posts: 24
Joined: Jan 12, 2023 0:44

Re: Please help to make inline ASM jumptable

Post by Emulog »

Since -O3 is a allmighty beast, to find out my cases i changed your sample to
dim as integer myselect,A,B,C,D,E,F,G
For MYSELECT=0 To 7
select case as const myselect
Case 0 : A+=1:print "_a_"
Case 1 : print "_b_":B+=1
case 3: C+=1:print "_c_"
Case 4 : Print "_d_":D+=1
case 5 : E+=1:print "_e_"
case 6: print "_f_":F+=1
case 7: G+=1:print "_g_"
End Select:Print "REPEAT":Next :Sleep
It has optimised fb_PrintString instances, but cases are intact, and yes i found
mov r8d, 1
mov edx, 123
xor ecx, ecx
call fb_PrintLongint
jmp [QWORD PTR [rbx]] and no extra jne's
.p2align 4
.p2align 3
Thank you so much, :D :D :D
[SOLVED]
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Please help to make inline ASM jumptable

Post by marcov »

Use an array of pointers to point to the integers and then simply

arrptr[0]=&a : arrptr[1]=&b: arrptr[2]=&c:
etc

then

For MYSELECT=0 To 7
*arrptr+=1

No jumps, much faster. I assumed the printing was only for debugging. (and if not, print() is much slower than any case table optimization anyway)
Emulog
Posts: 24
Joined: Jan 12, 2023 0:44

Re: Please help to make inline ASM jumptable

Post by Emulog »

It will be a bunch of cases doing "microcode" simulation for a virtual cpu.
All arrays and lut's will be at "and 31" offset used by *ptr's, double reference to simulated "registers" might hurt speed.
While most of data moves are optimized by gcc to register usage, those who not fit locally will be referenced by mov r**,[mem] indirectly, it costs time for data be located at L1 or L2 cache, and cache misses along with many jumps impact speed. So operand size matters too.
Emulog
Posts: 24
Joined: Jan 12, 2023 0:44

Re: Please help to make inline ASM jumptable

Post by Emulog »

And yet i am back for inline ASM jumptable. For x64 code model.
Now i have finished my rewrite of "select case" pile to pure asm, got rid of all variables, and all perform on registers only.
I am stuck with three problems :
1. GAS do not accept jump labels from freebasic program body.
2. "Select case as const" asm code header is somehow split to 2 chunks, first compare case bound, second calculate and jump.
3. Now I really need to build my own jumptable using inline ASM, and yes i've tried googling for that.
Can i hack in compiled code by scanning for certain specific "signature" and do calculated jumps by myself ? Just curios though. Need to find array of label offsets somehow, and probably some extra things too. :?:
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: Please help to make inline ASM jumptable

Post by srvaldez »

hello Emulog :)
here's something, not sure it will help
here's what I did
I Googled for: x64 asm jump table
I went to https://www.reddit.com/r/learnprogrammi ... mentation/
copied the C code and pasted it in https://godbolt.org/
copy the generated asm code and paste into geany IDE
the registers used are for linux, to make it work for Windows you need to search and replace the registers
search for rdx and replace with r8
search for rsi and replace with rdx
search for rdi and replace with rcx
so here's the FB code

Code: Select all

sub switch_eg naked cdecl(byval x as long, byval n as long, byref dest as long)
	asm
        sub     rdx, 100
        cmp     rdx, 6
        ja      .L10
        jmp     [QWORD PTR .L6[0+rdx*8]]
.L6:
        .quad   .L9
        .quad   .L10
        .quad   .L8
        .quad   .L7
        .quad   .L5
        .quad   .L10
        .quad   .L5
.L8:
        add     rcx, 10 'dest = x + 10
.L7: 'No break, falls through
        add     rcx, 11 'dest = x + 11
        mov     QWORD PTR [r8], rcx
        ret
.L5:
        imul    rcx, rcx 'dest = x * x
        mov     QWORD PTR [r8], rcx
        ret
.L9:
        lea     rax, [rcx+rcx*2]  'dest = x * 13
        lea     rcx, [rcx+rax*4]
        mov     QWORD PTR [r8], rcx
        ret
.L10:
        xor     edi, edi 'dest = x
        mov     QWORD PTR [r8], rcx
        ret
	end asm
end sub

dim as long z, k, r

switch_eg 2, 100, r
? r

switch_eg 2, 102, r
? r

switch_eg 2, 103, r
? r

switch_eg 2, 104, r
? r

switch_eg 2, 0, r
? r
I get
26
23
13
4
2
[edit]
this code may not compile with binutils versions newer than 2.34, unless you pass -Wl "--image-base 0x40000000" on the compile command
see viewtopic.php?p=287143#p287143
the offending line is jmp [QWORD PTR .L6[0+rdx*8]]
I don't see how you could add [rip] to that statement
the code in the next post has no problems compiling with binutils 2.40
[edit 2]
it works if you do
lea rax, [rip+.L6]
jmp [QWORD PTR [rax+rdx*8]]
Last edited by srvaldez on Feb 17, 2023 0:45, edited 3 times in total.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: Please help to make inline ASM jumptable

Post by srvaldez »

here's a version using the code generated by clang-15

Code: Select all

sub switch_eg naked cdecl(byval x as long, byval n as long, byref dest as long)
	asm
        xor     eax, eax
        add     rdx, -100
        cmp     rdx, 6
        ja      .LBB1_7
        lea     r9, [rip + .LJTI1_0]
        movsxd  rdx, dword ptr [r9 + 4*rdx]
        add     rdx, r9
        jmp     rdx
.LBB1_5:
        imul    rcx, rcx
        jmp     .LBB1_6
.LBB1_2:
        lea     rax, [rcx + 2*rcx]
        lea     rax, [rcx + 4*rax]
        mov     qword ptr [r8], rax
        ret
.LBB1_3:
        add     rcx, 10
.LBB1_4:
        add     rcx, 11
.LBB1_6:
        mov     rax, rcx
.LBB1_7:
        mov     qword ptr [r8], rcx
        ret
.LJTI1_0:
        .long   .LBB1_2-.LJTI1_0
        .long   .LBB1_7-.LJTI1_0
        .long   .LBB1_3-.LJTI1_0
        .long   .LBB1_4-.LJTI1_0
        .long   .LBB1_5-.LJTI1_0
        .long   .LBB1_7-.LJTI1_0
        .long   .LBB1_5-.LJTI1_0
	end asm
end sub

dim as long z, k, r

z=7

switch_eg z, 100, r
? r

switch_eg z, 102, r
? r

switch_eg z, 103, r
? r

switch_eg z, 104, r
? r

switch_eg z, 0, r
? r
there was a bug in the generated code --at least I think so-- the default option was returning 0 instead of the value of the first parameter
Emulog
Posts: 24
Joined: Jan 12, 2023 0:44

Re: Please help to make inline ASM jumptable

Post by Emulog »

:D :D :D
Ive got a workaround for labels, just enclose it to asm/end asm.
For the jumptable - i used first your sample.Also added .align's. Works nice.
Second one looks like a bit more opcodes issued.
Thank you for these two. :D
Topic solved. 8)

Code: Select all

ASMGO; 'EBX CONTAIN UOP
CMP EBX,346;
JA .ENDSEL
JMP [QWORD PTR .LABARR[0+RBX*8]]
.ALIGN 32
.LABARR:
.QUAD .JTL0
.QUAD .JTL1
.QUAD .JTL2
.QUAD .JTL3
.QUAD .JTL4
.... and then 
.ALIGN 8
.JTL0: REJUMP'XERR+=1 '"ERROR ZERO"
' SET ADDRESS BUS SERIES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
.ALIGN 8
.JTL1: ROR UMR,48;MOV UPRW,UMRW;ROR UPR,16;MOV UPRW,UMRW;ROL UPR,16;ROL UMR,48;REJUMP' "UADBC"
.ALIGN 8
.JTL2: ROR UMR,32;MOV UPRW,UMRW;ROR UPR,16;MOV UPRW,UMRW;ROL UPR,16;ROL UMR,32;REJUMP' "UADDE"
....
Post Reply