;; @file ; VirtualBox YASM/NASM macros, structs, etc. ; ; ; Copyright (C) 2006 InnoTek Systemberatung GmbH ; ; This file is part of VirtualBox Open Source Edition (OSE), as ; available from http://www.virtualbox.org. This file is free software; ; you can redistribute it and/or modify it under the terms of the GNU ; General Public License as published by the Free Software Foundation, ; in version 2 as it comes in the "COPYING" file of the VirtualBox OSE ; distribution. VirtualBox OSE is distributed in the hope that it will ; be useful, but WITHOUT ANY WARRANTY of any kind. ; ; If you received this file as part of a commercial VirtualBox ; distribution, then only the terms of your commercial VirtualBox ; license agreement apply instead of the previous paragraph. ; %ifndef __VBox_asmdefs_mac__ %define __VBox_asmdefs_mac__ ;; @def VBOX_WITH_STATISTICS ; When defined all statistics will be included in the build. ; This is enabled by default in all debug builds. %ifndef VBOX_WITH_STATISTICS %ifdef DEBUG %define VBOX_WITH_STATISTICS %endif %endif %include "iprt/asmdefs.mac" ;%define UART_BASE 2f8h ; com2 %define UART_BASE 3f8h ; com1 %define UART_RATE 12 ; 9600 bps %define UART_PARAMS 00000011b ; 8n1 ;; ; Initializes the com port to 9600 baud 8n1. ; al and dx are wasted. ; @todo comport init doesn't quite work. :/ %macro COM_INIT 0 push eax push edx mov dx, UART_BASE + 3 mov al, 80h out dx, al ; make DL register accessible mov dx, UART_BASE mov ax, UART_RATE out dx, ax ; write bps rate divisor mov dx, UART_BASE + 3 mov al, UART_PARAMS out dx, al ; write parameters xor ax, ax mov dx, UART_BASE + 4 ; disconnect the UART from the int line out dx, al mov dx, UART_BASE + 1 ; disable UART ints out dx, al mov dx, UART_BASE + 2 ; disable the fifos (old software relies on it) out dx, al mov dx, UART_BASE in al, dx ; clear receiver mov dx, UART_BASE + 5 in al, dx ; clear line status inc dx in al, dx ; clear modem status pop edx pop eax %endmacro ;; ; writes string to comport ; trashes nothing (uses stack though) %macro COM32_S_PRINT 1+ push esi push ecx push eax mov ecx, edx shl ecx, 16 call %%stringend %%string: db %1 %%stringend: pop esi mov cx, %%stringend - %%string %%status: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status mov al, [esi] mov dx, UART_BASE out dx, al inc esi dec cx jnz short %%status %%status2: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status2 shr ecx, 16 mov dx, cx pop eax pop ecx pop esi %endmacro %macro COM64_S_PRINT 1+ push rsi push rdx push rcx push rax jmp %%stringend %%string: db %1 %%stringend: lea rsi, [%%string wrt rip] mov cx, %%stringend - %%string %%status: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status mov al, [rsi] mov dx, UART_BASE out dx, al inc rsi dec cx jnz short %%status %%status2: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status2 pop rax pop rcx pop rdx pop rsi %endmacro %macro COM_S_PRINT 1+ %ifdef __AMD64__ COM64_S_PRINT %1 %else COM32_S_PRINT %1 %endif %endmacro ;; Write char. ; trashes esi %macro COM_CHAR 1 mov esi, eax shl esi, 16 mov si, dx %%status: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status mov al, %1 mov dx, UART_BASE out dx, al %%status2: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status2 mov dx, si shr esi, 16 mov ax, si %endmacro ;; Write char. ; trashes nothing (uses stack though) %macro COM32_S_CHAR 1 push eax push edx %%status: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status mov al, %1 mov dx, UART_BASE out dx, al %%status2: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status2 pop edx pop eax %endmacro %macro COM64_S_CHAR 1 push rax push rdx %%status: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status mov al, %1 mov dx, UART_BASE out dx, al %%status2: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status2 pop rdx pop rax %endmacro %macro COM_S_CHAR 1 %ifdef __AMD64__ COM64_S_CHAR %1 %else COM32_S_CHAR %1 %endif %endmacro ;; Writes newline ; trashes esi %macro COM_NEWLINE 0 mov esi, eax shl esi, 16 mov si, dx %%status1: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status1 mov al, 13 mov dx, UART_BASE out dx, al %%status2: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status2 mov al, 10 mov dx, UART_BASE out dx, al %%status3: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status3 mov dx, si shr esi, 16 mov ax, si %endmacro ;; Writes newline ; trashes nothing (uses stack though) %macro COM32_S_NEWLINE 0 push edx push eax %%status1: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status1 mov al, 13 mov dx, UART_BASE out dx, al %%status2: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status2 mov al, 10 mov dx, UART_BASE out dx, al %%status3: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status3 pop eax pop edx %endmacro %macro COM64_S_NEWLINE 0 push rdx push rax %%status1: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status1 mov al, 13 mov dx, UART_BASE out dx, al %%status2: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status2 mov al, 10 mov dx, UART_BASE out dx, al %%status3: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status3 pop rax pop rdx %endmacro %macro COM_S_NEWLINE 0 %ifdef __AMD64__ COM64_S_NEWLINE %else COM32_S_NEWLINE %endif %endmacro ;; Writes a dword from register to com port. ; trashes esi, edi ; edi cannot be used as input register %macro COM_DWORD_REG 1 mov edi, ebx ; save ebx mov ebx, %1 ; get value we're supposed to print mov esi, eax ; save ax shl esi, 16 ; save dx mov si, dx mov ah, 8 ; loop counter. %%daloop: rol ebx, 4 ; shift next digit to the front %%status0: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status0 mov al, bl ; get next char and al, 0fh cmp al, 10 jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK! add al, '0' jmp short %%print %%hex: add al, 'a' - 10 %%print: mov dx, UART_BASE out dx, al dec ah jnz short %%daloop ; loop mov dx, si ; restore dx shr esi, 16 mov ax, si ; restore ax mov ebx, edi ; restore ebx %endmacro ;; Writes a dword from register to com port. ; trashes nothing (uses stack though) %macro COM32_S_DWORD_REG 1 push edx push eax push ebx mov ebx, %1 ; get value we're supposed to print mov ah, 8 ; loop counter. %%daloop: rol ebx, 4 ; shift next digit to the front %%status0: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status0 mov al, bl ; get next char and al, 0fh cmp al, 10 jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK! add al, '0' jmp short %%print %%hex: add al, 'a' - 10 %%print: mov dx, UART_BASE out dx, al dec ah jnz short %%daloop ; loop pop ebx pop eax pop edx %endmacro %macro COM64_S_DWORD_REG 1 push rdx push rax push rbx mov ebx, %1 ; get value we're supposed to print mov ah, 8 ; loop counter. %%daloop: rol ebx, 4 ; shift next digit to the front %%status0: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status0 mov al, bl ; get next char and al, 0fh cmp al, 10 jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK! add al, '0' jmp short %%print %%hex: add al, 'a' - 10 %%print: mov dx, UART_BASE out dx, al dec ah jnz short %%daloop ; loop pop rbx pop rax pop rdx %endmacro %macro COM_S_DWORD_REG 1 %ifdef __AMD64__ COM64_S_DWORD_REG %1 %else COM32_S_DWORD_REG %1 %endif %endmacro ;; Writes a qword from register to com port. ; trashes nothing (uses stack though) %macro COM64_S_QWORD_REG 1 push rdx push rax push rbx mov rbx, %1 ; get value we're supposed to print mov ah, 16 ; loop counter. %%daloop: rol rbx, 4 ; shift next digit to the front %%status0: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status0 mov al, bl ; get next char and al, 0fh cmp al, 10 jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK! add al, '0' jmp short %%print %%hex: add al, 'a' - 10 %%print: mov dx, UART_BASE out dx, al dec ah jnz short %%daloop ; loop pop rbx pop rax pop rdx %endmacro ;; Writes a byte from register to com port. ; trashes nothing (uses stack though) %macro COM32_S_BYTE_REG 1 push edx push eax push ebx mov ebx, %1 ; get value we're supposed to print mov ah, 2 ; loop counter. ror ebx, 8 ; shift next digit to the front %%daloop: rol ebx, 4 ; shift next digit to the front %%status0: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status0 mov al, bl ; get next char and al, 0fh cmp al, 10 jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK! add al, '0' jmp short %%print %%hex: add al, 'a' - 10 %%print: mov dx, UART_BASE out dx, al dec ah jnz short %%daloop ; loop pop ebx pop eax pop edx %endmacro %macro COM64_S_BYTE_REG 1 push rdx push rax push rbx mov ebx, %1 ; get value we're supposed to print mov ah, 2 ; loop counter. ror ebx, 8 ; shift next digit to the front %%daloop: rol ebx, 4 ; shift next digit to the front %%status0: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status0 mov al, bl ; get next char and al, 0fh cmp al, 10 jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK! add al, '0' jmp short %%print %%hex: add al, 'a' - 10 %%print: mov dx, UART_BASE out dx, al dec ah jnz short %%daloop ; loop pop rbx pop rax pop rdx %endmacro %macro COM_S_BYTE_REG 1 %ifdef __AMD64__ COM64_S_BYTE_REG %1 %else COM32_S_BYTE_REG %1 %endif %endmacro ;; Writes a single hex digit from register to com port. ; trashes nothing (uses stack though) %macro COM32_S_DIGIT_REG 1 push edx push eax push ebx mov ebx, %1 ; get value we're supposed to print %%status0: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status0 mov al, bl ; get next char and al, 0fh cmp al, 10 jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK! add al, '0' jmp short %%print %%hex: add al, 'a' - 10 %%print: mov dx, UART_BASE out dx, al pop ebx pop eax pop edx %endmacro %macro COM64_S_DIGIT_REG 1 push rdx push rax push rbx mov ebx, %1 ; get value we're supposed to print %%status0: mov dx, UART_BASE + 5 in al, dx test al, 20h jz short %%status0 mov al, bl ; get next char and al, 0fh cmp al, 10 jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK! add al, '0' jmp short %%print %%hex: add al, 'a' - 10 %%print: mov dx, UART_BASE out dx, al pop rbx pop rax pop rdx %endmacro %macro COM_S_DIGIT_REG 1 %ifdef __AMD64__ COM64_S_DIGIT_REG %1 %else COM32_S_DIGIT_REG %1 %endif %endmacro ;; ; Loops for a while. ; ecx is trashed. %macro LOOP_A_WHILE 0 xor ecx, ecx dec ecx shr ecx, 1 %%looplabel: nop nop nop dec ecx jnz short %%looplabel %endmacro ;; ; Loops for a short while. ; ecx is trashed. %macro LOOP_SHORT_WHILE 0 xor ecx, ecx dec ecx shr ecx, 4 %%looplabel: nop nop dec ecx jnz short %%looplabel %endmacro %endif