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.
Please help to make inline ASM jumptable
Re: Please help to make inline ASM jumptable
Using 'as const' with select case creates a jump table.
Try this code compiled with -gen gas64 to see (asm code) the 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
Re: Please help to make inline ASM jumptable
Since -O3 is a allmighty beast, to find out my cases i changed your sample to
[SOLVED]
It has optimised fb_PrintString instances, but cases are intact, and yes i founddim 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
Thank you so much,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
[SOLVED]
Re: Please help to make inline ASM jumptable
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)
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)
Re: Please help to make inline ASM jumptable
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.
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.
Re: Please help to make inline ASM jumptable
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.
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.
Re: Please help to make inline ASM jumptable
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
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]]
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
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.
Re: Please help to make inline ASM jumptable
here's a version using the code generated by clang-15
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
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
Re: Please help to make inline ASM jumptable
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.
Topic solved.
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"
....