This commit is contained in:
julianb0 2019-06-15 20:21:38 +02:00
parent 24ef00ab3e
commit 8796f78bf5
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
13 changed files with 206 additions and 38 deletions

View File

@ -12,8 +12,8 @@ rcx
rdx
rsx
rbi
rdi
rsi
rdi
nx0
nx1
nx2

111
ka/ABI Normal file
View 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
#------------------------------------------------------------------------------#

View File

@ -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:

View File

@ -21,7 +21,6 @@ strncmp:
mov.cxz rax, 0
ret.cxz
cld
rep.e cmpzsb ax0, ax1
mov rax, b[ax0]

View File

@ -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:

View File

@ -5,7 +5,6 @@
; int strnlen(char *, int)
;
strnlen:
cld
mov rcx, ax1
rep.nz scasb ax0, 0

View File

@ -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

View File

@ -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
View 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

View File

@ -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"); \
}
//----------------------------------------------------------------------------//

View File

@ -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();

View File

@ -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 },

View File

@ -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,