;****************************************************************************
;
;AMDO64 by valy, 2004-2005. Alpha version
;For AMD64 machines (Opteron OK... Athlon 64 ? a priori)
;
;DOS->RM16->PM16->PM64 long mode AND idt64 OK->PM16->RM16->DOS
;1 GB RAM available through paging (easily extensible)
;
;note Win9x does NOT appreciate a "DOS reboot" : u should start only from DOS
;compile with yasm 0.3 : yasm mypgm.asm -fbin -omypgm.com
;launch this demo with a previous "mode con lines=50" to have a real screen,
;can u live with only 25 lines ?
;
;INTERRUPTS DO WORK now, AFTER a short while (cannot figure why)
;
;This source code is FRIENDWARE :
;if u want to use it, mention my name
;if u find some bugs, if SMP is easy to implement, please tell me
;
;****************************************************************************

;****************************************************************************
;
;What's new ? kbd bug solved : actually kbd.handler.dummy must at least
;             make an "in al,60h" else pressing ESC several times may bug
;
;nasm/yasm cannot compile lea rcx,[rcx-something] and error msg is ambiguous :
;code this instead : lea rcx,[dword rcx-something] !!!
;if I make an assembler, the default will be the shorter command :-P
;****************************************************************************


;from Masm32 to YASM

macro pushmmx n
{
 sub rsp,8
 movq [rsp],n
}

macro popmmx n
{
 movq n,[rsp]
 add rsp,8
}

macro pushxmm n
{
 sub rsp,16
 movups [rsp],n
}

macro popxmm n
{
 movups n,[rsp]
 add rsp,16
}

macro pushallmmx
{
 pushmmx mm7
 pushmmx mm6
 pushmmx mm5
 pushmmx mm4
 pushmmx mm3
 pushmmx mm2
 pushmmx mm1
 pushmmx mm0
}

macro popallmmx
{
 popmmx mm0
 popmmx mm1
 popmmx mm2
 popmmx mm3
 popmmx mm4
 popmmx mm5
 popmmx mm6
 popmmx mm7
}

macro pushallxmm
{
 pushxmm xmm7
 pushxmm xmm6
 pushxmm xmm5
 pushxmm xmm4
 pushxmm xmm3
 pushxmm xmm2
 pushxmm xmm1
 pushxmm xmm0
}

macro popallxmm
{
 popxmm xmm0
 popxmm xmm1
 popxmm xmm2
 popxmm xmm3
 popxmm xmm4
 popxmm xmm5
 popxmm xmm6
 popxmm xmm7
}

DEBUGLINE equ 0
DEBUGCOL  equ 0

macro mydebug n,d1,d2
{
 mov rax,n
 mov edi,0b8000h + (160 * d1) + (2 * d2)
 ;no chk then   mov edx,160 * %2 + 2 * %3
 ;mov edx,%2+256*%3
 call printR
}

macro mydebugR n,d1,d2
{
 movrax n
 mov edi,0b8000h+160*(DEBUGLINE+d1) +2*(DEBUGCOL+d2) ;
 call printR
}

macro mydebugN n,d1,d2,m
{
 mov rax,n
 mov ecx,m
 mov edi,0b8000h+160*(DEBUGLINE+d1) +2*(DEBUGCOL+d2) ;
 call printN
}

;my defines
PORT_8259M  equ 0x20
PORT_8259S  equ 0xA0
PORT_KBD_A  equ 0x60
EOI	    equ 0x20

SP16	    equ 0fff0h

SYSPAGE     equ 0
SYSPAGEPML4 equ SYSPAGE
SYSPAGEPDPE equ SYSPAGE + 4096
SYSPAGEPDE  equ SYSPAGE + 4096*2
SYSPAGEPTE  equ SYSPAGE + 4096*3

SYS_STACK   equ 7FFF0h
SYS_IDT     equ 80000h
SYS_INT0    equ 80400h ;64 INTERRUPTS : SYS_IDT + (SYS_INTN*16)
SYS_CS16    equ 82000h
SYS_SP16    equ 82008h
SYS_GDTR    equ 82010h
SYS_IDTR    equ 82020h
SYS_TMP     equ 82030h
SYS_SCR     equ 82040h
SYS_SCANCODE equ 82050h

