Indexed jump to the opted function
Beautifully arranged b_system_table:
Thank You!
Ok one issue I've noticed is systest.app cannot execute the SMP test anymore. The RCX register is not being preserved when b_system is called. Looking into a way around this. We may need to push rcx and have all b_system calls return back to b_system_end so it can do a pop rcx there.
I've updated the b_system branch to use push/pop for RCX. It works properly. Each sub function must have a jmp b_system_end... not as elegant as a simple ret but oh well. It leaves some room for other registers being push/popped in the future if needed.
I think this is a simpler solution, without introducing new jmp and ret instructions... Always save the index of the called function (in memory) and use it only when needed?
I checked the code and it works now, you can certainly do better because you know the whole system.
That would work as long as two or more CPU cores don't call b_system at the exact same time. There is a small possibility that the value in [b_system_function] gets overwritten by another core. A mutex could be added but I'd rather not lock b_system behind one.
You're right, I didn't know or think about that. I will work to suggest another solution...
I think this proposal is acceptable. Yes, it is slightly slower due to function calls, but the code is more elegant. ... My initial idea was like this to call functions but I tried with jump to make them faster....
I would definitely record an RCX here:
b_system:
push rcx ; save system function
cmp rcx, 0xFF
Because I only POP it here once:
; End of options
b_system_end:
pop rcx
ret
Because if you'll put it here, you'll have a memory leak every time the function index is greater than 0xFF:
; To save memory, the functions are placed in 16-bit frames
push rcx
Looks good!
There is just one fix to be made. The push rcx needs to be after the cmp and jg.
If you repeatedly call b_system with RCX being greater than 0xFF then you could overflow the stack.
I updated my branch to show that.
Another solution: call function from the stack! No more taking RCX reg at stack (just inside the functions).
Just one rygly thing: variable for empting the stack...
IF
cmp rcx, 0xFF
jg b_system_end
THEN
b_system_end:
pop rcx
ret
How are you going to POP RCX when you don't PUSH it anywhere for the case when RCX is greater than 0xFF?
Or the solution can be (as per your last commit):
; To save memory, the functions are placed in 16-bit frames
push rcx
lea ecx, [b_system_table+ecx*2] ; extract function from table by index
mov cx, [ecx] ; limit jump to 16-bit
call rcx ; call function
pop rcx ;(HERE)
b_system_end: ;because HERE you don't need POP rcx
ret
Yep - my bad. I read the code incorrectly.
Your code is good:
cmp rcx, 0xFF
jg b_system_end
; To save memory, the functions are placed in 16-bit frames
push rcx
lea ecx, [b_system_table+ecx*2] ; extract function from table by index
mov cx, [ecx] ; limit jump to 16-bit
call rcx ; call function
pop rcx
b_system_end:
ret
No problem!
What are you saying for
Another solution: call function from the stack! No more taking RCX reg at stack (just inside the functions).
Just one rygly thing: variable for empting the stack...
Doing the call rcx is better I think.
Great, If the final code is merged in your branch and if you agree I will copy it and do another final PR I would like to be merged it by your side tell me what the commit message should be?
My branch is up to date. You can copy it to your merge.
As for the commit message: "Rework b_system to use a index table instead of checking the value of CL multiple times"
It's done!
I am very happy!
I'm glad I could help, and also in the future too. You made my day man!
Awesome work there. It's much better than previous version with all those cmp's
It is very important that system functions are detected and executed as quickly as possible. If there are other similar bottlenecks in the system, please highlight them if we can speed them up?
The b_system function won't be called often so performance isn't much of a concern. It's the disk and network I/O functions that need the most performance and those have their own entry point at the start of kernel.asm