; memory headers
%pragma once

%define chseg(x,y)       _chseg x,y    ; chseg :: reg *seg -> int16 new -> void
%define sret(x)          _sret x       ; sret :: reg *seg -> void
;%define sret()          _sret         ; sret :: void -> void
%define palloc(x)        _palloc x     ; palloc :: int8 _blocks -> int32 *addr
%define valloc(h,l,x,li) _valloc h,l,x,li
%define valloc(h,l,x)    _valloc h,l,x ; valloc :: addr24 *hi:low -> int8 xs
                                      ;   -> int16 limit? -> int16 selector
; %define xdtr(x)         _xdtr x       ; xdtr :: int8 xdt -> gdtr *seg:addr
; %define xdt(x)          _xdt x        ; xdt :: int8 xdt -> gdtentry *seg:addr
%define showgdt()       _showgdt      ; showgdt :: void -> void

%define MaxGdtSz 248

%ifdef xpmemory
  global Palloc
%else
  extern Palloc
%endif

%ifdef xvmemory
  global Valloc
  global Showgdt
%else
  extern Valloc
  extern Showgdt
%endif

struc gdtentry
    .limit:   resw 1
    .baselo:  resw 1
    .basehi   resb 1
    .xs:      resb 1
    .reserv:  resw 1
endstruc

%macro _showgdt 0
  call Showgdt
%endmacro

%macro _chseg 2
;   %push chseg
;   %define %$reg %1
   mov ax,%1
   push ax
   cmp word ax,%2
   je %%eq
 %%neq:
   mov ax,%2   ; ax=new seg
   mov %1,ax
 %%eq:
%endmacro

;%macro _sret 0
;   pop bx
;   mov cx,%$reg
;   %undef %$reg
;   %pop
;
;   cmp bx,cx
;   je %%eq
; %%neq:
;   mov %1,bx
; %%eq:
;%endmacro

%macro _sret 1
   pop bx
   push cx
   mov cx,%1
   cmp bx,cx
   pop cx
   je %%eq
 %%neq:
   mov %1,bx
 %%eq:
%endmacro

%macro _palloc 1
  mov ax,%1
  push ax
  call Palloc
  add sp,0x0002
%endmacro

%macro _valloc 4
  mov ax,%4
  push ax
  mov ax,%3
  and ax,0xff
  push ax
  mov ax,%2
  push ax
  mov ax,%1
  and ax,0xff
  push ax
  call Valloc
  carry 4
%endmacro
%macro _valloc 3
  mov ax,0xffff
  push ax
  mov ax,%3
  and ax,0xff
  push ax
  mov ax,%2
  push ax
  mov ax,%1
  and ax,0xff
  push ax
  call Valloc
  carry 4
%endmacro

; todo: add ldt support
%macro _xdtr 1
  mov dx,csselector
  mov ax,confseg.gdtr
%endmacro

; todo: add ldt support
%macro _xdt 1
  push si

  mov dx,csselector
  chseg(ds,dx)
  mov si,confseg.gdtseg
  mov word dx,ds:[si]
  xor ax,ax

  sret(ds)
  pop si
  clc
%endmacro 

struc Gdtr
  .sz:   resw 1
  .low:  resw 1
  .hi:   resb 1
  .end:
endstruc