EXC_HAS_ERROR equ 00000000000000100111110100000000b

jmp0 equ db 0ebh,0

use16
org 100h

mainRM16:

 cli

;DISABLE NMI to enter 64-bit mode later

  ;/* save IRQ masks */
  in al,PORT_8259M+1
  mov byte [old_IRQ_mask],al
  in al,PORT_8259S+1
  mov byte [old_IRQ_mask+1],al

  ;/* setup PIC to redirect external interrupts to range 32-47 */
  mov bl,0x21
  mov bh,0x29
  call pic_setup ;(0x20, 0x28);

  ;/* set new IRQ masks */
  mov al,0xfc ;1st bit is for timer, 2nd for keyboard (master)
  out PORT_8259M+1,al
  mov al,0xff
  out PORT_8259S+1,al			;/* disable all (slave) */


 push word 2
 popf
 mov ax,fs
 mov [fs_save],ax
 mov ax,gs
 mov [gs_save],ax
 xor ax,ax
 mov fs,ax
 mov gs,ax

 movd mm6,esp
 mov esp,SP16
  
 xor ebx,ebx
 mov bx,cs
 shl ebx,4 ;ebx is our CS relocation
 movd mm7,ebx

 add [pGDT32+2],ebx
 add [pidt64+2],ebx
 add [jmp_64+2],ebx
 add [jmp64_16+3],ebx
 add [bootcode16+2],ebx
 add [bootdata16+2],ebx
 add [patchidt+4],ebx
 add [patchidt2+4],ebx
 add dword[bootvideo16+2], 0b8000h

 ;build idt64
 pxor mm0,mm0
 mov ecx,63*16
 mov edx,int6463
 add edx,ebx

.idtentry:
 mov eax,edx
 shr eax,16
 mov [idt64+0+ecx],dx
 mov word[idt64+2+ecx],(bootcode64-gdt)
 mov word[idt64+4+ecx],08E00h ;1000111000000000b
 mov [idt64+6+ecx],ax
 movq [idt64+8+ecx],mm0
 sub edx,64 ;sizeof(int64xx)
 sub ecx,16 ;sizeof(idt_entry)
 jns .idtentry


;enable A20 gate
 call  enablea20

 mov ax,0b800h
 mov es,ax
 call init_paging2M

 
 lgdt [pGDT32]

;Enable protected mode (CR0.PE=1).
 mov eax,cr0
 or al,1
 mov cr0,eax

;
;Execute a far jump to turn protected mode on.
;code16_sel must point to the previously-established 16-bit
;code descriptor located in the GDT (for the code currently
;being executed).
;
 db 0eah ;Far jump...
 dw PMnow
 dw bootcode16-gdt ;in current code segment.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;At this point we are in 16-bit protected mode,but long
;mode is still disabled.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PMnow:

;
;Set up the protected-mode stack pointer,SS:ESP.
;Stack_sel must point to the previously-established stack
;descriptor (read/write data segment),located in the GDT.
;

 mov ax,bootdata16-gdt
 mov ds,ax
 mov ss,ax

 mov ax,bootvideo16-gdt
 mov es,ax
 mov esp,SP16 ;normally esp==SP16 before that

 mov dword[es:160*6+150], 'P M '
 mov dword[es:160*6+154], '1 6 '

 xor eax,eax
 mov cr2,eax

;
;Enable the 64-bit page-translation-table entries by
;setting CR4.PAE=1 (this is _required_before activating
;long mode).Paging is not enabled until after long mode
;is enabled.
;
 mov eax,cr4
 bts eax,5 ;PAE
 bts eax,8 ;PCE, Perf Counters
 bts eax,9 ;OSFXSR, Save/Restore of x87/64/128-bit states, enabling XMM too
 mov cr4,eax

;
;Create the long-mode page tables,and initialize the
;64-bit CR3 (page-table base address)to point to the base
;of the PML4 page table.The PML4 page table must be located
;below 4 Gbytes because only 32 bits of CR3 are loaded when
;the processor is not in 64-bit mode.
;

 mov eax,90000h ;+SYSPAGEPML4 ;Pointer to PML4 table (<4GB).
 mov cr3,eax ;Initialize CR3 with PML4 base.

