mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
abi
This commit is contained in:
parent
24ef00ab3e
commit
8796f78bf5
@ -12,8 +12,8 @@ rcx
|
||||
rdx
|
||||
rsx
|
||||
rbi
|
||||
rdi
|
||||
rsi
|
||||
rdi
|
||||
nx0
|
||||
nx1
|
||||
nx2
|
||||
|
111
ka/ABI
Normal file
111
ka/ABI
Normal file
@ -0,0 +1,111 @@
|
||||
# The OS/K Team licenses this file to you under the MIT license.
|
||||
# See the LICENSE file in the project root for more information.
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
1. STACK
|
||||
|
||||
Stack grows downward. 'rbp' and 'rsp' are both used.
|
||||
There is no red zone. The lowest stack frame is marked by having 'rbp' = 0.
|
||||
|
||||
A function's assembly code looks like this:
|
||||
label:
|
||||
enter N
|
||||
...
|
||||
...
|
||||
...
|
||||
leave
|
||||
ret
|
||||
'N' is the number of local variables used by the function,
|
||||
and is omitted if there are none ('enter' alone takes N=0).
|
||||
|
||||
The above code is equivalent to the following, but faster:
|
||||
label:
|
||||
mov [rsp-8], rbp
|
||||
lea rbp, [rsp-8]
|
||||
sub rsp, (N+1)*8
|
||||
...
|
||||
...
|
||||
...
|
||||
lea rsp, [rbp]
|
||||
mov rbp, [rsp]
|
||||
ret
|
||||
|
||||
Between the 'enter' and the 'leave', the stack looks like this:
|
||||
. .
|
||||
. .
|
||||
. (caller's) .
|
||||
|---------------|
|
||||
| saved rip | rbp+8
|
||||
| saved rbp | rbp+0
|
||||
| . | rsp+(N*8) \
|
||||
| . | ... |
|
||||
| . | ... |
|
||||
| . | ... |- Local variables
|
||||
| . | rsp+16 |
|
||||
| . | rsp+8 |
|
||||
| . | rsp+0 /
|
||||
|---------------|
|
||||
. (undefined) .
|
||||
. .
|
||||
. .
|
||||
|
||||
|
||||
'enter' and 'leave' can be omitted if ALL the following hold:
|
||||
the function
|
||||
- uses no local variables (on the stack)
|
||||
- never uses any function that changes 'rbp' nor 'rsp',
|
||||
aside from 'call' and 'ret'
|
||||
- never calls a variadic function
|
||||
|
||||
You can never omit 'enter' without omitting 'leave', anc vice-versa.
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
2. CALLING CONVENTION
|
||||
|
||||
No matter whether 'enter' and 'leave' were ommited or not, the following must
|
||||
hold true whenever a function is entered or exited from:
|
||||
- 'rbp' must be 8-bytes aligned
|
||||
- 'rsp' must be 8-bytes aligned
|
||||
- the DF flag must be cleared
|
||||
|
||||
Aside from the DF flag, a function cannot assume anything about the state
|
||||
of the flags in the FLG register.
|
||||
|
||||
Passing parameters is done using the following registers, in that order:
|
||||
ax0-ax7, lx0-lx7
|
||||
|
||||
The stack is never used for argument passing. If you need to pass large
|
||||
structures of data, pass their address in an appropriate register.
|
||||
|
||||
Return values are passed in 'rax'. If the return value does not fit
|
||||
and require more registers, use the following registers, in that order:
|
||||
rax, rdx, lx0-lx7
|
||||
|
||||
The following registers are volatile; the calling function cannot assume
|
||||
that they will be left unmodified by the called function:
|
||||
rax, rcx, rdx, rsi, rdi, lx0-lx7, ax0-ax7
|
||||
|
||||
The following registers are nonvolatile; the called function must preserve them:
|
||||
rbp, rsp, rbx, rsx, rbi, nx0-nx7
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
3. SPECIAL REGISTERS
|
||||
|
||||
The 'inv' register cannot be referenced by machine code except when specified
|
||||
as an offset register in the [reg+reg(*/+...)] memory formats; in these case,
|
||||
'inv' can be assumed to be always null.
|
||||
|
||||
The following registers can only be used by the supervisor; they are intended
|
||||
to be used as fast global variables for the supervisor:
|
||||
sa0-sa7
|
||||
|
||||
The following registers cannot be referenced by machine code at all; they must
|
||||
be manipulated through specific instructions, and manipulating their values
|
||||
allow for controlling the machine in various ways:
|
||||
cr0-cr7
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
|
@ -8,7 +8,7 @@
|
||||
;
|
||||
_itoa:
|
||||
mov rax, ax0
|
||||
xor rdx, rdx
|
||||
xor lx0, lx0
|
||||
|
||||
; make sure base is in [2, 32]
|
||||
|
||||
@ -30,9 +30,9 @@ _itoa:
|
||||
cmp ax2, 10 ; base 10
|
||||
jmp.nz .conv
|
||||
|
||||
sgn rdx, ax1 ; extract ax1 sign
|
||||
sgn lx0, ax1 ; extract ax1 sign
|
||||
|
||||
cmp rdx, -1 ; negative?
|
||||
cmp lx0, -1 ; negative?
|
||||
neg.z ax1
|
||||
|
||||
; main loop
|
||||
@ -40,20 +40,20 @@ _itoa:
|
||||
test ax1, ax1
|
||||
jmp.z .fini
|
||||
|
||||
mov rsx, ax1
|
||||
mod rsx, ax2 ; ax1 % base
|
||||
mov lx1, ax1
|
||||
mod lx1, ax2 ; ax1 % base
|
||||
|
||||
cmp rsx, 9 ; rsx > 9 ?
|
||||
cmp lx1, 9 ; lx1 > 9 ?
|
||||
jmp.a .nondec
|
||||
|
||||
add rsx, 48 ; '0'
|
||||
add lx1, 48 ; '0'
|
||||
jmp .next
|
||||
|
||||
.nondec:
|
||||
add rsx, 87 ; 'a' - 10
|
||||
add lx1, 87 ; 'a' - 10
|
||||
|
||||
.next:
|
||||
mov b[ax0], rsx
|
||||
mov b[ax0], lx1
|
||||
inc ax0
|
||||
|
||||
div ax1, ax2
|
||||
@ -61,7 +61,7 @@ _itoa:
|
||||
|
||||
; add minus flag, null-terminate and reverse
|
||||
.fini:
|
||||
cmp rdx, -1
|
||||
cmp lx0, -1
|
||||
mov.z b[ax0], 45 ; '-'
|
||||
inc.z ax0
|
||||
|
||||
@ -78,7 +78,7 @@ _itoa:
|
||||
|
||||
.bad:
|
||||
mov q[errno], EINVAL
|
||||
mov b[rax], 0
|
||||
mov b[ax0], 0
|
||||
ret
|
||||
|
||||
.zero:
|
||||
|
@ -21,7 +21,6 @@ strncmp:
|
||||
mov.cxz rax, 0
|
||||
ret.cxz
|
||||
|
||||
cld
|
||||
rep.e cmpzsb ax0, ax1
|
||||
|
||||
mov rax, b[ax0]
|
||||
|
@ -15,7 +15,6 @@ strncpy:
|
||||
mov rcx, ax2
|
||||
ret.cxz
|
||||
|
||||
cld
|
||||
rep.nz movsb ax0, ax1
|
||||
|
||||
ret
|
||||
@ -30,7 +29,6 @@ strnzcpy:
|
||||
dec rcx
|
||||
jmp.cxz .1
|
||||
|
||||
cld
|
||||
rep.nz movsb ax0, ax1
|
||||
|
||||
.1:
|
||||
|
@ -5,7 +5,6 @@
|
||||
; int strnlen(char *, int)
|
||||
;
|
||||
strnlen:
|
||||
cld
|
||||
mov rcx, ax1
|
||||
rep.nz scasb ax0, 0
|
||||
|
||||
|
@ -12,7 +12,7 @@ strrev:
|
||||
ret.z
|
||||
|
||||
; save str's location
|
||||
mov rdx, ax1
|
||||
mov lx0, ax1
|
||||
|
||||
; go to str's end, just before
|
||||
; the null terminator
|
||||
@ -26,7 +26,7 @@ strrev:
|
||||
; and forward through buf
|
||||
mov b[ax0], b[ax1]
|
||||
|
||||
cmp ax1, rdx
|
||||
cmp ax1, lx0
|
||||
mov.z b[ax0+1], 0
|
||||
ret.z
|
||||
|
||||
|
4
ka/dos.k
4
ka/dos.k
@ -5,8 +5,8 @@
|
||||
; Entry point
|
||||
;
|
||||
_start:
|
||||
mov rbp, 0x200000
|
||||
mov rsp, rbp
|
||||
mov rsp, 0x200000
|
||||
xor rbp, rbp
|
||||
|
||||
call main
|
||||
|
||||
|
60
ka/sys/cpudev.k
Normal file
60
ka/sys/cpudev.k
Normal file
@ -0,0 +1,60 @@
|
||||
; The OS/K Team licenses this file to you under the MIT license.
|
||||
; See the LICENSE file in the project root for more information.
|
||||
|
||||
CPUDEV := 0
|
||||
|
||||
RFS.GetMaxIdx:
|
||||
iocall CPUDEV, 16
|
||||
ret
|
||||
|
||||
RFS.GetUsage:
|
||||
iocall CPUDEV, 17
|
||||
ret
|
||||
|
||||
RFS.GetCurIdx:
|
||||
iocall CPUDEV, 18
|
||||
ret
|
||||
|
||||
RFS.GetLeastAvail:
|
||||
iocall CPUDEV, 19
|
||||
ret
|
||||
|
||||
RFS.IsFrameActive:
|
||||
iocall CPUDEV, 20
|
||||
ret
|
||||
|
||||
RFS.ActivateFrame:
|
||||
iocall CPUDEV, 21
|
||||
ret
|
||||
|
||||
RFS.CopyFrame:
|
||||
iocall CPUDEV, 22
|
||||
ret
|
||||
|
||||
RFS.MoveFrame:
|
||||
iocall CPUDEV, 23
|
||||
ret
|
||||
|
||||
RFS.LoadArgs:
|
||||
iocall CPUDEV, 32
|
||||
ret
|
||||
|
||||
RFS.LoadReg:
|
||||
iocall CPUDEV, 33
|
||||
ret
|
||||
|
||||
RFS.StoreReg:
|
||||
iocall CPUDEV, 48
|
||||
ret
|
||||
|
||||
IDT.AddHandler:
|
||||
iocall CPUDEV, 64
|
||||
ret
|
||||
|
||||
IDT.DelHandler:
|
||||
iocall CPUDEV, 65
|
||||
ret
|
||||
|
||||
IDT.QueryHandler:
|
||||
iocall CPUDEV, 66
|
||||
|
@ -73,12 +73,9 @@ bool i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2, ulong *r1, ulong *r2) \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHK_STACK(op) \
|
||||
#define CHK_STACK() \
|
||||
if (rsp % 8 > 0 || rbp % 8 > 0) { \
|
||||
_except(ctx, E_STA, "Misaligned stack REGS"); \
|
||||
} \
|
||||
if (rbp op rsp) { \
|
||||
_except(ctx, E_STU, "Stack underflow"); \
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
@ -9,21 +9,21 @@
|
||||
|
||||
IMPL_START_1(push)
|
||||
{
|
||||
CHK_STACK(<);
|
||||
CHK_STACK();
|
||||
PUSH(v1);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_1(pop)
|
||||
{
|
||||
CHK_STACK(<=);
|
||||
CHK_STACK();
|
||||
POP(v1);
|
||||
}
|
||||
IMPL_OUT;
|
||||
|
||||
IMPL_START_1(call)
|
||||
{
|
||||
CHK_STACK(<);
|
||||
CHK_STACK();
|
||||
PUSH(rip);
|
||||
JUMP(v1);
|
||||
}
|
||||
@ -31,16 +31,14 @@ IMPL_END;
|
||||
|
||||
IMPL_START_0(ret)
|
||||
{
|
||||
CHK_STACK(<=);
|
||||
CHK_STACK();
|
||||
POP(rip);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_0(enter)
|
||||
{
|
||||
// We don't CHK_STACK(<) here because ENTER
|
||||
// (should) always be preceded by a CALL,
|
||||
// which already checks the stack
|
||||
CHK_STACK();
|
||||
|
||||
PUSH(rbp);
|
||||
rbp = rsp;
|
||||
@ -53,8 +51,6 @@ IMPL_END;
|
||||
|
||||
IMPL_START_0(leave)
|
||||
{
|
||||
// Do NOT check stack here
|
||||
// (it would always fail)
|
||||
rsp = rbp;
|
||||
POP(rbp);
|
||||
}
|
||||
@ -62,14 +58,14 @@ IMPL_END;
|
||||
|
||||
IMPL_START_0(pushf)
|
||||
{
|
||||
CHK_STACK(<);
|
||||
CHK_STACK();
|
||||
PUSH(flg);
|
||||
}
|
||||
IMPL_END;
|
||||
|
||||
IMPL_START_0(popf)
|
||||
{
|
||||
CHK_STACK(<=);
|
||||
CHK_STACK();
|
||||
|
||||
// XXX
|
||||
CHK_SUPERV();
|
||||
|
@ -30,8 +30,8 @@ reg_t arch_r[NREGS] =
|
||||
{ "rdx", 0, GPR },
|
||||
{ "rsx", 0, GPR },
|
||||
{ "rbi", 0, GPR },
|
||||
{ "rdi", 0, GPR },
|
||||
{ "rsi", 0, GPR },
|
||||
{ "rdi", 0, GPR },
|
||||
|
||||
// General-purpose non-volatile registers
|
||||
{ "nx0", 0, GPR },
|
||||
|
12
vm/pc/regs.h
12
vm/pc/regs.h
@ -52,15 +52,15 @@ enum
|
||||
#define rsp R(RSP)
|
||||
|
||||
RAX, RBX, RCX, RDX,
|
||||
RSX, RBI, RDI, RSI,
|
||||
RSX, RBI, RSI, RDI,
|
||||
#define rax R(RAX)
|
||||
#define rbx R(RBX)
|
||||
#define rcx R(RCX)
|
||||
#define rdx R(RDX)
|
||||
#define rsx R(RSX)
|
||||
#define rbi R(RBI)
|
||||
#define rdi R(RDI)
|
||||
#define rsi R(RSI)
|
||||
#define rdi R(RDI)
|
||||
|
||||
NX0, NX1, NX2, NX3,
|
||||
NX4, NX5, NX6, NX7,
|
||||
@ -82,6 +82,14 @@ enum
|
||||
|
||||
LX0, LX1, LX2, LX3,
|
||||
LX4, LX5, LX6, LX7,
|
||||
#define lx0 R(LX0)
|
||||
#define lx1 R(LX1)
|
||||
#define lx2 R(LX2)
|
||||
#define lx3 R(LX3)
|
||||
#define lx4 R(LX4)
|
||||
#define lx5 R(LX5)
|
||||
#define lx6 R(LX6)
|
||||
#define lx7 R(LX7)
|
||||
|
||||
CR0, CR1, CR2, CR3,
|
||||
CR4, CR5, CR6, CR7,
|
||||
|
Loading…
Reference in New Issue
Block a user