;
;Enable long mode (set EFER.LME=1).
;
 mov ecx,0c0000080h ;EFER MSR number.
 rdmsr ;Read EFER.
 bts eax,8 ;Set LME=1.
 wrmsr ;Write EFER.

;
;Enable paging to activate long mode (set CR0.PG=1)
;
 mov eax,cr0 ;Read CR0.
 bts eax,31 ;Set PE=1.
 mov cr0,eax ;Write CR0.
 jmp0

;
;At this point,we are in 16-bit compatibility mode
;(LMA=1,CS.L=0,CS.D=0 ).
;Now,jump to the 64-bit code segment.The offset must be
;equal to the linear address of the 64-bit entry point,
;because 64-bit code is in an unsegmented address space.
;The selector points to the 32/64-bit code selector in the
;current GDT.
;

 mov edx,2000000
 mov ebx,0b8000h + 160*15 + 10
 and esp,0fff0h

jmp_64:
 db 066h
 db 0eah
 dd main64
 dw bootcode64-gdt ;do NOT bother ds,es,ss : cs descriptor is enough
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;
;;;Start of 64-bit code
;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

align 8
use64
main64:;At this point,we're using 64-bit code

 mov rsp,SYS_STACK
 jmp0

 mov eax,SYS_SP16 ;not to place just after entering 64-bit mode (else bugs)
 movd ebx,mm6
 mov [rax],rbx

 mov eax,SYS_CS16
 movd ebx,mm7
 mov [rax],rbx

 movd ebx,mm7
 add ebx,pidt64
patchidt:
 lidt [pidt64] ;yasm : DB 0fh,1,1ch,25h,dword
 jmp0

 mov dword[SYS_SCANCODE],0
 mov eax,07000700h
 mov [SYS_SCR],eax
 mov [SYS_SCR+4],eax
 mov [SYS_SCR+8],eax
 mov [SYS_SCR+12],eax

 xor eax,eax
;beginning of a dark buggy tunnel : benign interrupts rush, timer masking
;is inefficient :-( ???
 sti
 mov al,al
 sti
 mov byte[0b8000h+160*49+0],'!'
 sti
 mov eax,eax
 int 21h
 int 21h
 int 21h
 int 21h
 int 21h
 sti
 nop
 nop
 nop
 mov al,al
 cli
 call clear.scr
;end of dark tunnel : idt64 should work now

 sti
 mov ebx,0b8000h+160*7 + 152
 mov rax,'P M 6 4 '; misunderstood by yasm 0.3
 mov [rbx],rax
 mov rax,'I D T ! '
 mov [rbx+160],rax

 ;test it ; try divide by 0 too : it brings u back to DOS
 int 22h

 ;test timer/kbd interrupt : wait an ESC key
 mydebug "WAITING ",49,60
 mydebug "ESC KEY ",49,68
 mov dword[SYS_SCANCODE],0
.wait_esc:
 cmp dword[SYS_SCANCODE],81h
 jne .wait_esc

 ;kill timer/kbd interrupt
 cli
 mov ebx,[SYS_CS16]
 mov edx,ebx
 add edx,timer.handler.dummy
 mov eax,edx
 shr eax,16
 mov [ebx+idt64+0+(32*16)],dx
 mov [ebx+idt64+6+(32*16)],ax

 mov ebx,[SYS_CS16]
 mov edx,ebx
 add edx,kbd.handler.dummy
 mov eax,edx
 shr eax,16
 mov [ebx+idt64+0+(33*16)],dx
 mov [ebx+idt64+6+(33*16)],ax

 mov ebx,[SYS_CS16]
 add ebx,pidt64
patchidt2:
 lidt [pidt64] ;yasm : DB 0fh,1,1ch,25h,dword
 jmp0
 sti

 ;test dummy isr functions with the patched IDT64
 mov edx,1000000000
.wait:
 dec edx
 jnz .wait

;try 64-bit movd and rip relative-addressing
 jmp trymovd
align 16
tryxmm:
 db 'X M M ! '
 db 'R I P ! '
trymovd:
 movq mm0,[rip-15]
 add rbx,1600
 ;no need for rex, below
 movd eax,mm0
 mov [rbx],rax

;try xmm  OK
 movd ecx,mm7
 movaps xmm0,[rcx+tryxmm]
 movaps [0b8000h+160*20+144],xmm0
 movdq2q mm0,xmm0
 movq [0b8000h+160*21+144],mm0

 cli

;return to PM16 : jmp far INdirect needed they say (and much coffee too)
gobacktoPM16:
 movd mm6,[SYS_SP16]
 movd mm7,[SYS_CS16]
jmp64_16:
 db 0ffh,2ch,25h
 dd jmpmem

use16
PM64Z:

 mov esp,SP16
 mov ax,bootdata16-gdt ;necessary to successfully go back to RM !!
 mov ds,ax
 mov es,ax
 mov ss,ax

;disable paging
 mov eax,cr0 ;Read CR0.
 btr eax,31 ;Set PE=0.
 mov cr0,eax ;Write CR0.
 jmp0

;disable LME
 mov ecx,0c0000080h ;EFER MSR number.
 rdmsr ;Read EFER.
 btr eax,8 ;Set LME=0.
 wrmsr ;Write EFER.
 jmp0

;leave PM
 mov eax,cr0
 and al,0feh
 mov cr0,eax
 jmp0

 movd eax,mm7
 shr eax,4
 push ax
 push word RM16
 retf

RM16:
 mov ds,ax
 mov ss,ax
 mov ax,0b800h
 mov es,ax
 mov dword[es:160*9+152], 'E N '
 mov dword[es:160*9+156], 'D ! '
 movd esp,mm6

 mov word[pIDT16.limit],03ffh
 mov word[pIDT16.base],0
 mov ax,[fs_save]
 mov fs,ax
 mov ax,[gs_save]
 mov gs,ax

 lidt [pIDT16]

;RESTORE NMI
  ;/* setup PIC */
  mov bl,8
  mov bh,0x70
  call pic_setup

  ;/* restore IRQ masks */
  mov al,byte [old_IRQ_mask]
  out PORT_8259M+1,al
  mov al,byte [old_IRQ_mask+1]
  out PORT_8259S+1,al

 sti

theend:
 ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use16

;IN  bl=master vector,bh=slave vector
;OUT
;UPD al
pic_setup:
  mov al,0x11
  out PORT_8259M,al		;/* start 8259 initialization */
  out PORT_8259S,al
  mov al,bl ;master_vector      ;/* master base interrupt vector */
  out PORT_8259M+1,al
  mov al,bh ;slave_vector       ;/* slave base interrupt vector */
  out PORT_8259S+1,al
  mov al,4 ;1<<2                ;/* bitmask for cascade on IRQ2 */
  out PORT_8259M+1,al
  mov al,2
  out PORT_8259S+1,al		;/* cascade on IRQ2 */
  mov al,1
  out PORT_8259M+1,al		;/* finish 8259 initialization */
  out PORT_8259S+1,al
  ret

enablea20:
	call  enablea201
	jnz enablea20done
	mov al,0d1h
	out 64h,al
	call  enablea201
	jnz enablea20done
	mov al,0dfh
	out 60h,al
enablea201:
	mov ecx,20000h
enablea201l:
	jmp short $+2
	in  al,64h
	test  al,2
	loopnz	enablea201l
enablea20done:
	ret

init_paging2M: ;here, 512*2 MB bytes = 1 GB
 mov ax,ds
 push ax ;!!! NO push cs !!!

 mov ax,9000h
 mov ds,ax

 xor eax,eax
 mov ecx,2048
 pxor mm0,mm0
 xor esi,esi
init_paging2M0:
 movq [ds:esi],mm0
 add esi,8
 dec ecx
 jnz init_paging2M0

;PML4/PDPE/PDE
 mov dword[ds:SYSPAGEPML4], 90000h + SYSPAGEPDPE+15
 mov dword[ds:SYSPAGEPDPE], 90000h + SYSPAGEPDE +15
;PDE
 xor esi,esi
 mov ecx,15+128 ;128==PDE.PS
 mov eax,1 SHL 21 ;2097152

init_paging2M1:
 mov [ds:SYSPAGEPDE+esi],ecx
 add ecx,eax
 add esi,8
 cmp esi,8*512 ;we paginate 512*2 MB bytes
 jne init_paging2M1

 pop ax
 mov ds,ax
 ret

use64
printR:
 mov ecx,8
.1:
 mov [rdi],al
 shr rax,8
 add rdi,2
 dec ecx
 jnz .1

 ret

use64
printS:
 lea rdi,[rdi+rcx*2]
 add rsi,rcx
.1:
 mov al,[rsi]
 mov [rdi],al
 add rdi,2
 dec rsi
 dec ecx
 jnz .1

 ret
		
use64
printN:
 mov rsi,rdi

 mov rdx,2020202020202020h
 mov [rsi],rdx ;with esi it bugs : yasm 0.3 ??! nasm's odd syntax ?
 mov [rsi+8],rdx
 mov [rsi+16],rdx
 mov [rsi+24],rdx
 mov [rsi+32],rdx
 mov [rsi+40],rdx
 mov [rsi+48],rdx
 mov [rsi+56],rdx
 add rsi,62
	
 xor rdx,rdx
 mov dl,10
 or ecx,ecx
 cmovz ecx,edx

 xor rbx,rbx
 xor rdx,rdx
 xor rdi,rdi
.1:
 div rcx
 cmp dl,10
 setl bl
 dec ebx
 and ebx,7
 lea edx,[edx+ebx+48] ;add dl,'0'
 mov byte[rsi],dl
 sub rsi,2
 add rdi,2
 xor dl,dl
 or rax,rax
 jnz .1

 lea rax,[rsi+1] ;output offset
 mov ebx,edi ;len
 ret



use64
align 16
kbd.handler.dummy:
in al,60h
mov al,EOI
out PORT_8259M,al
iretq

align 16
timer.handler.dummy:
;mov edi,0b8000h+38*160
;mov eax,edx
;pushfq
;push rdx
;call printN
;pop rdx
;popfq
mov al,EOI
out PORT_8259M,al
iretq

use64
align 16
kbd_handler:
in al,PORT_KBD_A
mov [SYS_SCANCODE],al
mov al,EOI
out PORT_8259M,al
ret

;IN
;OUT
;UPD ax,di
use64
align 16
timer_handler:
mov edi,0b8000h+160*49+79*2
mov al,[edi]
inc al
mov byte [edi],al

mov al,EOI
out PORT_8259M,al
ret

use64
align 4
clear.scr:
 mov edi,0b8000h
 movaps xmm0,[SYS_SCR]

.b:
 movaps [edi],xmm0
 add edi,16
 cmp edi,0b8000h+50*160
 jl .b
ret


use64
macro myint n
{
int64#n:
 
 ;;;cli

 mov ebx,n
 cmp ebx,32
 jl .reboot

.noreboot:
 cmp ebx,20h
 jne .timer_handlerz ;short .skip
 call timer_handler
.timer_handlerz:
 cmp ebx,21h
 jne .kbd_handlerz ;short .skip
 call kbd_handler
.kbd_handlerz:

 call myint.debug
.skip:
 mov al,EOI
 out PORT_8259M,al
 ;;;sti
 iretq

.reboot:
 cli;;;
 call myint.debug
 jmp gobacktoPM16

int64z#n:
 times (64-int64z#n+int64#n) db 0
}

align 16

rept 64 count
{
    myint count
}

use64
myint.debug:
 
 mydebug "EXC #   ",24,70

 mov edi,0b8000h+160*24+78*2
 mov al,bl
 and al,0fh
 shr bl,4
 add al,48
 add bl,48
 mov [edi],bl
 mov [edi+2],al


 mov rax,cr0
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+0)   +2*DEBUGCOL ;
 call printN
  
 mov rax,cr2
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+1)   +2*DEBUGCOL ;
 call printN
  
 mov rax,cr3
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+2) +2*DEBUGCOL ;
 call printN
  
 mov rax,cr4
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+3) +2*DEBUGCOL ;
 call printN

 mov rax,rsp
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+4) +2*DEBUGCOL ;
 call printN

 mydebug "  CR0   ",0,32
 mydebug "  CR2   ",1,32
 mydebug "  CR3   ",2,32
 mydebug "  CR4   ",3,32
 mydebug "  RSP   ",4,32

 mydebug "00000000",5,0
 mydebug "00IVVAVR",5,8
 mydebug "0NIOODIT",5,16
 mydebug "SZ0A0P1C",5,24
 mydebug "  RFLAGS",5,32

 mydebug "        ",6,0
 mydebug "   PFCMF",6,8
 mydebug " TPL    ",6,16
 mydebug "        ",6,24

 mydebug "DOSDEBUG",11,32
 mydebug "  RIP   ",12,32
 mydebug "   CS   ",13,32
 mydebug " EFLAGS ",14,32
 mydebug " @RSP   ",15,32
 mydebug "   SS   ",16,32

 mydebug "  CS16  ",18,32
 mydebug "   CS   ",19,32
 mydebug "   DS   ",20,32
 mydebug "   ES   ",21,32
 mydebug "   FS   ",22,32
 mydebug "   GS   ",23,32
 mydebug "   SS   ",24,32

 pushfq
 mov rax,[rsp]
 mov ecx,2
 mov edi,0b8000h+160*(DEBUGLINE+7) +2*DEBUGCOL ;
 call printN
 popfq

 mov rax,rsp
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+9)+2*DEBUGCOL
 call printN
 
 mov rax,[rsp+8]
 sub rax,[SYS_CS16]
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+11)+2*DEBUGCOL
 call printN
 
 mov rax,[rsp+8]
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+12)+2*DEBUGCOL
 call printN
 
 mov rax,[rsp+16]
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+13)+2*DEBUGCOL
 call printN
 
 mov rax,[rsp+24]
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+14)+2*DEBUGCOL
 call printN
 
 mov rax,[rsp+32]
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+15)+2*DEBUGCOL
 call printN
 
 mov rax,[rsp+40]
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+16)+2*DEBUGCOL
 call printN
 
 movd eax,mm7
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+18)+2*DEBUGCOL
 call printN
 
 mov eax,cs
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+19)+2*DEBUGCOL
 call printN
 
 mov eax,ds
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+20)+2*DEBUGCOL
 call printN
 
 mov eax,es
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+21)+2*DEBUGCOL
 call printN
 
 mov eax,fs
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+22)+2*DEBUGCOL
 call printN
 
 mov eax,gs
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+23)+2*DEBUGCOL
 call printN
 
 mov eax,ss
 mov ecx,16
 mov edi,0b8000h+160*(DEBUGLINE+24)+2*DEBUGCOL
 call printN
 
 mov al,[0b8000h+160*49+0]
 inc al
 mov [0b8000h+160*49+0],al
 ret

align 16
mydata:
pGDT32:
 dw gdtend-gdt ;gdt32_limit ;GDT limit ...
 dd gdt ;gdt32_base ;and 32-bit GDT base
 dd 0
pGDT64: ;label tbyte ;Used by LGDT.
 dw gdtend-gdt ;GDT limit ...
 dq gdt ;and 64-bit GDT base

align 8
gdt:
 dd 0,0
gdtCS16:
bootcode16:
 dd 0ffffh
 dd 09b00h
bootdata16:
 dd 0ffffh
 dd 09300h
bootvideo16:
 dd 0ffffh
 dd 09300h
gdtCS64:
bootcode64:
 dd 0ffffh
 dd 0af9b00h
gdtend:

pidt64:
 dw idt64end-1-idt64 ;idt_limit
 dd idt64 ;idt_base to be patched : linear address
 dd 0

align 16
idt64:
;low offset,code selector,std values,medium offset,high offset,highest offset,0,0
times 64 dw 0,bootcode64-gdt,8E00h,0,0,0,0,0
idt64end:

jmpmem:
 dw PM64Z
 dw 0
 dw bootcode16-gdt

align 16
mystack:
 dq 0,0,0,0,0,0,0,0

pIDT16:
.limit:
 dw 03ffh ;idt_limit
.base:
 dd 0 ;idt_base

fs_save:
 dw 0
gs_save:
 dw 0

old_IRQ_mask:
 db 0,0
irqmask:
 db 0,0

	
