From dceb33057199bf516c175dcdaeec1551deaadb09 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Mon, 25 Nov 2024 00:04:53 -0500 Subject: [PATCH] added fasm2 as well --- .../fasm2/examples/globstr/demo_linux.asm | 47 + .../fasm2/examples/globstr/demo_windows.asm | 44 + toolchain/fasm2/examples/globstr/globstr.inc | 82 + toolchain/fasm2/examples/tetros/tetros.asm | 340 ++ toolchain/fasm2/fasm2 | 3 + toolchain/fasm2/fasm2.cmd | 5 + toolchain/fasm2/fasmg.exe | Bin 0 -> 67072 bytes toolchain/fasm2/fasmg.x64 | Bin 0 -> 70646 bytes toolchain/fasm2/fasmgw.exe | Bin 0 -> 118784 bytes toolchain/fasm2/fasmgw.ini | 40 + toolchain/fasm2/include/@@.inc | 40 + toolchain/fasm2/include/align.inc | 97 + toolchain/fasm2/include/api/advapi32.inc | 535 ++ toolchain/fasm2/include/api/comctl32.inc | 81 + toolchain/fasm2/include/api/comdlg32.inc | 38 + toolchain/fasm2/include/api/gdi32.inc | 419 ++ toolchain/fasm2/include/api/kernel32.inc | 881 +++ toolchain/fasm2/include/api/shell32.inc | 167 + toolchain/fasm2/include/api/user32.inc | 756 +++ toolchain/fasm2/include/api/wsock32.inc | 85 + toolchain/fasm2/include/dd.inc | 125 + toolchain/fasm2/include/encoding/utf8.inc | 79 + toolchain/fasm2/include/encoding/win1250.inc | 37 + toolchain/fasm2/include/encoding/win1251.inc | 36 + toolchain/fasm2/include/encoding/win1252.inc | 34 + toolchain/fasm2/include/encoding/win1253.inc | 36 + toolchain/fasm2/include/encoding/win1254.inc | 39 + toolchain/fasm2/include/encoding/win1255.inc | 37 + toolchain/fasm2/include/encoding/win1256.inc | 37 + toolchain/fasm2/include/encoding/win1257.inc | 37 + toolchain/fasm2/include/encoding/win1258.inc | 37 + toolchain/fasm2/include/encoding/win874.inc | 34 + toolchain/fasm2/include/equates/comctl32.inc | 1869 +++++++ toolchain/fasm2/include/equates/comctl64.inc | 1899 +++++++ toolchain/fasm2/include/equates/comdlg32.inc | 333 ++ toolchain/fasm2/include/equates/comdlg64.inc | 343 ++ toolchain/fasm2/include/equates/gdi32.inc | 480 ++ toolchain/fasm2/include/equates/gdi64.inc | 482 ++ toolchain/fasm2/include/equates/kernel32.inc | 812 +++ toolchain/fasm2/include/equates/kernel64.inc | 810 +++ toolchain/fasm2/include/equates/shell32.inc | 128 + toolchain/fasm2/include/equates/shell64.inc | 134 + toolchain/fasm2/include/equates/user32.inc | 1934 +++++++ toolchain/fasm2/include/equates/user64.inc | 1956 +++++++ toolchain/fasm2/include/equates/wsock32.inc | 124 + toolchain/fasm2/include/fasm2.inc | 9 + toolchain/fasm2/include/fix.inc | 31 + toolchain/fasm2/include/format.inc | 381 ++ toolchain/fasm2/include/format/coff.inc | 403 ++ toolchain/fasm2/include/format/coffms.inc | 684 +++ toolchain/fasm2/include/format/elf32.inc | 573 ++ toolchain/fasm2/include/format/elf64.inc | 611 +++ toolchain/fasm2/include/format/elfexe.inc | 321 ++ toolchain/fasm2/include/format/macho.inc | 1128 ++++ toolchain/fasm2/include/format/mz.inc | 146 + toolchain/fasm2/include/format/pe.inc | 999 ++++ toolchain/fasm2/include/iset/3dnow.inc | 46 + toolchain/fasm2/include/iset/aes.inc | 58 + toolchain/fasm2/include/iset/avx.inc | 4319 +++++++++++++++ toolchain/fasm2/include/iset/bmi.inc | 290 + toolchain/fasm2/include/iset/cet.inc | 122 + toolchain/fasm2/include/iset/fpu.inc | 742 +++ toolchain/fasm2/include/iset/gfni.inc | 33 + toolchain/fasm2/include/iset/mmx.inc | 164 + toolchain/fasm2/include/iset/mpx.inc | 194 + toolchain/fasm2/include/iset/pclmulqdq.inc | 24 + toolchain/fasm2/include/iset/sse.inc | 444 ++ toolchain/fasm2/include/iset/sse2.inc | 579 ++ toolchain/fasm2/include/iset/sse3.inc | 84 + toolchain/fasm2/include/iset/sse4.inc | 278 + toolchain/fasm2/include/iset/vmx.inc | 72 + toolchain/fasm2/include/listing.inc | 155 + toolchain/fasm2/include/macro/com32.inc | 54 + toolchain/fasm2/include/macro/com64.inc | 51 + toolchain/fasm2/include/macro/export.inc | 67 + toolchain/fasm2/include/macro/if.inc | 337 ++ toolchain/fasm2/include/macro/import32.inc | 59 + toolchain/fasm2/include/macro/import64.inc | 59 + toolchain/fasm2/include/macro/inline.inc | 88 + toolchain/fasm2/include/macro/proc32.inc | 395 ++ toolchain/fasm2/include/macro/proc64.inc | 491 ++ toolchain/fasm2/include/macro/resource.inc | 314 ++ toolchain/fasm2/include/macro/struct.inc | 456 ++ toolchain/fasm2/include/pcount/advapi32.inc | 340 ++ toolchain/fasm2/include/pcount/comctl32.inc | 69 + toolchain/fasm2/include/pcount/comdlg32.inc | 18 + toolchain/fasm2/include/pcount/gdi32.inc | 319 ++ toolchain/fasm2/include/pcount/kernel32.inc | 557 ++ toolchain/fasm2/include/pcount/shell32.inc | 73 + toolchain/fasm2/include/pcount/user32.inc | 477 ++ toolchain/fasm2/include/pcount/wsock32.inc | 70 + toolchain/fasm2/include/times.inc | 30 + toolchain/fasm2/include/win32a.inc | 33 + toolchain/fasm2/include/win32ax.inc | 62 + toolchain/fasm2/include/win32axp.inc | 31 + toolchain/fasm2/include/win32w.inc | 33 + toolchain/fasm2/include/win32wx.inc | 62 + toolchain/fasm2/include/win32wxp.inc | 31 + toolchain/fasm2/include/win64a.inc | 35 + toolchain/fasm2/include/win64ax.inc | 67 + toolchain/fasm2/include/win64axp.inc | 31 + toolchain/fasm2/include/win64w.inc | 35 + toolchain/fasm2/include/win64wx.inc | 67 + toolchain/fasm2/include/win64wxp.inc | 31 + toolchain/fasm2/include/x86-2.inc | 4168 ++++++++++++++ toolchain/fasm2/include/xcalm.inc | 69 + toolchain/fasm2/license.txt | 25 + toolchain/fasm2/source/assembler.inc | 3383 ++++++++++++ toolchain/fasm2/source/calm.inc | 3293 +++++++++++ toolchain/fasm2/source/conditions.inc | 669 +++ toolchain/fasm2/source/console.inc | 560 ++ toolchain/fasm2/source/directives.inc | 4852 +++++++++++++++++ toolchain/fasm2/source/dos/fasmg.asm | 643 +++ toolchain/fasm2/source/dos/system.inc | 415 ++ toolchain/fasm2/source/errors.inc | 177 + toolchain/fasm2/source/expressions.inc | 4252 +++++++++++++++ toolchain/fasm2/source/floats.inc | 1182 ++++ toolchain/fasm2/source/ide/blocks.inc | 536 ++ toolchain/fasm2/source/ide/edit.inc | 1027 ++++ toolchain/fasm2/source/ide/memory.inc | 199 + toolchain/fasm2/source/ide/navigate.inc | 511 ++ toolchain/fasm2/source/ide/search.inc | 529 ++ toolchain/fasm2/source/ide/undo.inc | 339 ++ toolchain/fasm2/source/ide/variable.inc | 40 + toolchain/fasm2/source/ide/version.inc | 39 + toolchain/fasm2/source/ide/windows/fasmg.inc | 504 ++ toolchain/fasm2/source/ide/windows/fasmgw.asm | 3811 +++++++++++++ toolchain/fasm2/source/ide/windows/fedit.ash | 69 + toolchain/fasm2/source/ide/windows/fedit.inc | 2279 ++++++++ .../source/ide/windows/resource/assign.bmp | Bin 0 -> 206 bytes .../source/ide/windows/resource/fasmgw.ico | Bin 0 -> 766 bytes .../source/ide/windows/resource/fasmw.ico | Bin 0 -> 766 bytes toolchain/fasm2/source/libc/ccall.inc | 23 + toolchain/fasm2/source/libc/fasmg.asm | 489 ++ toolchain/fasm2/source/libc/selfhost.inc | 60 + toolchain/fasm2/source/libc/struct.inc | 17 + toolchain/fasm2/source/libc/system.inc | 225 + toolchain/fasm2/source/linux/fasmg.asm | 503 ++ toolchain/fasm2/source/linux/system.inc | 298 + toolchain/fasm2/source/linux/x64/32on64.alm | 79 + toolchain/fasm2/source/linux/x64/32on64.inc | 124 + toolchain/fasm2/source/linux/x64/fasmg.asm | 546 ++ toolchain/fasm2/source/linux/x64/system.inc | 334 ++ toolchain/fasm2/source/macos/fasmg.asm | 495 ++ toolchain/fasm2/source/macos/fasmg.o.asm | 489 ++ toolchain/fasm2/source/macos/macho.inc | 1174 ++++ toolchain/fasm2/source/macos/system.inc | 225 + toolchain/fasm2/source/macos/x64/ccall.inc | 23 + toolchain/fasm2/source/macos/x64/fasmg.asm | 540 ++ toolchain/fasm2/source/macos/x64/system.inc | 287 + toolchain/fasm2/source/malloc.inc | 343 ++ toolchain/fasm2/source/map.inc | 237 + toolchain/fasm2/source/messages.inc | 52 + toolchain/fasm2/source/output.inc | 883 +++ toolchain/fasm2/source/reader.inc | 451 ++ toolchain/fasm2/source/symbols.inc | 1547 ++++++ toolchain/fasm2/source/tables.inc | 649 +++ toolchain/fasm2/source/variables.inc | 314 ++ toolchain/fasm2/source/version.inc | 1 + toolchain/fasm2/source/windows/dll/fasmg.asm | 255 + .../fasm2/source/windows/dll/localptr.alm | 34 + .../fasm2/source/windows/dll/localptr.inc | 28 + toolchain/fasm2/source/windows/dll/system.inc | 214 + toolchain/fasm2/source/windows/fasmg.asm | 520 ++ toolchain/fasm2/source/windows/system.inc | 218 + 165 files changed, 78512 insertions(+) create mode 100644 toolchain/fasm2/examples/globstr/demo_linux.asm create mode 100644 toolchain/fasm2/examples/globstr/demo_windows.asm create mode 100644 toolchain/fasm2/examples/globstr/globstr.inc create mode 100644 toolchain/fasm2/examples/tetros/tetros.asm create mode 100644 toolchain/fasm2/fasm2 create mode 100644 toolchain/fasm2/fasm2.cmd create mode 100644 toolchain/fasm2/fasmg.exe create mode 100644 toolchain/fasm2/fasmg.x64 create mode 100644 toolchain/fasm2/fasmgw.exe create mode 100644 toolchain/fasm2/fasmgw.ini create mode 100644 toolchain/fasm2/include/@@.inc create mode 100644 toolchain/fasm2/include/align.inc create mode 100644 toolchain/fasm2/include/api/advapi32.inc create mode 100644 toolchain/fasm2/include/api/comctl32.inc create mode 100644 toolchain/fasm2/include/api/comdlg32.inc create mode 100644 toolchain/fasm2/include/api/gdi32.inc create mode 100644 toolchain/fasm2/include/api/kernel32.inc create mode 100644 toolchain/fasm2/include/api/shell32.inc create mode 100644 toolchain/fasm2/include/api/user32.inc create mode 100644 toolchain/fasm2/include/api/wsock32.inc create mode 100644 toolchain/fasm2/include/dd.inc create mode 100644 toolchain/fasm2/include/encoding/utf8.inc create mode 100644 toolchain/fasm2/include/encoding/win1250.inc create mode 100644 toolchain/fasm2/include/encoding/win1251.inc create mode 100644 toolchain/fasm2/include/encoding/win1252.inc create mode 100644 toolchain/fasm2/include/encoding/win1253.inc create mode 100644 toolchain/fasm2/include/encoding/win1254.inc create mode 100644 toolchain/fasm2/include/encoding/win1255.inc create mode 100644 toolchain/fasm2/include/encoding/win1256.inc create mode 100644 toolchain/fasm2/include/encoding/win1257.inc create mode 100644 toolchain/fasm2/include/encoding/win1258.inc create mode 100644 toolchain/fasm2/include/encoding/win874.inc create mode 100644 toolchain/fasm2/include/equates/comctl32.inc create mode 100644 toolchain/fasm2/include/equates/comctl64.inc create mode 100644 toolchain/fasm2/include/equates/comdlg32.inc create mode 100644 toolchain/fasm2/include/equates/comdlg64.inc create mode 100644 toolchain/fasm2/include/equates/gdi32.inc create mode 100644 toolchain/fasm2/include/equates/gdi64.inc create mode 100644 toolchain/fasm2/include/equates/kernel32.inc create mode 100644 toolchain/fasm2/include/equates/kernel64.inc create mode 100644 toolchain/fasm2/include/equates/shell32.inc create mode 100644 toolchain/fasm2/include/equates/shell64.inc create mode 100644 toolchain/fasm2/include/equates/user32.inc create mode 100644 toolchain/fasm2/include/equates/user64.inc create mode 100644 toolchain/fasm2/include/equates/wsock32.inc create mode 100644 toolchain/fasm2/include/fasm2.inc create mode 100644 toolchain/fasm2/include/fix.inc create mode 100644 toolchain/fasm2/include/format.inc create mode 100644 toolchain/fasm2/include/format/coff.inc create mode 100644 toolchain/fasm2/include/format/coffms.inc create mode 100644 toolchain/fasm2/include/format/elf32.inc create mode 100644 toolchain/fasm2/include/format/elf64.inc create mode 100644 toolchain/fasm2/include/format/elfexe.inc create mode 100644 toolchain/fasm2/include/format/macho.inc create mode 100644 toolchain/fasm2/include/format/mz.inc create mode 100644 toolchain/fasm2/include/format/pe.inc create mode 100644 toolchain/fasm2/include/iset/3dnow.inc create mode 100644 toolchain/fasm2/include/iset/aes.inc create mode 100644 toolchain/fasm2/include/iset/avx.inc create mode 100644 toolchain/fasm2/include/iset/bmi.inc create mode 100644 toolchain/fasm2/include/iset/cet.inc create mode 100644 toolchain/fasm2/include/iset/fpu.inc create mode 100644 toolchain/fasm2/include/iset/gfni.inc create mode 100644 toolchain/fasm2/include/iset/mmx.inc create mode 100644 toolchain/fasm2/include/iset/mpx.inc create mode 100644 toolchain/fasm2/include/iset/pclmulqdq.inc create mode 100644 toolchain/fasm2/include/iset/sse.inc create mode 100644 toolchain/fasm2/include/iset/sse2.inc create mode 100644 toolchain/fasm2/include/iset/sse3.inc create mode 100644 toolchain/fasm2/include/iset/sse4.inc create mode 100644 toolchain/fasm2/include/iset/vmx.inc create mode 100644 toolchain/fasm2/include/listing.inc create mode 100644 toolchain/fasm2/include/macro/com32.inc create mode 100644 toolchain/fasm2/include/macro/com64.inc create mode 100644 toolchain/fasm2/include/macro/export.inc create mode 100644 toolchain/fasm2/include/macro/if.inc create mode 100644 toolchain/fasm2/include/macro/import32.inc create mode 100644 toolchain/fasm2/include/macro/import64.inc create mode 100644 toolchain/fasm2/include/macro/inline.inc create mode 100644 toolchain/fasm2/include/macro/proc32.inc create mode 100644 toolchain/fasm2/include/macro/proc64.inc create mode 100644 toolchain/fasm2/include/macro/resource.inc create mode 100644 toolchain/fasm2/include/macro/struct.inc create mode 100644 toolchain/fasm2/include/pcount/advapi32.inc create mode 100644 toolchain/fasm2/include/pcount/comctl32.inc create mode 100644 toolchain/fasm2/include/pcount/comdlg32.inc create mode 100644 toolchain/fasm2/include/pcount/gdi32.inc create mode 100644 toolchain/fasm2/include/pcount/kernel32.inc create mode 100644 toolchain/fasm2/include/pcount/shell32.inc create mode 100644 toolchain/fasm2/include/pcount/user32.inc create mode 100644 toolchain/fasm2/include/pcount/wsock32.inc create mode 100644 toolchain/fasm2/include/times.inc create mode 100644 toolchain/fasm2/include/win32a.inc create mode 100644 toolchain/fasm2/include/win32ax.inc create mode 100644 toolchain/fasm2/include/win32axp.inc create mode 100644 toolchain/fasm2/include/win32w.inc create mode 100644 toolchain/fasm2/include/win32wx.inc create mode 100644 toolchain/fasm2/include/win32wxp.inc create mode 100644 toolchain/fasm2/include/win64a.inc create mode 100644 toolchain/fasm2/include/win64ax.inc create mode 100644 toolchain/fasm2/include/win64axp.inc create mode 100644 toolchain/fasm2/include/win64w.inc create mode 100644 toolchain/fasm2/include/win64wx.inc create mode 100644 toolchain/fasm2/include/win64wxp.inc create mode 100644 toolchain/fasm2/include/x86-2.inc create mode 100644 toolchain/fasm2/include/xcalm.inc create mode 100644 toolchain/fasm2/license.txt create mode 100644 toolchain/fasm2/source/assembler.inc create mode 100644 toolchain/fasm2/source/calm.inc create mode 100644 toolchain/fasm2/source/conditions.inc create mode 100644 toolchain/fasm2/source/console.inc create mode 100644 toolchain/fasm2/source/directives.inc create mode 100644 toolchain/fasm2/source/dos/fasmg.asm create mode 100644 toolchain/fasm2/source/dos/system.inc create mode 100644 toolchain/fasm2/source/errors.inc create mode 100644 toolchain/fasm2/source/expressions.inc create mode 100644 toolchain/fasm2/source/floats.inc create mode 100644 toolchain/fasm2/source/ide/blocks.inc create mode 100644 toolchain/fasm2/source/ide/edit.inc create mode 100644 toolchain/fasm2/source/ide/memory.inc create mode 100644 toolchain/fasm2/source/ide/navigate.inc create mode 100644 toolchain/fasm2/source/ide/search.inc create mode 100644 toolchain/fasm2/source/ide/undo.inc create mode 100644 toolchain/fasm2/source/ide/variable.inc create mode 100644 toolchain/fasm2/source/ide/version.inc create mode 100644 toolchain/fasm2/source/ide/windows/fasmg.inc create mode 100644 toolchain/fasm2/source/ide/windows/fasmgw.asm create mode 100644 toolchain/fasm2/source/ide/windows/fedit.ash create mode 100644 toolchain/fasm2/source/ide/windows/fedit.inc create mode 100644 toolchain/fasm2/source/ide/windows/resource/assign.bmp create mode 100644 toolchain/fasm2/source/ide/windows/resource/fasmgw.ico create mode 100644 toolchain/fasm2/source/ide/windows/resource/fasmw.ico create mode 100644 toolchain/fasm2/source/libc/ccall.inc create mode 100644 toolchain/fasm2/source/libc/fasmg.asm create mode 100644 toolchain/fasm2/source/libc/selfhost.inc create mode 100644 toolchain/fasm2/source/libc/struct.inc create mode 100644 toolchain/fasm2/source/libc/system.inc create mode 100644 toolchain/fasm2/source/linux/fasmg.asm create mode 100644 toolchain/fasm2/source/linux/system.inc create mode 100644 toolchain/fasm2/source/linux/x64/32on64.alm create mode 100644 toolchain/fasm2/source/linux/x64/32on64.inc create mode 100644 toolchain/fasm2/source/linux/x64/fasmg.asm create mode 100644 toolchain/fasm2/source/linux/x64/system.inc create mode 100644 toolchain/fasm2/source/macos/fasmg.asm create mode 100644 toolchain/fasm2/source/macos/fasmg.o.asm create mode 100644 toolchain/fasm2/source/macos/macho.inc create mode 100644 toolchain/fasm2/source/macos/system.inc create mode 100644 toolchain/fasm2/source/macos/x64/ccall.inc create mode 100644 toolchain/fasm2/source/macos/x64/fasmg.asm create mode 100644 toolchain/fasm2/source/macos/x64/system.inc create mode 100644 toolchain/fasm2/source/malloc.inc create mode 100644 toolchain/fasm2/source/map.inc create mode 100644 toolchain/fasm2/source/messages.inc create mode 100644 toolchain/fasm2/source/output.inc create mode 100644 toolchain/fasm2/source/reader.inc create mode 100644 toolchain/fasm2/source/symbols.inc create mode 100644 toolchain/fasm2/source/tables.inc create mode 100644 toolchain/fasm2/source/variables.inc create mode 100644 toolchain/fasm2/source/version.inc create mode 100644 toolchain/fasm2/source/windows/dll/fasmg.asm create mode 100644 toolchain/fasm2/source/windows/dll/localptr.alm create mode 100644 toolchain/fasm2/source/windows/dll/localptr.inc create mode 100644 toolchain/fasm2/source/windows/dll/system.inc create mode 100644 toolchain/fasm2/source/windows/fasmg.asm create mode 100644 toolchain/fasm2/source/windows/system.inc diff --git a/toolchain/fasm2/examples/globstr/demo_linux.asm b/toolchain/fasm2/examples/globstr/demo_linux.asm new file mode 100644 index 0000000..b91957b --- /dev/null +++ b/toolchain/fasm2/examples/globstr/demo_linux.asm @@ -0,0 +1,47 @@ + +; Global strings demonstration for Linux. + +format ELF64 executable 3 +entry start + +include 'globstr.inc' +include 'macro/inline.inc' + + inlinemacro GLOB(value&) + local data + data GLOBSTR value,0 + return equ data + end inlinemacro + +segment readable executable + + start: + lea rsi,[GLOB("Hello, it's ")] + call display_string + + mov rsi,[rsp+8] ; argv + call display_string + + lea rsi,[GLOB(' speaking.',10)] + call display_string + + xor edi,edi ; exit code 0 + mov eax,60 ; sys_exit + syscall + + display_string: ; rsi = address of ASCIIZ string + xor al,al + mov rdi,rsi + or rcx,-1 + repne scasb + neg rcx + sub rcx,2 + mov edi,1 + mov eax,1 ; sys_write + mov rdx,rcx + syscall + retn + +segment readable + + GLOBSTR.here diff --git a/toolchain/fasm2/examples/globstr/demo_windows.asm b/toolchain/fasm2/examples/globstr/demo_windows.asm new file mode 100644 index 0000000..c86edfa --- /dev/null +++ b/toolchain/fasm2/examples/globstr/demo_windows.asm @@ -0,0 +1,44 @@ + +; Global strings demonstration for Windows. + +include 'win64ax.inc' +include 'globstr.inc' + +GLOBSTR.reuse := 1 + +.data + GLOBSTR.here +.code + + start: + ; Inline macro allows to put string data in any expression + ; (getting the address in return): + inlinemacro GLOB(value) + local data + data GLOBSTR value,0 + return equ data + end inlinemacro + + lea rdx,[GLOB('Hello!')] + invoke MessageBox, HWND_DESKTOP, rdx, GLOB('Example'), MB_OK + + ; Alternatively, replacing the "fastcall?.inline_string" macro changes + ; how the string arguments to "fastcall" and "invoke" are handled: + macro fastcall?.inline_string var + local data + data GLOBSTR var,0 + redefine var data + end macro + ; For 32-bit case it would be the "stdcall?.push_string" macro, + ; provided here for completness: + macro stdcall?.push_string value& + local data + data GLOBSTR value,0 + push data + end macro + + invoke MessageBox, HWND_DESKTOP, 'And bye!', 'Example', MB_OK + + invoke ExitProcess,0 + +.end start diff --git a/toolchain/fasm2/examples/globstr/globstr.inc b/toolchain/fasm2/examples/globstr/globstr.inc new file mode 100644 index 0000000..f2277bf --- /dev/null +++ b/toolchain/fasm2/examples/globstr/globstr.inc @@ -0,0 +1,82 @@ + +define GLOBSTR GLOBSTR + +virtual at GLOBSTR.baseaddr + GLOBSTR.buffer:: +end virtual + +postpone + virtual GLOBSTR.buffer + load GLOBSTR.data:$-$$ from $$ + end virtual + if ~ defined GLOBSTR.where + display 'Global string data has been placed automatically at the end of the executable.',13,10 + display 'To place it elsewhere, use "GLOBSTR.here" macro in the intended location.',13,10 + GLOBSTR.baseaddr db GLOBSTR.data + end if +end postpone + +macro GLOBSTR.here + GLOBSTR.baseaddr db GLOBSTR.data + GLOBSTR.where := GLOBSTR.baseaddr +end macro + +if defined GLOBSTR.reuse & GLOBSTR.reuse + + virtual at 0 + GLOBSTR.chr_skips:: dd 256 dup ? + end virtual + + struc GLOBSTR data& + local buffer,size,a,b,c,p,skip,found + virtual at 0 + buffer:: db data + size := $ + end virtual + repeat 256 + store size:dword at GLOBSTR.chr_skips:(%-1)*4 + end repeat + repeat size-1 + load a:byte from buffer:%-1 + store size-%:dword at GLOBSTR.chr_skips:a*4 + end repeat + virtual GLOBSTR.buffer + found = -1 + p = 0 + while p + size <= $-$$ + c = size + while c > 0 + load a:byte from $$+p+c-1 + load b:byte from buffer:c-1 + if a <> b + c = -1 + break + end if + c = c - 1 + end while + if c = 0 + found = p + break + else + load a:byte from $$+p+size-1 + load skip:dword from GLOBSTR.chr_skips:a*4 + p = p + skip + end if + end while + if found >= 0 + label . at $$+found + else + . db data + end if + end virtual + end struc + +else + + struc GLOBSTR data& + virtual GLOBSTR.buffer + . db data + end virtual + end struc + +end if \ No newline at end of file diff --git a/toolchain/fasm2/examples/tetros/tetros.asm b/toolchain/fasm2/examples/tetros/tetros.asm new file mode 100644 index 0000000..7dea3e7 --- /dev/null +++ b/toolchain/fasm2/examples/tetros/tetros.asm @@ -0,0 +1,340 @@ + +; TetrOS version 1.05 + +; Requires VGA and 80386 CPU or higher. +; Can be run under DOSBox with the BOOT command. + +; Version 1.01 was submitted in 2004 for a 512-byte OS contest +; (https://web.archive.org/web/20040930044834/http://512.decard.net/) + +; For your playing pleasure, it's a boot-sector Tetris game. +; Keys: +; Left - move left +; Right - move right +; Up - rotate +; Down - drop +; Esc - new game at any time + +format binary as 'img' +org 7C00h + +use i386 + +ROWS = 23 +COLUMNS = 12 +BACKGROUND = 0 ; background color, 0 for randomized + +virtual at 46Ch + clock dw ? +end virtual + +virtual at bp + current dw ? + current_column db ? + current_row dw ? + filler db ? + next dw ? + score dw ? + last_tick dw ? + random dw ? + pics_wrt_bp: +end virtual + +label well at 8000h +label pics at well-2*64 +label origin at pics-(pics_wrt_bp-bp) + +assert origin and 1 = 0 +ORIGIN_PARITY = origin and 0FFh +while ORIGIN_PARITY and not 1 + ORIGIN_PARITY = (ORIGIN_PARITY shr 1) xor (ORIGIN_PARITY and 1) +end while + +include 'listing.inc' + + xor ax,ax + mov ss,ax + mov sp,origin + mov ds,ax + mov es,ax + push ax + push start + retf + +start: + mov al,13h + int 10h + +restart: + mov bp,sp + + xor ax,ax + cld + lea di,[next] + stosw ; [next] + stosw ; [score] + mov ax,[clock] + stosw ; [last_tick] + stosw ; [random] + + mov cx,64 +if BACKGROUND + mov ax,0F00h + BACKGROUND +else + mov ah,15 +end if + rep stosb + mov dx,7 + @@: + mov al,15 + stosb + mov al,ah + mov cl,6 + rep stosb + mov ax,0708h + stosb + dec dx + jnz @b + mov cl,8 + rep stosb + + or ax,-1 + stosw + stosw + stosw + mov cl,ROWS+4 + mov ax,not ( (1 shl COLUMNS - 1) shl ((16-COLUMNS)/2) ) + rep stosw + +new_piece: + mov bx,[random] + mov ax,257 + mul bx + inc ax + mov cx,43243 + div cx + mov [random],dx + and bx,7 + jz new_piece + shl bx,1 + mov ax,[pieces+bx-2] + xchg ax,[next] + or ax,ax + jz new_piece + lea di,[current] + stosw ; [current] + mov al,6 + stosb ; [current_column] + mov ax,well+(3+ROWS-4)*2 + stosw ; [current_row] + mov si,no_move + call first_move + jz update_screen + inc bp ; game over + +process_key: + xor ah,ah + int 16h + mov al,ah + dec ah + jz restart + test bp,bp +if ORIGIN_PARITY + jp process_key +else + jnp process_key +end if + mov si,rotate + cmp al,48h + je action + mov si,left + cmp al,4Bh + je action + mov si,right + cmp al,4Dh + je action + cmp al,50h + jne main_loop + +drop_down: + call do_move_down + jz drop_down + +action: + call do_move + +update_screen: + mov bx,15 + mov dx,12h + mov ah,2 + int 10h + mov cl,84h + print_score: + mov ax,[score] + rol ax,cl + and al,0Fh + cmp al,10 + sbb al,69h + das + mov ah,0Eh + int 10h + add cl,84h + jns print_score + xor bl,15 xor 7 + jnp print_score + push es + push 0A000h + pop es + mov si,well+3*2 + mov di,320*184+160-(COLUMNS*8)/2 + draw_well: + lodsw + push si + mov dl,COLUMNS + xchg bx,ax + shr bx,(16-COLUMNS)/2 + call draw_row + pop si + cmp si,well+(3+ROWS)*2 + jb draw_well + mov di,320*100+250 + mov bx,[next] + draw_preview: + mov dl,4 + call draw_row + cmp di,320*68 + ja draw_preview + pop es + +main_loop: + mov ah,1 + int 16h + jnz process_key + mov al,-1 + xor al,byte [score+1] + and al,11b + mov cx,[clock] + sub cx,[last_tick] + cmp cl,al + jbe main_loop + add [last_tick],cx + call do_move_down + jz update_screen + movzx dx,byte [current_row] + shr dx,2 + mov si,well+3*2 + mov di,si + check_row: + lodsw + inc ax + jz remove_row + dec ax + stosw + jmp check_next_row + remove_row: + shl dx,1 + check_next_row: + cmp di,well+(3+ROWS)*2 + jb check_row + add [score],dx + jmp new_piece + +draw_row: + push di + blit_row: + shr bx,1 + mov si,pics + jnc blit_block + add si,64 + blit_block: + mov cx,8 + rep movsb + add di,320-8 + test si,111111b + jnz blit_block + sub di,320*8-8 + dec dx + jnz blit_row + pop di + sub di,320*8 + ret + +do_move_down: + mov si,down +do_move: + mov al,1 + call on_piece +first_move: + push dword [current] + call si + xor ax,ax + call on_piece + inc ax + pop edx + test ah,ah + jz @f + mov dword [current],edx + @@: + jmp on_piece +down: + sub byte [current_row],2 + ret +left: + dec [current_column] + ret +right: + inc [current_column] +no_move: + ret +rotate: + mov cx,3 + @@: + bt [current],cx + rcl dx,1 + add cl,4 + cmp cl,16 + jb @b + sub cl,17 + jnc @b + mov [current],dx + ret + +on_piece: + pushf + mov di,[current_row] + mov bx,4 + on_piece_row: + mov dx,[current] + mov cl,bh + shr dx,cl + and dx,1111b + mov cl,[current_column] + add cl,4 + shl edx,cl + shr edx,4 + test al,al + jz @f + xor [di],dx + @@: + test [di],dx + jz @f + inc ah + @@: + add bh,4 + scasw + dec bl + jnz on_piece_row + popf + ret + +rb 510 - ($% + signature - pieces) + +pieces dw 0010001000100010b + dw 0010011000100000b + dw 0010001001100000b + dw 0100010001100000b + dw 0000011001100000b + dw 0100011000100000b + dw 0010011001000000b + +signature dw 0AA55h diff --git a/toolchain/fasm2/fasm2 b/toolchain/fasm2/fasm2 new file mode 100644 index 0000000..9d12415 --- /dev/null +++ b/toolchain/fasm2/fasm2 @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +DIR="$( dirname -- "$( readlink -f -- "$0"; )"; )" +INCLUDE="$DIR/include;$INCLUDE" "$DIR/fasmg.x64" -iInclude\ \'fasm2.inc\' "$@" diff --git a/toolchain/fasm2/fasm2.cmd b/toolchain/fasm2/fasm2.cmd new file mode 100644 index 0000000..deead54 --- /dev/null +++ b/toolchain/fasm2/fasm2.cmd @@ -0,0 +1,5 @@ +@echo off +setlocal +set include=%~dp0include;%include% +"%~dp0fasmg" -iInclude('fasm2.inc') %* +endlocal \ No newline at end of file diff --git a/toolchain/fasm2/fasmg.exe b/toolchain/fasm2/fasmg.exe new file mode 100644 index 0000000000000000000000000000000000000000..b4fbe5d18d9c3ebca070835db9c88a74400b7110 GIT binary patch literal 67072 zcmcG%d0Z4n`aeEB(*q+6G%6?>QM@)1jR6x9k->l%@LCmg!D}(snrnCC4&CY|CYjI> zXnNV4n@x6;tctljvgR^k5(Os#$?1^;lU+qgvNd)R53(F;nBV)Unn6t5&-bq%FYT`L zsi&TL>Zzxmdb;M9OMEuTX0yq*I9o7ivt?5Rf7$%`e?NT4jvcWx*7jPz4@d5h=6pDE z;jOooCa?6~d5iak-zDF4!|#88r<#1@Z<4**?~`x)ee(2q3zC0#=gq&F7!x%n40--_ zHrpJ@VY}nEslN%Qwc4(bq9wb{_B~Pt*=(bnHe2BUgyZNxA($<~C=x;!_=o;dk%IKw z7D_e;W%D|e7cMEPhKm!tp7U9~$^U-`CaS+#qoR@LzQcoXq`m_0zJJL!Tk^ykOG_z@ zXwch-lN3Jx=d;=BCwgzbLA}9dONmE1(Fk<2{iIy>MTYhE{{|DDip#Opek zhhKhLN;^>Jd;AGo=c(Fr0AsWu(1n0s&myok)g4TyKrmq&Km^kXnP5T{4-+mT>@NT^ zp>i)EkFZ$?Z065DpZ*rojfO>fcTg#xj68oqpUfS+lJ;?6IC3iL)uDP$7(0v&9=!eGLmkV`e%41br%wo@U>&hC@_4rK$?TN6Qpg2DyCgbz@0 zG1}Xd8AEB>hM(luhw`gK`DI;x)S~YDmF>+&0tdvw%}4q>0u3!Ln6M8)P@!UOFc|FI zXYztw{`Ev!Gl3}WUtlH?F|9}hh>{h}T5M{)(Wy5FPruZ8NDtVJ(>rW?ZMKYtRl`#n zqKd=3sxtyi|kBqP5q(k;zY?QT0O=x@VVZv?>FVaPDkTX|1D z!ISL;M|(5Z`=lIOrt@D&@wT!h-`H%sJ{rM6Ujop(md5k2LgBAPx&z^Wg7(-1l-9Gh z0Dw)Y_>l%xpr=&4j|hjHc7XliIEud80|3@QjCU3_C~3}JZHS=9PcC?(+=qM zlj;~4s`HfLH}-+kZw53lIORUt&#z7f&|w60B>^R@>VS=n-GJzN0fLM#cxD+qY*Zfh+<||3(+mE4RlLk zuM7l`nsdP*P3VU}VV3tbQvOcKt0>tnlHZI2Oe^xuRC@IicNfOgIE?PUjzE~Qe4v*Q zfOG=j5CC?K7{CctMr<&QG9;0aR$oiQSxdOp5^5WWIW`anH1Po?x-~g%L~kCF5sJH% zIN~wjYcv{7;M&ys(=VlT8r|%~S)kOE`qh^5dUc*>lsaUE-j%F6Hd)`N)^DngKx&33 zS##xC?YyYPi^=i)*>Lfjj+K0r^IeBbqv^(fGc%t=+!PBfw;X+>lls|8a=Qpb6 zxla9q=QgFBWU6PTQqJhTQYrrnz2__CHT3qXcX$fbTRf}OUwDetQJ&wcvS+ULj4y_I z8mx}+BrD}NfPc#CH6ySH0Y+XD>mp;($_Kh_{hI z1PTzhvuk*+CzN{?&n2P-ekAT0!gGg*atHBTnm2(X$W5y^_V}hIYmPjtYl|mY9SnL6 zoRI1r;OVzI_KpKlEBi@%yiV(@xg-jU!zEL{@=YCuIz8_g?Zzoi+B8&IU^Y{1kPw$Y`ui^_0%MbJ@b=H0co*iRwZmefsRJI z@)zeugnTizcuF0O(l*Il7%LkI3+)ii(c5fhe5{c$ACV2~P@>{XbvauChAb^Gk`__w zvq&|wZbi_SMI|JqoP>#yvhLH%u*Cqm$>F9I$bgB>>2JDq}24RLb5%2?51# zCQU~w`!7;Tzx`Pwq52$ps6q8=-i)>^+(Z&#!(Ib`a08{aCa)n%U^So)nM;RNe5qX} znl+cp=v$t-)XnZbUvZfC!4Ot#Idm#-ow*?1yvyxp1&E2T!TYY1-2{&Evkat{e&Nd^ z>e|#1jZPl$#So1plT*xG8gJh14zy5@MFNMpjtE(mEBOtMeuqO+D!vDebbs7#0JRzW z^wtp#$DK99bkjj=y@X7|KTrEc+0IEj*`Y1Ym@R7y&AVM0J?h;ahdQ%OYky9gYxJ12 z<&=+nW7iW_X2KkFzT$woxFc7R)HwZn*|Zyz4Ate<8)YlkoP?KA>hjH&Br9F|h}Si9 z4Y9!WbscV5nx>W6GL@M>iK%qcvieS+0Az)KrRzeN+eKe3v#S+!&GJ~di^ z7y}R|d|5;fo2IaSSSd)QEzbrE%88 zv@g>RbYn>siKhzYsh8CGP?XIhx;SX@=_QzTtZp)8UB$C%sWHR9cs;R+k?USZj9KL{ zX3HSiWnuDYgMC??Ug}^r6ZJyWv-%NT!ZfN`nrQVes7of`pW|WV#sTm;8uTiM=#9sr zDIrGHBFt%SpUZA6h!0Ufspto`Nv#J=InaSAjnUSRU0XBkQ5s`4((ng{BQ?}Zr92X) z3j$Z*DJC%ZH^NLRhmbQGcfR}du=|aemFQF*F-+>7+YUS`*`x;MI@Z4a;>jj2E@p)z zBm+Xs%2cdaA?8ns$wm`i_j(UrQVc!)1%<_Rq=GZ;zYxQFDibCX7I8IeWIZ4oSyaa0 z)r>u9^$h`g`(|U`@+FI{S2JU-Lf-0e1;u7oDne2WJyUq9(X~HNDs9BWzT(;TXN|_? zi~aX^qZM0eN`YuDBGlXjY9LOpr{-!2g25pyww^E08)SCm2VkE-g}~|kjfTo7!-c}8 zdrYy>Wc{^PRJXo0m&AjJ1M0xSHWm-U8uMjiTD;-+i=3`H+CH!|Gzu=sH$zGmxoKa% z;$W+hYUauqsdzJnG^5NJvO3n7A?w$>Y}PQr7rRl&$d!ZH@r|}*Q4A%_8LnWqt1a4S z;gBvzA-}mm#+0;c89+IudYbftq$PFidm&1l%eArb(_}RU+Ro~j>RbsN=}rNgMvjp-4b6<@i)RXIP=SRh;P z@}igx03rDo6q*ZARCO5B++0kmPGnifmn`*%%Q4cjy^^2p!@Jwh5g)_n1`$LlzXN3J z$ObBkIYZ9m)KMyk$~(^{LpnD=;-?+(bLuJOQ$vN73Kv4X6||cGHb<%W2Gy`Y&z9_n z%W8k$P10F}Txz5*<{8X2Nxv&zS}pm_X^BMXS@Fic%3PN*EinZC2|WJJs*e zT#m-5QSFldg90_PU8V%ciTav&n-&9ZGcmCJ8*Mf#sb)qZBw#YoXOp0TqQRKygwKp& zD2Az<3yx3ZEi3|r1<0T6s+^H%%t{2Qj9GHEt18Nz;WlQu+paDuHdngLyIh&G;#Q3< z)bEOe?pT0sO>?ojQ^DY3<70L+-b;*WE@M`l(QP!fZ(LsDZ?xM4i;SiIC>2iung6pl zG8pv^vp;z7Ue3^Kd{b;{sX0v!5&Kq*bwyB%GbEFbG!6O!SC>EIb9GWjK8Q6E&m8R< z-#jo){zaJvRr9ImMzP%GH>Hey>SlCbA!?o4dG$yz=`ig1u*TddiR}<3pfpWP(Gda- zbugClOui}7+?li7>MbFL1g%0u8d+GtsT3uM^w>!diRIuKCQ;M6Ewo(Np>{@9bf`{q zmb-nUztRh?193a_8{=%oNwy3%tUw65^#OpBBsjtAPPS{`w0(%WtsY5D1f0tV#&fDW zXYRaE4M0R%A$tem)cwNR_Zha3_0ju(SQ;8RCDzT95 zRes(SDRxMaLd|GECtdllvkogCfIg`fCEOck=*CN`Y zG45eOYy;M z#Za_YxByg;g;OmyvO#Qga9BSSrTVL=JHc*60+!rb#sY7~890uL*lJz|M;1~fl1=B4eTWEsq`U)=mLbZ9#oBDO*HZ>j zirs;XMw`@#ajm@-sd{~Kqs`8vzYRx4?n)7@{e)b*)JC^`^c-sSkd1MWI(HlnAWY3ly?Z=ot#R zDD)VG;wV&2p-(8}qfje_R#E6%3jG$LIvezJmPIWu0%W79&W3?Wt8d@DYZo|)OgL%E z_Lhb=yCaDTh^2cqG+HdyP{|UZg>0#^Z>gFl;lF(=)>`YmwE7LSU8$XeR)j(?U8vBn zCq}BJy~3^&q7^L;O)2HiVqEmGlwni0?@jxXZzPoM^6*J~Unh1Exf$_f4H z-Dl#mZ7k7GRcS`DI1YuTAkUtYg6!_zG>dgcbFxwj5ks=uD8$)uIfXbo{)$3fRChLo zI1}bjh%@0e6yi*HIfXd0j;0W2#~~Er?5I$Pv!jzj>j=}c|3QdmFgrydnzrme6r#z> z{!Jm`MRt%vlPLsFwymE)AqgQr*1u>ok-dt1qs2N!@kDcxi*4Wuh((cc@Jy?(vTt|_?6-lm{|!&m<7ImM z1CQEmRJooWZ_#5V@UMLV9jo0z50%pXMUPfI%%nAV8V=nr8%OFOw6Gl1CR4dFctEA< z@0$t@cL8%@#FsWYBrC;CCv35Tl|K*(C3Y%wfqM{Gz!Jd;OKIzKBchECn^7ub)3lzX zw(okot@dVWDK}X(8FcJgO}1|rnq(Tu{RF}rlSc6O?%RkBy&wh*#c}AuhS$(HwgPHN zTD_P>jtyi**+2#mG4-zk${RjLR5W2m&%C2~OwF=rXh@0KQf|C2)1j3AaSIqfH@Ws9 zw3c=NOF69P#vZ5@u->@Vmm?KnBjHbkY)loNzD&DP{uG8-A4{^uW|q2P%8?q4++n=) zBamfg5ues!kqQaWCnIdOEuNuD`9G258Kso}o!*x!<&WY`Lg(KUk5bA%qj#nj4OE;o zqLMmuljnM+{4q*jrfm_acCFSpU2UJ{iBh9HnQ9ztqmNi88uNq6dBNO7>w!>RrGiYy zlx%#4bP}X%P-P(5!#$U(37(;vwY5f#a9dx&fLt*Lg{?(frAF)1O~%R12yipA8Cx?w zHg5g`Gy5Fa)NVAgYz*kqlE5&O_e~wDR18F5%g>7qK{4;=>}C+e+BbK6soN-x3%o|; z;anDsRw}Zgg81&1C2eMyjnr$2!=}{SEpzsxRe*i8iw@+J@*&RNy2PR9d5Q)PtQ0r} z8%GT$MdJLQxuW%ymx%-UWzX1

06A$CeUvH=ojlrRbxEaYO?2gwb*KS*4kyp!qy^|%;!;S>t>^&eWUffkxr~w zXGh)kXTz;*K+HEaTQlsr}=Kg(1f=xL8bA~-%I0+EJ`rbiLpfyee7hUpv7B}#O8eu^M?z%v#iS2nzRE( zLKSi`Ss%lz!$~s9rBpIl0pFpGtG0V0mGal0!(_=;%GaW%2L|{X?#0`t zMeQsZ2~3M%I1?2B{3V>q(6bDne3R=1$+_J|O5m5N3rg=s!5L>sMG&^+f^ zLF;pC@y=E%{)Vz)+gR{M*E(W=F%A!8X9P+FuEtS};2bl|D1^JonJb4KjMhua4jO9PvjCGT9SIwT`~xVs}#ZSmP`&U}n+s$hKkdjU(()WcgyKV{%{x zfC(**{SBsxSNgH5sbab>i5I|f%104!+i}Mt5P$ksDn&d?g3RT7y1=RtQ z3|@BDjO4{^6=kLcts{ZYkHR>wyuH8jJzv0n@c6WY$Bg|;GWM_fhCP5XIM*UtnvP7T zjCbkmpyQ7EF)&Hv9JhWU*z{qrn>XpkgDhFLdv2K$J!Q!I~i^4MdxakIb_`$ zR zXRdZR(l-*?*CF3Jj3r$u*C2`dwyA8#Y8fF`%RgeeZcE){oJp(S!WYes{Gd-MPsGZE zL-wFO5Q|VR0uUnO01VCVpGOn>5=1x(ad^so5Q${(qJZ^p zwEE4($j;rGvbQusYUpgKJZ$V~8w95WTdVTOJ9dZf6C3t-cy2oOt+Br?R-}hgPA{oy z?b)kEWt>qX2_IG3WOS$OH)fp+NEf1mHY%Ex@&q7MyxRl*#Wo_+IGoqMaXrPBH?-Q# ztL)|+yPR@L`pk+Dno)tkHHfukv7U7mcmk5LePaMp)%Gk7kqG1y2yfXm6Uxtb(0KyT zdA^3uGYJfF)Yz*}wP{0)(`H}grUtq~gC1~M4Iynu#9rOH84yz%9&X?Gu=QNsV1N~^ z-;dU}Wp7%~)$2&$oiFQ6u3jcZRv+-#e#q_5cKd0@&Iw7EodXd*gv89H=5lsLGC?9&@v*85xGywGUIiqc21 zOkrA*M}qY-&*9rV7rsb4YGH+@mUzU9)?~LD4@xaP8ed4Pu1j{Ga~%e5mO?y#Jqf9ODekpY@>ngB4GQ+ zW5@h6%?NXF#y*XXsnJ;wSo_d#CT0%RzLHv`FCMQvQ~CZ(oHXY6)&z%YkvXE+kL}N& z(_(8@$~AY%20XlE?Fm1eXFfL$`OS#TNbQ9%G$#$$b7};P=2C-SYJhqK9Q`wQlD0`j z#qJ_pTvp0&NB%7BtH5-;Gt)_3^xC`83*Z|CD?9{qUXJxm9{2`_K>a%D-Dt#xlJ`Bd~*BhPI*Lk#^I--wV z22eKk4W_742JIA{Oko_1tm~0SlYrU>5fUB`&z(jii|SeZ=UK77tOEo>`+@xn)wcl2 zY#=#ZAgN9VjlH08fj*X?VT&?UEe4JYfa5&iI9H5^)|6VW^Y(1ouyDWL5&hEMnj6l- z$ssS~PpyX!CI_fR2s}4guRm+O6580n6Y7G@(4aytM1}@UY)#5Cc|T~5Ik4FYcg3lL z6Jo=iH=j(5axrk&{y&W!inApMvvvbAISSSn^)?5|3A9wP&@_))A5rB|Jg??+rITOh%b z@ukT*m%R6Oa?^vob~Ip(Lf8_~KFX&2rG8)QhD`+eKpHub4aI(R zBD7<`^Nd!?-7s8xu2sq%96pul@-qdSQ|~EX3;~kDJ4&O;Cp==(nyb?ZAiD;bc{4qu zwHVePH5B~=z8*vK`Gx0NZItgLDUS`LGJ{bjl6{A!yl%3akfq}lG+0z1_)h%|Qg850 zov1A{dLU04zJ+50QcXf+w-eo5%}BlJ@-$A)TI?3N?gIt2p@ zFvVCEHF6mh`GzL&9As5TATtf9RdW*a7T9GRIDBV_>K<(2iU1K32(4XDtxe-7Pa$a6 zpwTNm*Q&n{kyL}~MYW*Z6B+E(m=BFnul8aFds1QI>TS+zx{j{Ci+;LQN;>7I$|F%U}zu~Oi@5zDX_!v>`~B2b5RaHi#CV-ACMPlb~= zQ1X}RNMywpFc=j3b=7 z-15DSxKSA2$P5RiJ>pC7`7p5=4m;F^oN18DFg{qZ6Ns;Ia4m!9uP-Pv)4OO1>@p&_ z)jh2l&Blg3cXHsmV}0+7A-ld5vc3t0*nZJggf|fNg}reIR{6!|61N{Tybhe8lOH+iACtDBZah+lTl#1`Lxm|7?WT7>!r0_VI(9c5%Jyt$wU5pNd5&vB zn)jF|qVzD_YnrwGd8|JGdHZ4VoafKfK~XA#vZ}6@ct1zegkElL=t%YHnW847D1u< z$v7nlLmUkr8;&y-F-FGuF%kphpe)kvO3VZ*8=x(UaZr%9XaRdP0@LW=66=`)HURQ( zvG=ZRss5eA$b!)Sc_={w_5MJ8+bDlck!0FoOm#9F61;QJ4;d44Am(Z|I{>!3PJzl_L!%H;b{z;Fm^w@?+ zQ2}Pwe*n9tR5qixVDZoKELXEU8A|16Am@ZsHC-wD0HF>i6^H%nI3htO0WB&>Yp#r; zHdp`<7MJ+O5?tG{9oDGc;&1jA4?3x6xXfdVOISY~!g}YU%Q5Kk40Z(k=FPE4xMr>+ zG^3n^F`dR!+d*FpCBjNZtzbG64mJ{TH=zyh63}WX#(SkNi({e9^kwmCYBswE=%J@Q zY0bVYf&m{$Glr^<=jeAHa>NjUR>rfhr@+@flFaa0q;Y0($+n69#U*J6@XFho)(jYp z7=B+C;bqfq4!n<15`#~f>@keF@mZe|(*iG|#5U;x-V?ZK-yOpK*f{imGn(;k0N%C0 zdxvMdQa%ww=eb<_b4L=j5Ey|d!~jOcgHf3bf9gz6ROvM#;%XDk1VWqKt4D`$y2swx zBJEijZ}6NjvEK~*8EAyaXq^mGXq2)&FDNFe=Qm0@skWXKnp>2U0#}`{6BvguTa430 zZxrbWS7H8l9tzLfVSV-*8F_3HijgkMQYetxk+-#azU(`b>K*Mnld*a@lmOFJz0l?G zo%xOG^qsj*i}rnFw<1XK-7aA`PvaQVyAa}GCOBb^XQGx$gZwW_or=^ek$N?l<~WEJ zgGoIgZ)-=Rq;0m|AqY?ttT%l<4sD=kJm${jT6AiMwVUZ!!AsxsvuQ-~KcW^sctGP* zB-&*7vgqu~ru{c;e#8NQT^k5nCd?&;!UkMe3m+3d+x%agc+|04LS~Y0ELW&r!M7L0 z$pN^h4>mr>G8xUhpCduuHnhtR=E0K<0Rmm{iOjNLb#Y|TffOtNdt~2~F-my~7#Kzv zZ}f`$r=+eCl1$k?Jt{mnx59B1MLai#EYx>Gt)TcHl=6Cd->gOXK9FWA{jrXgk z4-JB6;=wa<5TRw?Q5nqWukoI(9W5xN<%sZLSHf^B_Ruh+MJ`zilg_1T3Fc3k&uK$ST9Tax45BmM$sAvR4(E+Kkipq3B8` zx^hi;DFPvYCYGuJ6VjBjqX^4Uo;XD(zvBa~u1MXIyo&FXtnJCKQmnTTE#0vs-*+jR zmC2A2n1czz8-ETp3JV$nj^5Uf!x!Ov>(#vRk!U;#bM`Key>wN$ftTQ%b2L)>H#N~h zO&qlT4w&Ae3p(@ni-1c8xM2V{-s390^dRu{H8_0TF0acMaOGEBnpRKHJ_*bMlI34% z5g=u^e>u1>6$|r)T-RW4IBJLKiPJ3=O>M1NR_QX%(8Bic<~Dhze)OF2nQ^2Tnw=cW zrlPkndk)9ezx2f7jBZsfKcGhV_N30M8l2LtpO6j3IO8|oH{{{EC3~Yxc{n46fab-^ zSUVOJ%!hKcU)i|Fo^nt>gb()K{M(aH4(V(&_A3AMOZ%4Gu{SE^J^f6SSJsb5WiMU| zXcJT18MDZAN7rT4gs5)l8Eg zhw-J+j3VxGRJ9t1#z(EPw{J>0QeNNX=Y2LgTNzo2n1qfgb*aFWrQr0WW?t&}C?kgE zCf17jI;=yOyZb)9`S2@|oW zrX-P-r=iMvDl0}og0(s|(@BkJE}bRvvuW&`GZSRY$kJG2|M(b!@0E@Bdg_gYcof|5 zI^+{nUkdxOD1sHtkwC@#Y&zQW#&9bW+nxX=Ba(LEMwedi)+gKWdBPgmrk>teI|}pt zPtO1uM&G`AqZu^ZAbT7&AfwV?Ue9s?o^R}S0?(Q-zo1-G63B%olW=s%95@9k@e705 zP~$UJjOvxAE02(3;$mOHH$iA4y5Fs5;@n?2cc0o^dBoa}scB9kV-U+tS>*V4Ga zosl_B)_%bz04wfm0B5|)PL_mdigP7;+~F+6v)<^rTY@EqQs@uHCpd6=-D?ua1PBBiR$DP0;Ui+q7Sp#V#~H!Z#&C8;UPhSpESL%ldsT z9QILs=YFgcM~g_2=bd(AMfcvy+!$2v4Mta5M~JGif~plA+H9lIIu0#Amu0}Fkk$!##(tD^n3~LEY%MRxvsLo~_eS+428fjk|`>hDj;WA^t zFC$wU+L2?=hLvIxM@x7>u?_$-$>_sN>5blwnl&A+jS5@HZPRv?mf+`o{8X z-&jtlz$oC{TVpQOpgA9!as7>hSlfFmBvFM?s9=5An?}}#9TO?7 z&Ma_M&$L&4=sS9?nM7m@71AbTCJ~9%F;ixDtsdcZcD(D;5^=1MRuBDxI@r+a-j=)> zQ)ILC3CjdTBN`s_y5D7RIH9h@@WBaprI?hmaOZU(AlhW-5L{2qjd#+Z35Oisz5o`k zPv3U(axjJwa=9U3YQ&BdfY{91@f0mXn41msZnL|LsAV#mJ?q@m)4LFwL zyo$s}rjuB%7yhGwpVpk2M6GKwWP<;v?f9~|2vX&Y7By+dIF!$U6y_x1A25dM?zQ&h zgo1BdZ>&!RJe|2R{Hv}kh5c+%7o z^5k`(ihrvB7;H8C-1)IC5hd7D#~?>L{rFrS)?~a@+)nIia3|4@^Qo(Dab>M3#H(+fg*O-@SuM+AHyY)lbO#c~4{7|pr&%gqP zf(+Rq_R0t711Bblh%Q*%fR$an(&JRh?;}b^DCMQ}hBww# z^p=(K<@8Qg%HJjmPg5#dQ42?qX&unws%06O%f2a8Gn##R=b-bc%iwj1*{yxXQ|%g7GU6<0$;yYP|HDw zxBMftfu@5_sr+&;XzSx8i*e?a@%}11gx?a(0wWS20y{CMfLI@l9sww$M`$fm#I`|r zy!{awY4zA^L@96kd+O_%qX!0`5fV6)WLYIwFpN$#3Bp{+DS-uOX4|L@J0L+XY;6p+ zw!D|C)=>$M^n*SG+X5iH#L;h&ZB|KI2Q2>|1^bYq5{1@pqm^Tk3m?;r zpDpVF_vliWbPB+B@ezvPBQ!Tm=+!QQb$+-?T<(&X#xCqrYuR!Nzjy>4 z%Z*PvU_H_Y*~!4EnAIT98qz0uBqa+^i<+gfSt`S3l4;WhnzPBj(QS05*3UfslHOqN zJY>9&jok&T$=d!63Sb>R1Qq-OPF&s;IqK((_#SN2de=DBE#$%XSR1YOH*S=fGq(fvtiYc@z2_y$=kuVVkhwN5;X}e z^u8Z#suKy;cTgz7cls@E+Xanv``J5y;=6VtzQc-yojQsoLaziDS|@4tzXfHEZ9ob3 zB9g6n>~RWzLg8FiP2sDDAbbtGHw0xYn+$avRq;Iy^!)pv=R4V0kz`o}@-_lF8O*9* zDIsojF*->vjS{f zBLyNuLx`*-MDEb<#pWrAf2|?l3jnHJu$dho^c7%v?6K6Soy|m@kq<%8MPk2&HNhy3 z4-N9N-Vvms209pR7eQAKTl;~VwQWbXvjn(kroB<$Zr1?pXh*?`djBzybeqrzqc!l|!%E0nNEi?A z4;813pfn>2ht17fI#OVG;t zhUjqxy5NoPD3&`%C}j<3r6*rjDs~{C?+qG}RrzvYGa^Oo3&1R?Y-jt1(;3-c5kr5T zbU2jlOXdCtaq{$J#z8HKe1q;rUNNo;8v9#FYMij4!t%fhB(|mF;4Q5VQtiH!y~bR5 zexFhgQ>n!SQrf#FMn3?f319}u4R+@Y8p1l5-}!KZ6@ z?(Pkm#XbO2si<#u(eV7Y#1(AwNf+BtyANt;XH!=$|$ks@{< zkRsA*u!SgP9>j+lZyYTe^5zxBz7?Cf z^q;&ss6{Kg@_Q!#pgHCpJ84AsHQ);2386~Dk@Qibbl|tt^sA85|Fh}8d@5%7MAnW8 z<8`8KtIX&W(zn5cPfSSHYPY3oeBwHfnU); zTn1zqxkO-^G`b<$zDI&NRMGFmQHM|$=2fF(*CWb)gs?P=W$azf=zHAy6!69jr0aJ< z1NlDJvhXzl>Al|4w%g66a^QWc(~LSK|LAoVds#bt8&8Yc&|RozNLDce-vVJFCX0q3 z{R!A+D?692xx_mJmV;Qef5^HRt=~=6ax9Bfm7TQTfKo`ikMNG9_yYBKDGp148hK23 zTTBOTEWoCv7@Gt)*f}xa5!r>5T?f3exq79d8Qme+Zosl*STCZW3FP<;BJ~{o5lW}O zsQAK(MGmJx*>{-oqe1!1W7vaTeSvE~bLs1v@QtwnoS> z>ka6m@KX4~sAm977nMdy$gS3NAY zM`Gf9Wjv=^4UR$hfq}qC z3^tmtX!f)9z``7uImj!UgDMXLFYuwjDYZVW8Ep^jXu)yLKsj07}Y->>J_ga*SA*-(W{oKlRQmGo4{}o z-r#~KM0wIN&7oL*`%?f1IHfqi0qOgWg z2W1ZQ+RcH5|BD3Cm&mbwNPsU41OcLl%CWr!$eevnT~gWpf6!sb|Dr?UMd-lOLUb4e zHu_(1jg||LJ5S%LmOj{lYXp5;5>Eo-5L|w#USIm|gjTeBAttmCqc6bYU(sn{0QH_h zo>=|*lz4!bs78sm4frkIUI z9is`0aDQqR$+X-Rv)FL*88B@~qMU&j88USzJ!c4k#KlpeIB?^g-~!tbKL|&%&{B_` zqV(P1#ooMdJg6+ zF0tUi*PJ=;9KJP{V>`!E3sMUfDa*yPcQFN->8Q&V|M z=hB)}>&2Wz3qz(WGNdRWVnO`mpL>#0hAdRbYc9n2?~-QRN29qwErf}iSTQ7Wo`((= zT3eKgNl%Z+tL(##5D!>nTJWU%L#CzWkkvTknuW<^z&pl+C)Kas8x~Ox}P}`7Wl3 zH=nmTg}0_uzCuY?5k^y{4|lA-!8>lYcFIhrCIvj914T6DaeJ&0394`nX_=W$O$#pM z+h%BEQM@$QAo{|njI6{4p0>?aPTzF)2uLof5X|$%`ogBYy_4Mx?h{oJ$00MdP4g|C zlZ5ZuNeSatZ9R)xsCb$#xm!&vLVMqR9P7Le3*R2FG~bJDg|$Lq2~aNg3wzH|FQ_ z_pf_H^Y~9;b{c61 zRI5+hsiYX7ZG5^;;vo=2!{1jr^+VUVLS&;rl(Dy8i@GeV7KOHh4(`h%=%O|f%M$yu zx3Hz)YSF6{xIiuX-%25NP3&%{OfVf`CWJaX`eGd(_5bYf$cuD1`6nG7hCyagyumr= z8;rhKgHiv_2K!y4LDx?j+)TXU9}~Huj#khu2Oagt9aRZC5ec!~Ur*B{rt{FJFz~*$ zc85)K%z)=o78QblE*GB=aev|S%c~hH9a73JLk4tJrEDYuVmQ8rdB1nFFdmRE90%+U zj6(%54{fTBA$-h1;MTM+GY+b;)nkSqY^@qIqFNrFYkiM(ba;@*7pHtI9V!WYg)zl` z>GLr*q8GMi#->1@CKtZYRwlnMb~QgM5A4EdrF^k!e2qFBxaAUZD@>rX z;vlPp@Y6$Ty(VKW`AK`u+%bJ%(5HSk`Iy(Odw_4~wT#u?et3<6eUx?zPgpZOWfcW8^QS zT|>ZG&pXBzM6N9mr~&M%;(n#&%Sjh0!s zx&;AcYs+Tq)IqixK7}(Ix*eT|q;4^Ng;`AOzOfjJqdwt@ma-qc6uw?YRA&U_E4VTn z8U6a%E$U zm89@yxDt2L^<9c+KNb?gk$WhM3!8Z;CCpD|I?W4XwX0_OaIrIW2!p|Jh~zKv0Z3G7 zD%|wsD(EOVv$d0mUqSH|PgJ#%pC??equO6mFA=t~?^eS$s*qbB&%YP*rG1lV6LyBA zwbWG78ax{vcGmF)Oa=F9Lqbj{II~1XwS&HKZu4C!S%=v!5KDQqv1(7-B9U7&JzC0i z`cQ7wxPn4l@=Op@8dChMq9J^@6|N5^Kv==3+>*tq^#l>O$>&x%j-3^mEA%t>D&=>9 zifkpYP|9d`Lk>_|FaVyl@I(Ja=tg+qfE32<1-lme0-P1HQS${!O|UM*4W)zGolq}D z5h#~~8yzqo5$HvIlLP2-z=hW`6w)5Cp3(HlsNuvLl|C+!si5E zGEh6d81f5}*n~rvfHCDr3Av7YH-;%dZ;Z`RdJn~^F7C9z zA-v7wfuGJ)^|ruXM99&k9&d6mt9XL~p^=;B3Y49XvQ6*8I5-d|;R;)YR=qAy7Cy0^ zswV7cL$|FZp=vv16|p(tSPSJ%4aL|Bf`RM%@Cnx>f*}J&~-=t=_+;5SECntt45AS znZuz$KLxUn79s3cs-OQwq}|`}cv5 z5M(n&(=S2ls$cTy6zcBhU{HLtOJzRbK|1)wjqQy`D4jmVFwU?#9=RV8{Vp7Tj=GIk-!Q$grSrdxuG8O zhh^|g7iFgN%pb|H5jn+4xk@?RgAzDSNn-4xcyT(XL=R+M;R9ZQLj$4#aG_F0J0uin zJ4}(yyg&$I#nXu4BL5*Q5q5ktitR=j=0-R(3Lk4BGu-8W01{izA>2mb!Y<6*DM39Q zScpU#wIQsPVXNGn2JeXd)Ltes0#oo{uOkEOFci{GsTf1aqwz><#^;nVKKKslWB)`m z!#B18oh83BZ9E?8c({Aq33rcceKC}QkHqlV6|OEAr5=UR{oiouI|N6NPXmXsVM*(# zOeY}l{e7pcpD&9;Qojo9L>_l!+ZqmRL?8sP?MZwEDQS;p%)lw?pO9`( z#Hw*kcHEdFxM4r=KB9oZ{%&4uQP-zE_k4P4? zlM)UTQugC!{k(Hfj?@v}_|yY6CFf>G4Lo*M`O6;PG0C;h>eq3o{;1<1JJ`w_+DRu; z)+@R~UuI`3Z!dg6))c)9ekExK=vdoValk*Vq1B0NZ1ZGk-%6{Z1K&60C~r^yvkZrr zZWQeHXEz+hEeG(ISKglUxJ#QjO+SNlm!5M}Mi;TSG0)Qe%vkuu3~iYd7;; zP-_=+j84esI2M5D5)jks53-9vS;}o}Rx|n!Z?gBGGlQI~UBEK%EyNSg6(B)7js=aA znkvHR+I?ET&ir_AgAE!abt*Xhud)_5OY6LU9u0+0&zGf@lAi{>(?R9%9rD|l;2}Nw zFV0z%5+t*R42YB`d3KpY>74>TdEikiY&`^YY7)V$eJxhy1 zadWPWPew%v7@1Xc!Z=&9+>D5J=&cwT%AY55*poPHZ4&QfmkA~tINg+u=?}`sPM7}1 z#3cp|lH$unC&BgO0VvcXYi3$AO1m)7B+oo zEo=bhJ^I$@frq0~{tm=Vj3KE0{T%Q zDk$ZHF>;mdy@^>o(T+r%;SNgMryq;xw-3b4l`)|dAMr!B;)}rxbE|lFBE&vE=HZ@V zo4F|9VdLX4yPK}go8dp|q=NkuhS4gKkc_8oX1*Sjy)E-9Kc?HWD5=s(*_FJg9<<%_ z*2UO*X1$r0<%%XP)&56`?m z0(~>`MXd8!=xN)9DT5!nz?{cdkmx75sLYdt^9zcboO6H!IZB25r8lKg*Rn-RypbKR z;jbP213z zY%qq})ebIan^1c3qR#yiX7!~J{UZH(tCI#QPzahVU@4g7OHn-n)&2MkRGou4Ek2&n zyIr{Q51g!bM_~uU1NfX^J-RJ4zc+8iQYbdh+bB4b%u8YER=;oWCO?bq4hGf#;A5i{ zDA~%IX==9KHKO!=?&5Q>b%ha`%dW@dSkW(%ZKbyqxnienE&2A0j$DB|{nz(`ThY*} zpqRh2g;!2#@K&&~RK01%ZcdfYpK3DKQrFl5W3U#cF=))iX(Ub48{>J_S^EU2yLUNyu+@-DwbtDfNb)*f_7`SuU zmk9RDcZ+^~gh+2E8+ar%IMkuNnMxCd<-_NiB(j;0u2kd|5+qpyA3WmDU^w~C*BA|Tl-&8CtE z*^AVK_B8;~r@yfH6&0B2Yp~Lp5#owP313eonpuw_sRrM5JD);e)nrEuy_K>N58=y< zClE|&C}f#0;W|gD!QgpDQ>BwgFg$|Ix4hS`j~vi38;}DUp1KD_*s>Yo!Uc` zG|yd~W3S4GoUF>1s`Bkde%yMxLvXy4Zqx&F)Z{1fE3RQ0ih_P$F-S{^^|JY5+D;ThD3Ec9l(DxmKhDT;`OSR%@`E}I{#=dbaHw3kqYOLW6Hj7Z zt-@DI+Hp8x`C{lQ0{lQ4kq$qsRR20mEm4_S6jkw&k)J*F3R0ZDsU9`zl?kaGY}~6@ zZSr23y4}N)5cEvdqVw2l6e2T{f9G2xv8ez0Ml31p#-G%@{(Q|}iJJTKSXQ`Zqq7;9 zxI81(D?&)ITp**A9S2ouuXzk_7E3U%^Gs1E!VZ>&!UL^qLKhyLvC~g-(S5bP7y>2d zvDTMSda!4THZYHUg0OEaWpsk{k_C(KYp^j1C%puG?S*TQ_(ohXA06W&Qv9aQIs$~B0f22XlWy(8mzlDfW*iCqQp!BHI>aodA98ZikJH4M z_YK2^ISjvpa@LA|q4!5U@Ch+0N@|z*^`T$fK;N;vB8e}xUW70(6XKxw^aQY1rMNDAR(wgod9ljPsKFS_;!0T= zuT1uTmVP@@BLPADc1-w6*^)rR3l~A4f?&*rk-|HWJ0+q9?(4>Kl~HLYeGStq8WCEAm9=d)RKl#KjhQ`Ii#bd||pbA3|1+Wcga7Owz z=v!YA|B9P(ndC-zfyWQ)N-_3qatOxf}_yM=j{%V^#06(&V-&#u6`k7gRVO;(YI!Z-4`p}C~`=~xBef^vuT^)p%_Xd#e z*O)4c^VnteGGlBKNuFK}oNJPzO@!@-=NVqnCzM%H1GD6^BF zP$K`<$Z8G=5nQrzZX2QV4fHG$Bj@lIS6s7(t?2i)=reAYyPD&+51FApZ+t}H*71*U zt4^TEG6Y69aExSN6e_NTiZ}Hs&TVbi@RDDELzx%z!6Di)=5kYee4rx3g$|Fm7_05Ah>`{h$BoRc1=gEFh>05NN6~Oz+pw- z2$h;2a9F373pT)SloK9c>D^C<*+x2l+bX*Z3?JBttS$6a_dK*f_h-hC=Q3`cal&@& z@IUJpKGXi{Y4#1zVVJ8E=owxVCt|WHWr;Xfp@Eu+H{HU)62X7$U=P1Z1;+zmk@!KNZAdU;2ucYX4k+GYKv+QZk3b=Ul1EUKiq2Hxe159~o6Vto zjg%sGI{^qw{g?mD7y7H%6mV8p1g%E@tdT`*=q>0*xMZa$8O7pIl1+t8p@iLrXW%qn zF!U_mF?E8}Sy*6l`~=q#oy_z^@Q+AcB<*eAxCD2P_oRH}e?|CDv28zumqerZ>^hSE zRrx`7?OW*Hbh(ULEV+JOh19!)wVsWjp)_Y$^&lWPb%MvcD&K-Bnic=N`e zMgTO%%K9im?Abaxv{5P^Kt%kY3cTi`YP@udxiptAaKY^O0#>>NH@^keU_TVPIYyjE zuu8NR3a$aR-ibn^%9tfE#@rQag3YXdI8G_VS*$j()x(W!qILovwu8x$a! zC4!nt*_A-2IzPyNr^YNkE0mbfk5p*U_|;1BLy^-G*`+8S7!Ocv16FLfbOA-rNcw^5 zp}h;>G3d~}OX|8y(CwEXJE_|bqI8jw@D`*1qbn1{+-IxMTRKsxppi;%rQDl%lD5id zH`B*qB=DOlN_jK#@iQy!H6=mBaSvIh);YJborIdnfztOqcFs%Y6t)#uQdaxM>bxL+ zR6NqNOm%F#0ykMx`}`9gxCRRp7O>Nc!NBdfLPC8EhP6HHYt;764*j$Ve#Io=W?+He zBE;F2i;X2d#&70cZ?_q_$tCP*469NWkHw8dLo(iaRw~#S%=XmfAa($I_L7~?5b>`s zLj3qM6z4w^FrVUIAZ{e^ju!$nz7ID}Q4iffTgK1L;Agzy@m7j^!;SYHQ90orzK@3Z zN8x8Gd1des+}qB!Z$!Vad!wb!$f_rDUj7D9OT`U@7=$Qb1Zy(SFrx)9<^!n8c1{#@ zUsP(ssCloZ9(_ImOV!SBB`)v9jQ#)Gd-wRLi|gTkH@iuekg!pRAeXud5n_;niULU_ zTntyan{d&@Kmw!&f_s4=R%4bJmi?yMs;#ZHnnqjY(&D8SZRHjXf>y-4qIf}Z*7d^0 zauI5t_nGNb*ujh~FpWo}pi|l8vXU@!=IWu$S%$W&-!Mo-R`GLPlBkU&WxahM6 zJa}*0L7aWt^hpAP|KoZVJ8H7V1gy?{>*w6Zsn-aHCnkF1L4MNh(gF3?7@X^BDm z6#MmO9Tv0(g8SNWNsk~4JYSsI_cQ9JscuB-5{D*~I2%okP~$k`Jg)F*i%Wm4TezuniY0|WL4bsz6Urm zTFwNb-=lh!HD2WSebBXzbU!6VJnZ&&@-iNQGM4wzkB(`5p=;m8{f5^UMj@cssb6U0&7qz&0f?eg{VH%vBU|Cq z7Dc%muJ}*P1D#aDK-KMt3S`0=E!CGMY10u7qm@cCboE#X&@#Z zm<}HpAPl{hrd5x9CEa$IsX-QIw-aG4s~Vn!%UsGj=BKea`EjHeEOWBLX~)o6t6OQQ zv0XSFCX{9b^gVIwn~5lqTHMgsO503xCCIbZn;Rb;YfQ6lIoqs9!@9ca4qBizlFt}4 zz@MF_3mSicpp6^acSPDxx3@p#i1)oa?3rOB^~a5 zDs6OA*@-+J+7e3yIWMktjDT`~gL};AkB>w?2Ur~P%(w@DBE07XMKOTiGMFE0?!S=9 z$zAUvGCx1yDr(af@~HCszMb4sm5mrp%mgLs^sY z+jr_dbR-M7JY7lOxh?XdNT_xD0jEQ&poK3DPhxox_(`~rBufYvHok}Y>UfO}7tGY1 zOn^GXKP0${jYJj`M(9vzci88O%^Q0|ZB%@WtMiz2e>%~eQqnJ&ZVYGXl?Apt9U8$< zS}<7ct^m4P*Dpx0QH(X0V=%g8tIft7yvSPeWs56W(T$;rU(zDdD z2$>~?Sn=oMt{1z%rIGbaD9_9kD>Y|d&17B;$Y(~2*MXPO>WoZ3$!K*(u4V|v2iCX8 zV;%-polxBezlWTjSLZ+o?)nNsgf(5u*J4duiFemeB0#8e4Bw)-d_X-1ExPM3uyToN zRBXr3){n|?_>mz5X+)?~~$g6q2mEkYtWL3ncgVBCCat(PKyPJ><}}&F!h4zq`HN(ML#<2UMQ! zN)q)p6fv`;m}_4de!|<6<@a%TiU?5D?4PsN?bc6y5k!1eHcy`X&|*Q+x!{0*)1YZcN5 zruwUJ#ix2Rrr>Ac^M=3UZp?M;e$%}OFZo-bl6N@>L! z^o@X~JXY?DaMdkJ`dam(=?G%5Pp1p(hRR~z9;va)yzl13GC#YIBBoI0a$V*!<&rY1 z*hf1toT-K5!07~>c=0>aS!C&F4qrxOD{pqyGp!)FYIyWKjsoVp;@MtZn~?2Jvc(1L z^>?x|zJcWNw0}xWTalQySkg`*?Gvfdq$g71c=SC=MNXyiCR!U6)NAyn1B_tJN!OIg zNlT&LeV^ui#o)qE#Nwkg4y$g%jlJ&TcG_2#a&vL%H8H5i_ymzTMc)glX*)qZMGcY0(XWn5$) z&R~IL=1Q@?{8B&bB?lgHhw{b*Bfr8{|2F&|!>a z*xSOXO*f}H)nnurWIK(_dWrI5$lReF(MsnsKm4p^GskK7pDX7^Pa%k zJLPSTwW;GqXh&ez$6t`Y3t5y*O1fFu)}`WZJg#2}i9a3kc#9M=k5%SQXY0a(!9D#i zEiC9c*#C-XMN9k3B2J#c=?jY{S0U@rOv%0afd*DB$?}rB zqs}~rWW6(U=Ig9xrnL*LlT@#_QHXYE1G(X0;T3keT&Vmu+MJghH)*0t3D4@{++_db zgJfaamKA}=XDu{4a*ub0UTz#JU~>*TvLI&6g zmGw?yafIyhO_h<|8khk4CSKgOw-UTQMaA*&+2 zD=;v~>uNl5^kM9oVtw`KdVS;BBtDPC8-DCKM~_sK<`k2kb-ELKgsoRXdG8UOxC(3i z-b{Ed`#=^1SG_ND#PvPmvb<}=X=Hgb)i`4HB)Ry#*d#e`cE|i_O_*G$YUl?z1bpxx z7Q~Tr@O`hmN29vDHvoi4v%AeUtc=v3;ZPqD7IB6W=KY&>Vy4nV`}BgmlbN6`0#Wne z0Pgx%*C3|l-Ks^vFyzMU?TP$@;P`xhsVTLL61W$7cpb2=SUdpO%%X$VV85L6;aQzaq@mF z&&ep4hVe1z5j%;zGu6Aq`YuynaWLhse}S0jNc3N{PmYHeBG2;%N*a#>J)mC-d|Evs z@O~A2m#B4&ng|cAr5CARU&qBoi~PLXQB&keME|JkAy zWaKj!s?H!5Jzr}FnIM}wLBjki-3{5oQq>g6HW1wVbPGXNo!R$oQ|WVg4!>$ zCmoQk=CCF8{X24{_*wbLttxdEVVqau)ZI2+=jbgdM)J5o-@pLXS8`>jD|Ac}G0|@H z$6nJH=j%|pWl+RL#0I%#P;4~^%Qa0}Ifqq&pqnj?WGe;DFaAf${5xqQH}Yc$ow{dI zNpNA2NDKIT)tzD_e@Zv2%ZVWV5L-%jeP`m^r=CWRPn3B|`*fP61*g(Usly(jaULas zFp)QJ5v&Sy`Th}MtyHD{bE6h;=C%}qRw!dEzu}=97)Rj@8BNx#rh2g^)0$MS(e~2F zQ%oTsvPdIR&x#^=>uLLnvB$=xBn7UF9TNPcI7R?hfq*6eVc!-3l*aoWIi*egnxDu} z5X4xoE?i{bG+CNNu9V0gM8=RG87>eMn*~EVPfqKBpO?G|@A5u8zSu0WIXl&m3N679 zUnoOj=b$!_gz=rw;YM8!B|HK}n?lW$=We)?v8>oV*dmwV(y&Zp^p zyRi2EOy<{*nH!_;GdV`z4h_AV%u~z(0#|eN*@(J#DYyps3H8~`=(5hQI3m;~@p4Q| zYf#4uHlZ;*wrP}+oTAxScjW+g!`sxhNX>)oy6cyp725;yrr!?6`Q1E-UF3S@kD{Rx z*2U2Gqcp`&B&`UlM)S=pkTMugxQk=Q9@68@!}!rVfLQ0=D|p0@mCn{PE~li8LAdm* zYqCT(t7L}NI_G!jS>K$BXjRN8)wSrdL+GJaLdd1+UgkM>{S%omMaJQJzD0%)BJ@Rg zy&K3{c&%!5LV1=+*HBlEYR2kUqONCjhE9~Z>yt?%bu0x~Ub3m<4BVD9n-In?lb9R3`Fgu~zEmhP^WY!^X(7Z%YvA_o@(sKVHN#Mfm=W7$=a z;1Db)MBRbY>Z{o375VKeGPzm@1G3K74U?;PfbP`~gM9StGlG64#Afz}W?#vs(vhKs zuII+)`FnPxO?R%zk|wGv5Jb59t1l}Kc~$KIjcBqedIN?as=52BnTFX zA(M6FD{s=Mk{T$)>`c|NMrqj@jD4y1b;1M8kjaoymOIfkUDZ&n+1@;E<#R9`8j~rS z7N{{a3k9^unFL|BX{98r|jQe9ve^a;2A4BmQSm%!V~Fy zin0r&-NtSI%<0f?xQOj=_v-z~aJci5v%NUfCgAhHa^?)V;v#!(THdTwr`O3+R7=jg zBR5ZwnrkH}9lj9nHz5J56Z~lwE9V7A z>$TpDGuFJw@uG+0YpfNu@tmkKeoL+TNGr+EDWfJar6Y$*(L>Khn8c;>%`1?UXi*|$ z(p~Dh0mfTLnAYJf++2Klp{)_UnVT|g{!YR9nHX>?r5@|pnz`%0TcLZg;aPGQX$icA zQ(z1R3IGyzj7P~`UTd&w78n_x_>fT;xTidYkU$AE=O? zw+gz;OY$F#T=pT$)a*N9W*n=HPHO2bbg(TjS>4QnO-@2{fv6WQTO~?$(u<7C2z0L* z#BZ=bf^D4e<58bzxmKjJ9_%iW@_&IlsCBo*%+_96BOTC*o|8l)xu+sz{ytEdGe)D0 zd4cFuJVm6c)e9<}xYN%~^ZbGE=$7Ic;S7z;W8Bl(UNMugaUGc-Y2(O<<6`s9+RMzLiUu$tv3FIm94SKmPg28Xr#y$o^dHvY}Og^3K6 zM5SJz3OpdyInW6NPv52cxhwtbmVSO&0`CMsbi=e*r@qG(mbtS{^OG(^{TgXG*1bs@ zy`A%Eb?YuU2VkVOW5Y}1WA)W{@I8F`v@snw_YZ18xt&;c*U4f7d4$&L>}^xs-_#vlpSVIo{_V6x*AFxW>=1`Yb{pQ zY@eF)yU5_P^i1m*VBst&$o=e&_`@gNMUJ@MoNcJb5c>eEljiGHuR>w>@Kf3vABKuO zYd?xp| zVISgBSL@UTWXvDoUi}YpY4ypLmuQS&_6z)ikbd&YFe5dI45~XnXK0&PkrzRd?)vxM zqye)8La2{Gup-ZroQ)LfuKyQ%l&wN?4vySXmn z9c_)FhuFSIrG!IUJ*?$lW@+tE0~llUKe1ZQf!*!$zI0hGdXr}CFdU;#kW+JCV@hPJ zX6%0lJz1tm1TR#xRj#c-uL-GE!_F~Q@F+*hw z^a~v?jT;<^y_u-1H2Y%u@VbZOoj~5_Q?YO97xao6kOrV$Gd8x^Z{iR2{LFv5R0zTCQ?5yZLI zTqbaPX&{{i2;Z4iPXLJxYj=GK#V3rqp<$r+uI;J1!`@UL z^;8!Sqes)&Hy7c(1+RKtgBe70Sc_XMB2ythk>8Tn1gm{|H=aVe82>H0 zqJ!`Pk3QAry{t4qzPcU<-dv)DDttO61;~~PMZ>SVz-RLKB$bAuu=h#7} zT`m8);EPVEX1FW(%E2@19|0F8sk?qY&d5z4QQnmr^548brsF0`COU33U)^!TaTpzQ zeW$(PJsOsUy#{repvr`pMH)-hJe2Vv35@o+dOnwji!ww}LITw(yrH22;2(0B#bIy8 zhPOm1@(ntELiFpLG~tiy^V{FFFh}DgNQ2@xs{ZvK4f{ITKHkRmuX~IrQrf8BXnL|W+ebPP@l>% z>i)VbMG&=STslG;(VmfAxccW!RO1i_tM%LA!m?a=ns41OL_eEwsO?m8v$SJ-umuu{e_(XJ^g4rj4j)Yk#&mNh-RL0C6aVPHDkBxOCb6vPSSrV(K1JWX` zOK6;b(PZxWKky5Qi9rPKD7AkM6(8|EO_>iCC6My{5lR_>6^Vz>7LJ9c%z>c&s;94W4TjPxSzAOY$^JL**uG`W@|xNiOtr;_)F> zl88qZu*{I%hX^K;M;!F|E>i%vphXyr;>#!0jiZND^$2@P--n#QVv&o*_SnwOmT8oS z!__hi2RR>j=G7|Ubp&%gt&l}3rFma(gX?f`iSJn->EIRSw{Pb)|?N7ndKS3 zoyW5!KCh?0yJ%!M!=2SPG##=vnIUG_ur zQ9EbK4$++CXC~&?h--Dcx@^f0Wljb*tWomY>oO$2T{Y_bJCo(0q;!9wEqab|*NB^I zq7q(*+jKZqUF4dXN@Z$s*LM|XFBpiszPmUXAvn`<8kNj~4wcMHcsny}2D)Z8vM*Lk zn8}-E1gvkCV)RSMI!z>(si627VZ`BrZ{*ilb?9=#u6}Z11Eu;QN-ZTyME3|CX*z!LRV!n9`I-MV6PVU zZ8y0NJYUFkf2pKOR^zrvmQ(?<3TK@@_dXsUPiGw@tU%8@?$ryJaOf1NNZwGXh`%Vz ztG3bvsN(APd9vcyR(Z*r$6b3kmOG=bhO_k8%aW9#Ob$(+`C6vFdFRuQU%8_DjG`qF zxG>csd?%rC!x@^34i#o67hGJ*NpqTp-n{lL_8{Rt8t#dlw?ku`Cb`_=GKXi(P5sqB zi#6l_NqDGEiJ;lcH>v8g*@R*JvyBjNFB1s& znGX{PcaxME*K=E>ORKR;Tf{e^1+~~ly$tvtC(r*`oKUUVXTWu9xZN$dZocZ>8maQZ zV+Pr2QAoNVYde` zX1bI&OAPxKGO+SRUV|fBIxurKjL?@F{8O2|SFr3|eK(m=UAY!Dy{vU?$fj{_H<<(b zm*Gd~21nbhoab#I#ZfEwSsd!6>I2Q_hi$2zanZ-7w1y5ru<|NriasCXz%U;iY^@JR zg9_ntdt@a)>P>#E!^ze6P&8MP{htHbg$_%g?&0X{O%JZqQ}h%y0nXxGhT5QTu#K2` zVt&=UUTlki-H?4TZ5C&kr?j-Pam!fJs*I~;v9hVxx@O55)@>RqbQTCmp_wB0{F<@9 zY3sVke!eP?nCRONJsf@AC_`lMm|x^MV&Xhx!M{mnXL5JfXW;yi)eAk-L~EPgF#R)7 z)d9m=k7(7!7%IEI5mX@MJvcgubcZJM-Gs@I*ugiLy#`Lntt2KWuc$DLE>bt)cGurS z?3x`-x7bznKCA(L$NGm5b)Al^mB==UoN7fbBxGSIOQ0pvA&NXU^#(E$i(Opuj-kVF zA0eaW#U#&pdwsLeqkJWMjJ8%(CbZ8Oz<1Q+TRj4j2$OnzdlbB$heNyT_u`al=aIKa zJw{j}G9qG8<2#U9^}azyvC6@sR0^4b7YmVRM!w}tJiZz;Yd1?aRhRJ?NZQq3ZWWBg zEz_)vTq0&=Hc2Q^?E|D)(djZuy`)_Y= zU$2z~);}D5XFb+xw4yk3$$`UXkP520NiFGA(ukV7QG`Xnr!~#!F0?4Y*kcd&waFa^ zZ8KdhpqMri*)OmJGf#sJilqcb_sc=$cwEXU-aV=}Vm0sQ2a?q{G+bz?OQ<1% zrd*DUT7q&jZk7mLxZY!_Rm_laGHqT%?D}R8zti*sy0hK&9^eme^L~8>*#Vj~>bER` z&6}p2<&48zyIW4RzXAiKIEwPId7KP>D?-4D0?Ml}lW3 zG~Y=hC9I0GILV5SfRBKnZq-GFadu$eqzk&oDyWIC!G6d-HI3xn^O!Yy2}Tt2`d5Fb|yZ!_* z(h7(8s(dnb3)GDzv)cq{~BfkP#JYVUL<-0eYZ}YVjvR+k^&tR=i)k^I}S4^s^b?hx6 zuxvCULlc490p8K6n>FQa`@*!_X1)mx(ZT)njCoE61~(kAX3SzHHt#%ozPw0H#I5$Q z7@w|+KxmG43^JT^iMuLXphuFHSnV9=9Q6qec8-PnAIPB2A-%U7NqbtMYY2_}{5n=Z za$7L6U9QE8b8;{~Nx#r593di@pw0;(B$d6t#W@MLlX^w*GsVt@{+req!O^ zl;k&)94)VQLq(t&Yx9G$1TWRGv#nUTLoD_MVk6I9n}BO58gKWoR@e?@4PzK`I-LBB z-e~p2WLl=bH)ea8%d^6>(>K3Fe5eQexX^f~UhyKkN!26M4KN|}Q~{c2_veRRGh21` z-)C&YTgM9eAASz;e_#x^IqN1S*|ps^4EJ%@E2cRNzR>Fvz%4jU(m4|))&TKz;oL)}-x0z*d zN>@>8h^_Y;=Owh-OfXNxPlIm)yoI0Mb{bY5nL@_c4WgLZU?|H554UDguS-msA8K(D zWbJIir7melIU+Pvg%;now4!va;impNPI#EVx_HL_jfS4F#1tN(J_Vt;hTaI8BT+eT zuGxDgT2cCB0(;P4TV^-~leBjC?PAtS%Z`*0 z(nir#RnhJ^NY8Wu%5-_FEXK#(ToPxSi$VmV2;^4F!qk(>1Anr zhXXCKT(2wSiz|xVNjcaOF>8_zEwPnzAYDsKYzc0oCH6WDDRS9NF~Xnp$5)tw!zi6; z&{*Q?=wyd4b7PAX&qE%Tn6&eRP-mn);aQzCEi*ZhFJ>T=YmqsTE#F3}EOoaZvcKF? zEs(YTnCXTL2|zb4ospiW@5-T##L8+zelP!^{0BK--|9bKu1a)c!Jf%BH=S+no91Ff z^yP=6FK+Uzi?(eVxh}dL6R;}jDjA&5(#u>&Ok!Wmin#%w949@|6>u%~O#xa|Gt{4{gkvvh`EHX)W(P&rL6};KSaqg^RV_m$Ed^OMPwP|2-MfWP; zaYNVO2e8OFy31S`_{`?6|8q$rZYEZHl&{%=(ZF7|#i|W=8AJ$oO7pesE`R3yFSkXU_)2h!~Kg_w?;PX}Upj1@De{@*lmfw~T0R-E9LyePi$X z#N-DPZtT7L!y9|KYwaJjEjk)gZ5m#rP$Z3Vr{ ziyUDsYbhFb$Uk)0EB-6=aY%=5JYqC|7Chb~_s014kh^1iGv)pmUku1c?6)ShjxrGa zjt$Yjooux{`C1?cp(T?z`uP-##LRnLnps%w)YS~0)vYYfXyia(T=dhr3>nAvkY&Zv zo~QS*{<*=gGQ*|mYF43U1(9MNlHeJL@Z~v&{g;bKL*#oG7xNmK;Zq!~Fx}lZOE&K@ z!$@=Il(Nf@o1#z~m}*L+e+Zj_FBV)=I4iJNy8VzP+z4i8!q>6P&r!0P#KO%xXssCL z9E6Brq#BNl$griPxHY^@BQ=hxSa+BpMMVC3lC1M@V{8}`ohE}L`Y(004%89~6X=X? z)}n@+$x{1o_1Hb_?RuheEI+No}?wfz4f^N#Du`V zgC}@2rLI78#K6wb{^(Pd$NvnTM`JPP(z%hdff$Q*Nr0Vzjb_4iU}m>1a)<>jeD(Wl zBz4o3G{ziQsXZ`P{fSxCI~P4}&YJDa(lJGDnMOln4uxl`@I+V6%OT$v;W4L~upboU z){NQTF=hXru@;-M@5HU=2h1l}vxPRM))gJg$o1gUmaHphIt!lPQUN%HVf=RQPPr4l zt5~(Na)6f`)nd6Z3MMVGc4iWcb9X&Uw^cPt1P6o}EXQV0qS$^j_CGgyc+pSau8FW3fa%7r+Js(=L%bh|Vx&nb#|4DW zTo4ADq6syiNIDre6%I@BXPObh6q{-;bMmy$(ewxC|F7iLnL^f+uS4xtbDrOl>jzBnGT2|K8p`3NyIu|rN-Ra^r@OGg$?vB&%JvOL zIf*(9(3)$|oR#K!N^}SBB9~FRxq>nytMN9Ax^Flw=LPS^A6U6@afIm=dWE6fd_V@b%wzuCP*fzq*y{YPKP!qMk4t^gx9^>^H?3U4Y z5fx&i7izTC#5OM#y_aCA%bk1^l+^Bo6L@c}{kgi8R45V;4g?ak0KF1hQ9IunO8+xl zh7yNdoH!U&G-TBl$!0!Z*3Jf+^=+mTu`VDp)$#9lVZgJ4dIZJ!vBmcaTs5T3hU9?mPqyynq|etC3VY2?epvDTFa_MO(g z$XkS}Uy{;$5Lh24H1TSndiU1uQ9g-%k=UIHs4bM(r)r;6*AN@W$4RP(^3nn+Qf_p> zwCOX^s z1Qau45{kbF-JS=(y%q(S;Hh^1EOjwBc!#3p;LD$ZyrCNJ?BWu`KG)jvlQ{=Y@y}-V zNz*)6eGOffiPR&y&TJ%405kfvUM;9E#C-rT*?9}x|*D8h_QkK$LEE|sPK4K z&YsY!FJdd3h)DW>Y!NesoG_@ssmQNMQCIK>Mhen;(dC>rb9!+}UB|diEt1$sf-EbwepmAVnTD}>ks%<491HdNf^Sow z4G0X_95|?Fx2D>;nV))i<3+zqQKiAOV1&Qyh|ySdAIjzITj zO)g`*96A$G9zSvD@^Ui-rO;bydw&Sk5voP&L&^`0cVR`%6&l~IskX;7wH>+9+|W(w z;i0Amf+`kqCuSafNaMr2*&2FN+cOBej4n>y%`On=5zf*W%yRu7FxcbhGD_uxgncJy z?7&J6Pgn6~ND|vnZB^G)uj!^9Gt{MmO=Jnoy;)j`4#c#_wjOE@;qtV}>~3nLROfAC zK5LOAt#V1h_S%8%2a=l7@7KccS1xRCzbmwTe8|zXio3E{%#agT^)$igzVHBCW^h|3 zw}*F*Nk0T5ZAF)Jo>P5BG@}I(Xt_lr>xKPX*zkjlIn%YHufYMjJgu^#XvdUJf zZ)k@}bVTnxv3(rvqbuXJKBGhg zQ^k z3+IdqW!M;pDv2B|r-g8LgmuV-HfNemJtcq&)gC^@>S1cqENRsF_)D9eWMqVCJk-r# zp+i`4#{(A;$Qwe4y5m8!2;$0+zRu%@p>JNnUsRQoC*H z1DSU0t)Zd1;0pu=DL1VB233<*eM?G%feGIGk=!=U=|{yRM<~O^ult_iQ26GBrtj1AEnf2Xw8nc)C&v>7hwBm$S!0c8UEh+Y5pD} zQf23pSv2gGK=QB@&R5qs-J^IRW8A6!YsZ~Jg~Gl^@1K}jHzRj_vMsfzfz(qV?R#42 zDztlz^Sm*Gw-5d}QP1)Wr2I}0dM8wN8oOq0dB|~BXe#Q@>4I;=EC`xC!?pRH{Ilx{ z1ZR)mKCW$Cdz#g5V0%8;4#cEE=%j9(ob77g1!wd?Yu%N+@+-;+MUlJtt-CVA-4NE^ z2JvdRylqz-_aL^r0S}^M-A)nFtPb~?WvGAaDd@uyY8A3yM@ini5~E}`7*B{hfO-s^ zLl=2H`e{m)ggbPCij8*}C~6xp(DP_5BlUJGYy)Auk`(HbNj00sxLUgLMYT}hQR8xf zSlpZ3ESK2A`Vw2Nqt{HQwCaxV$ z>PVK5@!M5;;r0*HIbCxOf5Dd&+KxfUOx5drYTDW?bqT%On2B`bjxk)WB7=r&s>1v+ z(>W707n-z$4Br0XRBlcU-lg`4@7$)6%v)f0Tm=0!wcS~l-wYx6exMHt~D z5cl+^@jdb~HWRXZLi3Y+a<=CrOM;wadE+N1S)x?W(GZBl+I5^=$6@n;r@|zjJbSiB zxL>% z1Yfl|#(&dw+6iXoY0f#(3+ABLCZ)Fs%%H~>yxvLXL>MiCa?@;=7?y!oW%Q7a5?CrJJw2WzVQy0SyAg&e4@=F_JwofW z(p_0+dPGvMVe&{=c(gq2bv7zXy{7X7FqhcXljq5rd4?*JZwNWo#7xv#n^vWpOe|X= zCS>fLb3R~&(UxRAY#o~D#5~p}L2ItdG0EkffJSRmzQexVJCX;<ZR`RLa^o-=&+^79&Zt886bE2{}qXDM-#>i`e0v2`8eYK@F!Y+0~JyX@m# zUN=)%@bmQCX->y97wp>Hd;RILSTcA!W#x(y*mMVLwec>di56+&7U>vF?#pk9i$uZe zU0|FZjHc(#b_O!?bXWV6gI}jd#kxP~T1gex?e(W07X>O-osaU%)gWluG27{`7y3gL z%w7M0gilP*dB>ZrO~!LqkC4Wrc5DQP_Q$pxt7RF;!Z(`gpgv-xUo?5Vm9ky8()cTe z>}%AQD`o66>zd&1JCMiB5FMRt!dDSO<0yIS9|w+q30#$5`mao*|fdQ*yMgRX=AD zO|Q$4C9~b^CT)l`PPW1c^xa2k3RjY;(2!kJDY#ea!>^-{0K^gKnm0FnMVF?0*pdY0 z>_G~UOWVC;3%GJ-yLK#4-O1u(>}C1hiEb`CpsMyUGO2d zzUv&!mTSK@kZtm%M>q16>!T&=ZknvjT`!`Dc%KBNPc$6%fH6opnmhV(nl4KUYp4C? z;~3ay>#s<`LJagJ3n5#wtGW6de^rn&rAp2^DcG;`$&tV$2p3fE*{+cOea zhUcDl8R=dc0^kLr}q;GW{lc@Y|Llp=3WXTQm2W5}xq zx@@q$?f%t{b=#vZ`)eN`F&E+FzU|v}x3t&&JNUM3y?e{J??x`!*c%| z5l<&62O*(%4kTlF+3d2iBw=f);B7vzxKH@Bcp%M|e*A>KWj;oAP$I+nuA+5$@kaVg zrS+6u!#<%ZGvYOZ){4>lh|7jZoF~0i>7D${e&?PTJlFD$9 zZ;t*A_R*21H`G7RW%gc@05R~FaIC!WG-q%}dd^<^4t0+tE3#q=c@taU1+z4yyrI@G zX-khxlL|aSVsklj>)9s?Z7KyxUa&x#0PWcmt!fSNCtK;_%fh+|V51jJQvrsS>O$09 z?**p53FT)=`6+4&pH?-V-}YpIhra4-Ad(d5ZAlgaXNS{NZ<>zt{WtZNH?+Uiav%6c z6_bkA%1R$xErD0q-BZ*}mSm+=t4%X>9T5R;)2dFEUe@+OHy#tZYr3VT>z22~qC z$GA$Tf@XH>)|WxbgiMx@u3+$;@xR^!Y1U#g7!h$d7WR$?E2$ufKwrn8%JS(&~*xE0aGDR>B9Hd>E02LWXdzwdm125I( zIs84gJYfo|Ay(ZD%DNe&Pj1<4!b=1hY1wFVtbxZ8#B1H=iOfJwa1}O#`fk}_()X80 zUpm%F)hJdOu{@as&(n7^xaGFITVy^Yyya!G7$`L9n z&AvrUx;gW+c@U}?uD2JnE1QTYmEbovsS3O^6W#OhylzUwc=MvWi?Q1Tv_?r7 z{ikSf$?iN{Z~{6JYeQw>NzP})!`*C~zjMBW2b7Zh=c10nJ|Ia=z8przTyvoRgtgAJ zb}W6HF{v(fx7gD#@~Be>ZZab)2+*P^ z$N9-*#gz*dL+ExaO8_ z4oAaddfVG_wl7aMdxs`xmzEQdc-~O?^(~ef`{z^3KGZUoTK4C7>=INKCYTcb49KGB zUT$)twgg*Kzt&|$x1s~J+^$$Qv^V*ZqnnCCM~YQ{#7_DhEwzkPrH;!H^+xXrwsnf$ z*}65IZb6S}{WC5cJCmeY)G_3JIzubI|409ZWikq_e*&D+8{;uS23V)^i{fxg_{%+^*SNuK5-v<6R^S7J7kNNwG zzyBBTY_>7gHNML6Mt($R+Y~;If6up(@GlGauggfAy39}N z@@kK-((kWYy2v*oBhACViz_|VRZFV;;s#BRe{rQ}NqKG6lE4zr(!i4W6jig(Q&Htx zR$acbvcgj-*!VmHDk>M22de#^AvqSDW&a&cIgPr4ydChCNktN&3?3YVBQjLlJ8C&C7 zTI2T!4xZ|oMdI^%d;uuhyOKWiNW%>Dm~W-H2GL;)YL-^$(D^I^`S=Fe7M4Re z6&`<$XN6FWM#A*BXQ2?D6jZsiCa`F+XG!If8t+O;N=24cS6Znpa$0FyP!p)8f5@3jXPc@w6LnS9OIt8BT2_EA5%rqFgV-wM9??LCUM-!4XnE-JJqZRh(_zLRGcB7FlL zTcN!uZBC)hv81K~w__&}j#`F8q1}0|gu@8LJrZ}437#RrzQxr9Cs!J`Bu`#7m+<+% zg}95JoTuFqUi8yz3vJ2seJjeBNvhrWQsbl~kipUg;+u^x#mDHckuoM8EiJUUswwmtJ_U5f?Y8u9rb!KYc1_?F>wRQeW(+qHohCO2vD zWLxIrfPq=~7St@$U>+hMd0D`_2%p_9U8}nq9)~|k`C6vaKQ)w~{}7b2uts`UyxSm4XC;%Kc-&7|9vKkl z;Bi#U*Bv4e;*NzURm>;7U4n5EYM0bW6)Ol$GNCI7O){Z$mfdMWD+qO(P-wuOVnUY@ znqoq4B-CX>ZzR-ZLIt}t6Y3{4O+pe}3|ow_zARM*CY>e`r4T^kdsYhyxnZA_@HjR_SzTqac4#)RtH zNT|bWY9qnomfDzbQyUX*Y9rxJ(&*Yqg!V{nbc{@R)YI1c@5G3Q7+VG&dq3M~yY1>3 zRI{IUo~NCK5;{RUv&GqKCMfjF*6xE6ob8w3dV*bLWquZnWo5B|w6ZcYy_=w?Od2WF z1Uz5@gn~`LF9>kTq;2!qZL)@TuBh==h$jh8az)IC{E0Cb^P$qmTyuu+#+Xm`9LfHe zFHQSm1&A-DBAzr;B5Pww#g}qpJklePD`S!3OQnfp{z8ep=?q_W`TR=Fv0H@$uVGg;H!Kn+t^tS@VSdAG9Yk<`}bmaLRH^JmO6%_lZ;5!BG)dCT=7hcwl#D z&Mn1^VT*BZybJJg#vJ~$u;RG45$_p{TLL;5_vyPOb)0cG!l)A&_fTQUF~%*CF~+SU zVvPF(c=Z`f*dc7!;*QC->(=9oGvPV-5?iW-iO=wMt2)=5QJr3AR;T;-t0Mt1W|jh{ zWZ@`H{vAB+2P`n&fZ8NBV17do2IZtK6B`dEuWJ&c|sc_%-qeZn;b z{-duDVirPG3w4RF2*_oD`PEfECQ!TW)jc$wzx)Obpl~mdvepd9glM;ody(=MEUsLj zXSYB9i=;6IJn&UKG0F+y>7blzUIR+Pdg61S#?}-2aXWvuveGBu+n*!iXG@s^?Y7Ps z!g2mAutd0%t-E-bm^97WU&m9)eo|ttctc>BNmbj<`QG#;3`D}?|AbsM1$%JFidFvU zKKIySZRfF#w8@&r=COI^*{-v($?9bD3>Y(N^3^%E{x)kLTUjx}W7FF@zGDImlqF_g zg?A9U0BiFm9L3W=+t*(&%onmvt+46smxonCg={q9DQrusd_D=GLY^A~HL#kh>gvix z?DrC8WLwozaI32DlzSHiWHOFtiw9KJ((9fDi_5*`3s}zhJnV0Tk;SuCRgkZ0VHMlh z7&No3v-wsonO{>4!d3k}RXz{c>ZN3b?7f(W^{z-(8#dW2fk%K{85^ZDbIBIO;0WQd z?+`$~N}ILZlie11Oc6`jqAXolUA4fkw<+xBq*+#aV#ONBwgu%&1t?4UYBoRu5FA*i z2`s%IVkcKlQ&g}iqRKRmXF-*BL7=+aOFJ*D^j0oqBOS-IYJtJsXA3N?tX*cZB(`y4 zPgGQSWnHqoGTzV&kaS2tF%*^~varS5K~}H2pJV$hz3l>9D(RG(kfn7bu7LH;$?5ZDtDlC zY0TrRS^|}U64C&wW5h2W$t68k;aRbmCe$^HHCL=lmXM=LdgY8=+EDio&%lo0^!nR;>O%;SC%^aiL`IVJRA>Rd%9$Ov3n>Fkr ggfieMK4EGyw1l2xR30OfL=x1T>Hq)v|5^+DFGC1;m;e9( literal 0 HcmV?d00001 diff --git a/toolchain/fasm2/fasmg.x64 b/toolchain/fasm2/fasmg.x64 new file mode 100644 index 0000000000000000000000000000000000000000..d3b8364fd8fc41f7e62e10a249eba1ea155e68f8 GIT binary patch literal 70646 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 z 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 k8;@~N%F?FUoQ;2a{%^6951J literal 0 HcmV?d00001 diff --git a/toolchain/fasm2/fasmgw.ini b/toolchain/fasm2/fasmgw.ini new file mode 100644 index 0000000..87b6bbf --- /dev/null +++ b/toolchain/fasm2/fasmgw.ini @@ -0,0 +1,40 @@ +[Environment] +Include=C:\projects\asm_dip\toolchain\fasm2\include +[Compiler] +SourceHeader=include 'fasm2.inc' +MaxPasses=100 +MaxRecursion=10000 +Priority=0 +[Options] +SecureSelection=0 +AutoBrackets=0 +AutoIndent=1 +SmartTabs=1 +OptimalFill=0 +ReviveDeadKeys=0 +ConsoleCaret=1 +TimeScroll=0 +[Colors] +Text=0,0,0 +Background=255,255,255 +SelectionText=255,255,255 +SelectionBackground=0,120,215 +Symbols=48,48,240 +Numbers=0,144,0 +Strings=176,0,0 +Comments=128,128,128 +[Font] +Face=Courier New +Height=16 +Width=0 +Weight=0 +Italic=0 +CharSet=1 +[Window] +Top=64 +Left=64 +Right=564 +Bottom=564 +Maximized=0 +[Help] +Path= diff --git a/toolchain/fasm2/include/@@.inc b/toolchain/fasm2/include/@@.inc new file mode 100644 index 0000000..3ae9cbe --- /dev/null +++ b/toolchain/fasm2/include/@@.inc @@ -0,0 +1,40 @@ + +; Extended implementation of anonymous labels. + +; Classic use like: +; @@: ; A +; je @f ; -> B +; loop @b ; -> A +; @@: ; B + +; Additional sets of labels are available for more flexibility: +; @1: ; A +; je @1f ; -> C +; jg @2f ; -> B +; loop @1b ; -> A +; @2: ; B +; loop @2b ; -> B +; @1: ; C + +macro @INIT name,prefix + + macro name tail& + match label, prefix#f? + label tail + prefix#b? equ prefix#f? + prefix#r? equ prefix#f? + end match + local anonymous + prefix#f? equ anonymous + end macro + + define prefix#f? + name + +end macro + +@INIT @@,@ + +repeat 10, i:0 + @INIT @#i,@#i +end repeat \ No newline at end of file diff --git a/toolchain/fasm2/include/align.inc b/toolchain/fasm2/include/align.inc new file mode 100644 index 0000000..8bd14ad --- /dev/null +++ b/toolchain/fasm2/include/align.inc @@ -0,0 +1,97 @@ + +; Universal implementation of ALIGN. + +; Basic use: +; align 4 + +; Ensure specific offset relative to an aligned address: +; align 4 | 1 + +; Provide information for the alignment of relocatable symbols: +; align.assume rbp, 16 + +; element RELOCATABLE_BASE +; org RELOCATABLE_BASE +; align.assume RELOCATABLE_BASE, 10000h + +; Pad with value: +; align 16, 90h + +; Use a custom command to pad: +; align 16, db # dup ($ and 0FFh) + +define align? align + +align?.count = 0 + +calminstruction align?.assume? address*, alignment* + local index, symbol + compute address, address + compute alignment, alignment + check address relativeto 0 + jyes absolute + compute index, 0 + find: + check index = align.count + jyes update + arrange symbol, align.=address#index + check address relativeto symbol + jyes update + compute index, index + 1 + jump find + update: + arrange symbol, align.=address#index + publish symbol, address + arrange symbol, align.=alignment#index + publish symbol, alignment + compute align.count, align.count + 1 + exit + absolute: + check address mod alignment = 0 + jyes ok + err 'false assumption about absolute address' + ok: +end calminstruction + +calminstruction align? alignment*, filler:rb # + local index, address, offset, symbol + compute offset, 0 + match alignment | offset, alignment + compute alignment, alignment + check alignment >= 0 + jyes alignment_ok + err 'invalid alignment value' + exit + alignment_ok: + compute address, $ + check address relativeto 0 + jyes align + compute index, 0 + find: + check index = align.count + jyes fail + arrange symbol, align.=address#index + check address relativeto symbol + jyes found + compute index, index + 1 + jump find + found: + compute address, address - symbol + arrange symbol, align.=alignment#index + check symbol > 0 & symbol mod alignment = 0 + jyes align + fail: + err 'variable portion of the address is not aligned enough' + exit + align: + compute alignment, (alignment-1) - (address-offset+alignment-1) mod alignment + local prefix, suffix + match prefix? # suffix?, filler + jyes custom + arrange alignment, =db alignment =dup (filler) + assemble alignment + exit + custom: + arrange alignment, prefix alignment suffix + assemble alignment +end calminstruction diff --git a/toolchain/fasm2/include/api/advapi32.inc b/toolchain/fasm2/include/api/advapi32.inc new file mode 100644 index 0000000..0a97a2c --- /dev/null +++ b/toolchain/fasm2/include/api/advapi32.inc @@ -0,0 +1,535 @@ + +; ADVAPI32 API calls + +import advapi32,\ + AbortSystemShutdownA,'AbortSystemShutdownA',\ + AbortSystemShutdownW,'AbortSystemShutdownW',\ + AccessCheck,'AccessCheck',\ + AccessCheckAndAuditAlarmA,'AccessCheckAndAuditAlarmA',\ + AccessCheckAndAuditAlarmW,'AccessCheckAndAuditAlarmW',\ + AccessCheckByType,'AccessCheckByType',\ + AccessCheckByTypeAndAuditAlarmA,'AccessCheckByTypeAndAuditAlarmA',\ + AccessCheckByTypeAndAuditAlarmW,'AccessCheckByTypeAndAuditAlarmW',\ + AccessCheckByTypeResultList,'AccessCheckByTypeResultList',\ + AccessCheckByTypeResultListAndAuditAlarmA,'AccessCheckByTypeResultListAndAuditAlarmA',\ + AccessCheckByTypeResultListAndAuditAlarmW,'AccessCheckByTypeResultListAndAuditAlarmW',\ + AddAccessAllowedAce,'AddAccessAllowedAce',\ + AddAccessAllowedAceEx,'AddAccessAllowedAceEx',\ + AddAccessAllowedObjectAce,'AddAccessAllowedObjectAce',\ + AddAccessDeniedAce,'AddAccessDeniedAce',\ + AddAccessDeniedAceEx,'AddAccessDeniedAceEx',\ + AddAccessDeniedObjectAce,'AddAccessDeniedObjectAce',\ + AddAce,'AddAce',\ + AddAuditAccessAce,'AddAuditAccessAce',\ + AddAuditAccessAceEx,'AddAuditAccessAceEx',\ + AddAuditAccessObjectAce,'AddAuditAccessObjectAce',\ + AdjustTokenGroups,'AdjustTokenGroups',\ + AdjustTokenPrivileges,'AdjustTokenPrivileges',\ + AllocateAndInitializeSid,'AllocateAndInitializeSid',\ + AllocateLocallyUniqueId,'AllocateLocallyUniqueId',\ + AreAllAccessesGranted,'AreAllAccessesGranted',\ + AreAnyAccessesGranted,'AreAnyAccessesGranted',\ + BackupEventLogA,'BackupEventLogA',\ + BackupEventLogW,'BackupEventLogW',\ + BuildExplicitAccessWithNameA,'BuildExplicitAccessWithNameA',\ + BuildExplicitAccessWithNameW,'BuildExplicitAccessWithNameW',\ + BuildImpersonateExplicitAccessWithNameA,'BuildImpersonateExplicitAccessWithNameA',\ + BuildImpersonateExplicitAccessWithNameW,'BuildImpersonateExplicitAccessWithNameW',\ + BuildImpersonateTrusteeA,'BuildImpersonateTrusteeA',\ + BuildImpersonateTrusteeW,'BuildImpersonateTrusteeW',\ + BuildSecurityDescriptorA,'BuildSecurityDescriptorA',\ + BuildSecurityDescriptorW,'BuildSecurityDescriptorW',\ + BuildTrusteeWithNameA,'BuildTrusteeWithNameA',\ + BuildTrusteeWithNameW,'BuildTrusteeWithNameW',\ + BuildTrusteeWithSidA,'BuildTrusteeWithSidA',\ + BuildTrusteeWithSidW,'BuildTrusteeWithSidW',\ + CancelOverlappedAccess,'CancelOverlappedAccess',\ + ChangeServiceConfig2A,'ChangeServiceConfig2A',\ + ChangeServiceConfig2W,'ChangeServiceConfig2W',\ + ChangeServiceConfigA,'ChangeServiceConfigA',\ + ChangeServiceConfigW,'ChangeServiceConfigW',\ + ClearEventLogA,'ClearEventLogA',\ + ClearEventLogW,'ClearEventLogW',\ + CloseEventLog,'CloseEventLog',\ + CloseRaw,'CloseRaw',\ + CloseServiceHandle,'CloseServiceHandle',\ + ControlService,'ControlService',\ + ConvertAccessToSecurityDescriptorA,'ConvertAccessToSecurityDescriptorA',\ + ConvertAccessToSecurityDescriptorW,'ConvertAccessToSecurityDescriptorW',\ + ConvertSecurityDescriptorToAccessA,'ConvertSecurityDescriptorToAccessA',\ + ConvertSecurityDescriptorToAccessW,'ConvertSecurityDescriptorToAccessW',\ + ConvertSecurityDescriptorToAccessNamedA,'ConvertSecurityDescriptorToAccessNamedA',\ + ConvertSecurityDescriptorToAccessNamedW,'ConvertSecurityDescriptorToAccessNamedW',\ + ConvertToAutoInheritPrivateObjectSecurity,'ConvertToAutoInheritPrivateObjectSecurity',\ + CopySid,'CopySid',\ + CreatePrivateObjectSecurity,'CreatePrivateObjectSecurity',\ + CreatePrivateObjectSecurityEx,'CreatePrivateObjectSecurityEx',\ + CreateProcessAsUserA,'CreateProcessAsUserA',\ + CreateProcessAsUserW,'CreateProcessAsUserW',\ + CreateRestrictedToken,'CreateRestrictedToken',\ + CreateServiceA,'CreateServiceA',\ + CreateServiceW,'CreateServiceW',\ + CryptAcquireContextA,'CryptAcquireContextA',\ + CryptAcquireContextW,'CryptAcquireContextW',\ + CryptContextAddRef,'CryptContextAddRef',\ + CryptCreateHash,'CryptCreateHash',\ + CryptDecrypt,'CryptDecrypt',\ + CryptDeriveKey,'CryptDeriveKey',\ + CryptDestroyHash,'CryptDestroyHash',\ + CryptDestroyKey,'CryptDestroyKey',\ + CryptDuplicateHash,'CryptDuplicateHash',\ + CryptDuplicateKey,'CryptDuplicateKey',\ + CryptEncrypt,'CryptEncrypt',\ + CryptEnumProviderTypesA,'CryptEnumProviderTypesA',\ + CryptEnumProviderTypesW,'CryptEnumProviderTypesW',\ + CryptEnumProvidersA,'CryptEnumProvidersA',\ + CryptEnumProvidersW,'CryptEnumProvidersW',\ + CryptExportKey,'CryptExportKey',\ + CryptGenKey,'CryptGenKey',\ + CryptGenRandom,'CryptGenRandom',\ + CryptGetDefaultProviderA,'CryptGetDefaultProviderA',\ + CryptGetDefaultProviderW,'CryptGetDefaultProviderW',\ + CryptGetHashParam,'CryptGetHashParam',\ + CryptGetKeyParam,'CryptGetKeyParam',\ + CryptGetProvParam,'CryptGetProvParam',\ + CryptGetUserKey,'CryptGetUserKey',\ + CryptHashData,'CryptHashData',\ + CryptHashSessionKey,'CryptHashSessionKey',\ + CryptImportKey,'CryptImportKey',\ + CryptReleaseContext,'CryptReleaseContext',\ + CryptSetHashParam,'CryptSetHashParam',\ + CryptSetKeyParam,'CryptSetKeyParam',\ + CryptSetProvParam,'CryptSetProvParam',\ + CryptSetProviderA,'CryptSetProviderA',\ + CryptSetProviderW,'CryptSetProviderW',\ + CryptSetProviderExA,'CryptSetProviderExA',\ + CryptSetProviderExW,'CryptSetProviderExW',\ + CryptSignHashA,'CryptSignHashA',\ + CryptSignHashW,'CryptSignHashW',\ + CryptVerifySignatureA,'CryptVerifySignatureA',\ + CryptVerifySignatureW,'CryptVerifySignatureW',\ + DecryptFileA,'DecryptFileA',\ + DecryptFileW,'DecryptFileW',\ + DeleteAce,'DeleteAce',\ + DeleteService,'DeleteService',\ + DeregisterEventSource,'DeregisterEventSource',\ + DestroyPrivateObjectSecurity,'DestroyPrivateObjectSecurity',\ + DuplicateToken,'DuplicateToken',\ + DuplicateTokenEx,'DuplicateTokenEx',\ + ElfBackupEventLogFileA,'ElfBackupEventLogFileA',\ + ElfBackupEventLogFileW,'ElfBackupEventLogFileW',\ + ElfChangeNotify,'ElfChangeNotify',\ + ElfClearEventLogFileA,'ElfClearEventLogFileA',\ + ElfClearEventLogFileW,'ElfClearEventLogFileW',\ + ElfCloseEventLog,'ElfCloseEventLog',\ + ElfDeregisterEventSource,'ElfDeregisterEventSource',\ + ElfNumberOfRecords,'ElfNumberOfRecords',\ + ElfOldestRecord,'ElfOldestRecord',\ + ElfOpenBackupEventLogA,'ElfOpenBackupEventLogA',\ + ElfOpenBackupEventLogW,'ElfOpenBackupEventLogW',\ + ElfOpenEventLogA,'ElfOpenEventLogA',\ + ElfOpenEventLogW,'ElfOpenEventLogW',\ + ElfReadEventLogA,'ElfReadEventLogA',\ + ElfReadEventLogW,'ElfReadEventLogW',\ + ElfRegisterEventSourceA,'ElfRegisterEventSourceA',\ + ElfRegisterEventSourceW,'ElfRegisterEventSourceW',\ + ElfReportEventA,'ElfReportEventA',\ + ElfReportEventW,'ElfReportEventW',\ + EncryptFileA,'EncryptFileA',\ + EncryptFileW,'EncryptFileW',\ + EnumDependentServicesA,'EnumDependentServicesA',\ + EnumDependentServicesW,'EnumDependentServicesW',\ + EnumServicesStatusA,'EnumServicesStatusA',\ + EnumServicesStatusW,'EnumServicesStatusW',\ + EqualPrefixSid,'EqualPrefixSid',\ + EqualSid,'EqualSid',\ + FindFirstFreeAce,'FindFirstFreeAce',\ + FreeSid,'FreeSid',\ + GetAccessPermissionsForObjectA,'GetAccessPermissionsForObjectA',\ + GetAccessPermissionsForObjectW,'GetAccessPermissionsForObjectW',\ + GetAce,'GetAce',\ + GetAclInformation,'GetAclInformation',\ + GetAuditedPermissionsFromAclA,'GetAuditedPermissionsFromAclA',\ + GetAuditedPermissionsFromAclW,'GetAuditedPermissionsFromAclW',\ + GetCurrentHwProfileA,'GetCurrentHwProfileA',\ + GetCurrentHwProfileW,'GetCurrentHwProfileW',\ + GetEffectiveRightsFromAclA,'GetEffectiveRightsFromAclA',\ + GetEffectiveRightsFromAclW,'GetEffectiveRightsFromAclW',\ + GetExplicitEntriesFromAclA,'GetExplicitEntriesFromAclA',\ + GetExplicitEntriesFromAclW,'GetExplicitEntriesFromAclW',\ + GetFileSecurityA,'GetFileSecurityA',\ + GetFileSecurityW,'GetFileSecurityW',\ + GetKernelObjectSecurity,'GetKernelObjectSecurity',\ + GetLengthSid,'GetLengthSid',\ + GetMultipleTrusteeA,'GetMultipleTrusteeA',\ + GetMultipleTrusteeW,'GetMultipleTrusteeW',\ + GetMultipleTrusteeOperationA,'GetMultipleTrusteeOperationA',\ + GetMultipleTrusteeOperationW,'GetMultipleTrusteeOperationW',\ + GetNamedSecurityInfoA,'GetNamedSecurityInfoA',\ + GetNamedSecurityInfoW,'GetNamedSecurityInfoW',\ + GetNamedSecurityInfoExA,'GetNamedSecurityInfoExA',\ + GetNamedSecurityInfoExW,'GetNamedSecurityInfoExW',\ + GetNumberOfEventLogRecords,'GetNumberOfEventLogRecords',\ + GetOldestEventLogRecord,'GetOldestEventLogRecord',\ + GetOverlappedAccessResults,'GetOverlappedAccessResults',\ + GetPrivateObjectSecurity,'GetPrivateObjectSecurity',\ + GetSecurityDescriptorControl,'GetSecurityDescriptorControl',\ + GetSecurityDescriptorDacl,'GetSecurityDescriptorDacl',\ + GetSecurityDescriptorGroup,'GetSecurityDescriptorGroup',\ + GetSecurityDescriptorLength,'GetSecurityDescriptorLength',\ + GetSecurityDescriptorOwner,'GetSecurityDescriptorOwner',\ + GetSecurityDescriptorSacl,'GetSecurityDescriptorSacl',\ + GetSecurityInfo,'GetSecurityInfo',\ + GetSecurityInfoExA,'GetSecurityInfoExA',\ + GetSecurityInfoExW,'GetSecurityInfoExW',\ + GetServiceDisplayNameA,'GetServiceDisplayNameA',\ + GetServiceDisplayNameW,'GetServiceDisplayNameW',\ + GetServiceKeyNameA,'GetServiceKeyNameA',\ + GetServiceKeyNameW,'GetServiceKeyNameW',\ + GetSidLengthRequiredA,'GetSidLengthRequiredA',\ + GetSidLengthRequiredW,'GetSidLengthRequiredW',\ + GetSidSubAuthority,'GetSidSubAuthority',\ + GetSidSubAuthorityCount,'GetSidSubAuthorityCount',\ + GetTokenInformation,'GetTokenInformation',\ + GetTrusteeNameA,'GetTrusteeNameA',\ + GetTrusteeNameW,'GetTrusteeNameW',\ + GetTrusteeTypeA,'GetTrusteeTypeA',\ + GetTrusteeTypeW,'GetTrusteeTypeW',\ + GetUserNameA,'GetUserNameA',\ + GetUserNameW,'GetUserNameW',\ + I_ScSetServiceBitsA,'I_ScSetServiceBitsA',\ + I_ScSetServiceBitsW,'I_ScSetServiceBitsW',\ + ImpersonateLoggedOnUser,'ImpersonateLoggedOnUser',\ + ImpersonateNamedPipeClient,'ImpersonateNamedPipeClient',\ + ImpersonateSelf,'ImpersonateSelf',\ + InitializeAcl,'InitializeAcl',\ + InitializeSecurityDescriptor,'InitializeSecurityDescriptor',\ + InitializeSid,'InitializeSid',\ + InitiateSystemShutdownA,'InitiateSystemShutdownA',\ + InitiateSystemShutdownW,'InitiateSystemShutdownW',\ + IsTextUnicode,'IsTextUnicode',\ + IsTokenRestricted,'IsTokenRestricted',\ + IsValidAcl,'IsValidAcl',\ + IsValidSecurityDescriptor,'IsValidSecurityDescriptor',\ + IsValidSid,'IsValidSid',\ + LockServiceDatabase,'LockServiceDatabase',\ + LogonUserA,'LogonUserA',\ + LogonUserW,'LogonUserW',\ + LookupAccountNameA,'LookupAccountNameA',\ + LookupAccountNameW,'LookupAccountNameW',\ + LookupAccountSidA,'LookupAccountSidA',\ + LookupAccountSidW,'LookupAccountSidW',\ + LookupPrivilegeDisplayNameA,'LookupPrivilegeDisplayNameA',\ + LookupPrivilegeDisplayNameW,'LookupPrivilegeDisplayNameW',\ + LookupPrivilegeNameA,'LookupPrivilegeNameA',\ + LookupPrivilegeNameW,'LookupPrivilegeNameW',\ + LookupPrivilegeValueA,'LookupPrivilegeValueA',\ + LookupPrivilegeValueW,'LookupPrivilegeValueW',\ + LookupSecurityDescriptorPartsA,'LookupSecurityDescriptorPartsA',\ + LookupSecurityDescriptorPartsW,'LookupSecurityDescriptorPartsW',\ + LsaAddAccountRights,'LsaAddAccountRights',\ + LsaAddPrivilegesToAccount,'LsaAddPrivilegesToAccount',\ + LsaClearAuditLog,'LsaClearAuditLog',\ + LsaClose,'LsaClose',\ + LsaCreateAccount,'LsaCreateAccount',\ + LsaCreateSecret,'LsaCreateSecret',\ + LsaCreateTrustedDomain,'LsaCreateTrustedDomain',\ + LsaCreateTrustedDomainEx,'LsaCreateTrustedDomainEx',\ + LsaDelete,'LsaDelete',\ + LsaDeleteTrustedDomain,'LsaDeleteTrustedDomain',\ + LsaEnumerateAccountRights,'LsaEnumerateAccountRights',\ + LsaEnumerateAccounts,'LsaEnumerateAccounts',\ + LsaEnumerateAccountsWithUserRight,'LsaEnumerateAccountsWithUserRight',\ + LsaEnumeratePrivileges,'LsaEnumeratePrivileges',\ + LsaEnumeratePrivilegesOfAccount,'LsaEnumeratePrivilegesOfAccount',\ + LsaEnumerateTrustedDomains,'LsaEnumerateTrustedDomains',\ + LsaEnumerateTrustedDomainsEx,'LsaEnumerateTrustedDomainsEx',\ + LsaFreeMemory,'LsaFreeMemory',\ + LsaGetQuotasForAccount,'LsaGetQuotasForAccount',\ + LsaGetSystemAccessAccount,'LsaGetSystemAccessAccount',\ + LsaGetUserName,'LsaGetUserName',\ + LsaICLookupNames,'LsaICLookupNames',\ + LsaICLookupSids,'LsaICLookupSids',\ + LsaIGetTrustedDomainAuthInfoBlobs,'LsaIGetTrustedDomainAuthInfoBlobs',\ + LsaISetTrustedDomainAuthInfoBlobs,'LsaISetTrustedDomainAuthInfoBlobs',\ + LsaLookupNames,'LsaLookupNames',\ + LsaLookupPrivilegeDisplayName,'LsaLookupPrivilegeDisplayName',\ + LsaLookupPrivilegeName,'LsaLookupPrivilegeName',\ + LsaLookupPrivilegeValue,'LsaLookupPrivilegeValue',\ + LsaLookupSids,'LsaLookupSids',\ + LsaNtStatusToWinError,'LsaNtStatusToWinError',\ + LsaOpenAccount,'LsaOpenAccount',\ + LsaOpenPolicy,'LsaOpenPolicy',\ + LsaOpenSecret,'LsaOpenSecret',\ + LsaOpenTrustedDomain,'LsaOpenTrustedDomain',\ + LsaQueryDomainInformationPolicy,'LsaQueryDomainInformationPolicy',\ + LsaQueryInfoTrustedDomain,'LsaQueryInfoTrustedDomain',\ + LsaQueryInformationPolicy,'LsaQueryInformationPolicy',\ + LsaQueryLocalInformationPolicy,'LsaQueryLocalInformationPolicy',\ + LsaQuerySecret,'LsaQuerySecret',\ + LsaQuerySecurityObject,'LsaQuerySecurityObject',\ + LsaQueryTrustedDomainInfo,'LsaQueryTrustedDomainInfo',\ + LsaQueryTrustedDomainInfoByName,'LsaQueryTrustedDomainInfoByName',\ + LsaRemoveAccountRights,'LsaRemoveAccountRights',\ + LsaRemovePrivilegesFromAccount,'LsaRemovePrivilegesFromAccount',\ + LsaRetrievePrivateData,'LsaRetrievePrivateData',\ + LsaSetDomainInformationPolicy,'LsaSetDomainInformationPolicy',\ + LsaSetInformationPolicy,'LsaSetInformationPolicy',\ + LsaSetInformationTrustedDomain,'LsaSetInformationTrustedDomain',\ + LsaSetLocalInformationPolicy,'LsaSetLocalInformationPolicy',\ + LsaSetQuotasForAccount,'LsaSetQuotasForAccount',\ + LsaSetSecret,'LsaSetSecret',\ + LsaSetSecurityObject,'LsaSetSecurityObject',\ + LsaSetSystemAccessAccount,'LsaSetSystemAccessAccount',\ + LsaSetTrustedDomainInfoByName,'LsaSetTrustedDomainInfoByName',\ + LsaSetTrustedDomainInformation,'LsaSetTrustedDomainInformation',\ + LsaStorePrivateData,'LsaStorePrivateData',\ + MakeAbsoluteSD,'MakeAbsoluteSD',\ + MakeSelfRelativeSD,'MakeSelfRelativeSD',\ + MapGenericMask,'MapGenericMask',\ + NotifyBootConfigStatus,'NotifyBootConfigStatus',\ + NotifyChangeEventLog,'NotifyChangeEventLog',\ + ObjectCloseAuditAlarmA,'ObjectCloseAuditAlarmA',\ + ObjectCloseAuditAlarmW,'ObjectCloseAuditAlarmW',\ + ObjectDeleteAuditAlarmA,'ObjectDeleteAuditAlarmA',\ + ObjectDeleteAuditAlarmW,'ObjectDeleteAuditAlarmW',\ + ObjectOpenAuditAlarmA,'ObjectOpenAuditAlarmA',\ + ObjectOpenAuditAlarmW,'ObjectOpenAuditAlarmW',\ + ObjectPrivilegeAuditAlarmA,'ObjectPrivilegeAuditAlarmA',\ + ObjectPrivilegeAuditAlarmW,'ObjectPrivilegeAuditAlarmW',\ + OpenBackupEventLogA,'OpenBackupEventLogA',\ + OpenBackupEventLogW,'OpenBackupEventLogW',\ + OpenEventLogA,'OpenEventLogA',\ + OpenEventLogW,'OpenEventLogW',\ + OpenProcessToken,'OpenProcessToken',\ + OpenRawA,'OpenRawA',\ + OpenRawW,'OpenRawW',\ + OpenSCManagerA,'OpenSCManagerA',\ + OpenSCManagerW,'OpenSCManagerW',\ + OpenServiceA,'OpenServiceA',\ + OpenServiceW,'OpenServiceW',\ + OpenThreadToken,'OpenThreadToken',\ + PrivilegeCheck,'PrivilegeCheck',\ + PrivilegedServiceAuditAlarmA,'PrivilegedServiceAuditAlarmA',\ + PrivilegedServiceAuditAlarmW,'PrivilegedServiceAuditAlarmW',\ + QueryRecoveryAgentsA,'QueryRecoveryAgentsA',\ + QueryRecoveryAgentsW,'QueryRecoveryAgentsW',\ + QueryServiceConfig2A,'QueryServiceConfig2A',\ + QueryServiceConfig2W,'QueryServiceConfig2W',\ + QueryServiceConfigA,'QueryServiceConfigA',\ + QueryServiceConfigW,'QueryServiceConfigW',\ + QueryServiceLockStatusA,'QueryServiceLockStatusA',\ + QueryServiceLockStatusW,'QueryServiceLockStatusW',\ + QueryServiceObjectSecurity,'QueryServiceObjectSecurity',\ + QueryServiceStatus,'QueryServiceStatus',\ + QueryWindows31FilesMigration,'QueryWindows31FilesMigration',\ + ReadEventLogA,'ReadEventLogA',\ + ReadEventLogW,'ReadEventLogW',\ + ReadRaw,'ReadRaw',\ + RegCloseKey,'RegCloseKey',\ + RegConnectRegistryA,'RegConnectRegistryA',\ + RegConnectRegistryW,'RegConnectRegistryW',\ + RegCreateKeyA,'RegCreateKeyA',\ + RegCreateKeyW,'RegCreateKeyW',\ + RegCreateKeyExA,'RegCreateKeyExA',\ + RegCreateKeyExW,'RegCreateKeyExW',\ + RegDeleteKeyA,'RegDeleteKeyA',\ + RegDeleteKeyW,'RegDeleteKeyW',\ + RegDeleteValueA,'RegDeleteValueA',\ + RegDeleteValueW,'RegDeleteValueW',\ + RegEnumKeyA,'RegEnumKeyA',\ + RegEnumKeyW,'RegEnumKeyW',\ + RegEnumKeyExA,'RegEnumKeyExA',\ + RegEnumKeyExW,'RegEnumKeyExW',\ + RegEnumValueA,'RegEnumValueA',\ + RegEnumValueW,'RegEnumValueW',\ + RegFlushKey,'RegFlushKey',\ + RegGetKeySecurity,'RegGetKeySecurity',\ + RegLoadKeyA,'RegLoadKeyA',\ + RegLoadKeyW,'RegLoadKeyW',\ + RegNotifyChangeKeyValue,'RegNotifyChangeKeyValue',\ + RegOpenKeyA,'RegOpenKeyA',\ + RegOpenKeyW,'RegOpenKeyW',\ + RegOpenKeyExA,'RegOpenKeyExA',\ + RegOpenKeyExW,'RegOpenKeyExW',\ + RegOverridePredefKey,'RegOverridePredefKey',\ + RegQueryInfoKeyA,'RegQueryInfoKeyA',\ + RegQueryInfoKeyW,'RegQueryInfoKeyW',\ + RegQueryMultipleValuesA,'RegQueryMultipleValuesA',\ + RegQueryMultipleValuesW,'RegQueryMultipleValuesW',\ + RegQueryValueA,'RegQueryValueA',\ + RegQueryValueW,'RegQueryValueW',\ + RegQueryValueExA,'RegQueryValueExA',\ + RegQueryValueExW,'RegQueryValueExW',\ + RegReplaceKeyA,'RegReplaceKeyA',\ + RegReplaceKeyW,'RegReplaceKeyW',\ + RegRestoreKeyA,'RegRestoreKeyA',\ + RegRestoreKeyW,'RegRestoreKeyW',\ + RegSaveKeyA,'RegSaveKeyA',\ + RegSaveKeyW,'RegSaveKeyW',\ + RegSetKeySecurity,'RegSetKeySecurity',\ + RegSetValueA,'RegSetValueA',\ + RegSetValueW,'RegSetValueW',\ + RegSetValueExA,'RegSetValueExA',\ + RegSetValueExW,'RegSetValueExW',\ + RegUnLoadKeyA,'RegUnLoadKeyA',\ + RegUnLoadKeyW,'RegUnLoadKeyW',\ + RegisterEventSourceA,'RegisterEventSourceA',\ + RegisterEventSourceW,'RegisterEventSourceW',\ + RegisterServiceCtrlHandlerA,'RegisterServiceCtrlHandlerA',\ + RegisterServiceCtrlHandlerW,'RegisterServiceCtrlHandlerW',\ + ReportEventA,'ReportEventA',\ + ReportEventW,'ReportEventW',\ + RevertToSelf,'RevertToSelf',\ + SetAclInformation,'SetAclInformation',\ + SetEntriesInAccessListA,'SetEntriesInAccessListA',\ + SetEntriesInAccessListW,'SetEntriesInAccessListW',\ + SetEntriesInAclA,'SetEntriesInAclA',\ + SetEntriesInAclW,'SetEntriesInAclW',\ + SetEntriesInAuditListA,'SetEntriesInAuditListA',\ + SetEntriesInAuditListW,'SetEntriesInAuditListW',\ + SetFileSecurityA,'SetFileSecurityA',\ + SetFileSecurityW,'SetFileSecurityW',\ + SetKernelObjectSecurity,'SetKernelObjectSecurity',\ + SetNamedSecurityInfoA,'SetNamedSecurityInfoA',\ + SetNamedSecurityInfoW,'SetNamedSecurityInfoW',\ + SetNamedSecurityInfoExA,'SetNamedSecurityInfoExA',\ + SetNamedSecurityInfoExW,'SetNamedSecurityInfoExW',\ + SetPrivateObjectSecurity,'SetPrivateObjectSecurity',\ + SetPrivateObjectSecurityEx,'SetPrivateObjectSecurityEx',\ + SetSecurityDescriptorControl,'SetSecurityDescriptorControl',\ + SetSecurityDescriptorDacl,'SetSecurityDescriptorDacl',\ + SetSecurityDescriptorGroup,'SetSecurityDescriptorGroup',\ + SetSecurityDescriptorOwner,'SetSecurityDescriptorOwner',\ + SetSecurityDescriptorSacl,'SetSecurityDescriptorSacl',\ + SetSecurityInfo,'SetSecurityInfo',\ + SetSecurityInfoExA,'SetSecurityInfoExA',\ + SetSecurityInfoExW,'SetSecurityInfoExW',\ + SetServiceBits,'SetServiceBits',\ + SetServiceObjectSecurity,'SetServiceObjectSecurity',\ + SetServiceStatus,'SetServiceStatus',\ + SetThreadToken,'SetThreadToken',\ + SetTokenInformation,'SetTokenInformation',\ + StartServiceA,'StartServiceA',\ + StartServiceW,'StartServiceW',\ + StartServiceCtrlDispatcherA,'StartServiceCtrlDispatcherA',\ + StartServiceCtrlDispatcherW,'StartServiceCtrlDispatcherW',\ + SynchronizeWindows31FilesAndWindowsNTRegistry,'SynchronizeWindows31FilesAndWindowsNTRegistry',\ + TrusteeAccessToObjectA,'TrusteeAccessToObjectA',\ + TrusteeAccessToObjectW,'TrusteeAccessToObjectW',\ + UnlockServiceDatabase,'UnlockServiceDatabase',\ + WriteRaw,'WriteRaw' + +api AbortSystemShutdown,\ + AccessCheckAndAuditAlarm,\ + AccessCheckByTypeAndAuditAlarm,\ + AccessCheckByTypeResultListAndAuditAlarm,\ + BackupEventLog,\ + BuildExplicitAccessWithName,\ + BuildImpersonateExplicitAccessWithName,\ + BuildImpersonateTrustee,\ + BuildSecurityDescriptor,\ + BuildTrusteeWithName,\ + BuildTrusteeWithSid,\ + ChangeServiceConfig2,\ + ChangeServiceConfig,\ + ClearEventLog,\ + ConvertAccessToSecurityDescriptor,\ + ConvertSecurityDescriptorToAccess,\ + ConvertSecurityDescriptorToAccessNamed,\ + CreateProcessAsUser,\ + CreateService,\ + CryptAcquireContext,\ + CryptEnumProviderTypes,\ + CryptEnumProviders,\ + CryptGetDefaultProvider,\ + CryptSetProvider,\ + CryptSetProviderEx,\ + CryptSignHash,\ + CryptVerifySignature,\ + DecryptFile,\ + ElfBackupEventLogFile,\ + ElfClearEventLogFile,\ + ElfOpenBackupEventLog,\ + ElfOpenEventLog,\ + ElfReadEventLog,\ + ElfRegisterEventSource,\ + ElfReportEvent,\ + EncryptFile,\ + EnumDependentServices,\ + EnumServicesStatus,\ + GetAccessPermissionsForObject,\ + GetAuditedPermissionsFromAcl,\ + GetCurrentHwProfile,\ + GetEffectiveRightsFromAcl,\ + GetExplicitEntriesFromAcl,\ + GetFileSecurity,\ + GetMultipleTrustee,\ + GetMultipleTrusteeOperation,\ + GetNamedSecurityInfo,\ + GetNamedSecurityInfoEx,\ + GetSecurityInfoEx,\ + GetServiceDisplayName,\ + GetServiceKeyName,\ + GetSidLengthRequired,\ + GetTrusteeName,\ + GetTrusteeType,\ + GetUserName,\ + I_ScSetServiceBits,\ + InitiateSystemShutdown,\ + LogonUser,\ + LookupAccountName,\ + LookupAccountSid,\ + LookupPrivilegeDisplayName,\ + LookupPrivilegeName,\ + LookupPrivilegeValue,\ + LookupSecurityDescriptorParts,\ + ObjectCloseAuditAlarm,\ + ObjectDeleteAuditAlarm,\ + ObjectOpenAuditAlarm,\ + ObjectPrivilegeAuditAlarm,\ + OpenBackupEventLog,\ + OpenEventLog,\ + OpenRaw,\ + OpenSCManager,\ + OpenService,\ + PrivilegedServiceAuditAlarm,\ + QueryRecoveryAgents,\ + QueryServiceConfig2,\ + QueryServiceConfig,\ + QueryServiceLockStatus,\ + ReadEventLog,\ + RegConnectRegistry,\ + RegCreateKey,\ + RegCreateKeyEx,\ + RegDeleteKey,\ + RegDeleteValue,\ + RegEnumKey,\ + RegEnumKeyEx,\ + RegEnumValue,\ + RegLoadKey,\ + RegOpenKey,\ + RegOpenKeyEx,\ + RegQueryInfoKey,\ + RegQueryMultipleValues,\ + RegQueryValue,\ + RegQueryValueEx,\ + RegReplaceKey,\ + RegRestoreKey,\ + RegSaveKey,\ + RegSetValue,\ + RegSetValueEx,\ + RegUnLoadKey,\ + RegisterEventSource,\ + RegisterServiceCtrlHandler,\ + ReportEvent,\ + SetEntriesInAccessList,\ + SetEntriesInAcl,\ + SetEntriesInAuditList,\ + SetFileSecurity,\ + SetNamedSecurityInfo,\ + SetNamedSecurityInfoEx,\ + SetSecurityInfoEx,\ + StartService,\ + StartServiceCtrlDispatcher,\ + TrusteeAccessToObject diff --git a/toolchain/fasm2/include/api/comctl32.inc b/toolchain/fasm2/include/api/comctl32.inc new file mode 100644 index 0000000..dc28c61 --- /dev/null +++ b/toolchain/fasm2/include/api/comctl32.inc @@ -0,0 +1,81 @@ + +; COMCTL32 API calls + +import comctl32,\ + CreateMappedBitmap,'CreateMappedBitmap',\ + CreatePropertySheetPageA,'CreatePropertySheetPageA',\ + CreatePropertySheetPageW,'CreatePropertySheetPageW',\ + CreateStatusWindowA,'CreateStatusWindowA',\ + CreateStatusWindowW,'CreateStatusWindowW',\ + CreateToolbar,'CreateToolbar',\ + CreateToolbarEx,'CreateToolbarEx',\ + CreateUpDownControl,'CreateUpDownControl',\ + DestroyPropertySheetPage,'DestroyPropertySheetPage',\ + DrawInsert,'DrawInsert',\ + DrawStatusTextA,'DrawStatusTextA',\ + DrawStatusTextW,'DrawStatusTextW',\ + FlatSB_EnableScrollBar,'FlatSB_EnableScrollBar',\ + FlatSB_GetScrollInfo,'FlatSB_GetScrollInfo',\ + FlatSB_GetScrollPos,'FlatSB_GetScrollPos',\ + FlatSB_GetScrollProp,'FlatSB_GetScrollProp',\ + FlatSB_GetScrollRange,'FlatSB_GetScrollRange',\ + FlatSB_SetScrollInfo,'FlatSB_SetScrollInfo',\ + FlatSB_SetScrollPos,'FlatSB_SetScrollPos',\ + FlatSB_SetScrollProp,'FlatSB_SetScrollProp',\ + FlatSB_SetScrollRange,'FlatSB_SetScrollRange',\ + FlatSB_ShowScrollBar,'FlatSB_ShowScrollBar',\ + GetEffectiveClientRect,'GetEffectiveClientRect',\ + ImageList_Add,'ImageList_Add',\ + ImageList_AddIcon,'ImageList_AddIcon',\ + ImageList_AddMasked,'ImageList_AddMasked',\ + ImageList_BeginDrag,'ImageList_BeginDrag',\ + ImageList_Copy,'ImageList_Copy',\ + ImageList_Create,'ImageList_Create',\ + ImageList_Destroy,'ImageList_Destroy',\ + ImageList_DragEnter,'ImageList_DragEnter',\ + ImageList_DragLeave,'ImageList_DragLeave',\ + ImageList_DragMove,'ImageList_DragMove',\ + ImageList_DragShowNolock,'ImageList_DragShowNolock',\ + ImageList_Draw,'ImageList_Draw',\ + ImageList_DrawEx,'ImageList_DrawEx',\ + ImageList_DrawIndirect,'ImageList_DrawIndirect',\ + ImageList_Duplicate,'ImageList_Duplicate',\ + ImageList_EndDrag,'ImageList_EndDrag',\ + ImageList_GetBkColor,'ImageList_GetBkColor',\ + ImageList_GetDragImage,'ImageList_GetDragImage',\ + ImageList_GetIcon,'ImageList_GetIcon',\ + ImageList_GetIconSize,'ImageList_GetIconSize',\ + ImageList_GetImageCount,'ImageList_GetImageCount',\ + ImageList_GetImageInfo,'ImageList_GetImageInfo',\ + ImageList_GetImageRect,'ImageList_GetImageRect',\ + ImageList_LoadImageA,'ImageList_LoadImageA',\ + ImageList_LoadImageW,'ImageList_LoadImageW',\ + ImageList_Merge,'ImageList_Merge',\ + ImageList_Read,'ImageList_Read',\ + ImageList_Remove,'ImageList_Remove',\ + ImageList_Replace,'ImageList_Replace',\ + ImageList_ReplaceIcon,'ImageList_ReplaceIcon',\ + ImageList_SetBkColor,'ImageList_SetBkColor',\ + ImageList_SetDragCursorImage,'ImageList_SetDragCursorImage',\ + ImageList_SetFilter,'ImageList_SetFilter',\ + ImageList_SetIconSize,'ImageList_SetIconSize',\ + ImageList_SetImageCount,'ImageList_SetImageCount',\ + ImageList_SetOverlayImage,'ImageList_SetOverlayImage',\ + ImageList_Write,'ImageList_Write',\ + InitCommonControls,'InitCommonControls',\ + InitCommonControlsEx,'InitCommonControlsEx',\ + InitializeFlatSB,'InitializeFlatSB',\ + LBItemFromPt,'LBItemFromPt',\ + MakeDragList,'MakeDragList',\ + MenuHelp,'MenuHelp',\ + PropertySheetA,'PropertySheetA',\ + PropertySheetW,'PropertySheetW',\ + ShowHideMenuCtl,'ShowHideMenuCtl',\ + UninitializeFlatSB,'UninitializeFlatSB',\ + _TrackMouseEvent,'_TrackMouseEvent' + +api CreatePropertySheetPage,\ + CreateStatusWindow,\ + DrawStatusText,\ + ImageList_LoadImage,\ + PropertySheet diff --git a/toolchain/fasm2/include/api/comdlg32.inc b/toolchain/fasm2/include/api/comdlg32.inc new file mode 100644 index 0000000..9347fbc --- /dev/null +++ b/toolchain/fasm2/include/api/comdlg32.inc @@ -0,0 +1,38 @@ + +; COMDLG32 API calls + +import comdlg32,\ + ChooseColorA,'ChooseColorA',\ + ChooseColorW,'ChooseColorW',\ + ChooseFontA,'ChooseFontA',\ + ChooseFontW,'ChooseFontW',\ + CommDlgExtendedError,'CommDlgExtendedError',\ + FindTextA,'FindTextA',\ + FindTextW,'FindTextW',\ + FormatCharDlgProc,'FormatCharDlgProc',\ + GetFileTitleA,'GetFileTitleA',\ + GetFileTitleW,'GetFileTitleW',\ + GetOpenFileNameA,'GetOpenFileNameA',\ + GetOpenFileNameW,'GetOpenFileNameW',\ + GetSaveFileNameA,'GetSaveFileNameA',\ + GetSaveFileNameW,'GetSaveFileNameW',\ + LoadAlterBitmap,'LoadAlterBitmap',\ + PageSetupDlgA,'PageSetupDlgA',\ + PageSetupDlgW,'PageSetupDlgW',\ + PrintDlgA,'PrintDlgA',\ + PrintDlgW,'PrintDlgW',\ + ReplaceTextA,'ReplaceTextA',\ + ReplaceTextW,'ReplaceTextW',\ + WantArrows,'WantArrows',\ + dwLBSubclass,'dwLBSubclass',\ + dwOKSubclass,'dwOKSubclass' + +api ChooseColor,\ + ChooseFont,\ + FindText,\ + GetFileTitle,\ + GetOpenFileName,\ + GetSaveFileName,\ + PageSetupDlg,\ + PrintDlg,\ + ReplaceText diff --git a/toolchain/fasm2/include/api/gdi32.inc b/toolchain/fasm2/include/api/gdi32.inc new file mode 100644 index 0000000..4cec631 --- /dev/null +++ b/toolchain/fasm2/include/api/gdi32.inc @@ -0,0 +1,419 @@ + +; GDI32 API calls + +import gdi32,\ + AbortDoc,'AbortDoc',\ + AbortPath,'AbortPath',\ + AddFontMemResourceEx,'AddFontMemResourceEx',\ + AddFontResourceA,'AddFontResourceA',\ + AddFontResourceW,'AddFontResourceW',\ + AddFontResourceExA,'AddFontResourceExA',\ + AddFontResourceExW,'AddFontResourceExW',\ + AngleArc,'AngleArc',\ + AnimatePalette,'AnimatePalette',\ + Arc,'Arc',\ + ArcTo,'ArcTo',\ + BeginPath,'BeginPath',\ + BitBlt,'BitBlt',\ + CancelDC,'CancelDC',\ + CheckColorsInGamut,'CheckColorsInGamut',\ + ChoosePixelFormat,'ChoosePixelFormat',\ + Chord,'Chord',\ + CloseEnhMetaFile,'CloseEnhMetaFile',\ + CloseFigure,'CloseFigure',\ + CloseMetaFile,'CloseMetaFile',\ + ColorCorrectPalette,'ColorCorrectPalette',\ + ColorMatchToTarget,'ColorMatchToTarget',\ + CombineRgn,'CombineRgn',\ + CombineTransform,'CombineTransform',\ + CopyEnhMetaFileA,'CopyEnhMetaFileA',\ + CopyEnhMetaFileW,'CopyEnhMetaFileW',\ + CopyMetaFileA,'CopyMetaFileA',\ + CopyMetaFileW,'CopyMetaFileW',\ + CreateBitmap,'CreateBitmap',\ + CreateBitmapIndirect,'CreateBitmapIndirect',\ + CreateBrushIndirect,'CreateBrushIndirect',\ + CreateColorSpaceA,'CreateColorSpaceA',\ + CreateColorSpaceW,'CreateColorSpaceW',\ + CreateCompatibleBitmap,'CreateCompatibleBitmap',\ + CreateCompatibleDC,'CreateCompatibleDC',\ + CreateDCA,'CreateDCA',\ + CreateDCW,'CreateDCW',\ + CreateDIBPatternBrush,'CreateDIBPatternBrush',\ + CreateDIBPatternBrushPt,'CreateDIBPatternBrushPt',\ + CreateDIBSection,'CreateDIBSection',\ + CreateDIBitmap,'CreateDIBitmap',\ + CreateDiscardableBitmap,'CreateDiscardableBitmap',\ + CreateEllipticRgn,'CreateEllipticRgn',\ + CreateEllipticRgnIndirect,'CreateEllipticRgnIndirect',\ + CreateEnhMetaFileA,'CreateEnhMetaFileA',\ + CreateEnhMetaFileW,'CreateEnhMetaFileW',\ + CreateFontA,'CreateFontA',\ + CreateFontW,'CreateFontW',\ + CreateFontIndirectA,'CreateFontIndirectA',\ + CreateFontIndirectW,'CreateFontIndirectW',\ + CreateFontIndirectExA,'CreateFontIndirectExA',\ + CreateFontIndirectExW,'CreateFontIndirectExW',\ + CreateHalftonePalette,'CreateHalftonePalette',\ + CreateHatchBrush,'CreateHatchBrush',\ + CreateICA,'CreateICA',\ + CreateICW,'CreateICW',\ + CreateMetaFileA,'CreateMetaFileA',\ + CreateMetaFileW,'CreateMetaFileW',\ + CreatePalette,'CreatePalette',\ + CreatePatternBrush,'CreatePatternBrush',\ + CreatePen,'CreatePen',\ + CreatePenIndirect,'CreatePenIndirect',\ + CreatePolyPolygonRgn,'CreatePolyPolygonRgn',\ + CreatePolygonRgn,'CreatePolygonRgn',\ + CreateRectRgn,'CreateRectRgn',\ + CreateRectRgnIndirect,'CreateRectRgnIndirect',\ + CreateRoundRectRgn,'CreateRoundRectRgn',\ + CreateScalableFontResourceA,'CreateScalableFontResourceA',\ + CreateScalableFontResourceW,'CreateScalableFontResourceW',\ + CreateSolidBrush,'CreateSolidBrush',\ + DPtoLP,'DPtoLP',\ + DeleteColorSpace,'DeleteColorSpace',\ + DeleteDC,'DeleteDC',\ + DeleteEnhMetaFile,'DeleteEnhMetaFile',\ + DeleteMetaFile,'DeleteMetaFile',\ + DeleteObject,'DeleteObject',\ + DescribePixelFormat,'DescribePixelFormat',\ + DeviceCapabilitiesExA,'DeviceCapabilitiesExA',\ + DeviceCapabilitiesExW,'DeviceCapabilitiesExW',\ + DrawEscape,'DrawEscape',\ + Ellipse,'Ellipse',\ + EnableEUDC,'EnableEUDC',\ + EndDoc,'EndDoc',\ + EndPage,'EndPage',\ + EndPath,'EndPath',\ + EnumEnhMetaFile,'EnumEnhMetaFile',\ + EnumFontFamiliesA,'EnumFontFamiliesA',\ + EnumFontFamiliesW,'EnumFontFamiliesW',\ + EnumFontFamiliesExA,'EnumFontFamiliesExA',\ + EnumFontFamiliesExW,'EnumFontFamiliesExW',\ + EnumFontsA,'EnumFontsA',\ + EnumFontsW,'EnumFontsW',\ + EnumICMProfilesA,'EnumICMProfilesA',\ + EnumICMProfilesW,'EnumICMProfilesW',\ + EnumMetaFile,'EnumMetaFile',\ + EnumObjects,'EnumObjects',\ + EqualRgn,'EqualRgn',\ + Escape,'Escape',\ + ExcludeClipRect,'ExcludeClipRect',\ + ExtCreatePen,'ExtCreatePen',\ + ExtCreateRegion,'ExtCreateRegion',\ + ExtEscape,'ExtEscape',\ + ExtFloodFill,'ExtFloodFill',\ + ExtSelectClipRgn,'ExtSelectClipRgn',\ + ExtTextOutA,'ExtTextOutA',\ + ExtTextOutW,'ExtTextOutW',\ + FillPath,'FillPath',\ + FillRgn,'FillRgn',\ + FixBrushOrgEx,'FixBrushOrgEx',\ + FlattenPath,'FlattenPath',\ + FloodFill,'FloodFill',\ + FrameRgn,'FrameRgn',\ + GdiComment,'GdiComment',\ + GdiDeleteSpoolFileHandle,'GdiDeleteSpoolFileHandle',\ + GdiEndDocEMF,'GdiEndDocEMF',\ + GdiEndPageEMF,'GdiEndPageEMF',\ + GdiFlush,'GdiFlush',\ + GdiGetBatchLimit,'GdiGetBatchLimit',\ + GdiGetDC,'GdiGetDC',\ + GdiGetDevmodeForPage,'GdiGetDevmodeForPage',\ + GdiGetPageCount,'GdiGetPageCount',\ + GdiGetPageHandle,'GdiGetPageHandle',\ + GdiGetSpoolFileHandle,'GdiGetSpoolFileHandle',\ + GdiPlayDCScript,'GdiPlayDCScript',\ + GdiPlayEMF,'GdiPlayEMF',\ + GdiPlayJournal,'GdiPlayJournal',\ + GdiPlayPageEMF,'GdiPlayPageEMF',\ + GdiPlayPrivatePageEMF,'GdiPlayPrivatePageEMF',\ + GdiPlayScript,'GdiPlayScript',\ + GdiResetDCEMF,'GdiResetDCEMF',\ + GdiSetBatchLimit,'GdiSetBatchLimit',\ + GdiStartDocEMF,'GdiStartDocEMF',\ + GdiStartPageEMF,'GdiStartPageEMF',\ + GetArcDirection,'GetArcDirection',\ + GetAspectRatioFilterEx,'GetAspectRatioFilterEx',\ + GetBitmapBits,'GetBitmapBits',\ + GetBitmapDimensionEx,'GetBitmapDimensionEx',\ + GetBkColor,'GetBkColor',\ + GetBkMode,'GetBkMode',\ + GetBoundsRect,'GetBoundsRect',\ + GetBrushOrgEx,'GetBrushOrgEx',\ + GetCharABCWidthsA,'GetCharABCWidthsA',\ + GetCharABCWidthsW,'GetCharABCWidthsW',\ + GetCharABCWidthsFloatA,'GetCharABCWidthsFloatA',\ + GetCharABCWidthsFloatW,'GetCharABCWidthsFloatW',\ + GetCharABCWidthsI,'GetCharABCWidthsI',\ + GetCharWidth32A,'GetCharWidth32A',\ + GetCharWidth32W,'GetCharWidth32W',\ + GetCharWidthA,'GetCharWidthA',\ + GetCharWidthW,'GetCharWidthW',\ + GetCharWidthFloatA,'GetCharWidthFloatA',\ + GetCharWidthFloatW,'GetCharWidthFloatW',\ + GetCharWidthI,'GetCharWidthI',\ + GetCharacterPlacementA,'GetCharacterPlacementA',\ + GetCharacterPlacementW,'GetCharacterPlacementW',\ + GetClipBox,'GetClipBox',\ + GetClipRgn,'GetClipRgn',\ + GetColorAdjustment,'GetColorAdjustment',\ + GetColorSpace,'GetColorSpace',\ + GetCurrentObject,'GetCurrentObject',\ + GetCurrentPositionEx,'GetCurrentPositionEx',\ + GetDCBrushColor,'GetDCBrushColor',\ + GetDCOrgEx,'GetDCOrgEx',\ + GetDCPenColor,'GetDCPenColor',\ + GetDIBColorTable,'GetDIBColorTable',\ + GetDIBits,'GetDIBits',\ + GetDeviceCaps,'GetDeviceCaps',\ + GetDeviceGammaRamp,'GetDeviceGammaRamp',\ + GetEnhMetaFileA,'GetEnhMetaFileA',\ + GetEnhMetaFileW,'GetEnhMetaFileW',\ + GetEnhMetaFileBits,'GetEnhMetaFileBits',\ + GetEnhMetaFileDescriptionA,'GetEnhMetaFileDescriptionA',\ + GetEnhMetaFileDescriptionW,'GetEnhMetaFileDescriptionW',\ + GetEnhMetaFileHeader,'GetEnhMetaFileHeader',\ + GetEnhMetaFilePaletteEntries,'GetEnhMetaFilePaletteEntries',\ + GetEnhMetaFilePixelFormat,'GetEnhMetaFilePixelFormat',\ + GetFontAssocStatus,'GetFontAssocStatus',\ + GetFontData,'GetFontData',\ + GetFontLanguageInfo,'GetFontLanguageInfo',\ + GetFontUnicodeRanges,'GetFontUnicodeRanges',\ + GetGlyphIndicesA,'GetGlyphIndicesA',\ + GetGlyphIndicesW,'GetGlyphIndicesW',\ + GetGlyphOutlineA,'GetGlyphOutlineA',\ + GetGlyphOutlineW,'GetGlyphOutlineW',\ + GetGraphicsMode,'GetGraphicsMode',\ + GetICMProfileA,'GetICMProfileA',\ + GetICMProfileW,'GetICMProfileW',\ + GetKerningPairsA,'GetKerningPairsA',\ + GetKerningPairsW,'GetKerningPairsW',\ + GetLogColorSpaceA,'GetLogColorSpaceA',\ + GetLogColorSpaceW,'GetLogColorSpaceW',\ + GetMapMode,'GetMapMode',\ + GetMetaFileA,'GetMetaFileA',\ + GetMetaFileW,'GetMetaFileW',\ + GetMetaFileBitsEx,'GetMetaFileBitsEx',\ + GetMetaRgn,'GetMetaRgn',\ + GetMiterLimit,'GetMiterLimit',\ + GetNearestColor,'GetNearestColor',\ + GetNearestPaletteIndex,'GetNearestPaletteIndex',\ + GetObjectA,'GetObjectA',\ + GetObjectW,'GetObjectW',\ + GetObjectType,'GetObjectType',\ + GetOutlineTextMetricsA,'GetOutlineTextMetricsA',\ + GetOutlineTextMetricsW,'GetOutlineTextMetricsW',\ + GetPaletteEntries,'GetPaletteEntries',\ + GetPath,'GetPath',\ + GetPixel,'GetPixel',\ + GetPixelFormat,'GetPixelFormat',\ + GetPolyFillMode,'GetPolyFillMode',\ + GetROP2,'GetROP2',\ + GetRandomRgn,'GetRandomRgn',\ + GetRasterizerCaps,'GetRasterizerCaps',\ + GetRegionData,'GetRegionData',\ + GetRelAbs,'GetRelAbs',\ + GetRgnBox,'GetRgnBox',\ + GetStockObject,'GetStockObject',\ + GetStretchBltMode,'GetStretchBltMode',\ + GetSystemPaletteEntries,'GetSystemPaletteEntries',\ + GetSystemPaletteUse,'GetSystemPaletteUse',\ + GetTextAlign,'GetTextAlign',\ + GetTextCharacterExtra,'GetTextCharacterExtra',\ + GetTextCharset,'GetTextCharset',\ + GetTextCharsetInfo,'GetTextCharsetInfo',\ + GetTextColor,'GetTextColor',\ + GetTextExtentExPointA,'GetTextExtentExPointA',\ + GetTextExtentExPointW,'GetTextExtentExPointW',\ + GetTextExtentExPointI,'GetTextExtentExPointI',\ + GetTextExtentPoint32A,'GetTextExtentPoint32A',\ + GetTextExtentPoint32W,'GetTextExtentPoint32W',\ + GetTextExtentPointA,'GetTextExtentPointA',\ + GetTextExtentPointW,'GetTextExtentPointW',\ + GetTextExtentPointI,'GetTextExtentPointI',\ + GetTextFaceA,'GetTextFaceA',\ + GetTextFaceW,'GetTextFaceW',\ + GetTextMetricsA,'GetTextMetricsA',\ + GetTextMetricsW,'GetTextMetricsW',\ + GetViewportExtEx,'GetViewportExtEx',\ + GetViewportOrgEx,'GetViewportOrgEx',\ + GetWinMetaFileBits,'GetWinMetaFileBits',\ + GetWindowExtEx,'GetWindowExtEx',\ + GetWindowOrgEx,'GetWindowOrgEx',\ + GetWorldTransform,'GetWorldTransform',\ + IntersectClipRect,'IntersectClipRect',\ + InvertRgn,'InvertRgn',\ + LPtoDP,'LPtoDP',\ + LineDDA,'LineDDA',\ + LineDDW,'LineDDW',\ + LineTo,'LineTo',\ + MaskBlt,'MaskBlt',\ + ModifyWorldTransform,'ModifyWorldTransform',\ + MoveToEx,'MoveToEx',\ + OffsetClipRgn,'OffsetClipRgn',\ + OffsetRgn,'OffsetRgn',\ + OffsetViewportOrgEx,'OffsetViewportOrgEx',\ + OffsetWindowOrgEx,'OffsetWindowOrgEx',\ + PaintRgn,'PaintRgn',\ + PatBlt,'PatBlt',\ + PathToRegion,'PathToRegion',\ + Pie,'Pie',\ + PlayEnhMetaFile,'PlayEnhMetaFile',\ + PlayEnhMetaFileRecord,'PlayEnhMetaFileRecord',\ + PlayMetaFile,'PlayMetaFile',\ + PlayMetaFileRecord,'PlayMetaFileRecord',\ + PlgBlt,'PlgBlt',\ + PolyBezier,'PolyBezier',\ + PolyBezierTo,'PolyBezierTo',\ + PolyDraw,'PolyDraw',\ + PolyPatBlt,'PolyPatBlt',\ + PolyPolygon,'PolyPolygon',\ + PolyPolyline,'PolyPolyline',\ + PolyTextOutA,'PolyTextOutA',\ + PolyTextOutW,'PolyTextOutW',\ + Polygon,'Polygon',\ + Polyline,'Polyline',\ + PolylineTo,'PolylineTo',\ + PtInRegion,'PtInRegion',\ + PtVisible,'PtVisible',\ + RealizePalette,'RealizePalette',\ + RectInRegion,'RectInRegion',\ + RectVisible,'RectVisible',\ + Rectangle,'Rectangle',\ + RemoveFontMemResourceEx,'RemoveFontMemResourceEx',\ + RemoveFontResourceA,'RemoveFontResourceA',\ + RemoveFontResourceW,'RemoveFontResourceW',\ + RemoveFontResourceExA,'RemoveFontResourceExA',\ + RemoveFontResourceExW,'RemoveFontResourceExW',\ + ResetDCA,'ResetDCA',\ + ResetDCW,'ResetDCW',\ + ResizePalette,'ResizePalette',\ + RestoreDC,'RestoreDC',\ + RoundRect,'RoundRect',\ + SaveDC,'SaveDC',\ + ScaleViewportExtEx,'ScaleViewportExtEx',\ + ScaleWindowExtEx,'ScaleWindowExtEx',\ + SelectBrushLocal,'SelectBrushLocal',\ + SelectClipPath,'SelectClipPath',\ + SelectClipRgn,'SelectClipRgn',\ + SelectFontLocal,'SelectFontLocal',\ + SelectObject,'SelectObject',\ + SelectPalette,'SelectPalette',\ + SetAbortProc,'SetAbortProc',\ + SetArcDirection,'SetArcDirection',\ + SetBitmapBits,'SetBitmapBits',\ + SetBitmapDimensionEx,'SetBitmapDimensionEx',\ + SetBkColor,'SetBkColor',\ + SetBkMode,'SetBkMode',\ + SetBoundsRect,'SetBoundsRect',\ + SetBrushOrgEx,'SetBrushOrgEx',\ + SetColorAdjustment,'SetColorAdjustment',\ + SetColorSpace,'SetColorSpace',\ + SetDCBrushColor,'SetDCBrushColor',\ + SetDCPenColor,'SetDCPenColor',\ + SetDIBColorTable,'SetDIBColorTable',\ + SetDIBits,'SetDIBits',\ + SetDIBitsToDevice,'SetDIBitsToDevice',\ + SetDeviceGammaRamp,'SetDeviceGammaRamp',\ + SetEnhMetaFileBits,'SetEnhMetaFileBits',\ + SetFontEnumeration,'SetFontEnumeration',\ + SetGraphicsMode,'SetGraphicsMode',\ + SetICMMode,'SetICMMode',\ + SetICMProfileA,'SetICMProfileA',\ + SetICMProfileW,'SetICMProfileW',\ + SetMagicColors,'SetMagicColors',\ + SetMapMode,'SetMapMode',\ + SetMapperFlags,'SetMapperFlags',\ + SetMetaFileBitsEx,'SetMetaFileBitsEx',\ + SetMetaRgn,'SetMetaRgn',\ + SetMiterLimit,'SetMiterLimit',\ + SetPaletteEntries,'SetPaletteEntries',\ + SetPixel,'SetPixel',\ + SetPixelFormat,'SetPixelFormat',\ + SetPixelV,'SetPixelV',\ + SetPolyFillMode,'SetPolyFillMode',\ + SetROP2,'SetROP2',\ + SetRectRgn,'SetRectRgn',\ + SetRelAbs,'SetRelAbs',\ + SetStretchBltMode,'SetStretchBltMode',\ + SetSystemPaletteUse,'SetSystemPaletteUse',\ + SetTextAlign,'SetTextAlign',\ + SetTextCharacterExtra,'SetTextCharacterExtra',\ + SetTextColor,'SetTextColor',\ + SetTextJustification,'SetTextJustification',\ + SetViewportExtEx,'SetViewportExtEx',\ + SetViewportOrgEx,'SetViewportOrgEx',\ + SetWinMetaFileBits,'SetWinMetaFileBits',\ + SetWindowExtEx,'SetWindowExtEx',\ + SetWindowOrgEx,'SetWindowOrgEx',\ + SetWorldTransform,'SetWorldTransform',\ + StartDocA,'StartDocA',\ + StartDocW,'StartDocW',\ + StartPage,'StartPage',\ + StretchBlt,'StretchBlt',\ + StretchDIBits,'StretchDIBits',\ + StrokeAndFillPath,'StrokeAndFillPath',\ + StrokePath,'StrokePath',\ + SwapBuffers,'SwapBuffers',\ + TextOutA,'TextOutA',\ + TextOutW,'TextOutW',\ + TranslateCharsetInfo,'TranslateCharsetInfo',\ + UnrealizeObject,'UnrealizeObject',\ + UpdateColors,'UpdateColors',\ + UpdateICMRegKeyA,'UpdateICMRegKeyA',\ + UpdateICMRegKeyW,'UpdateICMRegKeyW',\ + WidenPath,'WidenPath',\ + gdiPlaySpoolStream,'gdiPlaySpoolStream' + +api AddFontResource,\ + AddFontResourceEx,\ + CopyEnhMetaFile,\ + CopyMetaFile,\ + CreateColorSpace,\ + CreateDC,\ + CreateEnhMetaFile,\ + CreateFont,\ + CreateFontIndirect,\ + CreateFontIndirectEx,\ + CreateIC,\ + CreateMetaFile,\ + CreateScalableFontResource,\ + DeviceCapabilitiesEx,\ + EnumFontFamilies,\ + EnumFontFamiliesEx,\ + EnumFonts,\ + EnumICMProfiles,\ + ExtTextOut,\ + GetCharABCWidths,\ + GetCharABCWidthsFloat,\ + GetCharWidth32,\ + GetCharWidth,\ + GetCharWidthFloat,\ + GetCharacterPlacement,\ + GetEnhMetaFile,\ + GetEnhMetaFileDescription,\ + GetGlyphIndices,\ + GetGlyphOutline,\ + GetICMProfile,\ + GetKerningPairs,\ + GetLogColorSpace,\ + GetMetaFile,\ + GetObject,\ + GetOutlineTextMetrics,\ + GetTextExtentExPoint,\ + GetTextExtentPoint32,\ + GetTextExtentPoint,\ + GetTextFace,\ + GetTextMetrics,\ + LineDD,\ + PolyTextOut,\ + RemoveFontResource,\ + RemoveFontResourceEx,\ + ResetDC,\ + SetICMProfile,\ + StartDoc,\ + TextOut,\ + UpdateICMRegKey diff --git a/toolchain/fasm2/include/api/kernel32.inc b/toolchain/fasm2/include/api/kernel32.inc new file mode 100644 index 0000000..31c4672 --- /dev/null +++ b/toolchain/fasm2/include/api/kernel32.inc @@ -0,0 +1,881 @@ + +; KERNEL32 API calls + +import kernel32,\ + AddAtomA,'AddAtomA',\ + AddAtomW,'AddAtomW',\ + AddConsoleAliasA,'AddConsoleAliasA',\ + AddConsoleAliasW,'AddConsoleAliasW',\ + AllocConsole,'AllocConsole',\ + AreFileApisANSI,'AreFileApisANSI',\ + AssignProcessToJobObject,'AssignProcessToJobObject',\ + BackupRead,'BackupRead',\ + BackupSeek,'BackupSeek',\ + BackupWrite,'BackupWrite',\ + BaseAttachCompleteThunk,'BaseAttachCompleteThunk',\ + Beep,'Beep',\ + BeginUpdateResourceA,'BeginUpdateResourceA',\ + BeginUpdateResourceW,'BeginUpdateResourceW',\ + BuildCommDCBA,'BuildCommDCBA',\ + BuildCommDCBW,'BuildCommDCBW',\ + BuildCommDCBAndTimeoutsA,'BuildCommDCBAndTimeoutsA',\ + BuildCommDCBAndTimeoutsW,'BuildCommDCBAndTimeoutsW',\ + CallNamedPipeA,'CallNamedPipeA',\ + CallNamedPipeW,'CallNamedPipeW',\ + CancelIo,'CancelIo',\ + CancelWaitableTimer,'CancelWaitableTimer',\ + ClearCommBreak,'ClearCommBreak',\ + ClearCommError,'ClearCommError',\ + CloseConsoleHandle,'CloseConsoleHandle',\ + CloseHandle,'CloseHandle',\ + CloseProfileUserMapping,'CloseProfileUserMapping',\ + CmdBatNotification,'CmdBatNotification',\ + CommConfigDialogA,'CommConfigDialogA',\ + CommConfigDialogW,'CommConfigDialogW',\ + CompareFileTime,'CompareFileTime',\ + CompareStringA,'CompareStringA',\ + CompareStringW,'CompareStringW',\ + ConnectNamedPipe,'ConnectNamedPipe',\ + ConsoleMenuControl,'ConsoleMenuControl',\ + ContinueDebugEvent,'ContinueDebugEvent',\ + ConvertDefaultLocale,'ConvertDefaultLocale',\ + ConvertThreadToFiber,'ConvertThreadToFiber',\ + CopyFileA,'CopyFileA',\ + CopyFileW,'CopyFileW',\ + CopyFileExA,'CopyFileExA',\ + CopyFileExW,'CopyFileExW',\ + CreateConsoleScreenBuffer,'CreateConsoleScreenBuffer',\ + CreateDirectoryA,'CreateDirectoryA',\ + CreateDirectoryW,'CreateDirectoryW',\ + CreateDirectoryExA,'CreateDirectoryExA',\ + CreateDirectoryExW,'CreateDirectoryExW',\ + CreateEventA,'CreateEventA',\ + CreateEventW,'CreateEventW',\ + CreateFiber,'CreateFiber',\ + CreateFileA,'CreateFileA',\ + CreateFileW,'CreateFileW',\ + CreateFileMappingA,'CreateFileMappingA',\ + CreateFileMappingW,'CreateFileMappingW',\ + CreateHardLinkA,'CreateHardLinkA',\ + CreateHardLinkW,'CreateHardLinkW',\ + CreateIoCompletionPort,'CreateIoCompletionPort',\ + CreateJobObjectA,'CreateJobObjectA',\ + CreateJobObjectW,'CreateJobObjectW',\ + CreateMailslotA,'CreateMailslotA',\ + CreateMailslotW,'CreateMailslotW',\ + CreateMutexA,'CreateMutexA',\ + CreateMutexW,'CreateMutexW',\ + CreateNamedPipeA,'CreateNamedPipeA',\ + CreateNamedPipeW,'CreateNamedPipeW',\ + CreatePipe,'CreatePipe',\ + CreateProcessA,'CreateProcessA',\ + CreateProcessW,'CreateProcessW',\ + CreateRemoteThread,'CreateRemoteThread',\ + CreateSemaphoreA,'CreateSemaphoreA',\ + CreateSemaphoreW,'CreateSemaphoreW',\ + CreateTapePartition,'CreateTapePartition',\ + CreateThread,'CreateThread',\ + CreateToolhelp32Snapshot,'CreateToolhelp32Snapshot',\ + CreateVirtualBuffer,'CreateVirtualBuffer',\ + CreateWaitableTimerA,'CreateWaitableTimerA',\ + CreateWaitableTimerW,'CreateWaitableTimerW',\ + DebugActiveProcess,'DebugActiveProcess',\ + DebugBreak,'DebugBreak',\ + DefineDosDeviceA,'DefineDosDeviceA',\ + DefineDosDeviceW,'DefineDosDeviceW',\ + DeleteAtom,'DeleteAtom',\ + DeleteCriticalSection,'DeleteCriticalSection',\ + DeleteFiber,'DeleteFiber',\ + DeleteFileA,'DeleteFileA',\ + DeleteFileW,'DeleteFileW',\ + DeviceIoControl,'DeviceIoControl',\ + DisableThreadLibraryCalls,'DisableThreadLibraryCalls',\ + DisconnectNamedPipe,'DisconnectNamedPipe',\ + DosDateTimeToFileTime,'DosDateTimeToFileTime',\ + DuplicateConsoleHandle,'DuplicateConsoleHandle',\ + DuplicateHandle,'DuplicateHandle',\ + EndUpdateResourceA,'EndUpdateResourceA',\ + EndUpdateResourceW,'EndUpdateResourceW',\ + EnterCriticalSection,'EnterCriticalSection',\ + EnumCalendarInfoA,'EnumCalendarInfoA',\ + EnumCalendarInfoW,'EnumCalendarInfoW',\ + EnumCalendarInfoExA,'EnumCalendarInfoExA',\ + EnumCalendarInfoExW,'EnumCalendarInfoExW',\ + EnumDateFormatsA,'EnumDateFormatsA',\ + EnumDateFormatsW,'EnumDateFormatsW',\ + EnumDateFormatsExA,'EnumDateFormatsExA',\ + EnumDateFormatsExW,'EnumDateFormatsExW',\ + EnumResourceLanguagesA,'EnumResourceLanguagesA',\ + EnumResourceLanguagesW,'EnumResourceLanguagesW',\ + EnumResourceNamesA,'EnumResourceNamesA',\ + EnumResourceNamesW,'EnumResourceNamesW',\ + EnumResourceTypesA,'EnumResourceTypesA',\ + EnumResourceTypesW,'EnumResourceTypesW',\ + EnumSystemCodePagesA,'EnumSystemCodePagesA',\ + EnumSystemCodePagesW,'EnumSystemCodePagesW',\ + EnumSystemLocalesA,'EnumSystemLocalesA',\ + EnumSystemLocalesW,'EnumSystemLocalesW',\ + EnumTimeFormatsA,'EnumTimeFormatsA',\ + EnumTimeFormatsW,'EnumTimeFormatsW',\ + EraseTape,'EraseTape',\ + EscapeCommFunction,'EscapeCommFunction',\ + ExitProcess,'ExitProcess',\ + ExitThread,'ExitThread',\ + ExitVDM,'ExitVDM',\ + ExpandEnvironmentStringsA,'ExpandEnvironmentStringsA',\ + ExpandEnvironmentStringsW,'ExpandEnvironmentStringsW',\ + ExpungeConsoleCommandHistoryA,'ExpungeConsoleCommandHistoryA',\ + ExpungeConsoleCommandHistoryW,'ExpungeConsoleCommandHistoryW',\ + ExtendVirtualBuffer,'ExtendVirtualBuffer',\ + FatalAppExitA,'FatalAppExitA',\ + FatalAppExitW,'FatalAppExitW',\ + FatalExit,'FatalExit',\ + FileTimeToDosDateTime,'FileTimeToDosDateTime',\ + FileTimeToLocalFileTime,'FileTimeToLocalFileTime',\ + FileTimeToSystemTime,'FileTimeToSystemTime',\ + FillConsoleOutputAttribute,'FillConsoleOutputAttribute',\ + FillConsoleOutputCharacterA,'FillConsoleOutputCharacterA',\ + FillConsoleOutputCharacterW,'FillConsoleOutputCharacterW',\ + FindAtomA,'FindAtomA',\ + FindAtomW,'FindAtomW',\ + FindClose,'FindClose',\ + FindCloseChangeNotification,'FindCloseChangeNotification',\ + FindFirstChangeNotificationA,'FindFirstChangeNotificationA',\ + FindFirstChangeNotificationW,'FindFirstChangeNotificationW',\ + FindFirstFileA,'FindFirstFileA',\ + FindFirstFileW,'FindFirstFileW',\ + FindFirstFileExA,'FindFirstFileExA',\ + FindFirstFileExW,'FindFirstFileExW',\ + FindNextChangeNotification,'FindNextChangeNotification',\ + FindNextFileA,'FindNextFileA',\ + FindNextFileW,'FindNextFileW',\ + FindResourceA,'FindResourceA',\ + FindResourceW,'FindResourceW',\ + FindResourceExA,'FindResourceExA',\ + FindResourceExW,'FindResourceExW',\ + FlushConsoleInputBuffer,'FlushConsoleInputBuffer',\ + FlushFileBuffers,'FlushFileBuffers',\ + FlushInstructionCache,'FlushInstructionCache',\ + FlushViewOfFile,'FlushViewOfFile',\ + FoldStringA,'FoldStringA',\ + FoldStringW,'FoldStringW',\ + FormatMessageA,'FormatMessageA',\ + FormatMessageW,'FormatMessageW',\ + FreeConsole,'FreeConsole',\ + FreeEnvironmentStringsA,'FreeEnvironmentStringsA',\ + FreeEnvironmentStringsW,'FreeEnvironmentStringsW',\ + FreeLibrary,'FreeLibrary',\ + FreeLibraryAndExitThread,'FreeLibraryAndExitThread',\ + FreeResource,'FreeResource',\ + FreeVirtualBuffer,'FreeVirtualBuffer',\ + GenerateConsoleCtrlEvent,'GenerateConsoleCtrlEvent',\ + GetACP,'GetACP',\ + GetAtomNameA,'GetAtomNameA',\ + GetAtomNameW,'GetAtomNameW',\ + GetBinaryTypeA,'GetBinaryTypeA',\ + GetBinaryTypeW,'GetBinaryTypeW',\ + GetCPInfo,'GetCPInfo',\ + GetCPInfoExA,'GetCPInfoExA',\ + GetCPInfoExW,'GetCPInfoExW',\ + GetCommConfig,'GetCommConfig',\ + GetCommMask,'GetCommMask',\ + GetCommModemStatus,'GetCommModemStatus',\ + GetCommProperties,'GetCommProperties',\ + GetCommState,'GetCommState',\ + GetCommTimeouts,'GetCommTimeouts',\ + GetCommandLineA,'GetCommandLineA',\ + GetCommandLineW,'GetCommandLineW',\ + GetCompressedFileSizeA,'GetCompressedFileSizeA',\ + GetCompressedFileSizeW,'GetCompressedFileSizeW',\ + GetComputerNameA,'GetComputerNameA',\ + GetComputerNameW,'GetComputerNameW',\ + GetConsoleAliasA,'GetConsoleAliasA',\ + GetConsoleAliasW,'GetConsoleAliasW',\ + GetConsoleAliasExesA,'GetConsoleAliasExesA',\ + GetConsoleAliasExesW,'GetConsoleAliasExesW',\ + GetConsoleAliasExesLengthA,'GetConsoleAliasExesLengthA',\ + GetConsoleAliasExesLengthW,'GetConsoleAliasExesLengthW',\ + GetConsoleAliasesA,'GetConsoleAliasesA',\ + GetConsoleAliasesW,'GetConsoleAliasesW',\ + GetConsoleAliasesLengthA,'GetConsoleAliasesLengthA',\ + GetConsoleAliasesLengthW,'GetConsoleAliasesLengthW',\ + GetConsoleCP,'GetConsoleCP',\ + GetConsoleCommandHistoryA,'GetConsoleCommandHistoryA',\ + GetConsoleCommandHistoryW,'GetConsoleCommandHistoryW',\ + GetConsoleCommandHistoryLengthA,'GetConsoleCommandHistoryLengthA',\ + GetConsoleCommandHistoryLengthW,'GetConsoleCommandHistoryLengthW',\ + GetConsoleCursorInfo,'GetConsoleCursorInfo',\ + GetConsoleDisplayMode,'GetConsoleDisplayMode',\ + GetConsoleFontInfo,'GetConsoleFontInfo',\ + GetConsoleFontSize,'GetConsoleFontSize',\ + GetConsoleHardwareState,'GetConsoleHardwareState',\ + GetConsoleInputExeNameA,'GetConsoleInputExeNameA',\ + GetConsoleInputExeNameW,'GetConsoleInputExeNameW',\ + GetConsoleInputWaitHandle,'GetConsoleInputWaitHandle',\ + GetConsoleKeyboardLayoutNameA,'GetConsoleKeyboardLayoutNameA',\ + GetConsoleKeyboardLayoutNameW,'GetConsoleKeyboardLayoutNameW',\ + GetConsoleMode,'GetConsoleMode',\ + GetConsoleOutputCP,'GetConsoleOutputCP',\ + GetConsoleScreenBufferInfo,'GetConsoleScreenBufferInfo',\ + GetConsoleTitleA,'GetConsoleTitleA',\ + GetConsoleTitleW,'GetConsoleTitleW',\ + GetConsoleWindow,'GetConsoleWindow',\ + GetCurrencyFormatA,'GetCurrencyFormatA',\ + GetCurrencyFormatW,'GetCurrencyFormatW',\ + GetCurrentConsoleFont,'GetCurrentConsoleFont',\ + GetCurrentDirectoryA,'GetCurrentDirectoryA',\ + GetCurrentDirectoryW,'GetCurrentDirectoryW',\ + GetCurrentProcess,'GetCurrentProcess',\ + GetCurrentProcessId,'GetCurrentProcessId',\ + GetCurrentThread,'GetCurrentThread',\ + GetCurrentThreadId,'GetCurrentThreadId',\ + GetDateFormatA,'GetDateFormatA',\ + GetDateFormatW,'GetDateFormatW',\ + GetDefaultCommConfigA,'GetDefaultCommConfigA',\ + GetDefaultCommConfigW,'GetDefaultCommConfigW',\ + GetDevicePowerState,'GetDevicePowerState',\ + GetDiskFreeSpaceA,'GetDiskFreeSpaceA',\ + GetDiskFreeSpaceW,'GetDiskFreeSpaceW',\ + GetDiskFreeSpaceExA,'GetDiskFreeSpaceExA',\ + GetDiskFreeSpaceExW,'GetDiskFreeSpaceExW',\ + GetDriveTypeA,'GetDriveTypeA',\ + GetDriveTypeW,'GetDriveTypeW',\ + GetEnvironmentStringsA,'GetEnvironmentStringsA',\ + GetEnvironmentStringsW,'GetEnvironmentStringsW',\ + GetEnvironmentVariableA,'GetEnvironmentVariableA',\ + GetEnvironmentVariableW,'GetEnvironmentVariableW',\ + GetExitCodeProcess,'GetExitCodeProcess',\ + GetExitCodeThread,'GetExitCodeThread',\ + GetFileAttributesA,'GetFileAttributesA',\ + GetFileAttributesW,'GetFileAttributesW',\ + GetFileAttributesExA,'GetFileAttributesExA',\ + GetFileAttributesExW,'GetFileAttributesExW',\ + GetFileInformationByHandle,'GetFileInformationByHandle',\ + GetFileSize,'GetFileSize',\ + GetFileSizeEx,'GetFileSizeEx',\ + GetFileTime,'GetFileTime',\ + GetFileType,'GetFileType',\ + GetFullPathNameA,'GetFullPathNameA',\ + GetFullPathNameW,'GetFullPathNameW',\ + GetHandleInformation,'GetHandleInformation',\ + GetLargestConsoleWindowSize,'GetLargestConsoleWindowSize',\ + GetLastError,'GetLastError',\ + GetLocalTime,'GetLocalTime',\ + GetLocaleInfoA,'GetLocaleInfoA',\ + GetLocaleInfoW,'GetLocaleInfoW',\ + GetLogicalDriveStringsA,'GetLogicalDriveStringsA',\ + GetLogicalDriveStringsW,'GetLogicalDriveStringsW',\ + GetLogicalDrives,'GetLogicalDrives',\ + GetLongPathNameA,'GetLongPathNameA',\ + GetLongPathNameW,'GetLongPathNameW',\ + GetMailslotInfo,'GetMailslotInfo',\ + GetModuleFileNameA,'GetModuleFileNameA',\ + GetModuleFileNameW,'GetModuleFileNameW',\ + GetModuleHandleA,'GetModuleHandleA',\ + GetModuleHandleW,'GetModuleHandleW',\ + GetNamedPipeHandleStateA,'GetNamedPipeHandleStateA',\ + GetNamedPipeHandleStateW,'GetNamedPipeHandleStateW',\ + GetNamedPipeInfo,'GetNamedPipeInfo',\ + GetNextVDMCommand,'GetNextVDMCommand',\ + GetNumberFormatA,'GetNumberFormatA',\ + GetNumberFormatW,'GetNumberFormatW',\ + GetNumberOfConsoleFonts,'GetNumberOfConsoleFonts',\ + GetNumberOfConsoleInputEvents,'GetNumberOfConsoleInputEvents',\ + GetNumberOfConsoleMouseButtons,'GetNumberOfConsoleMouseButtons',\ + GetOEMCP,'GetOEMCP',\ + GetOverlappedResult,'GetOverlappedResult',\ + GetPriorityClass,'GetPriorityClass',\ + GetPrivateProfileIntA,'GetPrivateProfileIntA',\ + GetPrivateProfileIntW,'GetPrivateProfileIntW',\ + GetPrivateProfileSectionA,'GetPrivateProfileSectionA',\ + GetPrivateProfileSectionW,'GetPrivateProfileSectionW',\ + GetPrivateProfileSectionNamesA,'GetPrivateProfileSectionNamesA',\ + GetPrivateProfileSectionNamesW,'GetPrivateProfileSectionNamesW',\ + GetPrivateProfileStringA,'GetPrivateProfileStringA',\ + GetPrivateProfileStringW,'GetPrivateProfileStringW',\ + GetPrivateProfileStructA,'GetPrivateProfileStructA',\ + GetPrivateProfileStructW,'GetPrivateProfileStructW',\ + GetProcAddress,'GetProcAddress',\ + GetProcessAffinityMask,'GetProcessAffinityMask',\ + GetProcessHeap,'GetProcessHeap',\ + GetProcessHeaps,'GetProcessHeaps',\ + GetProcessPriorityBoost,'GetProcessPriorityBoost',\ + GetProcessShutdownParameters,'GetProcessShutdownParameters',\ + GetProcessTimes,'GetProcessTimes',\ + GetProcessVersion,'GetProcessVersion',\ + GetProcessWorkingSetSize,'GetProcessWorkingSetSize',\ + GetProfileIntA,'GetProfileIntA',\ + GetProfileIntW,'GetProfileIntW',\ + GetProfileSectionA,'GetProfileSectionA',\ + GetProfileSectionW,'GetProfileSectionW',\ + GetProfileStringA,'GetProfileStringA',\ + GetProfileStringW,'GetProfileStringW',\ + GetQueuedCompletionStatus,'GetQueuedCompletionStatus',\ + GetShortPathNameA,'GetShortPathNameA',\ + GetShortPathNameW,'GetShortPathNameW',\ + GetStartupInfoA,'GetStartupInfoA',\ + GetStartupInfoW,'GetStartupInfoW',\ + GetStdHandle,'GetStdHandle',\ + GetStringTypeA,'GetStringTypeA',\ + GetStringTypeW,'GetStringTypeW',\ + GetStringTypeExA,'GetStringTypeExA',\ + GetStringTypeExW,'GetStringTypeExW',\ + GetSystemDefaultLCID,'GetSystemDefaultLCID',\ + GetSystemDefaultLangID,'GetSystemDefaultLangID',\ + GetSystemDirectoryA,'GetSystemDirectoryA',\ + GetSystemDirectoryW,'GetSystemDirectoryW',\ + GetSystemInfo,'GetSystemInfo',\ + GetSystemPowerStatus,'GetSystemPowerStatus',\ + GetSystemTime,'GetSystemTime',\ + GetSystemTimeAdjustment,'GetSystemTimeAdjustment',\ + GetSystemTimeAsFileTime,'GetSystemTimeAsFileTime',\ + GetTapeParameters,'GetTapeParameters',\ + GetTapePosition,'GetTapePosition',\ + GetTapeStatus,'GetTapeStatus',\ + GetTempFileNameA,'GetTempFileNameA',\ + GetTempFileNameW,'GetTempFileNameW',\ + GetTempPathA,'GetTempPathA',\ + GetTempPathW,'GetTempPathW',\ + GetThreadContext,'GetThreadContext',\ + GetThreadLocale,'GetThreadLocale',\ + GetThreadPriority,'GetThreadPriority',\ + GetThreadPriorityBoost,'GetThreadPriorityBoost',\ + GetThreadSelectorEntry,'GetThreadSelectorEntry',\ + GetThreadTimes,'GetThreadTimes',\ + GetTickCount,'GetTickCount',\ + GetTimeFormatA,'GetTimeFormatA',\ + GetTimeFormatW,'GetTimeFormatW',\ + GetTimeZoneInformation,'GetTimeZoneInformation',\ + GetUserDefaultLCID,'GetUserDefaultLCID',\ + GetUserDefaultLangID,'GetUserDefaultLangID',\ + GetVDMCurrentDirectories,'GetVDMCurrentDirectories',\ + GetVersion,'GetVersion',\ + GetVersionExA,'GetVersionExA',\ + GetVersionExW,'GetVersionExW',\ + GetVolumeInformationA,'GetVolumeInformationA',\ + GetVolumeInformationW,'GetVolumeInformationW',\ + GetWindowsDirectoryA,'GetWindowsDirectoryA',\ + GetWindowsDirectoryW,'GetWindowsDirectoryW',\ + GlobalAddAtomA,'GlobalAddAtomA',\ + GlobalAddAtomW,'GlobalAddAtomW',\ + GlobalAlloc,'GlobalAlloc',\ + GlobalCompact,'GlobalCompact',\ + GlobalDeleteAtom,'GlobalDeleteAtom',\ + GlobalFindAtomA,'GlobalFindAtomA',\ + GlobalFindAtomW,'GlobalFindAtomW',\ + GlobalFix,'GlobalFix',\ + GlobalFlags,'GlobalFlags',\ + GlobalFree,'GlobalFree',\ + GlobalGetAtomNameA,'GlobalGetAtomNameA',\ + GlobalGetAtomNameW,'GlobalGetAtomNameW',\ + GlobalHandle,'GlobalHandle',\ + GlobalLock,'GlobalLock',\ + GlobalMemoryStatus,'GlobalMemoryStatus',\ + GlobalMemoryStatusVlm,'GlobalMemoryStatusVlm',\ + GlobalReAlloc,'GlobalReAlloc',\ + GlobalSize,'GlobalSize',\ + GlobalUnWire,'GlobalUnWire',\ + GlobalUnfix,'GlobalUnfix',\ + GlobalUnlock,'GlobalUnlock',\ + GlobalWire,'GlobalWire',\ + Heap32First,'Heap32First',\ + Heap32ListFirst,'Heap32ListFirst',\ + Heap32ListNext,'Heap32ListNext',\ + Heap32Next,'Heap32Next',\ + HeapAlloc,'HeapAlloc',\ + HeapCompact,'HeapCompact',\ + HeapCreate,'HeapCreate',\ + HeapDestroy,'HeapDestroy',\ + HeapExtend,'HeapExtend',\ + HeapFree,'HeapFree',\ + HeapLock,'HeapLock',\ + HeapReAlloc,'HeapReAlloc',\ + HeapSize,'HeapSize',\ + HeapSummary,'HeapSummary',\ + HeapUnlock,'HeapUnlock',\ + HeapUsage,'HeapUsage',\ + HeapValidate,'HeapValidate',\ + HeapWalk,'HeapWalk',\ + InitAtomTable,'InitAtomTable',\ + InitializeCriticalSection,'InitializeCriticalSection',\ + InitializeCriticalSectionAndSpinCount,'InitializeCriticalSectionAndSpinCount',\ + InterlockedCompareExchange,'InterlockedCompareExchange',\ + InterlockedDecrement,'InterlockedDecrement',\ + InterlockedExchange,'InterlockedExchange',\ + InterlockedExchangeAdd,'InterlockedExchangeAdd',\ + InterlockedIncrement,'InterlockedIncrement',\ + InvalidateConsoleDIBits,'InvalidateConsoleDIBits',\ + IsBadCodePtr,'IsBadCodePtr',\ + IsBadHugeReadPtr,'IsBadHugeReadPtr',\ + IsBadHugeWritePtr,'IsBadHugeWritePtr',\ + IsBadReadPtr,'IsBadReadPtr',\ + IsBadStringPtrA,'IsBadStringPtrA',\ + IsBadStringPtrW,'IsBadStringPtrW',\ + IsBadWritePtr,'IsBadWritePtr',\ + IsDBCSLeadByte,'IsDBCSLeadByte',\ + IsDBCSLeadByteEx,'IsDBCSLeadByteEx',\ + IsDebuggerPresent,'IsDebuggerPresent',\ + IsProcessorFeaturePresent,'IsProcessorFeaturePresent',\ + IsValidCodePage,'IsValidCodePage',\ + IsValidLocale,'IsValidLocale',\ + LCMapStringA,'LCMapStringA',\ + LCMapStringW,'LCMapStringW',\ + LeaveCriticalSection,'LeaveCriticalSection',\ + LoadLibraryA,'LoadLibraryA',\ + LoadLibraryW,'LoadLibraryW',\ + LoadLibraryExA,'LoadLibraryExA',\ + LoadLibraryExW,'LoadLibraryExW',\ + LoadModule,'LoadModule',\ + LoadResource,'LoadResource',\ + LocalAlloc,'LocalAlloc',\ + LocalCompact,'LocalCompact',\ + LocalFileTimeToFileTime,'LocalFileTimeToFileTime',\ + LocalFlags,'LocalFlags',\ + LocalFree,'LocalFree',\ + LocalHandle,'LocalHandle',\ + LocalLock,'LocalLock',\ + LocalReAlloc,'LocalReAlloc',\ + LocalShrink,'LocalShrink',\ + LocalSize,'LocalSize',\ + LocalUnlock,'LocalUnlock',\ + LockFile,'LockFile',\ + LockFileEx,'LockFileEx',\ + LockResource,'LockResource',\ + MapViewOfFile,'MapViewOfFile',\ + MapViewOfFileEx,'MapViewOfFileEx',\ + MapViewOfFileVlm,'MapViewOfFileVlm',\ + Module32First,'Module32First',\ + Module32Next,'Module32Next',\ + MoveFileA,'MoveFileA',\ + MoveFileW,'MoveFileW',\ + MoveFileExA,'MoveFileExA',\ + MoveFileExW,'MoveFileExW',\ + MoveFileWithProgressA,'MoveFileWithProgressA',\ + MoveFileWithProgressW,'MoveFileWithProgressW',\ + MulDiv,'MulDiv',\ + MultiByteToWideChar,'MultiByteToWideChar',\ + OpenEventA,'OpenEventA',\ + OpenEventW,'OpenEventW',\ + OpenFile,'OpenFile',\ + OpenFileMappingA,'OpenFileMappingA',\ + OpenFileMappingW,'OpenFileMappingW',\ + OpenJobObjectA,'OpenJobObjectA',\ + OpenJobObjectW,'OpenJobObjectW',\ + OpenMutexA,'OpenMutexA',\ + OpenMutexW,'OpenMutexW',\ + OpenProcess,'OpenProcess',\ + OpenProfileUserMapping,'OpenProfileUserMapping',\ + OpenSemaphoreA,'OpenSemaphoreA',\ + OpenSemaphoreW,'OpenSemaphoreW',\ + OpenWaitableTimerA,'OpenWaitableTimerA',\ + OpenWaitableTimerW,'OpenWaitableTimerW',\ + OutputDebugStringA,'OutputDebugStringA',\ + OutputDebugStringW,'OutputDebugStringW',\ + PeekConsoleInputA,'PeekConsoleInputA',\ + PeekConsoleInputW,'PeekConsoleInputW',\ + PeekNamedPipe,'PeekNamedPipe',\ + PostQueuedCompletionStatus,'PostQueuedCompletionStatus',\ + PrepareTape,'PrepareTape',\ + Process32First,'Process32First',\ + Process32Next,'Process32Next',\ + PulseEvent,'PulseEvent',\ + PurgeComm,'PurgeComm',\ + QueryDosDeviceA,'QueryDosDeviceA',\ + QueryDosDeviceW,'QueryDosDeviceW',\ + QueryInformationJobObject,'QueryInformationJobObject',\ + QueryPerformanceCounter,'QueryPerformanceCounter',\ + QueryPerformanceFrequency,'QueryPerformanceFrequency',\ + QueryWin31IniFilesMappedToRegistry,'QueryWin31IniFilesMappedToRegistry',\ + QueueUserAPC,'QueueUserAPC',\ + RaiseException,'RaiseException',\ + ReadConsoleA,'ReadConsoleA',\ + ReadConsoleW,'ReadConsoleW',\ + ReadConsoleInputA,'ReadConsoleInputA',\ + ReadConsoleInputW,'ReadConsoleInputW',\ + ReadConsoleInputExA,'ReadConsoleInputExA',\ + ReadConsoleInputExW,'ReadConsoleInputExW',\ + ReadConsoleOutputA,'ReadConsoleOutputA',\ + ReadConsoleOutputW,'ReadConsoleOutputW',\ + ReadConsoleOutputAttribute,'ReadConsoleOutputAttribute',\ + ReadConsoleOutputCharacterA,'ReadConsoleOutputCharacterA',\ + ReadConsoleOutputCharacterW,'ReadConsoleOutputCharacterW',\ + ReadFile,'ReadFile',\ + ReadFileEx,'ReadFileEx',\ + ReadFileScatter,'ReadFileScatter',\ + ReadFileVlm,'ReadFileVlm',\ + ReadProcessMemory,'ReadProcessMemory',\ + ReadProcessMemoryVlm,'ReadProcessMemoryVlm',\ + RegisterConsoleVDM,'RegisterConsoleVDM',\ + RegisterWaitForInputIdle,'RegisterWaitForInputIdle',\ + RegisterWowBaseHandlers,'RegisterWowBaseHandlers',\ + RegisterWowExec,'RegisterWowExec',\ + ReleaseMutex,'ReleaseMutex',\ + ReleaseSemaphore,'ReleaseSemaphore',\ + RemoveDirectoryA,'RemoveDirectoryA',\ + RemoveDirectoryW,'RemoveDirectoryW',\ + RequestWakeupLatency,'RequestWakeupLatency',\ + ResetEvent,'ResetEvent',\ + ResumeThread,'ResumeThread',\ + RtlFillMemory,'RtlFillMemory',\ + RtlMoveMemory,'RtlMoveMemory',\ + RtlUnwind,'RtlUnwind',\ + RtlZeroMemory,'RtlZeroMemory',\ + ScrollConsoleScreenBufferA,'ScrollConsoleScreenBufferA',\ + ScrollConsoleScreenBufferW,'ScrollConsoleScreenBufferW',\ + SearchPathA,'SearchPathA',\ + SearchPathW,'SearchPathW',\ + SetCommBreak,'SetCommBreak',\ + SetCommConfig,'SetCommConfig',\ + SetCommMask,'SetCommMask',\ + SetCommState,'SetCommState',\ + SetCommTimeouts,'SetCommTimeouts',\ + SetComputerNameA,'SetComputerNameA',\ + SetComputerNameW,'SetComputerNameW',\ + SetConsoleActiveScreenBuffer,'SetConsoleActiveScreenBuffer',\ + SetConsoleCP,'SetConsoleCP',\ + SetConsoleCommandHistoryMode,'SetConsoleCommandHistoryMode',\ + SetConsoleCtrlHandler,'SetConsoleCtrlHandler',\ + SetConsoleCursor,'SetConsoleCursor',\ + SetConsoleCursorInfo,'SetConsoleCursorInfo',\ + SetConsoleCursorPosition,'SetConsoleCursorPosition',\ + SetConsoleDisplayMode,'SetConsoleDisplayMode',\ + SetConsoleFont,'SetConsoleFont',\ + SetConsoleHardwareState,'SetConsoleHardwareState',\ + SetConsoleIcon,'SetConsoleIcon',\ + SetConsoleInputExeNameA,'SetConsoleInputExeNameA',\ + SetConsoleInputExeNameW,'SetConsoleInputExeNameW',\ + SetConsoleKeyShortcuts,'SetConsoleKeyShortcuts',\ + SetConsoleMaximumWindowSize,'SetConsoleMaximumWindowSize',\ + SetConsoleMenuClose,'SetConsoleMenuClose',\ + SetConsoleMode,'SetConsoleMode',\ + SetConsoleNumberOfCommandsA,'SetConsoleNumberOfCommandsA',\ + SetConsoleNumberOfCommandsW,'SetConsoleNumberOfCommandsW',\ + SetConsoleOutputCP,'SetConsoleOutputCP',\ + SetConsolePalette,'SetConsolePalette',\ + SetConsoleScreenBufferSize,'SetConsoleScreenBufferSize',\ + SetConsoleTextAttribute,'SetConsoleTextAttribute',\ + SetConsoleTitleA,'SetConsoleTitleA',\ + SetConsoleTitleW,'SetConsoleTitleW',\ + SetConsoleWindowInfo,'SetConsoleWindowInfo',\ + SetCriticalSectionSpinCount,'SetCriticalSectionSpinCount',\ + SetCurrentDirectoryA,'SetCurrentDirectoryA',\ + SetCurrentDirectoryW,'SetCurrentDirectoryW',\ + SetDefaultCommConfigA,'SetDefaultCommConfigA',\ + SetDefaultCommConfigW,'SetDefaultCommConfigW',\ + SetEndOfFile,'SetEndOfFile',\ + SetEnvironmentVariableA,'SetEnvironmentVariableA',\ + SetEnvironmentVariableW,'SetEnvironmentVariableW',\ + SetErrorMode,'SetErrorMode',\ + SetEvent,'SetEvent',\ + SetFileApisToANSI,'SetFileApisToANSI',\ + SetFileApisToOEM,'SetFileApisToOEM',\ + SetFileAttributesA,'SetFileAttributesA',\ + SetFileAttributesW,'SetFileAttributesW',\ + SetFilePointer,'SetFilePointer',\ + SetFilePointerEx,'SetFilePointerEx',\ + SetFileTime,'SetFileTime',\ + SetHandleCount,'SetHandleCount',\ + SetHandleInformation,'SetHandleInformation',\ + SetInformationJobObject,'SetInformationJobObject',\ + SetLastConsoleEventActive,'SetLastConsoleEventActive',\ + SetLastError,'SetLastError',\ + SetLocalTime,'SetLocalTime',\ + SetLocaleInfoA,'SetLocaleInfoA',\ + SetLocaleInfoW,'SetLocaleInfoW',\ + SetMailslotInfo,'SetMailslotInfo',\ + SetNamedPipeHandleState,'SetNamedPipeHandleState',\ + SetPriorityClass,'SetPriorityClass',\ + SetProcessAffinityMask,'SetProcessAffinityMask',\ + SetProcessPriorityBoost,'SetProcessPriorityBoost',\ + SetProcessShutdownParameters,'SetProcessShutdownParameters',\ + SetProcessWorkingSetSize,'SetProcessWorkingSetSize',\ + SetStdHandle,'SetStdHandle',\ + SetSystemPowerState,'SetSystemPowerState',\ + SetSystemTime,'SetSystemTime',\ + SetSystemTimeAdjustment,'SetSystemTimeAdjustment',\ + SetTapeParameters,'SetTapeParameters',\ + SetTapePosition,'SetTapePosition',\ + SetThreadAffinityMask,'SetThreadAffinityMask',\ + SetThreadContext,'SetThreadContext',\ + SetThreadExecutionState,'SetThreadExecutionState',\ + SetThreadIdealProcessor,'SetThreadIdealProcessor',\ + SetThreadLocale,'SetThreadLocale',\ + SetThreadPriority,'SetThreadPriority',\ + SetThreadPriorityBoost,'SetThreadPriorityBoost',\ + SetTimeZoneInformation,'SetTimeZoneInformation',\ + SetUnhandledExceptionFilter,'SetUnhandledExceptionFilter',\ + SetVDMCurrentDirectories,'SetVDMCurrentDirectories',\ + SetVolumeLabelA,'SetVolumeLabelA',\ + SetVolumeLabelW,'SetVolumeLabelW',\ + SetWaitableTimer,'SetWaitableTimer',\ + SetupComm,'SetupComm',\ + ShowConsoleCursor,'ShowConsoleCursor',\ + SignalObjectAndWait,'SignalObjectAndWait',\ + SizeofResource,'SizeofResource',\ + Sleep,'Sleep',\ + SleepEx,'SleepEx',\ + SuspendThread,'SuspendThread',\ + SwitchToFiber,'SwitchToFiber',\ + SwitchToThread,'SwitchToThread',\ + SystemTimeToFileTime,'SystemTimeToFileTime',\ + SystemTimeToTzSpecificLocalTime,'SystemTimeToTzSpecificLocalTime',\ + TerminateJobObject,'TerminateJobObject',\ + TerminateProcess,'TerminateProcess',\ + TerminateThread,'TerminateThread',\ + Thread32First,'Thread32First',\ + Thread32Next,'Thread32Next',\ + TlsAlloc,'TlsAlloc',\ + TlsFree,'TlsFree',\ + TlsGetValue,'TlsGetValue',\ + TlsSetValue,'TlsSetValue',\ + Toolhelp32ReadProcessMemory,'Toolhelp32ReadProcessMemory',\ + TransactNamedPipe,'TransactNamedPipe',\ + TransmitCommChar,'TransmitCommChar',\ + TrimVirtualBuffer,'TrimVirtualBuffer',\ + TryEnterCriticalSection,'TryEnterCriticalSection',\ + UnhandledExceptionFilter,'UnhandledExceptionFilter',\ + UnlockFile,'UnlockFile',\ + UnlockFileEx,'UnlockFileEx',\ + UnmapViewOfFile,'UnmapViewOfFile',\ + UnmapViewOfFileVlm,'UnmapViewOfFileVlm',\ + UpdateResourceA,'UpdateResourceA',\ + UpdateResourceW,'UpdateResourceW',\ + VDMConsoleOperation,'VDMConsoleOperation',\ + VDMOperationStarted,'VDMOperationStarted',\ + VerLanguageNameA,'VerLanguageNameA',\ + VerLanguageNameW,'VerLanguageNameW',\ + VerifyConsoleIoHandle,'VerifyConsoleIoHandle',\ + VirtualAlloc,'VirtualAlloc',\ + VirtualAllocEx,'VirtualAllocEx',\ + VirtualAllocVlm,'VirtualAllocVlm',\ + VirtualBufferExceptionHandler,'VirtualBufferExceptionHandler',\ + VirtualFree,'VirtualFree',\ + VirtualFreeEx,'VirtualFreeEx',\ + VirtualFreeVlm,'VirtualFreeVlm',\ + VirtualLock,'VirtualLock',\ + VirtualProtect,'VirtualProtect',\ + VirtualProtectEx,'VirtualProtectEx',\ + VirtualProtectVlm,'VirtualProtectVlm',\ + VirtualQuery,'VirtualQuery',\ + VirtualQueryEx,'VirtualQueryEx',\ + VirtualQueryVlm,'VirtualQueryVlm',\ + VirtualUnlock,'VirtualUnlock',\ + WaitCommEvent,'WaitCommEvent',\ + WaitForDebugEvent,'WaitForDebugEvent',\ + WaitForMultipleObjects,'WaitForMultipleObjects',\ + WaitForMultipleObjectsEx,'WaitForMultipleObjectsEx',\ + WaitForSingleObject,'WaitForSingleObject',\ + WaitForSingleObjectEx,'WaitForSingleObjectEx',\ + WaitNamedPipeA,'WaitNamedPipeA',\ + WaitNamedPipeW,'WaitNamedPipeW',\ + WideCharToMultiByte,'WideCharToMultiByte',\ + WinExec,'WinExec',\ + WriteConsoleA,'WriteConsoleA',\ + WriteConsoleW,'WriteConsoleW',\ + WriteConsoleInputA,'WriteConsoleInputA',\ + WriteConsoleInputW,'WriteConsoleInputW',\ + WriteConsoleInputVDMA,'WriteConsoleInputVDMA',\ + WriteConsoleInputVDMW,'WriteConsoleInputVDMW',\ + WriteConsoleOutputA,'WriteConsoleOutputA',\ + WriteConsoleOutputW,'WriteConsoleOutputW',\ + WriteConsoleOutputAttribute,'WriteConsoleOutputAttribute',\ + WriteConsoleOutputCharacterA,'WriteConsoleOutputCharacterA',\ + WriteConsoleOutputCharacterW,'WriteConsoleOutputCharacterW',\ + WriteFile,'WriteFile',\ + WriteFileEx,'WriteFileEx',\ + WriteFileGather,'WriteFileGather',\ + WriteFileVlm,'WriteFileVlm',\ + WritePrivateProfileSectionA,'WritePrivateProfileSectionA',\ + WritePrivateProfileSectionW,'WritePrivateProfileSectionW',\ + WritePrivateProfileStringA,'WritePrivateProfileStringA',\ + WritePrivateProfileStringW,'WritePrivateProfileStringW',\ + WritePrivateProfileStructA,'WritePrivateProfileStructA',\ + WritePrivateProfileStructW,'WritePrivateProfileStructW',\ + WriteProcessMemory,'WriteProcessMemory',\ + WriteProcessMemoryVlm,'WriteProcessMemoryVlm',\ + WriteProfileSectionA,'WriteProfileSectionA',\ + WriteProfileSectionW,'WriteProfileSectionW',\ + WriteProfileStringA,'WriteProfileStringA',\ + WriteProfileStringW,'WriteProfileStringW',\ + WriteTapemark,'WriteTapemark',\ + _hread,'_hread',\ + _hwrite,'_hwrite',\ + _lclose,'_lclose',\ + _lcreat,'_lcreat',\ + _llseek,'_llseek',\ + _lopen,'_lopen',\ + _lread,'_lread',\ + _lwrite,'_lwrite',\ + lstrcatA,'lstrcatA',\ + lstrcatW,'lstrcatW',\ + lstrcmpA,'lstrcmpA',\ + lstrcmpW,'lstrcmpW',\ + lstrcmpiA,'lstrcmpiA',\ + lstrcmpiW,'lstrcmpiW',\ + lstrcpyA,'lstrcpyA',\ + lstrcpyW,'lstrcpyW',\ + lstrcpynA,'lstrcpynA',\ + lstrcpynW,'lstrcpynW',\ + lstrlenA,'lstrlenA',\ + lstrlenW,'lstrlenW' + +api AddAtom,\ + AddConsoleAlias,\ + BeginUpdateResource,\ + BuildCommDCB,\ + BuildCommDCBAndTimeouts,\ + CallNamedPipe,\ + CommConfigDialog,\ + CompareString,\ + CopyFile,\ + CopyFileEx,\ + CreateDirectory,\ + CreateDirectoryEx,\ + CreateEvent,\ + CreateFile,\ + CreateFileMapping,\ + CreateHardLink,\ + CreateJobObject,\ + CreateMailslot,\ + CreateMutex,\ + CreateNamedPipe,\ + CreateProcess,\ + CreateSemaphore,\ + CreateWaitableTimer,\ + DefineDosDevice,\ + DeleteFile,\ + EndUpdateResource,\ + EnumCalendarInfo,\ + EnumCalendarInfoEx,\ + EnumDateFormats,\ + EnumDateFormatsEx,\ + EnumResourceLanguages,\ + EnumResourceNames,\ + EnumResourceTypes,\ + EnumSystemCodePages,\ + EnumSystemLocales,\ + EnumTimeFormats,\ + ExpandEnvironmentStrings,\ + ExpungeConsoleCommandHistory,\ + FatalAppExit,\ + FillConsoleOutputCharacter,\ + FindAtom,\ + FindFirstChangeNotification,\ + FindFirstFile,\ + FindFirstFileEx,\ + FindNextFile,\ + FindResource,\ + FindResourceEx,\ + FoldString,\ + FormatMessage,\ + FreeEnvironmentStrings,\ + GetAtomName,\ + GetBinaryType,\ + GetCPInfoEx,\ + GetCommandLine,\ + GetCompressedFileSize,\ + GetComputerName,\ + GetConsoleAlias,\ + GetConsoleAliasExes,\ + GetConsoleAliasExesLength,\ + GetConsoleAliases,\ + GetConsoleAliasesLength,\ + GetConsoleCommandHistory,\ + GetConsoleCommandHistoryLength,\ + GetConsoleInputExeName,\ + GetConsoleKeyboardLayoutName,\ + GetConsoleTitle,\ + GetCurrencyFormat,\ + GetCurrentDirectory,\ + GetDateFormat,\ + GetDefaultCommConfig,\ + GetDiskFreeSpace,\ + GetDiskFreeSpaceEx,\ + GetDriveType,\ + GetEnvironmentStrings,\ + GetEnvironmentVariable,\ + GetFileAttributes,\ + GetFileAttributesEx,\ + GetFullPathName,\ + GetLocaleInfo,\ + GetLogicalDriveStrings,\ + GetLongPathName,\ + GetModuleFileName,\ + GetModuleHandle,\ + GetNamedPipeHandleState,\ + GetNumberFormat,\ + GetPrivateProfileInt,\ + GetPrivateProfileSection,\ + GetPrivateProfileSectionNames,\ + GetPrivateProfileString,\ + GetPrivateProfileStruct,\ + GetProfileInt,\ + GetProfileSection,\ + GetProfileString,\ + GetShortPathName,\ + GetStartupInfo,\ + GetStringType,\ + GetStringTypeEx,\ + GetSystemDirectory,\ + GetTempFileName,\ + GetTempPath,\ + GetTimeFormat,\ + GetVersionEx,\ + GetVolumeInformation,\ + GetWindowsDirectory,\ + GlobalAddAtom,\ + GlobalFindAtom,\ + GlobalGetAtomName,\ + IsBadStringPtr,\ + LCMapString,\ + LoadLibrary,\ + LoadLibraryEx,\ + MoveFile,\ + MoveFileEx,\ + MoveFileWithProgress,\ + OpenEvent,\ + OpenFileMapping,\ + OpenJobObject,\ + OpenMutex,\ + OpenSemaphore,\ + OpenWaitableTimer,\ + OutputDebugString,\ + PeekConsoleInput,\ + QueryDosDevice,\ + ReadConsole,\ + ReadConsoleInput,\ + ReadConsoleInputEx,\ + ReadConsoleOutput,\ + ReadConsoleOutputCharacter,\ + RemoveDirectory,\ + ScrollConsoleScreenBuffer,\ + SearchPath,\ + SetComputerName,\ + SetConsoleInputExeName,\ + SetConsoleNumberOfCommands,\ + SetConsoleTitle,\ + SetCurrentDirectory,\ + SetDefaultCommConfig,\ + SetEnvironmentVariable,\ + SetFileAttributes,\ + SetLocaleInfo,\ + SetVolumeLabel,\ + UpdateResource,\ + VerLanguageName,\ + WaitNamedPipe,\ + WriteConsole,\ + WriteConsoleInput,\ + WriteConsoleInputVDM,\ + WriteConsoleOutput,\ + WriteConsoleOutputCharacter,\ + WritePrivateProfileSection,\ + WritePrivateProfileString,\ + WritePrivateProfileStruct,\ + WriteProfileSection,\ + WriteProfileString,\ + lstrcat,\ + lstrcmp,\ + lstrcmpi,\ + lstrcpy,\ + lstrcpyn,\ + lstrlen diff --git a/toolchain/fasm2/include/api/shell32.inc b/toolchain/fasm2/include/api/shell32.inc new file mode 100644 index 0000000..1ca3a14 --- /dev/null +++ b/toolchain/fasm2/include/api/shell32.inc @@ -0,0 +1,167 @@ + +; SHELL32 API calls + +import shell32,\ + CheckEscapesA,'CheckEscapesA',\ + CheckEscapesW,'CheckEscapesW',\ + DoEnvironmentSubstA,'DoEnvironmentSubstA',\ + DoEnvironmentSubstW,'DoEnvironmentSubstW',\ + DragAcceptFiles,'DragAcceptFiles',\ + DragFinish,'DragFinish',\ + DragQueryFileA,'DragQueryFileA',\ + DragQueryFileW,'DragQueryFileW',\ + DragQueryPoint,'DragQueryPoint',\ + DuplicateIcon,'DuplicateIcon',\ + ExtractAssociatedIconA,'ExtractAssociatedIconA',\ + ExtractAssociatedIconW,'ExtractAssociatedIconW',\ + ExtractAssociatedIconExA,'ExtractAssociatedIconExA',\ + ExtractAssociatedIconExW,'ExtractAssociatedIconExW',\ + ExtractIconA,'ExtractIconA',\ + ExtractIconW,'ExtractIconW',\ + ExtractIconExA,'ExtractIconExA',\ + ExtractIconExW,'ExtractIconExW',\ + ExtractIconResInfoA,'ExtractIconResInfoA',\ + ExtractIconResInfoW,'ExtractIconResInfoW',\ + FindExeDlgProc,'FindExeDlgProc',\ + FindExecutableA,'FindExecutableA',\ + FindExecutableW,'FindExecutableW',\ + FreeIconList,'FreeIconList',\ + InternalExtractIconListA,'InternalExtractIconListA',\ + InternalExtractIconListW,'InternalExtractIconListW',\ + RealShellExecuteA,'RealShellExecuteA',\ + RealShellExecuteW,'RealShellExecuteW',\ + RealShellExecuteExA,'RealShellExecuteExA',\ + RealShellExecuteExW,'RealShellExecuteExW',\ + RegenerateUserEnvironment,'RegenerateUserEnvironment',\ + SHAddToRecentDocs,'SHAddToRecentDocs',\ + SHAppBarMessage,'SHAppBarMessage',\ + SHBrowseForFolderA,'SHBrowseForFolderA',\ + SHBrowseForFolderW,'SHBrowseForFolderW',\ + SHChangeNotify,'SHChangeNotify',\ + SHEmptyRecycleBinA,'SHEmptyRecycleBinA',\ + SHEmptyRecycleBinW,'SHEmptyRecycleBinW',\ + SHFileOperationA,'SHFileOperationA',\ + SHFileOperationW,'SHFileOperationW',\ + SHFormatDrive,'SHFormatDrive',\ + SHFreeNameMappings,'SHFreeNameMappings',\ + SHGetDataFromIDListA,'SHGetDataFromIDListA',\ + SHGetDataFromIDListW,'SHGetDataFromIDListW',\ + SHGetDesktopFolder,'SHGetDesktopFolder',\ + SHGetDiskFreeSpaceA,'SHGetDiskFreeSpaceA',\ + SHGetDiskFreeSpaceW,'SHGetDiskFreeSpaceW',\ + SHGetFileInfoA,'SHGetFileInfoA',\ + SHGetFileInfoW,'SHGetFileInfoW',\ + SHGetInstanceExplorer,'SHGetInstanceExplorer',\ + SHGetMalloc,'SHGetMalloc',\ + SHGetNewLinkInfo,'SHGetNewLinkInfo',\ + SHGetPathFromIDListA,'SHGetPathFromIDListA',\ + SHGetPathFromIDListW,'SHGetPathFromIDListW',\ + SHGetSettings,'SHGetSettings',\ + SHGetSpecialFolderLocation,'SHGetSpecialFolderLocation',\ + SHGetSpecialFolderPathA,'SHGetSpecialFolderPathA',\ + SHGetSpecialFolderPathW,'SHGetSpecialFolderPathW',\ + SHInvokePrinterCommandA,'SHInvokePrinterCommandA',\ + SHInvokePrinterCommandW,'SHInvokePrinterCommandW',\ + SHLoadInProc,'SHLoadInProc',\ + SHQueryRecycleBinA,'SHQueryRecycleBinA',\ + SHQueryRecycleBinW,'SHQueryRecycleBinW',\ + SHUpdateRecycleBinIcon,'SHUpdateRecycleBinIcon',\ + SheChangeDirA,'SheChangeDirA',\ + SheChangeDirW,'SheChangeDirW',\ + SheChangeDirExA,'SheChangeDirExA',\ + SheChangeDirExW,'SheChangeDirExW',\ + SheFullPathA,'SheFullPathA',\ + SheFullPathW,'SheFullPathW',\ + SheGetCurDrive,'SheGetCurDrive',\ + SheGetDirA,'SheGetDirA',\ + SheGetDirW,'SheGetDirW',\ + SheRemoveQuotesA,'SheRemoveQuotesA',\ + SheRemoveQuotesW,'SheRemoveQuotesW',\ + SheSetCurDrive,'SheSetCurDrive',\ + SheShortenPathA,'SheShortenPathA',\ + SheShortenPathW,'SheShortenPathW',\ + ShellAboutA,'ShellAboutA',\ + ShellAboutW,'ShellAboutW',\ + ShellExecuteA,'ShellExecuteA',\ + ShellExecuteW,'ShellExecuteW',\ + ShellExecuteExA,'ShellExecuteExA',\ + ShellExecuteExW,'ShellExecuteExW',\ + ShellHookProc,'ShellHookProc',\ + Shell_NotifyIconA,'Shell_NotifyIconA',\ + Shell_NotifyIconW,'Shell_NotifyIconW',\ + StrChrA,'StrChrA',\ + StrChrW,'StrChrW',\ + StrChrIA,'StrChrIA',\ + StrChrIW,'StrChrIW',\ + StrCmpNA,'StrCmpNA',\ + StrCmpNW,'StrCmpNW',\ + StrCmpNIA,'StrCmpNIA',\ + StrCmpNIW,'StrCmpNIW',\ + StrCpyNA,'StrCpyNA',\ + StrCpyNW,'StrCpyNW',\ + StrNCmpA,'StrNCmpA',\ + StrNCmpW,'StrNCmpW',\ + StrNCmpIA,'StrNCmpIA',\ + StrNCmpIW,'StrNCmpIW',\ + StrNCpyA,'StrNCpyA',\ + StrNCpyW,'StrNCpyW',\ + StrRChrA,'StrRChrA',\ + StrRChrW,'StrRChrW',\ + StrRChrIA,'StrRChrIA',\ + StrRChrIW,'StrRChrIW',\ + StrRStrA,'StrRStrA',\ + StrRStrW,'StrRStrW',\ + StrRStrIA,'StrRStrIA',\ + StrRStrIW,'StrRStrIW',\ + StrStrA,'StrStrA',\ + StrStrW,'StrStrW',\ + StrStrIA,'StrStrIA',\ + StrStrIW,'StrStrIW',\ + WOWShellExecute,'WOWShellExecute' + +api CheckEscapes,\ + DoEnvironmentSubst,\ + DragQueryFile,\ + ExtractAssociatedIcon,\ + ExtractAssociatedIconEx,\ + ExtractIcon,\ + ExtractIconEx,\ + ExtractIconResInfo,\ + FindExecutable,\ + InternalExtractIconList,\ + RealShellExecute,\ + RealShellExecuteEx,\ + SHBrowseForFolder,\ + SHEmptyRecycleBin,\ + SHFileOperation,\ + SHGetDataFromIDList,\ + SHGetDiskFreeSpace,\ + SHGetFileInfo,\ + SHGetPathFromIDList,\ + SHGetSpecialFolderPath,\ + SHInvokePrinterCommand,\ + SHQueryRecycleBin,\ + SheChangeDir,\ + SheChangeDirEx,\ + SheFullPath,\ + SheGetDir,\ + SheRemoveQuotes,\ + SheShortenPath,\ + ShellAbout,\ + ShellExecute,\ + ShellExecuteEx,\ + Shell_NotifyIcon,\ + StrChr,\ + StrChrI,\ + StrCmpN,\ + StrCmpNI,\ + StrCpyN,\ + StrNCmp,\ + StrNCmpI,\ + StrNCpy,\ + StrRChr,\ + StrRChrI,\ + StrRStr,\ + StrRStrI,\ + StrStr,\ + StrStrI diff --git a/toolchain/fasm2/include/api/user32.inc b/toolchain/fasm2/include/api/user32.inc new file mode 100644 index 0000000..bffafa3 --- /dev/null +++ b/toolchain/fasm2/include/api/user32.inc @@ -0,0 +1,756 @@ + +; USER32 API calls + +import user32,\ + ActivateKeyboardLayout,'ActivateKeyboardLayout',\ + AdjustWindowRect,'AdjustWindowRect',\ + AdjustWindowRectEx,'AdjustWindowRectEx',\ + AnimateWindow,'AnimateWindow',\ + AnyPopup,'AnyPopup',\ + AppendMenuA,'AppendMenuA',\ + AppendMenuW,'AppendMenuW',\ + ArrangeIconicWindows,'ArrangeIconicWindows',\ + AttachThreadInput,'AttachThreadInput',\ + BeginDeferWindowPos,'BeginDeferWindowPos',\ + BeginPaint,'BeginPaint',\ + BlockInput,'BlockInput',\ + BringWindowToTop,'BringWindowToTop',\ + BroadcastSystemMessageA,'BroadcastSystemMessageA',\ + BroadcastSystemMessageW,'BroadcastSystemMessageW',\ + CallMsgFilterA,'CallMsgFilterA',\ + CallMsgFilterW,'CallMsgFilterW',\ + CallNextHookEx,'CallNextHookEx',\ + CallWindowProcA,'CallWindowProcA',\ + CallWindowProcW,'CallWindowProcW',\ + CascadeChildWindows,'CascadeChildWindows',\ + CascadeWindows,'CascadeWindows',\ + ChangeClipboardChain,'ChangeClipboardChain',\ + ChangeDisplaySettingsA,'ChangeDisplaySettingsA',\ + ChangeDisplaySettingsW,'ChangeDisplaySettingsW',\ + ChangeDisplaySettingsExA,'ChangeDisplaySettingsExA',\ + ChangeDisplaySettingsExW,'ChangeDisplaySettingsExW',\ + ChangeMenuA,'ChangeMenuA',\ + ChangeMenuW,'ChangeMenuW',\ + CharLowerA,'CharLowerA',\ + CharLowerW,'CharLowerW',\ + CharLowerBuffA,'CharLowerBuffA',\ + CharLowerBuffW,'CharLowerBuffW',\ + CharNextA,'CharNextA',\ + CharNextW,'CharNextW',\ + CharNextExA,'CharNextExA',\ + CharNextExW,'CharNextExW',\ + CharPrevA,'CharPrevA',\ + CharPrevW,'CharPrevW',\ + CharPrevExA,'CharPrevExA',\ + CharPrevExW,'CharPrevExW',\ + CharToOemA,'CharToOemA',\ + CharToOemW,'CharToOemW',\ + CharToOemBuffA,'CharToOemBuffA',\ + CharToOemBuffW,'CharToOemBuffW',\ + CharUpperA,'CharUpperA',\ + CharUpperW,'CharUpperW',\ + CharUpperBuffA,'CharUpperBuffA',\ + CharUpperBuffW,'CharUpperBuffW',\ + CheckDlgButton,'CheckDlgButton',\ + CheckMenuItem,'CheckMenuItem',\ + CheckMenuRadioItem,'CheckMenuRadioItem',\ + CheckRadioButton,'CheckRadioButton',\ + ChildWindowFromPoint,'ChildWindowFromPoint',\ + ChildWindowFromPointEx,'ChildWindowFromPointEx',\ + ClientToScreen,'ClientToScreen',\ + ClipCursor,'ClipCursor',\ + CloseClipboard,'CloseClipboard',\ + CloseDesktop,'CloseDesktop',\ + CloseWindow,'CloseWindow',\ + CloseWindowStation,'CloseWindowStation',\ + CopyAcceleratorTableA,'CopyAcceleratorTableA',\ + CopyAcceleratorTableW,'CopyAcceleratorTableW',\ + CopyIcon,'CopyIcon',\ + CopyImage,'CopyImage',\ + CopyRect,'CopyRect',\ + CountClipboardFormats,'CountClipboardFormats',\ + CreateAcceleratorTableA,'CreateAcceleratorTableA',\ + CreateAcceleratorTableW,'CreateAcceleratorTableW',\ + CreateCaret,'CreateCaret',\ + CreateCursor,'CreateCursor',\ + CreateDesktopA,'CreateDesktopA',\ + CreateDesktopW,'CreateDesktopW',\ + CreateDialogIndirectParamA,'CreateDialogIndirectParamA',\ + CreateDialogIndirectParamW,'CreateDialogIndirectParamW',\ + CreateDialogParamA,'CreateDialogParamA',\ + CreateDialogParamW,'CreateDialogParamW',\ + CreateIcon,'CreateIcon',\ + CreateIconFromResource,'CreateIconFromResource',\ + CreateIconFromResourceEx,'CreateIconFromResourceEx',\ + CreateIconIndirect,'CreateIconIndirect',\ + CreateMDIWindowA,'CreateMDIWindowA',\ + CreateMDIWindowW,'CreateMDIWindowW',\ + CreateMenu,'CreateMenu',\ + CreatePopupMenu,'CreatePopupMenu',\ + CreateWindowExA,'CreateWindowExA',\ + CreateWindowExW,'CreateWindowExW',\ + CreateWindowStationA,'CreateWindowStationA',\ + CreateWindowStationW,'CreateWindowStationW',\ + DdeAbandonTransaction,'DdeAbandonTransaction',\ + DdeAccessData,'DdeAccessData',\ + DdeAddData,'DdeAddData',\ + DdeClientTransaction,'DdeClientTransaction',\ + DdeCmpStringHandles,'DdeCmpStringHandles',\ + DdeConnect,'DdeConnect',\ + DdeConnectList,'DdeConnectList',\ + DdeCreateDataHandle,'DdeCreateDataHandle',\ + DdeCreateStringHandleA,'DdeCreateStringHandleA',\ + DdeCreateStringHandleW,'DdeCreateStringHandleW',\ + DdeDisconnect,'DdeDisconnect',\ + DdeDisconnectList,'DdeDisconnectList',\ + DdeEnableCallback,'DdeEnableCallback',\ + DdeFreeDataHandle,'DdeFreeDataHandle',\ + DdeFreeStringHandle,'DdeFreeStringHandle',\ + DdeGetData,'DdeGetData',\ + DdeGetLastError,'DdeGetLastError',\ + DdeGetQualityOfService,'DdeGetQualityOfService',\ + DdeImpersonateClient,'DdeImpersonateClient',\ + DdeInitializeA,'DdeInitializeA',\ + DdeInitializeW,'DdeInitializeW',\ + DdeKeepStringHandle,'DdeKeepStringHandle',\ + DdeNameService,'DdeNameService',\ + DdePostAdvise,'DdePostAdvise',\ + DdeQueryConvInfo,'DdeQueryConvInfo',\ + DdeQueryNextServer,'DdeQueryNextServer',\ + DdeQueryStringA,'DdeQueryStringA',\ + DdeQueryStringW,'DdeQueryStringW',\ + DdeReconnect,'DdeReconnect',\ + DdeSetQualityOfService,'DdeSetQualityOfService',\ + DdeSetUserHandle,'DdeSetUserHandle',\ + DdeUnaccessData,'DdeUnaccessData',\ + DdeUninitialize,'DdeUninitialize',\ + DefDlgProcA,'DefDlgProcA',\ + DefDlgProcW,'DefDlgProcW',\ + DefFrameProcA,'DefFrameProcA',\ + DefFrameProcW,'DefFrameProcW',\ + DefMDIChildProcA,'DefMDIChildProcA',\ + DefMDIChildProcW,'DefMDIChildProcW',\ + DefWindowProcA,'DefWindowProcA',\ + DefWindowProcW,'DefWindowProcW',\ + DeferWindowPos,'DeferWindowPos',\ + DeleteMenu,'DeleteMenu',\ + DestroyAcceleratorTable,'DestroyAcceleratorTable',\ + DestroyCaret,'DestroyCaret',\ + DestroyCursor,'DestroyCursor',\ + DestroyIcon,'DestroyIcon',\ + DestroyMenu,'DestroyMenu',\ + DestroyWindow,'DestroyWindow',\ + DialogBoxIndirectParamA,'DialogBoxIndirectParamA',\ + DialogBoxIndirectParamW,'DialogBoxIndirectParamW',\ + DialogBoxParamA,'DialogBoxParamA',\ + DialogBoxParamW,'DialogBoxParamW',\ + DispatchMessageA,'DispatchMessageA',\ + DispatchMessageW,'DispatchMessageW',\ + DlgDirListA,'DlgDirListA',\ + DlgDirListW,'DlgDirListW',\ + DlgDirListComboBoxA,'DlgDirListComboBoxA',\ + DlgDirListComboBoxW,'DlgDirListComboBoxW',\ + DlgDirSelectComboBoxExA,'DlgDirSelectComboBoxExA',\ + DlgDirSelectComboBoxExW,'DlgDirSelectComboBoxExW',\ + DlgDirSelectExA,'DlgDirSelectExA',\ + DlgDirSelectExW,'DlgDirSelectExW',\ + DragDetect,'DragDetect',\ + DragObject,'DragObject',\ + DrawAnimatedRects,'DrawAnimatedRects',\ + DrawCaption,'DrawCaption',\ + DrawEdge,'DrawEdge',\ + DrawFocusRect,'DrawFocusRect',\ + DrawFrame,'DrawFrame',\ + DrawFrameControl,'DrawFrameControl',\ + DrawIcon,'DrawIcon',\ + DrawIconEx,'DrawIconEx',\ + DrawMenuBar,'DrawMenuBar',\ + DrawStateA,'DrawStateA',\ + DrawStateW,'DrawStateW',\ + DrawTextA,'DrawTextA',\ + DrawTextW,'DrawTextW',\ + DrawTextExA,'DrawTextExA',\ + DrawTextExW,'DrawTextExW',\ + EditWndProc,'EditWndProc',\ + EmptyClipboard,'EmptyClipboard',\ + EnableMenuItem,'EnableMenuItem',\ + EnableScrollBar,'EnableScrollBar',\ + EnableWindow,'EnableWindow',\ + EndDeferWindowPos,'EndDeferWindowPos',\ + EndDialog,'EndDialog',\ + EndMenu,'EndMenu',\ + EndPaint,'EndPaint',\ + EnumChildWindows,'EnumChildWindows',\ + EnumClipboardFormats,'EnumClipboardFormats',\ + EnumDesktopWindows,'EnumDesktopWindows',\ + EnumDesktopsA,'EnumDesktopsA',\ + EnumDesktopsW,'EnumDesktopsW',\ + EnumDisplayMonitors,'EnumDisplayMonitors',\ + EnumDisplaySettingsA,'EnumDisplaySettingsA',\ + EnumDisplaySettingsW,'EnumDisplaySettingsW',\ + EnumDisplaySettingsExA,'EnumDisplaySettingsExA',\ + EnumDisplaySettingsExW,'EnumDisplaySettingsExW',\ + EnumPropsA,'EnumPropsA',\ + EnumPropsW,'EnumPropsW',\ + EnumPropsExA,'EnumPropsExA',\ + EnumPropsExW,'EnumPropsExW',\ + EnumThreadWindows,'EnumThreadWindows',\ + EnumWindowStationsA,'EnumWindowStationsA',\ + EnumWindowStationsW,'EnumWindowStationsW',\ + EnumWindows,'EnumWindows',\ + EqualRect,'EqualRect',\ + ExcludeUpdateRgn,'ExcludeUpdateRgn',\ + ExitWindowsEx,'ExitWindowsEx',\ + FillRect,'FillRect',\ + FindWindowA,'FindWindowA',\ + FindWindowW,'FindWindowW',\ + FindWindowExA,'FindWindowExA',\ + FindWindowExW,'FindWindowExW',\ + FlashWindow,'FlashWindow',\ + FrameRect,'FrameRect',\ + FreeDDElParam,'FreeDDElParam',\ + GetActiveWindow,'GetActiveWindow',\ + GetAltTabInfoA,'GetAltTabInfoA',\ + GetAltTabInfoW,'GetAltTabInfoW',\ + GetAncestor,'GetAncestor',\ + GetAsyncKeyState,'GetAsyncKeyState',\ + GetCapture,'GetCapture',\ + GetCaretBlinkTime,'GetCaretBlinkTime',\ + GetCaretPos,'GetCaretPos',\ + GetClassInfoA,'GetClassInfoA',\ + GetClassInfoW,'GetClassInfoW',\ + GetClassInfoExA,'GetClassInfoExA',\ + GetClassInfoExW,'GetClassInfoExW',\ + GetClassLongA,'GetClassLongA',\ + GetClassLongW,'GetClassLongW',\ + GetClassNameA,'GetClassNameA',\ + GetClassNameW,'GetClassNameW',\ + GetClassWord,'GetClassWord',\ + GetClientRect,'GetClientRect',\ + GetClipCursor,'GetClipCursor',\ + GetClipboardData,'GetClipboardData',\ + GetClipboardFormatNameA,'GetClipboardFormatNameA',\ + GetClipboardFormatNameW,'GetClipboardFormatNameW',\ + GetClipboardSequenceNumberA,'GetClipboardSequenceNumberA',\ + GetClipboardSequenceNumberW,'GetClipboardSequenceNumberW',\ + GetClipboardViewer,'GetClipboardViewer',\ + GetComboBoxInfo,'GetComboBoxInfo',\ + GetCursor,'GetCursor',\ + GetCursorInfo,'GetCursorInfo',\ + GetCursorPos,'GetCursorPos',\ + GetDC,'GetDC',\ + GetDCEx,'GetDCEx',\ + GetDesktopWindow,'GetDesktopWindow',\ + GetDialogBaseUnits,'GetDialogBaseUnits',\ + GetDlgCtrlID,'GetDlgCtrlID',\ + GetDlgItem,'GetDlgItem',\ + GetDlgItemInt,'GetDlgItemInt',\ + GetDlgItemTextA,'GetDlgItemTextA',\ + GetDlgItemTextW,'GetDlgItemTextW',\ + GetDoubleClickTime,'GetDoubleClickTime',\ + GetFocus,'GetFocus',\ + GetForegroundWindow,'GetForegroundWindow',\ + GetGUIThreadInfo,'GetGUIThreadInfo',\ + GetGuiResources,'GetGuiResources',\ + GetIconInfo,'GetIconInfo',\ + GetInputDesktop,'GetInputDesktop',\ + GetInputState,'GetInputState',\ + GetKBCodePage,'GetKBCodePage',\ + GetKeyNameTextA,'GetKeyNameTextA',\ + GetKeyNameTextW,'GetKeyNameTextW',\ + GetKeyState,'GetKeyState',\ + GetKeyboardLayout,'GetKeyboardLayout',\ + GetKeyboardLayoutList,'GetKeyboardLayoutList',\ + GetKeyboardLayoutNameA,'GetKeyboardLayoutNameA',\ + GetKeyboardLayoutNameW,'GetKeyboardLayoutNameW',\ + GetKeyboardState,'GetKeyboardState',\ + GetKeyboardType,'GetKeyboardType',\ + GetLastActivePopup,'GetLastActivePopup',\ + GetLastInputInfo,'GetLastInputInfo',\ + GetLayeredWindowAttributes,'GetLayeredWindowAttributes',\ + GetListBoxInfo,'GetListBoxInfo',\ + GetMenu,'GetMenu',\ + GetMenuBarInfo,'GetMenuBarInfo',\ + GetMenuCheckMarkDimensions,'GetMenuCheckMarkDimensions',\ + GetMenuContextHelpId,'GetMenuContextHelpId',\ + GetMenuDefaultItem,'GetMenuDefaultItem',\ + GetMenuInfo,'GetMenuInfo',\ + GetMenuItemCount,'GetMenuItemCount',\ + GetMenuItemID,'GetMenuItemID',\ + GetMenuItemInfoA,'GetMenuItemInfoA',\ + GetMenuItemInfoW,'GetMenuItemInfoW',\ + GetMenuItemRect,'GetMenuItemRect',\ + GetMenuState,'GetMenuState',\ + GetMenuStringA,'GetMenuStringA',\ + GetMenuStringW,'GetMenuStringW',\ + GetMessageA,'GetMessageA',\ + GetMessageW,'GetMessageW',\ + GetMessageExtraInfo,'GetMessageExtraInfo',\ + GetMessagePos,'GetMessagePos',\ + GetMessageTime,'GetMessageTime',\ + GetMonitorInfoA,'GetMonitorInfoA',\ + GetMonitorInfoW,'GetMonitorInfoW',\ + GetMouseMovePoints,'GetMouseMovePoints',\ + GetNextDlgGroupItem,'GetNextDlgGroupItem',\ + GetNextDlgTabItem,'GetNextDlgTabItem',\ + GetOpenClipboardWindow,'GetOpenClipboardWindow',\ + GetParent,'GetParent',\ + GetPriorityClipboardFormat,'GetPriorityClipboardFormat',\ + GetProcessWindowStation,'GetProcessWindowStation',\ + GetPropA,'GetPropA',\ + GetPropW,'GetPropW',\ + GetQueueStatus,'GetQueueStatus',\ + GetScrollBarInfo,'GetScrollBarInfo',\ + GetScrollInfo,'GetScrollInfo',\ + GetScrollPos,'GetScrollPos',\ + GetScrollRange,'GetScrollRange',\ + GetShellWindow,'GetShellWindow',\ + GetSubMenu,'GetSubMenu',\ + GetSysColor,'GetSysColor',\ + GetSysColorBrush,'GetSysColorBrush',\ + GetSystemMenu,'GetSystemMenu',\ + GetSystemMetrics,'GetSystemMetrics',\ + GetTabbedTextExtentA,'GetTabbedTextExtentA',\ + GetTabbedTextExtentW,'GetTabbedTextExtentW',\ + GetThreadDesktop,'GetThreadDesktop',\ + GetTitleBarInfo,'GetTitleBarInfo',\ + GetTopWindow,'GetTopWindow',\ + GetUpdateRect,'GetUpdateRect',\ + GetUpdateRgn,'GetUpdateRgn',\ + GetUserObjectInformationA,'GetUserObjectInformationA',\ + GetUserObjectInformationW,'GetUserObjectInformationW',\ + GetUserObjectSecurity,'GetUserObjectSecurity',\ + GetWindow,'GetWindow',\ + GetWindowContextHelpId,'GetWindowContextHelpId',\ + GetWindowDC,'GetWindowDC',\ + GetWindowInfo,'GetWindowInfo',\ + GetWindowLongA,'GetWindowLongA',\ + GetWindowLongW,'GetWindowLongW',\ + GetWindowLongPtrA,'GetWindowLongPtrA',\ + GetWindowLongPtrW,'GetWindowLongPtrW',\ + GetWindowModuleFileNameA,'GetWindowModuleFileNameA',\ + GetWindowModuleFileNameW,'GetWindowModuleFileNameW',\ + GetWindowPlacement,'GetWindowPlacement',\ + GetWindowRect,'GetWindowRect',\ + GetWindowRgn,'GetWindowRgn',\ + GetWindowTextA,'GetWindowTextA',\ + GetWindowTextW,'GetWindowTextW',\ + GetWindowTextLengthA,'GetWindowTextLengthA',\ + GetWindowTextLengthW,'GetWindowTextLengthW',\ + GetWindowThreadProcessId,'GetWindowThreadProcessId',\ + GetWindowWord,'GetWindowWord',\ + GrayStringA,'GrayStringA',\ + GrayStringW,'GrayStringW',\ + HideCaret,'HideCaret',\ + HiliteMenuItem,'HiliteMenuItem',\ + IMPGetIMEA,'IMPGetIMEA',\ + IMPGetIMEW,'IMPGetIMEW',\ + IMPQueryIMEA,'IMPQueryIMEA',\ + IMPQueryIMEW,'IMPQueryIMEW',\ + IMPSetIMEA,'IMPSetIMEA',\ + IMPSetIMEW,'IMPSetIMEW',\ + ImpersonateDdeClientWindow,'ImpersonateDdeClientWindow',\ + InSendMessage,'InSendMessage',\ + InSendMessageEx,'InSendMessageEx',\ + InflateRect,'InflateRect',\ + InsertMenuA,'InsertMenuA',\ + InsertMenuW,'InsertMenuW',\ + InsertMenuItemA,'InsertMenuItemA',\ + InsertMenuItemW,'InsertMenuItemW',\ + IntersectRect,'IntersectRect',\ + InvalidateRect,'InvalidateRect',\ + InvalidateRgn,'InvalidateRgn',\ + InvertRect,'InvertRect',\ + IsCharAlphaA,'IsCharAlphaA',\ + IsCharAlphaW,'IsCharAlphaW',\ + IsCharAlphaNumericA,'IsCharAlphaNumericA',\ + IsCharAlphaNumericW,'IsCharAlphaNumericW',\ + IsCharLowerA,'IsCharLowerA',\ + IsCharLowerW,'IsCharLowerW',\ + IsCharUpperA,'IsCharUpperA',\ + IsCharUpperW,'IsCharUpperW',\ + IsChild,'IsChild',\ + IsClipboardFormatAvailable,'IsClipboardFormatAvailable',\ + IsDialogMessageA,'IsDialogMessageA',\ + IsDialogMessageW,'IsDialogMessageW',\ + IsDlgButtonChecked,'IsDlgButtonChecked',\ + IsIconic,'IsIconic',\ + IsMenu,'IsMenu',\ + IsRectEmpty,'IsRectEmpty',\ + IsWindow,'IsWindow',\ + IsWindowEnabled,'IsWindowEnabled',\ + IsWindowUnicode,'IsWindowUnicode',\ + IsWindowVisible,'IsWindowVisible',\ + IsZoomed,'IsZoomed',\ + KillSystemTimer,'KillSystemTimer',\ + KillTimer,'KillTimer',\ + LoadAcceleratorsA,'LoadAcceleratorsA',\ + LoadAcceleratorsW,'LoadAcceleratorsW',\ + LoadBitmapA,'LoadBitmapA',\ + LoadBitmapW,'LoadBitmapW',\ + LoadCursorA,'LoadCursorA',\ + LoadCursorW,'LoadCursorW',\ + LoadCursorFromFileA,'LoadCursorFromFileA',\ + LoadCursorFromFileW,'LoadCursorFromFileW',\ + LoadIconA,'LoadIconA',\ + LoadIconW,'LoadIconW',\ + LoadImageA,'LoadImageA',\ + LoadImageW,'LoadImageW',\ + LoadKeyboardLayoutA,'LoadKeyboardLayoutA',\ + LoadKeyboardLayoutW,'LoadKeyboardLayoutW',\ + LoadMenuA,'LoadMenuA',\ + LoadMenuW,'LoadMenuW',\ + LoadMenuIndirectA,'LoadMenuIndirectA',\ + LoadMenuIndirectW,'LoadMenuIndirectW',\ + LoadStringA,'LoadStringA',\ + LoadStringW,'LoadStringW',\ + LockWindowUpdate,'LockWindowUpdate',\ + LockWorkStation,'LockWorkStation',\ + LookupIconIdFromDirectory,'LookupIconIdFromDirectory',\ + LookupIconIdFromDirectoryEx,'LookupIconIdFromDirectoryEx',\ + MapDialogRect,'MapDialogRect',\ + MapVirtualKeyA,'MapVirtualKeyA',\ + MapVirtualKeyW,'MapVirtualKeyW',\ + MapVirtualKeyExA,'MapVirtualKeyExA',\ + MapVirtualKeyExW,'MapVirtualKeyExW',\ + MapWindowPoints,'MapWindowPoints',\ + MenuItemFromPoint,'MenuItemFromPoint',\ + MessageBeep,'MessageBeep',\ + MessageBoxA,'MessageBoxA',\ + MessageBoxW,'MessageBoxW',\ + MessageBoxExA,'MessageBoxExA',\ + MessageBoxExW,'MessageBoxExW',\ + MessageBoxIndirectA,'MessageBoxIndirectA',\ + MessageBoxIndirectW,'MessageBoxIndirectW',\ + ModifyMenuA,'ModifyMenuA',\ + ModifyMenuW,'ModifyMenuW',\ + MonitorFromPoint,'MonitorFromPoint',\ + MonitorFromRect,'MonitorFromRect',\ + MonitorFromWindow,'MonitorFromWindow',\ + MoveWindow,'MoveWindow',\ + MsgWaitForMultipleObjects,'MsgWaitForMultipleObjects',\ + MsgWaitForMultipleObjectsEx,'MsgWaitForMultipleObjectsEx',\ + NotifyWinEvent,'NotifyWinEvent',\ + OemKeyScan,'OemKeyScan',\ + OemToCharA,'OemToCharA',\ + OemToCharW,'OemToCharW',\ + OemToCharBuffA,'OemToCharBuffA',\ + OemToCharBuffW,'OemToCharBuffW',\ + OffsetRect,'OffsetRect',\ + OpenClipboard,'OpenClipboard',\ + OpenDesktopA,'OpenDesktopA',\ + OpenDesktopW,'OpenDesktopW',\ + OpenIcon,'OpenIcon',\ + OpenInputDesktop,'OpenInputDesktop',\ + OpenWindowStationA,'OpenWindowStationA',\ + OpenWindowStationW,'OpenWindowStationW',\ + PackDDElParam,'PackDDElParam',\ + PaintDesktop,'PaintDesktop',\ + PeekMessageA,'PeekMessageA',\ + PeekMessageW,'PeekMessageW',\ + PostMessageA,'PostMessageA',\ + PostMessageW,'PostMessageW',\ + PostQuitMessage,'PostQuitMessage',\ + PostThreadMessageA,'PostThreadMessageA',\ + PostThreadMessageW,'PostThreadMessageW',\ + PtInRect,'PtInRect',\ + RealChildWindowFromPoint,'RealChildWindowFromPoint',\ + RealGetWindowClassA,'RealGetWindowClassA',\ + RealGetWindowClassW,'RealGetWindowClassW',\ + RedrawWindow,'RedrawWindow',\ + RegisterClassA,'RegisterClassA',\ + RegisterClassW,'RegisterClassW',\ + RegisterClassExA,'RegisterClassExA',\ + RegisterClassExW,'RegisterClassExW',\ + RegisterClipboardFormatA,'RegisterClipboardFormatA',\ + RegisterClipboardFormatW,'RegisterClipboardFormatW',\ + RegisterDeviceNotificationA,'RegisterDeviceNotificationA',\ + RegisterDeviceNotificationW,'RegisterDeviceNotificationW',\ + RegisterHotKey,'RegisterHotKey',\ + RegisterWindowMessageA,'RegisterWindowMessageA',\ + RegisterWindowMessageW,'RegisterWindowMessageW',\ + ReleaseCapture,'ReleaseCapture',\ + ReleaseDC,'ReleaseDC',\ + RemoveMenu,'RemoveMenu',\ + RemovePropA,'RemovePropA',\ + RemovePropW,'RemovePropW',\ + ReplyMessage,'ReplyMessage',\ + ReuseDDElParam,'ReuseDDElParam',\ + ScreenToClient,'ScreenToClient',\ + ScrollChildren,'ScrollChildren',\ + ScrollDC,'ScrollDC',\ + ScrollWindow,'ScrollWindow',\ + ScrollWindowEx,'ScrollWindowEx',\ + SendDlgItemMessageA,'SendDlgItemMessageA',\ + SendDlgItemMessageW,'SendDlgItemMessageW',\ + SendIMEMessageExA,'SendIMEMessageExA',\ + SendIMEMessageExW,'SendIMEMessageExW',\ + SendInput,'SendInput',\ + SendMessageA,'SendMessageA',\ + SendMessageW,'SendMessageW',\ + SendMessageCallbackA,'SendMessageCallbackA',\ + SendMessageCallbackW,'SendMessageCallbackW',\ + SendMessageTimeoutA,'SendMessageTimeoutA',\ + SendMessageTimeoutW,'SendMessageTimeoutW',\ + SendNotifyMessageA,'SendNotifyMessageA',\ + SendNotifyMessageW,'SendNotifyMessageW',\ + SetActiveWindow,'SetActiveWindow',\ + SetCapture,'SetCapture',\ + SetCaretBlinkTime,'SetCaretBlinkTime',\ + SetCaretPos,'SetCaretPos',\ + SetClassLongA,'SetClassLongA',\ + SetClassLongW,'SetClassLongW',\ + SetClassWord,'SetClassWord',\ + SetClipboardData,'SetClipboardData',\ + SetClipboardViewer,'SetClipboardViewer',\ + SetCursor,'SetCursor',\ + SetCursorPos,'SetCursorPos',\ + SetDebugErrorLevel,'SetDebugErrorLevel',\ + SetDeskWallpaper,'SetDeskWallpaper',\ + SetDlgItemInt,'SetDlgItemInt',\ + SetDlgItemTextA,'SetDlgItemTextA',\ + SetDlgItemTextW,'SetDlgItemTextW',\ + SetDoubleClickTime,'SetDoubleClickTime',\ + SetFocus,'SetFocus',\ + SetForegroundWindow,'SetForegroundWindow',\ + SetKeyboardState,'SetKeyboardState',\ + SetLastErrorEx,'SetLastErrorEx',\ + SetLayeredWindowAttributes,'SetLayeredWindowAttributes',\ + SetMenu,'SetMenu',\ + SetMenuContextHelpId,'SetMenuContextHelpId',\ + SetMenuDefaultItem,'SetMenuDefaultItem',\ + SetMenuInfo,'SetMenuInfo',\ + SetMenuItemBitmaps,'SetMenuItemBitmaps',\ + SetMenuItemInfoA,'SetMenuItemInfoA',\ + SetMenuItemInfoW,'SetMenuItemInfoW',\ + SetMessageExtraInfo,'SetMessageExtraInfo',\ + SetMessageQueue,'SetMessageQueue',\ + SetParent,'SetParent',\ + SetProcessWindowStation,'SetProcessWindowStation',\ + SetPropA,'SetPropA',\ + SetPropW,'SetPropW',\ + SetRect,'SetRect',\ + SetRectEmpty,'SetRectEmpty',\ + SetScrollInfo,'SetScrollInfo',\ + SetScrollPos,'SetScrollPos',\ + SetScrollRange,'SetScrollRange',\ + SetShellWindow,'SetShellWindow',\ + SetSysColors,'SetSysColors',\ + SetSystemCursor,'SetSystemCursor',\ + SetSystemMenu,'SetSystemMenu',\ + SetSystemTimer,'SetSystemTimer',\ + SetThreadDesktop,'SetThreadDesktop',\ + SetTimer,'SetTimer',\ + SetUserObjectInformationA,'SetUserObjectInformationA',\ + SetUserObjectInformationW,'SetUserObjectInformationW',\ + SetUserObjectSecurity,'SetUserObjectSecurity',\ + SetWinEventHook,'SetWinEventHook',\ + SetWindowContextHelpId,'SetWindowContextHelpId',\ + SetWindowLongA,'SetWindowLongA',\ + SetWindowLongW,'SetWindowLongW',\ + SetWindowPlacement,'SetWindowPlacement',\ + SetWindowPos,'SetWindowPos',\ + SetWindowRgn,'SetWindowRgn',\ + SetWindowTextA,'SetWindowTextA',\ + SetWindowTextW,'SetWindowTextW',\ + SetWindowWord,'SetWindowWord',\ + SetWindowsHookA,'SetWindowsHookA',\ + SetWindowsHookW,'SetWindowsHookW',\ + SetWindowsHookExA,'SetWindowsHookExA',\ + SetWindowsHookExW,'SetWindowsHookExW',\ + ShowCaret,'ShowCaret',\ + ShowCursor,'ShowCursor',\ + ShowOwnedPopups,'ShowOwnedPopups',\ + ShowScrollBar,'ShowScrollBar',\ + ShowWindow,'ShowWindow',\ + ShowWindowAsync,'ShowWindowAsync',\ + SubtractRect,'SubtractRect',\ + SwapMouseButton,'SwapMouseButton',\ + SwitchDesktop,'SwitchDesktop',\ + SystemParametersInfoA,'SystemParametersInfoA',\ + SystemParametersInfoW,'SystemParametersInfoW',\ + TabbedTextOutA,'TabbedTextOutA',\ + TabbedTextOutW,'TabbedTextOutW',\ + TileChildWindows,'TileChildWindows',\ + TileWindows,'TileWindows',\ + ToAscii,'ToAscii',\ + ToAsciiEx,'ToAsciiEx',\ + ToUnicode,'ToUnicode',\ + ToUnicodeEx,'ToUnicodeEx',\ + TrackMouseEvent,'TrackMouseEvent',\ + TrackPopupMenu,'TrackPopupMenu',\ + TrackPopupMenuEx,'TrackPopupMenuEx',\ + TranslateAcceleratorA,'TranslateAcceleratorA',\ + TranslateAcceleratorW,'TranslateAcceleratorW',\ + TranslateMDISysAccel,'TranslateMDISysAccel',\ + TranslateMessage,'TranslateMessage',\ + UnhookWinEvent,'UnhookWinEvent',\ + UnhookWindowsHook,'UnhookWindowsHook',\ + UnhookWindowsHookEx,'UnhookWindowsHookEx',\ + UnionRect,'UnionRect',\ + UnloadKeyboardLayout,'UnloadKeyboardLayout',\ + UnpackDDElParam,'UnpackDDElParam',\ + UnregisterClassA,'UnregisterClassA',\ + UnregisterClassW,'UnregisterClassW',\ + UnregisterDeviceNotification,'UnregisterDeviceNotification',\ + UnregisterHotKey,'UnregisterHotKey',\ + UpdateWindow,'UpdateWindow',\ + UserHandleGrantAccess,'UserHandleGrantAccess',\ + ValidateRect,'ValidateRect',\ + ValidateRgn,'ValidateRgn',\ + VkKeyScanA,'VkKeyScanA',\ + VkKeyScanW,'VkKeyScanW',\ + VkKeyScanExA,'VkKeyScanExA',\ + VkKeyScanExW,'VkKeyScanExW',\ + WINNLSEnableIME,'WINNLSEnableIME',\ + WINNLSGetEnableStatus,'WINNLSGetEnableStatus',\ + WINNLSGetIMEHotkey,'WINNLSGetIMEHotkey',\ + WaitForInputIdle,'WaitForInputIdle',\ + WaitMessage,'WaitMessage',\ + WinHelpA,'WinHelpA',\ + WinHelpW,'WinHelpW',\ + WindowFromDC,'WindowFromDC',\ + WindowFromPoint,'WindowFromPoint',\ + keybd_event,'keybd_event',\ + mouse_event,'mouse_event',\ + wsprintfA,'wsprintfA',\ + wsprintfW,'wsprintfW',\ + wvsprintfA,'wvsprintfA',\ + wvsprintfW,'wvsprintfW' + +api AppendMenu,\ + BroadcastSystemMessage,\ + CallMsgFilter,\ + CallWindowProc,\ + ChangeDisplaySettings,\ + ChangeDisplaySettingsEx,\ + ChangeMenu,\ + CharLower,\ + CharLowerBuff,\ + CharNext,\ + CharNextEx,\ + CharPrev,\ + CharPrevEx,\ + CharToOem,\ + CharToOemBuff,\ + CharUpper,\ + CharUpperBuff,\ + CopyAcceleratorTable,\ + CreateAcceleratorTable,\ + CreateDesktop,\ + CreateDialogIndirectParam,\ + CreateDialogParam,\ + CreateMDIWindow,\ + CreateWindowEx,\ + CreateWindowStation,\ + DdeCreateStringHandle,\ + DdeInitialize,\ + DdeQueryString,\ + DefDlgProc,\ + DefFrameProc,\ + DefMDIChildProc,\ + DefWindowProc,\ + DialogBoxIndirectParam,\ + DialogBoxParam,\ + DispatchMessage,\ + DlgDirList,\ + DlgDirListComboBox,\ + DlgDirSelectComboBoxEx,\ + DlgDirSelectEx,\ + DrawState,\ + DrawText,\ + DrawTextEx,\ + EnumDesktops,\ + EnumDisplaySettings,\ + EnumDisplaySettingsEx,\ + EnumProps,\ + EnumPropsEx,\ + EnumWindowStations,\ + FindWindow,\ + FindWindowEx,\ + GetAltTabInfo,\ + GetClassInfo,\ + GetClassInfoEx,\ + GetClassLong,\ + GetClassName,\ + GetClipboardFormatName,\ + GetClipboardSequenceNumber,\ + GetDlgItemText,\ + GetKeyNameText,\ + GetKeyboardLayoutName,\ + GetMenuItemInfo,\ + GetMenuString,\ + GetMessage,\ + GetMonitorInfo,\ + GetProp,\ + GetTabbedTextExtent,\ + GetUserObjectInformation,\ + GetWindowLong,\ + GetWindowModuleFileName,\ + GetWindowText,\ + GetWindowTextLength,\ + GrayString,\ + IMPGetIME,\ + IMPQueryIME,\ + IMPSetIME,\ + InsertMenu,\ + InsertMenuItem,\ + IsCharAlpha,\ + IsCharAlphaNumeric,\ + IsCharLower,\ + IsCharUpper,\ + IsDialogMessage,\ + LoadAccelerators,\ + LoadBitmap,\ + LoadCursor,\ + LoadCursorFromFile,\ + LoadIcon,\ + LoadImage,\ + LoadKeyboardLayout,\ + LoadMenu,\ + LoadMenuIndirect,\ + LoadString,\ + MapVirtualKey,\ + MapVirtualKeyEx,\ + MessageBox,\ + MessageBoxEx,\ + MessageBoxIndirect,\ + ModifyMenu,\ + OemToChar,\ + OemToCharBuff,\ + OpenDesktop,\ + OpenWindowStation,\ + PeekMessage,\ + PostMessage,\ + PostThreadMessage,\ + RealGetWindowClass,\ + RegisterClass,\ + RegisterClassEx,\ + RegisterClipboardFormat,\ + RegisterDeviceNotification,\ + RegisterWindowMessage,\ + RemoveProp,\ + SendDlgItemMessage,\ + SendIMEMessageEx,\ + SendMessage,\ + SendMessageCallback,\ + SendMessageTimeout,\ + SendNotifyMessage,\ + SetClassLong,\ + SetDlgItemText,\ + SetMenuItemInfo,\ + SetProp,\ + SetUserObjectInformation,\ + SetWindowLong,\ + SetWindowText,\ + SetWindowsHook,\ + SetWindowsHookEx,\ + SystemParametersInfo,\ + TabbedTextOut,\ + TranslateAccelerator,\ + UnregisterClass,\ + VkKeyScan,\ + VkKeyScanEx,\ + WinHelp,\ + wsprintf,\ + wvsprintf diff --git a/toolchain/fasm2/include/api/wsock32.inc b/toolchain/fasm2/include/api/wsock32.inc new file mode 100644 index 0000000..8b8edb6 --- /dev/null +++ b/toolchain/fasm2/include/api/wsock32.inc @@ -0,0 +1,85 @@ + +; WSOCK32 API calls + +import wsock32,\ + AcceptEx,'AcceptEx',\ + EnumProtocolsA,'EnumProtocolsA',\ + EnumProtocolsW,'EnumProtocolsW',\ + GetAcceptExSockaddrs,'GetAcceptExSockaddrs',\ + GetAddressByNameA,'GetAddressByNameA',\ + GetAddressByNameW,'GetAddressByNameW',\ + GetNameByTypeA,'GetNameByTypeA',\ + GetNameByTypeW,'GetNameByTypeW',\ + GetServiceA,'GetServiceA',\ + GetServiceW,'GetServiceW',\ + GetTypeByNameA,'GetTypeByNameA',\ + GetTypeByNameW,'GetTypeByNameW',\ + MigrateWinsockConfiguration,'MigrateWinsockConfiguration',\ + NPLoadNameSpaces,'NPLoadNameSpaces',\ + SetServiceA,'SetServiceA',\ + SetServiceW,'SetServiceW',\ + TransmitFile,'TransmitFile',\ + WEP,'WEP',\ + WSAAsyncGetHostByAddr,'WSAAsyncGetHostByAddr',\ + WSAAsyncGetHostByName,'WSAAsyncGetHostByName',\ + WSAAsyncGetProtoByName,'WSAAsyncGetProtoByName',\ + WSAAsyncGetProtoByNumber,'WSAAsyncGetProtoByNumber',\ + WSAAsyncGetServByName,'WSAAsyncGetServByName',\ + WSAAsyncGetServByPort,'WSAAsyncGetServByPort',\ + WSAAsyncSelect,'WSAAsyncSelect',\ + WSACancelAsyncRequest,'WSACancelAsyncRequest',\ + WSACancelBlockingCall,'WSACancelBlockingCall',\ + WSACleanup,'WSACleanup',\ + WSAGetLastError,'WSAGetLastError',\ + WSAIsBlocking,'WSAIsBlocking',\ + WSARecvEx,'WSARecvEx',\ + WSASetBlockingHook,'WSASetBlockingHook',\ + WSASetLastError,'WSASetLastError',\ + WSAStartup,'WSAStartup',\ + WSAUnhookBlockingHook,'WSAUnhookBlockingHook',\ + __WSAFDIsSet,'__WSAFDIsSet',\ + accept,'accept',\ + bind,'bind',\ + closesocket,'closesocket',\ + connect,'connect',\ + dn_expand,'dn_expand',\ + gethostbyaddr,'gethostbyaddr',\ + gethostbyname,'gethostbyname',\ + gethostname,'gethostname',\ + getnetbyname,'getnetbyname',\ + getpeername,'getpeername',\ + getprotobyname,'getprotobyname',\ + getprotobynumber,'getprotobynumber',\ + getservbyname,'getservbyname',\ + getservbyport,'getservbyport',\ + getsockname,'getsockname',\ + getsockopt,'getsockopt',\ + htonl,'htonl',\ + htons,'htons',\ + inet_addr,'inet_addr',\ + inet_network,'inet_network',\ + inet_ntoa,'inet_ntoa',\ + ioctlsocket,'ioctlsocket',\ + listen,'listen',\ + ntohl,'ntohl',\ + ntohs,'ntohs',\ + rcmd,'rcmd',\ + recv,'recv',\ + recvfrom,'recvfrom',\ + rexec,'rexec',\ + rresvport,'rresvport',\ + s_perror,'s_perror',\ + select,'select',\ + send,'send',\ + sendto,'sendto',\ + sethostname,'sethostname',\ + setsockopt,'setsockopt',\ + shutdown,'shutdown',\ + socket,'socket' + +api EnumProtocols,\ + GetAddressByName,\ + GetNameByType,\ + GetService,\ + GetTypeByName,\ + SetService diff --git a/toolchain/fasm2/include/dd.inc b/toolchain/fasm2/include/dd.inc new file mode 100644 index 0000000..1e4221d --- /dev/null +++ b/toolchain/fasm2/include/dd.inc @@ -0,0 +1,125 @@ + +; x86 data directives with customizable backend. + +iterate , word, qword + + calminstruction word? value* + emit word, value + end calminstruction + + macro calminstruction?.word? var* + call word, var + end macro + +end iterate + +iterate , dword,word, pword,dword, tword,qword + + calminstruction fword? value* + emit fword, value + end calminstruction + + macro calminstruction?.fword? var* + local seg, off + match seg:off, var + jyes far + plain: + call fword, var + jump ok + far: + call dword, off + call word, seg + ok: + end macro + +end iterate + +macro calminstruction?.byte? var* + compute var, var + check var eqtype '' + jyes string + emit byte, var + jump ok + string: + emit lengthof var, var + ok: +end macro + +define WCHAR? 2 + +calminstruction wchar? value* + compute value, value + check value eqtype '' + jno plain + local n + compute n, lengthof value + string: + check n + jno done + emit WCHAR, value and 0FFh + compute value, value shr 8 + compute n, n - 1 + jump string + plain: + emit WCHAR, value + done: +end calminstruction + +macro calminstruction?.wchar? var* + arrange var, =WCHAR var + assemble var +end macro + +iterate , db,byte, dw,word, du,wchar, dd,dword, dp,pword, df,pword, dq,qword, dt,tword + + calminstruction dw? definitions*& + local value, n + unroll: + transform definitions + jyes unroll + start: + match value=,definitions, definitions, () + jyes recognize + match value, definitions + arrange definitions, + recognize: + match n =dup? value, value, () + jyes duplicate + match ?, value + jyes reserve + word value + next: + match , definitions + jno start + take , definitions + take definitions, definitions + jyes next + exit + reserve: + emit word + jump next + duplicate: + match (value), value + check n < 0 + jyes negative + stack: + check n + jno next + take definitions, value + arrange value, definitions + compute n, n - 1 + jump stack + negative: + err 'the number of copies must be positive' + jump next + end calminstruction + + calminstruction (label) dw? &definitions*& + local cmd + arrange cmd, =label label : word + assemble cmd + arrange cmd, =dw definitions + assemble cmd + end calminstruction + +end iterate diff --git a/toolchain/fasm2/include/encoding/utf8.inc b/toolchain/fasm2/include/encoding/utf8.inc new file mode 100644 index 0000000..db076ea --- /dev/null +++ b/toolchain/fasm2/include/encoding/utf8.inc @@ -0,0 +1,79 @@ + +; UTF-8 + +macro WCHAR arg + local count,current,__input,char,wide + if arg eqtype '' + virtual at 0 + __input:: + db arg + count = $ + end virtual + current = 0 + while current < count + load char byte from __input:current + wide = char + current = current + 1 + if char > 0C0h + if char < 0E0h + wide = char and 11111b + load char byte from __input:current + wide = wide shl 6 + (char and 111111b) + current = current + 1 + else if char < 0F0h + wide = char and 1111b + load char byte from __input:current + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+1 + wide = wide shl 6 + (char and 111111b) + current = current + 2 + else if char < 0F8h + wide = char and 111b + load char byte from __input:current + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+1 + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+2 + wide = wide shl 6 + (char and 111111b) + current = current + 3 + else if char < 0FCh + wide = char and 11b + load char byte from __input:current + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+1 + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+2 + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+3 + wide = wide shl 6 + (char and 111111b) + current = current + 4 + else + wide = char and 1 + load char byte from __input:current + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+1 + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+2 + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+3 + wide = wide shl 6 + (char and 111111b) + load char byte from __input:current+4 + wide = wide shl 6 + (char and 111111b) + current = current + 5 + end if + end if + if wide < 10000h + dw wide + else + dw 0D7C0h + wide shr 10,0DC00h or (wide and 3FFh) + end if + end while + else + wide = arg + if wide < 10000h + dw wide + else + dw 0D7C0h + wide shr 10,0DC00h or (wide and 3FFh) + end if + end if +end macro diff --git a/toolchain/fasm2/include/encoding/win1250.inc b/toolchain/fasm2/include/encoding/win1250.inc new file mode 100644 index 0000000..5bc85c8 --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1250.inc @@ -0,0 +1,37 @@ + +; Windows 1250 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,?,201Ah,?,201Eh,2026h,2020h,2021h,?,2030h,160h,2039h,15Ah,164h,17Dh,179h + dw ?,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,?,2122h,161h,203Ah,15Bh,165h,17Eh,17Ah + dw 0A0h,2C7h,2D8h,141h,0A4h,104h,0A6h,0A7h,0A8h,0A9h,15Eh,0ABh,0ACh,0ADh,0AEh,17Bh + dw 0B0h,0B1h,2DBh,142h,0B4h,0B5h,0B6h,0B7h,0B8h,105h,15Fh,0BBh,13Dh,2DDh,13Eh,17Ch + dw 154h,0C1h,0C2h,102h,0C4h,139h,106h,0C7h,10Ch,0C9h,118h,0CBh,11Ah,0CDh,0CEh,10Eh + dw 110h,143h,147h,0D3h,0D4h,150h,0D6h,0D7h,158h,16Eh,0DAh,170h,0DCh,0DDh,162h,0DFh + dw 155h,0E1h,0E2h,103h,0E4h,13Ah,107h,0E7h,10Dh,0E9h,119h,0EBh,11Bh,0EDh,0EEh,10Fh + dw 111h,144h,148h,0F3h,0F4h,151h,0F6h,0F7h,159h,16Fh,0FAh,171h,0FCh,0FDh,163h,2D9h + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win1251.inc b/toolchain/fasm2/include/encoding/win1251.inc new file mode 100644 index 0000000..57c572f --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1251.inc @@ -0,0 +1,36 @@ + +; Windows 1251 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 401h,403h,201Ah,453h,201Eh,2026h,2020h,2021h,20ACh,2030h,409h,2039h,40Ah,40Ch,40Bh,40Fh + dw 452h,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,?,2122h,459h,203Ah,45Ah,45Ch,45Bh,45Fh + dw 0A0h,40Eh,45Eh,408h,0A4h,490h,0A6h,0A7h,401h,0A9h,404h,0ABh,0ACh,0ADh,0AEh,407h + dw 0B0h,0B1h,406h,456h,491h,0B5h,0B6h,0B7h,451h,2116h,454h,0BBh,458h,405h,455h,457h + repeat 40h + dw 410h+%-1 + end repeat + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win1252.inc b/toolchain/fasm2/include/encoding/win1252.inc new file mode 100644 index 0000000..0773c07 --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1252.inc @@ -0,0 +1,34 @@ + +; Windows 1252 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,?,201Ah,192h,201Eh,2026h,2020h,2021h,2C6h,2030h,160h,2039h,152h,?,17D,? + dw ?,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,2DCh,2122h,161h,203Ah,153h,?,17Eh,178h + repeat 60h + dw 0A0h+%-1 + end repeat + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win1253.inc b/toolchain/fasm2/include/encoding/win1253.inc new file mode 100644 index 0000000..e63d531 --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1253.inc @@ -0,0 +1,36 @@ + +; Windows 1253 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,?,201Ah,192h,201Eh,2026h,2020h,2021h,?,2030h,?,2039h,?,?,?,? + dw ?,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,?,2122h,?,203Ah,?,?,?,? + dw 0A0h,385h,386h,0A3h,0A4h,0A5h,0A6h,0A7h,0A8h,0A9h,?,0ABh,0ACh,0ADh,0AEh,2015h + dw 0B0h,0B1h,0B2h,0B3h,384h,0B5h,0B6h,0B7h,288h,389h,38Ah,0BBh,38Ch,0BDh,38Eh,38Fh + repeat 40h + dw 390h+%-1 + end repeat + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win1254.inc b/toolchain/fasm2/include/encoding/win1254.inc new file mode 100644 index 0000000..e211b19 --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1254.inc @@ -0,0 +1,39 @@ + +; Windows 1254 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,?,201Ah,192h,201Eh,2026h,2020h,2021h,2C6h,2030h,160h,2039h,152h,?,?,? + dw ?,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,2DCh,2122h,161h,203Ah,153h,?,?,178h + repeat 30h + dw 0A0h+%-1 + end repeat + dw 11Eh,0D1h,0D2h,0D3h,0D4h,0D5h,0D6h,0D7h,0D8h,0D9h,0DAh,0DBh,0DCh,130h,15Eh,0DFh + repeat 10h + dw 0E0h+%-1 + end repeat + dw 11Fh,0F1h,0F2h,0F3h,0F4h,0F5h,0F6h,0F7h,0F8h,0F9h,0FAh,0FBh,0FCh,131h,15Fh,0FFh + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win1255.inc b/toolchain/fasm2/include/encoding/win1255.inc new file mode 100644 index 0000000..5a6e825 --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1255.inc @@ -0,0 +1,37 @@ + +; Windows 1255 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,?,201Ah,192h,201Eh,2026h,2020h,2021h,2C6h,2030h,?,2039h,?,?,?,? + dw ?,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,2DCh,2122h,?,203Ah,?,?,?,? + dw 0A0h,0A1h,0A2h,0A3h,20AAh,0A5h,0A6h,0A7h,0A8h,0A9h,0D7h,0ABh,0ACh,0ADh,0AEh,0AFh + dw 0B0h,0B1h,0B2h,0B3h,0B4h,0B5h,0B6h,0B7h,0B8h,0B9h,0F7h,0BBh,0BCh,0BDh,0BEh,0BFh + dw 5B0h,5B1h,5B2h,5B3h,5B4h,5B5h,5B6h,5B7h,5B8h,5B9h,?,5BBh,5BCh,5BDh,5BEh,5BFh + dw 5C0h,5C1h,5C2h,5C3h,5F0h,5F1h,5F2h,5F3h,5F4h,?,?,?,?,?,?,? + dw 5D0h,5D1h,5D2h,5D3h,5D4h,5D5h,5D6h,5D7h,5D8h,5D9h,5DAh,5DBh,5DCh,5DDh,5DEh,5DFh + dw 5E0h,5E1h,5E2h,5E3h,5E4h,5E5h,5E6h,5E7h,5E8h,5E9h,5EAh,?,?,200Eh,200Fh,? + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win1256.inc b/toolchain/fasm2/include/encoding/win1256.inc new file mode 100644 index 0000000..25a17ad --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1256.inc @@ -0,0 +1,37 @@ + +; Windows 1256 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,67Eh,201Ah,192h,201Eh,2026h,2020h,2021h,2C6h,2030h,679h,2039h,152h,686h,698h,688h + dw 6AFh,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,6A9h,2122h,691h,203Ah,153h,200Ch,200Dh,6BAh + dw 0A0h,60Ch,0A2h,0A3h,0A4h,0A5h,0A6h,0A7h,0A8h,0A9h,6BEh,0ABh,0ACh,0ADh,0AEh,0AFh + dw 0B0h,0B1h,0B2h,0B3h,0B4h,0B5h,0B6h,0B7h,0B8h,0B9h,0BAh,0BBh,0BCh,0BDh,0BEh,0BFh + dw 6C1h,621h,622h,623h,624h,625h,626h,627h,628h,629h,62Ah,62Bh,62Ch,62Dh,62Eh,62Fh + dw 630h,631h,632h,633h,634h,635h,636h,0D7h,637h,638h,639h,63Ah,640h,641h,642h,643h + dw 0E0h,644h,0E2h,645h,646h,647h,648h,0E7h,0E8h,0E9h,0EAh,0EBh,649h,64Ah,0EEh,0EFh + dw 64Bh,64Ch,64Dh,64Eh,0F4h,64Fh,650h,0F7h,651h,0F9h,652h,0FBh,0FCh,200Eh,200Fh,6D2h + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win1257.inc b/toolchain/fasm2/include/encoding/win1257.inc new file mode 100644 index 0000000..d1efb19 --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1257.inc @@ -0,0 +1,37 @@ + +; Windows 1257 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,?,201Ah,?,201Eh,2026h,2020h,2021h,?,2030h,?,2039h,?,0A8h,2C7h,0B8h + dw ?,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,?,2122h,?,203Ah,?,0AFh,2DBh,? + dw 0A0h,?,0A2h,0A3h,0A4h,?,0A6h,0A7h,0D8h,0A9h,156h,0ABh,0ACh,0ADh,0AEh,0C6h + dw 0B0h,0B1h,0B2h,0B3h,0B4h,0B5h,0B6h,0B7h,0F8h,0B9h,157h,0BBh,0BCh,0BDh,0BEh,0E6h + dw 104h,12Eh,100h,106h,0C4h,0C5h,118h,112h,10Ch,0C9h,179h,116h,122h,136h,12Ah,13Bh + dw 160h,143h,145h,0D3h,14Ch,0D5h,0D6h,0D7h,172h,141h,15Ah,16Ah,0DCh,17Bh,17Dh,0DFh + dw 105h,12Fh,101h,107h,0E4h,0E5h,119h,113h,10Dh,0E9h,17Ah,117h,123h,137h,12Bh,13Ch + dw 161h,144h,146h,0F3h,14Dh,0F5h,0F6h,0F7h,173h,142h,15Bh,16Bh,0FCh,17Ch,17Eh,2D9h + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win1258.inc b/toolchain/fasm2/include/encoding/win1258.inc new file mode 100644 index 0000000..a62fe6b --- /dev/null +++ b/toolchain/fasm2/include/encoding/win1258.inc @@ -0,0 +1,37 @@ + +; Windows 1258 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,?,201Ah,192h,201Eh,2026h,2020h,2021h,2C6h,2030h,?,2039h,152h,?,?,? + dw ?,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,2DCh,2122h,?,203Ah,153h,?,?,178h + dw 0A0h,0A1h,0A2h,0A3h,0A4h,0A5h,0A6h,0A7h,0A8h,0A9h,0AAh,0ABh,0ACh,0ADh,0AEh,0AFh + dw 0B0h,0B1h,0B2h,0B3h,0B4h,0B5h,0B6h,0B7h,0B8h,0B9h,0BAh,0BBh,0BCh,0BDh,0BEh,0BFh + dw 0C0h,0C1h,0C2h,102h,0C4h,0C5h,0C6h,0C7h,0C8h,0C9h,0CAh,0CBh,300h,0CDh,0CEh,0CFh + dw 110h,0D1h,309h,0D3h,0D4h,1A0h,0D6h,0D7h,0D8h,0D9h,0DAh,0DBh,0DCh,1AFh,303h,0DFh + dw 0E0h,0E1h,0E2h,103h,0E4h,0E5h,0E6h,0E7h,0E8h,0E9h,0EAh,0EBh,301h,0EDh,0EEh,0EFh + dw 111h,0F1h,323h,0F3h,0F4h,1A1h,0F6h,0F7h,0F8h,0F9h,0FAh,0FBh,0FCh,1B0h,20ABh,0FFh + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/encoding/win874.inc b/toolchain/fasm2/include/encoding/win874.inc new file mode 100644 index 0000000..4ef1ad2 --- /dev/null +++ b/toolchain/fasm2/include/encoding/win874.inc @@ -0,0 +1,34 @@ + +; Windows 874 + +macro define + local encoding + virtual at 0 + encoding:: + repeat 80h + dw %-1 + end repeat + dw 20ACh,?,?,?,?,2026h,?,?,?,?,?,?,?,?,?,? + dw ?,2018h,2019h,201Ch,201Dh,2022h,2013h,2014h,?,?,?,?,?,?,?,? + repeat 60h + dw 0E00h+%-1 + end repeat + end virtual + macro WCHAR arg + if arg eqtype '' + local data,char + data db arg + rb ($-data) + repeat ($-data)/2 + load char:byte from data+%%-% + load char:word from encoding:char*2 + store char:word at data+(%%-%)*2 + end repeat + else + dw arg + end if + end macro +end macro + +define +purge define diff --git a/toolchain/fasm2/include/equates/comctl32.inc b/toolchain/fasm2/include/equates/comctl32.inc new file mode 100644 index 0000000..6e5deb4 --- /dev/null +++ b/toolchain/fasm2/include/equates/comctl32.inc @@ -0,0 +1,1869 @@ + +; COMCTL32.DLL structures and constants + +struct PROPSHEETPAGE + dwSize dd ? + dwFlags dd ? + hInstance dd ? + pszTemplate dd ? + pszIcon dd ? + pszTitle dd ? + pfnDlgProc dd ? + lParam dd ? + pfnCallback dd ? + pcRefParent dd ? +ends + +struct PROPSHEETHEADER + dwSize dd ? + dwFlags dd ? + hwndParent dd ? + hInstance dd ? + pszIcon dd ? + pszCaption dd ? + nPages dd ? + pStartPage dd ? + ppsp dd ? + pfnCallback dd ? +ends + +struct IMAGEINFO + hbmImage dd ? + hbmMask dd ? + Unused1 dd ? + Unused2 dd ? + rcImage RECT +ends + +struct HD_ITEM + mask dd ? + cxy dd ? + pszText dd ? + hbm dd ? + cchTextMax dd ? + fmt dd ? + lParam dd ? +ends + +struct HD_LAYOUT + prc dd ? + pwpos dd ? +ends + +struct HD_HITTESTINFO + pt POINT + flags dd ? + iItem dd ? +ends + +struct HD_NOTIFY + hdr NMHDR + iItem dd ? + iButton dd ? + pitem dd ? +ends + +struct TBBUTTON + iBitmap dd ? + idCommand dd ? + fsState db ? + fsStyle db ? + dw ? + dwData dd ? + iString dd ? +ends + +struct COLORMAP + from dd ? + to dd ? +ends + +struct TBADDBITMAP + hInst dd ? + nID dd ? +ends + +struct TBSAVEPARAMS + hkr dd ? + pszSubKey dd ? + pszValueName dd ? +ends + +struct TBREPLACEBITMAP + hInstOld dd ? + nIDOld dd ? + hInstNew dd ? + nIDNew dd ? + nButtons dd ? +ends + +struct NMTOOLBAR + hdr NMHDR + iItem dd ? + tbButton TBBUTTON + cchText dd ? + pszText dd ? +ends + +struct REBARINFO + cbSize dd ? + fMask dd ? + himl dd ? +ends + +struct REBARBANDINFO + cbSize dd ? + fMask dd ? + fStyle dd ? + clrFore dd ? + clrBack dd ? + lpText dd ? + cch dd ? + iImage dd ? + hwndChild dd ? + cxMinChild dd ? + cyMinChild dd ? + cx dd ? + hbmBack dd ? + wID dd ? +ends + +struct TOOLINFO + cbSize dd ? + uFlags dd ? + hwnd dd ? + uId dd ? + rect RECT + hInst dd ? + lpszText dd ? +ends + +struct TTHITTESTINFO + hwnd dd ? + pt POINT + ti TOOLINFO +ends + +struct TOOLTIPTEXT + hdr NMHDR + lpszText dd ? + szText db 80 dup (?) + hinst dd ? + uFlags dd ? +ends + +struct UDACCEL + nSec dd ? + nInc dd ? +ends + +struct NM_UPDOWN + hdr NMHDR + iPos dd ? + iDelta dd ? +ends + +struct LV_ITEM + mask dd ? + iItem dd ? + iSubItem dd ? + state dd ? + stateMask dd ? + pszText dd ? + cchTextMax dd ? + iImage dd ? + lParam dd ? + iIndent dd ? +ends + +struct LV_FINDINFO + flags dd ? + psz dd ? + lParam dd ? + pt POINT + vkDirection dd ? +ends + +struct LV_HITTESTINFO + pt POINT + flags dd ? + iItem dd ? +ends + +struct LV_COLUMN + mask dd ? + fmt dd ? + cx dd ? + pszText dd ? + cchTextMax dd ? + iSubItem dd ? +ends + +struct NM_LISTVIEW + hdr NMHDR + iItem dd ? + iSubItem dd ? + uNewState dd ? + uOldState dd ? + uChanged dd ? + ptAction POINT + lParam dd ? +ends + +struct NM_CACHEHINT + hdr NMHDR + iFrom dd ? + iTo dd ? +ends + +struct NM_FINDITEM + hdr NMHDR + iStart dd ? + lvfi LV_FINDINFO +ends + +struct LV_DISPINFO + hdr NMHDR + item LV_ITEM +ends + +struct LV_KEYDOWN + hdr NMHDR + wVKey dw ? + flags dd ? +ends + +struct TV_ITEM + mask dd ? + hItem dd ? + state dd ? + stateMask dd ? + pszText dd ? + cchTextMax dd ? + iImage dd ? + iSelectedImage dd ? + cChildren dd ? + lParam dd ? +ends + +struct TV_INSERTSTRUCT + hParent dd ? + hInsertAfter dd ? + item TV_ITEM +ends + +struct TV_HITTESTINFO + pt POINT + flags dd ? + hItem dd ? +ends + +struct TV_SORTCB + hParent dd ? + lpfnCompare dd ? + lParam dd ? +ends + +struct NM_TREEVIEW + hdr NMHDR + action dd ? + itemOld TV_ITEM + itemNew TV_ITEM + ptDrag POINT +ends + +struct TV_DISPINFO + hdr NMHDR + item TV_ITEM +ends + +struct TV_KEYDOWN + hdr NMHDR + wVKey dw ? + flags dd ? +ends + +struct TC_ITEMHEADER + mask dd ? + lpReserved1 dd ? + lpReserved2 dd ? + pszText dd ? + cchTextMax dd ? + iImage dd ? +ends + +struct TC_ITEM + mask dd ? + lpReserved1 dd ? + lpReserved2 dd ? + pszText dd ? + cchTextMax dd ? + iImage dd ? + lParam dd ? +ends + +struct TC_HITTESTINFO + pt POINT + flags dd ? +ends + +struct TC_KEYDOWN + hdr NMHDR + wVKey dw ? + flags dd ? +ends + +struct MC_HITTESTINFO + cbSize dd ? + pt POINT + uHit dd ? + st SYSTEMTIME +ends + +struct NM_SELCHANGE + nmhdr NMHDR + stSelStart SYSTEMTIME + stSelEnd SYSTEMTIME +ends + +struct NM_DAYSTATE + nmhdr NMHDR + stStart SYSTEMTIME + cDayState dd ? + prgDayState dd ? +ends + +struct NM_DATETIMECHANGE + nmhdr NMHDR + dwFlags dd ? + st SYSTEMTIME +ends + +struct NM_DATETIMESTRING + nmhdr NMHDR + pszUserString dd ? + st SYSTEMTIME + dwFlags dd ? +ends + +struct NM_DATETIMEWMKEYDOWN + nmhdr NMHDR + nVirtKey dd ? + pszFormat dd ? + st SYSTEMTIME +ends + +struct NM_DATETIMEFORMAT + nmhdr NMHDR + pszFormat dd ? + st SYSTEMTIME + pszDisplay dd ? + szDisplay db 64 dup (?) +ends + +struct NM_DATETIMEFORMATQUERY + nmhdr NMHDR + pszFormat dd ? + szMax SIZE +ends + +struct INITCOMMONCONTROLSEX + dwSize dd ? + dwICC dd ? +ends + +; Common control window classes + +HOTKEY_CLASS equ 'msctls_hotkey32' +PROGRESS_CLASS equ 'msctls_progress32' +STATUS_CLASS equ 'msctls_statusbar32' +TRACKBAR_CLASS equ 'msctls_trackbar32' +UPDOWN_CLASS equ 'msctls_updown32' +TOOLTIPS_CLASS equ 'tooltips_class32' +ANIMATE_CLASS equ 'SysAnimate32' +HEADER_CLASS equ 'SysHeader32' +LISTVIEW_CLASS equ 'SysListView32' +TREEVIEW_CLASS equ 'SysTreeView32' +TABCONTROL_CLASS equ 'SysTabControl32' +MONTHCAL_CLASS equ 'SysMonthCal32' +DATETIMEPICK_CLASS equ 'SysDateTimePick32' +TOOLBAR_CLASS equ 'ToolbarWindow32' +REBAR_CLASS equ 'ReBarWindow32' + +; Ranges for control message IDs + +LVM_FIRST = 1000h +TV_FIRST = 1100h +HDM_FIRST = 1200h +TCM_FIRST = 1300h +MCM_FIRST = 1000h +DTM_FIRST = 1000h +CCM_FIRST = 2000h + +; Ranges for control notification IDs + +NM_FIRST = 0 +LVN_FIRST = -100 +PSN_FIRST = -200 +HDN_FIRST = -300 +TVN_FIRST = -400 +TTN_FIRST = -520 +TCN_FIRST = -550 +CDN_FIRST = -601 +TBN_FIRST = -700 +UDN_FIRST = -721 +MCN_FIRST = -750 +DTN_FIRST = -760 +CBEN_FIRST = -800 +RBN_FIRST = -831 + +; Generic notifications + +NM_OUTOFMEMORY = NM_FIRST - 1 +NM_CLICK = NM_FIRST - 2 +NM_DBLCLK = NM_FIRST - 3 +NM_RETURN = NM_FIRST - 4 +NM_RCLICK = NM_FIRST - 5 +NM_RDBLCLK = NM_FIRST - 6 +NM_SETFOCUS = NM_FIRST - 7 +NM_KILLFOCUS = NM_FIRST - 8 +NM_CUSTOMDRAW = NM_FIRST - 12 + +; Common control styles + +CCS_TOP = 01h +CCS_NOMOVEY = 02h +CCS_BOTTOM = 03h +CCS_NORESIZE = 04h +CCS_NOPARENTALIGN = 08h +CCS_ADJUSTABLE = 20h +CCS_NODIVIDER = 40h +CCS_VERT = 80h +CCS_LEFT = CCS_VERT or CCS_TOP +CCS_RIGHT = CCS_VERT or CCS_BOTTOM +CCS_NOMOVEX = CCS_VERT or CCS_NOMOVEY + +; Owner-drawn control types + +ODT_HEADER = 100 +ODT_TAB = 101 +ODT_LISTVIEW = 102 + +; InitCommonControlsEx classes + +ICC_ANIMATE_CLASS = 0080h +ICC_BAR_CLASSES = 0004h +ICC_COOL_CLASSES = 0400h +ICC_DATE_CLASSES = 0100h +ICC_HOTKEY_CLASS = 0040h +ICC_INTERNET_CLASSES = 0800h +ICC_LISTVIEW_CLASSES = 0001h +ICC_PAGESCROLLER_CLASS = 1000h +ICC_PROGRESS_CLASS = 0020h +ICC_TAB_CLASSES = 0008h +ICC_TREEVIEW_CLASSES = 0002h +ICC_UPDOWN_CLASS = 0010h +ICC_USEREX_CLASSES = 0200h +ICC_WIN95_CLASSES = 00FFh + +; Shared messages + +CCM_SETCOLORSCHEME = CCM_FIRST + 2 +CCM_GETCOLORSCHEME = CCM_FIRST + 3 +CCM_GETDROPTARGET = CCM_FIRST + 4 +CCM_SETUNICODEFORMAT = CCM_FIRST + 5 +CCM_GETUNICODEFORMAT = CCM_FIRST + 6 + +; Property sheet page flags + +PSP_DEFAULT = 0000h +PSP_DLGINDIRECT = 0001h +PSP_USEHICON = 0002h +PSP_USEICONID = 0004h +PSP_USETITLE = 0008h +PSP_HASHELP = 0020h +PSP_USEREFPARENT = 0040h +PSP_USECALLBACK = 0080h + +; Property sheet page actions + +PSPCB_RELEASE = 1 +PSPCB_CREATE = 2 + +; Property sheet header flags + +PSH_DEFAULT = 0000h +PSH_PROPTITLE = 0001h +PSH_USEHICON = 0002h +PSH_USEICONID = 0004h +PSH_PROPSHEETPAGE = 0008h +PSH_MULTILINETABS = 0010h +PSH_WIZARD = 0020h +PSH_USEPSTARTPAGE = 0040h +PSH_NOAPPLYNOW = 0080h +PSH_USECALLBACK = 0100h +PSH_HASHELP = 0200h +PSH_MODELESS = 0400h + +; Property sheet actions + +PSCB_INITIALIZED = 1 + +; Property sheet notifications + +PSN_SETACTIVE = PSN_FIRST - 0 +PSN_KILLACTIVE = PSN_FIRST - 1 +PSN_APPLY = PSN_FIRST - 2 +PSN_RESET = PSN_FIRST - 3 +PSN_HELP = PSN_FIRST - 5 +PSN_WIZBACK = PSN_FIRST - 6 +PSN_WIZNEXT = PSN_FIRST - 7 +PSN_WIZFINISH = PSN_FIRST - 8 +PSN_QUERYCANCEL = PSN_FIRST - 9 + +; Property sheet return values + +PSNRET_NOERROR = 0 +PSNRET_INVALID = 1 +PSNRET_INVALID_NOCHANGEPAGE = 2 + +; Property sheet messages + +PSM_SETCURSEL = WM_USER + 101 +PSM_REMOVEPAGE = WM_USER + 102 +PSM_ADDPAGE = WM_USER + 103 +PSM_CHANGED = WM_USER + 104 +PSM_RESTARTWINDOWS = WM_USER + 105 +PSM_REBOOTSYSTEM = WM_USER + 106 +PSM_CANCELTOCLOSE = WM_USER + 107 +PSM_QUERYSIBLINGS = WM_USER + 108 +PSM_UNCHANGED = WM_USER + 109 +PSM_APPLY = WM_USER + 110 +PSM_SETTITLE = WM_USER + 111 +PSM_SETTITLEW = WM_USER + 120 +PSM_SETWIZBUTTONS = WM_USER + 112 +PSM_PRESSBUTTON = WM_USER + 113 +PSM_SETCURSELID = WM_USER + 114 +PSM_SETFINISHTEXT = WM_USER + 115 +PSM_SETFINISHTEXTW = WM_USER + 121 +PSM_GETTABCONTROL = WM_USER + 116 +PSM_ISDIALOGMESSAGE = WM_USER + 117 + +; Property sheet buttons + +PSBTN_BACK = 0 +PSBTN_NEXT = 1 +PSBTN_FINISH = 2 +PSBTN_OK = 3 +PSBTN_APPLYNOW = 4 +PSBTN_CANCEL = 5 +PSBTN_HELP = 6 +PSWIZB_BACK = 1 +PSWIZB_NEXT = 2 +PSWIZB_FINISH = 4 +PSWIZB_DISABLEDFINISH = 8 +ID_PSRESTARTWINDOWS = 2 +ID_PSREBOOTSYSTEM = ID_PSRESTARTWINDOWS or 1 + +; Property sheet sizes + +PROP_SM_CXDLG = 212 +PROP_SM_CYDLG = 188 +PROP_MED_CXDLG = 227 +PROP_MED_CYDLG = 215 +PROP_LG_CXDLG = 252 +PROP_LG_CYDLG = 218 +WIZ_CXDLG = 276 +WIZ_CYDLG = 140 +WIZ_CXBMP = 80 +WIZ_BODYX = 92 +WIZ_BODYCX = 184 + +; Image list types + +ILC_MASK = 001h +ILC_COLOR = 0FEh +ILC_COLORDDB = 0FEh +ILC_COLOR4 = 004h +ILC_COLOR8 = 008h +ILC_COLOR16 = 010h +ILC_COLOR24 = 018h +ILC_COLOR32 = 020h +ILC_PALETTE = 800h + +; Image list color values + +CLR_NONE = 0FFFFFFFFh +CLR_DEFAULT = 0FF000000h +CLR_HILIGHT = CLR_DEFAULT + +; Image list drawing styles + +ILD_NORMAL = 0000h +ILD_TRANSPARENT = 0001h +ILD_MASK = 0010h +ILD_IMAGE = 0020h +ILD_BLEND25 = 0002h +ILD_BLEND50 = 0004h +ILD_OVERLAYMASK = 0F00h +ILD_SELECTED = ILD_BLEND50 +ILD_FOCUS = ILD_BLEND25 +ILD_BLEND = ILD_BLEND50 + +; Header control styles + +HDS_HORZ = 00h +HDS_BUTTONS = 02h +HDS_HOTTRACK = 04h +HDS_HIDDEN = 08h +HDS_DRAGDROP = 40h +HDS_FULLDRAG = 80h + +; Header control structure flags + +HDI_WIDTH = 01h +HDI_HEIGHT = HDI_WIDTH +HDI_TEXT = 02h +HDI_FORMAT = 04h +HDI_LPARAM = 08h +HDI_BITMAP = 10h + +; Header control flags + +HDF_LEFT = 0000h +HDF_RIGHT = 0001h +HDF_CENTER = 0002h +HDF_JUSTIFYMASK = 0003h +HDF_RTLREADING = 0004h +HDF_BITMAP = 2000h +HDF_STRING = 4000h +HDF_OWNERDRAW = 8000h + +; Header control messages + +HDM_GETITEMCOUNT = HDM_FIRST + 0 +HDM_INSERTITEMA = HDM_FIRST + 1 +HDM_DELETEITEM = HDM_FIRST + 2 +HDM_GETITEMA = HDM_FIRST + 3 +HDM_SETITEMA = HDM_FIRST + 4 +HDM_LAYOUT = HDM_FIRST + 5 +HDM_HITTEST = HDM_FIRST + 6 +HDM_INSERTITEMW = HDM_FIRST + 10 +HDM_GETITEMW = HDM_FIRST + 11 +HDM_SETITEMW = HDM_FIRST + 12 +HDM_INSERTITEM = HDM_INSERTITEMA +HDM_GETITEM = HDM_GETITEMA +HDM_SETITEM = HDM_SETITEMA + +; Hit test result flags + +HHT_NOWHERE = 001h +HHT_ONHEADER = 002h +HHT_ONDIVIDER = 004h +HHT_ONDIVOPEN = 008h +HHT_ABOVE = 100h +HHT_BELOW = 200h +HHT_TORIGHT = 400h +HHT_TOLEFT = 800h + +; Header control notifications + +HDN_ITEMCHANGINGA = HDN_FIRST - 0 +HDN_ITEMCHANGEDA = HDN_FIRST - 1 +HDN_ITEMCLICKA = HDN_FIRST - 2 +HDN_ITEMDBLCLICKA = HDN_FIRST - 3 +HDN_DIVIDERDBLCLICKA = HDN_FIRST - 5 +HDN_BEGINTRACKA = HDN_FIRST - 6 +HDN_ENDTRACKA = HDN_FIRST - 7 +HDN_TRACKA = HDN_FIRST - 8 +HDN_ITEMCHANGINGW = HDN_FIRST - 20 +HDN_ITEMCHANGEDW = HDN_FIRST - 21 +HDN_ITEMCLICKW = HDN_FIRST - 22 +HDN_ITEMDBLCLICKW = HDN_FIRST - 23 +HDN_DIVIDERDBLCLICKW = HDN_FIRST - 25 +HDN_BEGINTRACKW = HDN_FIRST - 26 +HDN_ENDTRACKW = HDN_FIRST - 27 +HDN_TRACKW = HDN_FIRST - 28 +HDN_ITEMCHANGING = HDN_ITEMCHANGINGA +HDN_ITEMCHANGED = HDN_ITEMCHANGEDA +HDN_ITEMCLICK = HDN_ITEMCLICKA +HDN_ITEMDBLCLICK = HDN_ITEMDBLCLICKA +HDN_DIVIDERDBLCLICK = HDN_DIVIDERDBLCLICKA +HDN_BEGINTRACK = HDN_BEGINTRACKA +HDN_ENDTRACK = HDN_ENDTRACKA +HDN_TRACK = HDN_TRACKA + +; Toolbar bitmap flags + +CMB_MASKED = 2 + +; Toolbar button states + +TBSTATE_CHECKED = 01h +TBSTATE_PRESSED = 02h +TBSTATE_ENABLED = 04h +TBSTATE_HIDDEN = 08h +TBSTATE_INDETERMINATE = 10h +TBSTATE_WRAP = 20h +TBSTATE_ELLIPSES = 40h + +; Toolbar button styles + +TBSTYLE_BUTTON = 0000h +TBSTYLE_SEP = 0001h +TBSTYLE_CHECK = 0002h +TBSTYLE_GROUP = 0004h +TBSTYLE_CHECKGROUP = TBSTYLE_GROUP or TBSTYLE_CHECK +TBSTYLE_DROPDOWN = 0008h +TBSTYLE_TOOLTIPS = 0100h +TBSTYLE_WRAPABLE = 0200h +TBSTYLE_ALTDRAG = 0400h +TBSTYLE_FLAT = 0800h +TBSTYLE_LIST = 1000h +TBSTYLE_CUSTOMERASE = 2000h +TBSTYLE_TRANSPARENT = 8000h + +; Toolbar button extended styles + +TBSTYLE_EX_DRAWDDARROWS = 0001h + +; Toolbar messages + +TB_ENABLEBUTTON = WM_USER + 1 +TB_CHECKBUTTON = WM_USER + 2 +TB_PRESSBUTTON = WM_USER + 3 +TB_HIDEBUTTON = WM_USER + 4 +TB_INDETERMINATE = WM_USER + 5 +TB_ISBUTTONENABLED = WM_USER + 9 +TB_ISBUTTONCHECKED = WM_USER + 10 +TB_ISBUTTONPRESSED = WM_USER + 11 +TB_ISBUTTONHIDDEN = WM_USER + 12 +TB_ISBUTTONINDETERMINATE = WM_USER + 13 +TB_SETSTATE = WM_USER + 17 +TB_GETSTATE = WM_USER + 18 +TB_ADDBITMAP = WM_USER + 19 +TB_ADDBUTTONS = WM_USER + 20 +TB_INSERTBUTTON = WM_USER + 21 +TB_DELETEBUTTON = WM_USER + 22 +TB_GETBUTTON = WM_USER + 23 +TB_BUTTONCOUNT = WM_USER + 24 +TB_COMMANDTOINDEX = WM_USER + 25 +TB_SAVERESTOREA = WM_USER + 26 +TB_ADDSTRINGA = WM_USER + 28 +TB_CUSTOMIZE = WM_USER + 27 +TB_GETITEMRECT = WM_USER + 29 +TB_BUTTONSTRUCTSIZE = WM_USER + 30 +TB_SETBUTTONSIZE = WM_USER + 31 +TB_SETBITMAPSIZE = WM_USER + 32 +TB_AUTOSIZE = WM_USER + 33 +TB_GETTOOLTIPS = WM_USER + 35 +TB_SETTOOLTIPS = WM_USER + 36 +TB_SETPARENT = WM_USER + 37 +TB_SETROWS = WM_USER + 39 +TB_GETROWS = WM_USER + 40 +TB_GETBITMAPFLAGS = WM_USER + 41 +TB_SETCMDID = WM_USER + 42 +TB_CHANGEBITMAP = WM_USER + 43 +TB_GETBITMAP = WM_USER + 44 +TB_GETBUTTONTEXTA = WM_USER + 45 +TB_REPLACEBITMAP = WM_USER + 46 +TB_SETINDENT = WM_USER + 47 +TB_SETIMAGELIST = WM_USER + 48 +TB_GETIMAGELIST = WM_USER + 49 +TB_LOADIMAGES = WM_USER + 50 +TB_GETRECT = WM_USER + 51 +TB_SETHOTIMAGELIST = WM_USER + 52 +TB_GETHOTIMAGELIST = WM_USER + 53 +TB_SETDISABLEDIMAGELIST = WM_USER + 54 +TB_GETDISABLEDIMAGELIST = WM_USER + 55 +TB_SETSTYLE = WM_USER + 56 +TB_GETSTYLE = WM_USER + 57 +TB_GETBUTTONSIZE = WM_USER + 58 +TB_SETBUTTONWIDTH = WM_USER + 59 +TB_SETMAXTEXTROWS = WM_USER + 60 +TB_GETTEXTROWS = WM_USER + 61 +TB_GETBUTTONTEXTW = WM_USER + 75 +TB_SAVERESTOREW = WM_USER + 76 +TB_ADDSTRINGW = WM_USER + 77 +TB_SETEXTENDEDSTYLE = WM_USER + 84 +TB_GETEXTENDEDSTYLE = WM_USER + 85 +TB_GETBUTTONTEXT = TB_GETBUTTONTEXTA +TB_SAVERESTORE = TB_SAVERESTOREA +TB_ADDSTRING = TB_ADDSTRINGA + +; System-defined button bitmaps + +HINST_COMMCTRL = -1 +IDB_STD_SMALL_COLOR = 0 +IDB_STD_LARGE_COLOR = 1 +IDB_VIEW_SMALL_COLOR = 4 +IDB_VIEW_LARGE_COLOR = 5 +IDB_HIST_SMALL_COLOR = 8 +IDB_HIST_LARGE_COLOR = 9 + +; Icon indexes for standard bitmap + +STD_CUT = 0 +STD_COPY = 1 +STD_PASTE = 2 +STD_UNDO = 3 +STD_REDOW = 4 +STD_DELETE = 5 +STD_FILENEW = 6 +STD_FILEOPEN = 7 +STD_FILESAVE = 8 +STD_PRINTPRE = 9 +STD_PROPERTIES = 10 +STD_HELP = 11 +STD_FIND = 12 +STD_REPLACE = 13 +STD_PRINT = 14 + +; Icon indexes for standard view bitmap + +VIEW_LARGEICONS = 0 +VIEW_SMALLICONS = 1 +VIEW_LIST = 2 +VIEW_DETAILS = 3 +VIEW_SORTNAME = 4 +VIEW_SORTSIZE = 5 +VIEW_SORTDATE = 6 +VIEW_SORTTYPE = 7 +VIEW_PARENTFOLDER = 8 +VIEW_NETCONNECT = 9 +VIEW_NETDISCONNECT = 10 +VIEW_NEWFOLDER = 11 + +; Icon indexes for history bitmap + +HIST_BACK = 0 +HIST_FORWARD = 1 +HIST_FAVORITES = 2 +HIST_ADDTOFAVORITES = 3 +HIST_VIEWTREE = 4 + +; Toolbar bitmap flags + +TBBF_LARGE = 1 + +; Toolbar notifications + +TBN_GETBUTTONINFOA = TBN_FIRST - 0 +TBN_BEGINDRAG = TBN_FIRST - 1 +TBN_ENDDRAG = TBN_FIRST - 2 +TBN_BEGINADJUST = TBN_FIRST - 3 +TBN_ENDADJUST = TBN_FIRST - 4 +TBN_RESET = TBN_FIRST - 5 +TBN_QUERYINSERT = TBN_FIRST - 6 +TBN_QUERYDELETE = TBN_FIRST - 7 +TBN_TOOLBARCHANGE = TBN_FIRST - 8 +TBN_CUSTHELP = TBN_FIRST - 9 +TBN_DROPDOWN = TBN_FIRST - 10 +TBN_CLOSEUP = TBN_FIRST - 11 +TBN_GETBUTTONINFOW = TBN_FIRST - 20 +TBN_GETBUTTONINFO = TBN_GETBUTTONINFOA + +; ReBar styles + +RBS_TOOLTIPS = 100h +RBS_VARHEIGHT = 200h +RBS_BANDBORDERS = 400h +RBS_FIXEDORDER = 800h +RBS_REGISTERDROP = 1000h +RBS_AUTOSIZE = 2000h +RBS_VERTICALGRIPPER = 4000h +RBS_DBLCLKTOGGLE = 8000h + +; ReBar band info structure flags + +RBBIM_STYLE = 001h +RBBIM_COLORS = 002h +RBBIM_TEXT = 004h +RBBIM_IMAGE = 008h +RBBIM_CHILD = 010h +RBBIM_CHILDSIZE = 020h +RBBIM_SIZE = 040h +RBBIM_BACKGROUND = 080h +RBBIM_ID = 100h +RBBIM_IDEALSIZE = 200h +RBBIM_LPARAM = 400h +RBBIM_HEADERSIZE = 800h + +; ReBar band styles + +RBBS_BREAK = 001h +RBBS_FIXEDSIZE = 002h +RBBS_CHILDEDGE = 004h +RBBS_HIDDEN = 008h +RBBS_NOVERT = 010h +RBBS_FIXEDBMP = 020h +RBBS_VARIABLEHEIGHT = 040h +RBBS_GRIPPERALWAYS = 080h +RBBS_NOGRIPPER = 100h + +; ReBar messages + +RB_INSERTBANDA = WM_USER + 1 +RB_DELETEBAND = WM_USER + 2 +RB_GETBARINFO = WM_USER + 3 +RB_SETBARINFO = WM_USER + 4 +RB_GETBANDINFO = WM_USER + 5 +RB_SETBANDINFOA = WM_USER + 6 +RB_SETPARENT = WM_USER + 7 +RB_INSERTBANDW = WM_USER + 10 +RB_SETBANDINFOW = WM_USER + 11 +RB_GETBANDCOUNT = WM_USER + 12 +RB_GETROWCOUNT = WM_USER + 13 +RB_GETROWHEIGHT = WM_USER + 14 +RB_IDTOINDEX = WM_USER + 16 +RB_GETTOOLTIPS = WM_USER + 17 +RB_SETTOOLTIPS = WM_USER + 18 +RB_SETBKCOLOR = WM_USER + 19 +RB_GETBKCOLOR = WM_USER + 20 +RB_SETTEXTCOLOR = WM_USER + 21 +RB_GETTEXTCOLOR = WM_USER + 22 +RB_SIZETORECT = WM_USER + 23 +RB_BEGINDRAG = WM_USER + 24 +RB_ENDDRAG = WM_USER + 25 +RB_DRAGMOVE = WM_USER + 26 +RB_GETBARHEIGHT = WM_USER + 27 +RB_GETBANDINFOW = WM_USER + 28 +RB_GETBANDINFOA = WM_USER + 29 +RB_MINIMIZEBAND = WM_USER + 30 +RB_MAXIMIZEBAND = WM_USER + 31 +RB_GETDROPTARGET = CCM_GETDROPTARGET +RB_GETBANDBORDERS = WM_USER + 34 +RB_SHOWBAND = WM_USER + 35 +RB_SETPALETTE = WM_USER + 37 +RB_GETPALETTE = WM_USER + 38 +RB_MOVEBAND = WM_USER + 39 +RB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +RB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +RB_INSERTBAND = RB_INSERTBANDA +RB_SETBANDINFO = RB_SETBANDINFOA + +; ReBar notifications + +RBN_HEIGHTCHANGE = RBN_FIRST - 0 +RBN_GETOBJECT = RBN_FIRST - 1 +RBN_LAYOUTCHANGED = RBN_FIRST - 2 +RBN_AUTOSIZE = RBN_FIRST - 3 +RBN_BEGINDRAG = RBN_FIRST - 4 +RBN_ENDDRAG = RBN_FIRST - 5 +RBN_DELETINGBAND = RBN_FIRST - 6 +RBN_DELETEDBAND = RBN_FIRST - 7 +RBN_CHILDSIZE = RBN_FIRST - 8 + +; Tooltip styles + +TTS_ALWAYSTIP = 1 +TTS_NOPREFIX = 2 + +; Tooltip flags + +TTF_IDISHWND = 01h +TTF_CENTERTIP = 02h +TTF_RTLREADING = 04h +TTF_SUBCLASS = 10h + +; Tooltip durations + +TTDT_AUTOMATIC = 0 +TTDT_RESHOW = 1 +TTDT_AUTOPOP = 2 +TTDT_INITIAL = 3 + +; Tooltip messages + +TTM_ACTIVATE = WM_USER + 1 +TTM_SETDELAYTIME = WM_USER + 3 +TTM_ADDTOOLA = WM_USER + 4 +TTM_DELTOOLA = WM_USER + 5 +TTM_NEWTOOLRECTA = WM_USER + 6 +TTM_RELAYEVENT = WM_USER + 7 +TTM_GETTOOLINFOA = WM_USER + 8 +TTM_SETTOOLINFOA = WM_USER + 9 +TTM_HITTESTA = WM_USER + 10 +TTM_GETTEXTA = WM_USER + 11 +TTM_UPDATETIPTEXTA = WM_USER + 12 +TTM_GETTOOLCOUNT = WM_USER + 13 +TTM_ENUMTOOLSA = WM_USER + 14 +TTM_GETCURRENTTOOLA = WM_USER + 15 +TTM_WINDOWFROMPOINT = WM_USER + 16 +TTM_ADDTOOLW = WM_USER + 50 +TTM_DELTOOLW = WM_USER + 51 +TTM_NEWTOOLRECTW = WM_USER + 52 +TTM_GETTOOLINFOW = WM_USER + 53 +TTM_SETTOOLINFOW = WM_USER + 54 +TTM_HITTESTW = WM_USER + 55 +TTM_GETTEXTW = WM_USER + 56 +TTM_UPDATETIPTEXTW = WM_USER + 57 +TTM_ENUMTOOLSW = WM_USER + 58 +TTM_GETCURRENTTOOLW = WM_USER + 59 +TTM_ADDTOOL = TTM_ADDTOOLA +TTM_DELTOOL = TTM_DELTOOLA +TTM_NEWTOOLRECT = TTM_NEWTOOLRECTA +TTM_GETTOOLINFO = TTM_GETTOOLINFOA +TTM_SETTOOLINFO = TTM_SETTOOLINFOA +TTM_HITTEST = TTM_HITTESTA +TTM_GETTEXT = TTM_GETTEXTA +TTM_UPDATETIPTEXT = TTM_UPDATETIPTEXTA +TTM_ENUMTOOLS = TTM_ENUMTOOLSA +TTM_GETCURRENTTOOL = TTM_GETCURRENTTOOLA + +; Tooltip notifications + +TTN_NEEDTEXTA = TTN_FIRST - 0 +TTN_SHOW = TTN_FIRST - 1 +TTN_POP = TTN_FIRST - 2 +TTN_NEEDTEXTW = TTN_FIRST - 10 +TTN_NEEDTEXT = TTN_NEEDTEXTA + +; Status bar styles + +SBARS_SIZEGRIP = 100h + +; Status bar messages + +SB_SETTEXTA = WM_USER + 1 +SB_GETTEXTA = WM_USER + 2 +SB_GETTEXTLENGTHA = WM_USER + 3 +SB_SETPARTS = WM_USER + 4 +SB_GETPARTS = WM_USER + 6 +SB_GETBORDERS = WM_USER + 7 +SB_SETMINHEIGHT = WM_USER + 8 +SB_SIMPLE = WM_USER + 9 +SB_GETRECT = WM_USER + 10 +SB_SETTEXTW = WM_USER + 11 +SB_GETTEXTW = WM_USER + 13 +SB_GETTEXTLENGTHW = WM_USER + 12 +SB_SETTEXT = SB_SETTEXTA +SB_GETTEXT = SB_GETTEXTA +SB_GETTEXTLENGTH = SB_GETTEXTLENGTHA + +; Status bar drawing types + +SBT_OWNERDRAW = 1000h +SBT_NOBORDERS = 0100h +SBT_POPOUT = 0200h +SBT_RTLREADING = 0400h + +; Trackbar styles + +TBS_AUTOTICKS = 01h +TBS_VERT = 02h +TBS_HORZ = 00h +TBS_TOP = 04h +TBS_BOTTOM = 00h +TBS_LEFT = 04h +TBS_RIGHT = 00h +TBS_BOTH = 08h +TBS_NOTICKS = 10h +TBS_ENABLESELRANGE = 20h +TBS_FIXEDLENGTH = 40h +TBS_NOTHUMB = 80h + +; Trackbar messages + +TBM_GETPOS = WM_USER + 0 +TBM_GETRANGEMIN = WM_USER + 1 +TBM_GETRANGEMAX = WM_USER + 2 +TBM_GETTIC = WM_USER + 3 +TBM_SETTIC = WM_USER + 4 +TBM_SETPOS = WM_USER + 5 +TBM_SETRANGE = WM_USER + 6 +TBM_SETRANGEMIN = WM_USER + 7 +TBM_SETRANGEMAX = WM_USER + 8 +TBM_CLEARTICS = WM_USER + 9 +TBM_SETSEL = WM_USER + 10 +TBM_SETSELSTART = WM_USER + 11 +TBM_SETSELEND = WM_USER + 12 +TBM_GETPTICS = WM_USER + 14 +TBM_GETTICPOS = WM_USER + 15 +TBM_GETNUMTICS = WM_USER + 16 +TBM_GETSELSTART = WM_USER + 17 +TBM_GETSELEND = WM_USER + 18 +TBM_CLEARSEL = WM_USER + 19 +TBM_SETTICFREQ = WM_USER + 20 +TBM_SETPAGESIZE = WM_USER + 21 +TBM_GETPAGESIZE = WM_USER + 22 +TBM_SETLINESIZE = WM_USER + 23 +TBM_GETLINESIZE = WM_USER + 24 +TBM_GETTHUMBRECT = WM_USER + 25 +TBM_GETCHANNELRECT = WM_USER + 26 +TBM_SETTHUMBLENGTH = WM_USER + 27 +TBM_GETTHUMBLENGTH = WM_USER + 28 + +; Trackbar notifications + +TB_LINEUP = 0 +TB_LINEDOWN = 1 +TB_PAGEUP = 2 +TB_PAGEDOWN = 3 +TB_THUMBPOSITION = 4 +TB_THUMBTRACK = 5 +TB_TOP = 6 +TB_BOTTOM = 7 +TB_ENDTRACK = 8 + +; Up-down control styles + +UDS_WRAP = 01h +UDS_SETBUDDYINT = 02h +UDS_ALIGNRIGHT = 04h +UDS_ALIGNLEFT = 08h +UDS_AUTOBUDDY = 10h +UDS_ARROWKEYS = 20h +UDS_HORZ = 40h +UDS_NOTHOUSANDS = 80h + +; Up-down control messages + +UDM_SETRANGE = WM_USER + 101 +UDM_GETRANGE = WM_USER + 102 +UDM_SETPOS = WM_USER + 103 +UDM_GETPOS = WM_USER + 104 +UDM_SETBUDDY = WM_USER + 105 +UDM_GETBUDDY = WM_USER + 106 +UDM_SETACCEL = WM_USER + 107 +UDM_GETACCEL = WM_USER + 108 +UDM_SETBASE = WM_USER + 109 +UDM_GETBASE = WM_USER + 110 + +; Up-down control notifications + +UDN_DELTAPOS = UDN_FIRST - 1 + +; Progress bar messages + +PBM_SETRANGE = WM_USER + 1 +PBM_SETPOS = WM_USER + 2 +PBM_DELTAPOS = WM_USER + 3 +PBM_SETSTEP = WM_USER + 4 +PBM_STEPIT = WM_USER + 5 +PBM_SETRANGE32 = WM_USER + 6 +PBM_GETRANGE = WM_USER + 7 +PBM_GETPOS = WM_USER + 8 + +; Hot-key control messages + +HKM_SETHOTKEY = WM_USER + 1 +HKM_GETHOTKEY = WM_USER + 2 +HKM_SETRULES = WM_USER + 3 + +; Hot key flags + +HOTKEYF_SHIFT = 1 +HOTKEYF_CONTROL = 2 +HOTKEYF_ALT = 4 +HOTKEYF_EXT = 8 + +; Key combination flags + +HKCOMB_NONE = 01h +HKCOMB_S = 02h +HKCOMB_C = 04h +HKCOMB_A = 08h +HKCOMB_SC = 10h +HKCOMB_SA = 20h +HKCOMB_CA = 40h +HKCOMB_SCA = 80h + +; List view styles + +LVS_ICON = 0000h +LVS_REPORT = 0001h +LVS_SMALLICON = 0002h +LVS_LIST = 0003h +LVS_TYPEMASK = 0003h +LVS_SINGLESEL = 0004h +LVS_SHOWSELALWAYS = 0008h +LVS_SORTASCENDING = 0010h +LVS_SORTDESCENDING = 0020h +LVS_SHAREIMAGELISTS = 0040h +LVS_NOLABELWRAP = 0080h +LVS_AUTOARRANGE = 0100h +LVS_EDITLABELS = 0200h +LVS_OWNERDATA = 1000h +LVS_NOSCROLL = 2000h +LVS_ALIGNTOP = 0000h +LVS_ALIGNLEFT = 0800h +LVS_OWNERDRAWFIXED = 0400h +LVS_NOCOLUMNHEADER = 4000h +LVS_NOSORTHEADER = 8000h + +; List view extended styles + +LVS_EX_GRIDLINES = 0001h +LVS_EX_SUBITEMIMAGES = 0002h +LVS_EX_CHECKBOXES = 0004h +LVS_EX_TRACKSELECT = 0008h +LVS_EX_HEADERDRAGDROP = 0010h +LVS_EX_FULLROWSELECT = 0020h +LVS_EX_ONECLICKACTIVATE = 0040h +LVS_EX_TWOCLICKACTIVATE = 0080h +LVS_EX_FLATSB = 0100h +LVS_EX_REGIONAL = 0200h +LVS_EX_INFOTIP = 0400h +LVS_EX_UNDERLINEHOT = 0800h +LVS_EX_UNDERLINECOLD = 1000h +LVS_EX_MULTIWORKAREAS = 2000h +LVS_EX_LABELTIP = 4000h + +; List view messages + +LVM_GETBKCOLOR = LVM_FIRST + 0 +LVM_SETBKCOLOR = LVM_FIRST + 1 +LVM_GETIMAGELIST = LVM_FIRST + 2 +LVM_SETIMAGELIST = LVM_FIRST + 3 +LVM_GETITEMCOUNT = LVM_FIRST + 4 +LVM_GETITEMA = LVM_FIRST + 5 +LVM_SETITEMA = LVM_FIRST + 6 +LVM_INSERTITEMA = LVM_FIRST + 7 +LVM_DELETEITEM = LVM_FIRST + 8 +LVM_DELETEALLITEMS = LVM_FIRST + 9 +LVM_GETCALLBACKMASK = LVM_FIRST + 10 +LVM_SETCALLBACKMASK = LVM_FIRST + 11 +LVM_GETNEXTITEM = LVM_FIRST + 12 +LVM_FINDITEMA = LVM_FIRST + 13 +LVM_GETITEMRECT = LVM_FIRST + 14 +LVM_SETITEMPOSITION = LVM_FIRST + 15 +LVM_GETITEMPOSITION = LVM_FIRST + 16 +LVM_GETSTRINGWIDTHA = LVM_FIRST + 17 +LVM_HITTEST = LVM_FIRST + 18 +LVM_ENSUREVISIBLE = LVM_FIRST + 19 +LVM_SCROLL = LVM_FIRST + 20 +LVM_REDRAWITEMS = LVM_FIRST + 21 +LVM_ARRANGE = LVM_FIRST + 22 +LVM_EDITLABELA = LVM_FIRST + 23 +LVM_GETEDITCONTROL = LVM_FIRST + 24 +LVM_GETCOLUMNA = LVM_FIRST + 25 +LVM_SETCOLUMNA = LVM_FIRST + 26 +LVM_INSERTCOLUMNA = LVM_FIRST + 27 +LVM_DELETECOLUMN = LVM_FIRST + 28 +LVM_GETCOLUMNWIDTH = LVM_FIRST + 29 +LVM_SETCOLUMNWIDTH = LVM_FIRST + 30 +LVM_CREATEDRAGIMAGE = LVM_FIRST + 33 +LVM_GETVIEWRECT = LVM_FIRST + 34 +LVM_GETTEXTCOLOR = LVM_FIRST + 35 +LVM_SETTEXTCOLOR = LVM_FIRST + 36 +LVM_GETTEXTBKCOLOR = LVM_FIRST + 37 +LVM_SETTEXTBKCOLOR = LVM_FIRST + 38 +LVM_GETTOPINDEX = LVM_FIRST + 39 +LVM_GETCOUNTPERPAGE = LVM_FIRST + 40 +LVM_GETORIGIN = LVM_FIRST + 41 +LVM_UPDATE = LVM_FIRST + 42 +LVM_SETITEMSTATE = LVM_FIRST + 43 +LVM_GETITEMSTATE = LVM_FIRST + 44 +LVM_GETITEMTEXTA = LVM_FIRST + 45 +LVM_SETITEMTEXTA = LVM_FIRST + 46 +LVM_SETITEMCOUNT = LVM_FIRST + 47 +LVM_SORTITEMS = LVM_FIRST + 48 +LVM_SETITEMPOSITION32 = LVM_FIRST + 49 +LVM_GETSELECTEDCOUNT = LVM_FIRST + 50 +LVM_GETITEMSPACING = LVM_FIRST + 51 +LVM_GETISEARCHSTRINGA = LVM_FIRST + 52 +LVM_SETICONSPACING = LVM_FIRST + 53 +LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 54 +LVM_GETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 55 +LVM_GETSUBITEMRECT = LVM_FIRST + 56 +LVM_SUBITEMHITTEST = LVM_FIRST + 57 +LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58 +LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59 +LVM_SETHOTITEM = LVM_FIRST + 60 +LVM_GETHOTITEM = LVM_FIRST + 61 +LVM_SETHOTCURSOR = LVM_FIRST + 62 +LVM_GETHOTCURSOR = LVM_FIRST + 63 +LVM_APPROXIMATEVIEWRECT = LVM_FIRST + 64 +LVM_SETWORKAREA = LVM_FIRST + 65 +LVM_GETITEMW = LVM_FIRST + 75 +LVM_SETITEMW = LVM_FIRST + 76 +LVM_INSERTITEMW = LVM_FIRST + 77 +LVM_FINDITEMW = LVM_FIRST + 83 +LVM_GETSTRINGWIDTHW = LVM_FIRST + 87 +LVM_GETCOLUMNW = LVM_FIRST + 95 +LVM_SETCOLUMNW = LVM_FIRST + 96 +LVM_INSERTCOLUMNW = LVM_FIRST + 97 +LVM_GETITEMTEXTW = LVM_FIRST + 115 +LVM_SETITEMTEXTW = LVM_FIRST + 116 +LVM_GETISEARCHSTRINGW = LVM_FIRST + 117 +LVM_EDITLABELW = LVM_FIRST + 118 +LVM_GETITEM = LVM_GETITEMA +LVM_SETITEM = LVM_SETITEMA +LVM_INSERTITEM = LVM_INSERTITEMA +LVM_FINDITEM = LVM_FINDITEMA +LVM_GETSTRINGWIDTH = LVM_GETSTRINGWIDTHA +LVM_GETCOLUMN = LVM_GETCOLUMNA +LVM_SETCOLUMN = LVM_SETCOLUMNA +LVM_INSERTCOLUMN = LVM_INSERTCOLUMNA +LVM_GETITEMTEXT = LVM_GETITEMTEXTA +LVM_SETITEMTEXT = LVM_SETITEMTEXTA +LVM_GETISEARCHSTRING = LVM_GETISEARCHSTRINGA +LVM_EDITLABEL = LVM_EDITLABELA + +; List view image list types + +LVSIL_NORMAL = 0 +LVSIL_SMALL = 1 +LVSIL_STATE = 2 + +; LVM_SETITEMCOUNT flags + +LVSICF_NOINVALIDATEALL = 1 +LVSICF_NOSCROLL = 2 + +; List view item structure flags + +LVIF_TEXT = 0001h +LVIF_IMAGE = 0002h +LVIF_PARAM = 0004h +LVIF_STATE = 0008h +LVIF_INDENT = 0010h +LVIF_NORECOMPUTE = 0800h +LVIF_DI_SETITEM = 1000h + +; List view item states + +LVIS_FOCUSED = 00001h +LVIS_SELECTED = 00002h +LVIS_CUT = 00004h +LVIS_DROPHILITED = 00008h +LVIS_ACTIVATING = 0020h +LVIS_OVERLAYMASK = 00F00h +LVIS_STATEIMAGEMASK = 0F000h + +; List view callback item values + +LPSTR_TEXTCALLBACK = -1 +I_IMAGECALLBACK = -1 +I_CHILDRENCALLBACK = -1 + +; List view next item relations + +LVNI_ALL = 000h +LVNI_FOCUSED = 001h +LVNI_SELECTED = 002h +LVNI_CUT = 004h +LVNI_DROPHILITED = 008h +LVNI_ABOVE = 100h +LVNI_BELOW = 200h +LVNI_TOLEFT = 400h +LVNI_TORIGHT = 800h + +; List view search types + +LVFI_PARAM = 01h +LVFI_STRING = 02h +LVFI_PARTIAL = 08h +LVFI_WRAP = 20h +LVFI_NEARESTXY = 40h + +; List view item rectangle types + +LVIR_BOUNDS = 0 +LVIR_ICON = 1 +LVIR_LABEL = 2 +LVIR_SELECTBOUNDS = 3 + +; List view hit test flags + +LVHT_NOWHERE = 01h +LVHT_ONITEMICON = 02h +LVHT_ONITEMLABEL = 04h +LVHT_ONITEMSTATEICON= 08h +LVHT_ONITEM = LVHT_ONITEMICON or LVHT_ONITEMLABEL or LVHT_ONITEMSTATEICON +LVHT_ABOVE = 08h +LVHT_BELOW = 10h +LVHT_TORIGHT = 20h +LVHT_TOLEFT = 40h + +; List view alignment values + +LVA_DEFAULT = 000h +LVA_ALIGNLEFT = 001h +LVA_ALIGNTOP = 002h +LVA_ALIGNRIGHT = 003h +LVA_ALIGNBOTTOM = 004h +LVA_SNAPTOGRID = 005h +LVA_SORTASCENDING = 100h +LVA_SORTDESCENDING = 200h + +; List view column structure flags + +LVCF_FMT = 1 +LVCF_WIDTH = 2 +LVCF_TEXT = 4 +LVCF_SUBITEM = 8 + +; List view column alignment values + +LVCFMT_LEFT = 0 +LVCFMT_RIGHT = 1 +LVCFMT_CENTER = 2 +LVCFMT_JUSTIFYMASK = 3 + +; List view column width values + +LVSCW_AUTOSIZE = -1 +LVSCW_AUTOSIZE_USEHEADER = -2 + +; List view notifications + +LVN_ITEMCHANGING = LVN_FIRST - 0 +LVN_ITEMCHANGED = LVN_FIRST - 1 +LVN_INSERTITEM = LVN_FIRST - 2 +LVN_DELETEITEM = LVN_FIRST - 3 +LVN_DELETEALLITEMS = LVN_FIRST - 4 +LVN_BEGINLABELEDITA = LVN_FIRST - 5 +LVN_ENDLABELEDITA = LVN_FIRST - 6 +LVN_COLUMNCLICK = LVN_FIRST - 8 +LVN_BEGINDRAG = LVN_FIRST - 9 +LVN_BEGINRDRAG = LVN_FIRST - 11 +LVN_ODCACHEHINT = LVN_FIRST - 13 +LVN_GETDISPINFOA = LVN_FIRST - 50 +LVN_SETDISPINFOA = LVN_FIRST - 51 +LVN_ODFINDITEMA = LVN_FIRST - 52 +LVN_KEYDOWN = LVN_FIRST - 55 +LVN_BEGINLABELEDITW = LVN_FIRST - 75 +LVN_ENDLABELEDITW = LVN_FIRST - 76 +LVN_GETDISPINFOW = LVN_FIRST - 77 +LVN_SETDISPINFOW = LVN_FIRST - 78 +LVN_ODFINDITEMW = LVN_FIRST - 79 +LVN_BEGINLABELEDIT = LVN_BEGINLABELEDITA +LVN_ENDLABELEDIT = LVN_ENDLABELEDITA +LVN_GETDISPINFO = LVN_GETDISPINFOA +LVN_SETDISPINFO = LVN_SETDISPINFOA +LVN_ODFINDITEM = LVN_ODFINDITEMA + +; Tree view styles + +TVS_HASBUTTONS = 0001h +TVS_HASLINES = 0002h +TVS_LINESATROOT = 0004h +TVS_EDITLABELS = 0008h +TVS_DISABLEDRAGDROP = 0010h +TVS_SHOWSELALWAYS = 0020h +TVS_RTLREADING = 0040h +TVS_NOTOOLTIPS = 0080h +TVS_CHECKBOXES = 0100h +TVS_TRACKSELECT = 0200h +TVS_SINGLEEXPAND = 0400h +TVS_INFOTIP = 0800h +TVS_FULLROWSELECT = 1000h +TVS_NOSCROLL = 2000h +TVS_NONEVENHEIGHT = 4000h + +; Tree view item structure flags + +TVIF_TEXT = 0001h +TVIF_IMAGE = 0002h +TVIF_PARAM = 0004h +TVIF_STATE = 0008h +TVIF_HANDLE = 0010h +TVIF_SELECTEDIMAGE = 0020h +TVIF_CHILDREN = 0040h +TVIF_DI_SETITEM = 1000h + +; Tree view item states + +TVIS_FOCUSED = 00001h +TVIS_SELECTED = 00002h +TVIS_CUT = 00004h +TVIS_DROPHILITED = 00008h +TVIS_BOLD = 00010h +TVIS_EXPANDED = 00020h +TVIS_EXPANDEDONCE = 00040h +TVIS_EXPANDPARTIAL = 00080h +TVIS_OVERLAYMASK = 00F00h +TVIS_STATEIMAGEMASK = 0F000h +TVIS_USERMASK = 0F000h + +; Tree view predefined item values + +TVI_ROOT = 0FFFF0000h +TVI_FIRST = 0FFFF0001h +TVI_LAST = 0FFFF0002h +TVI_SORT = 0FFFF0003h + +; Tree view messages + +TVM_INSERTITEMA = TV_FIRST + 0 +TVM_DELETEITEM = TV_FIRST + 1 +TVM_EXPAND = TV_FIRST + 2 +TVM_GETITEMRECT = TV_FIRST + 4 +TVM_GETCOUNT = TV_FIRST + 5 +TVM_GETINDENT = TV_FIRST + 6 +TVM_SETINDENT = TV_FIRST + 7 +TVM_GETIMAGELIST = TV_FIRST + 8 +TVM_SETIMAGELIST = TV_FIRST + 9 +TVM_GETNEXTITEM = TV_FIRST + 10 +TVM_SELECTITEM = TV_FIRST + 11 +TVM_GETITEMA = TV_FIRST + 12 +TVM_SETITEMA = TV_FIRST + 13 +TVM_EDITLABELA = TV_FIRST + 14 +TVM_GETEDITCONTROL = TV_FIRST + 15 +TVM_GETVISIBLECOUNT = TV_FIRST + 16 +TVM_HITTEST = TV_FIRST + 17 +TVM_CREATEDRAGIMAGE = TV_FIRST + 18 +TVM_SORTCHILDREN = TV_FIRST + 19 +TVM_ENSUREVISIBLE = TV_FIRST + 20 +TVM_SORTCHILDRENCB = TV_FIRST + 21 +TVM_ENDEDITLABELNOW = TV_FIRST + 22 +TVM_GETISEARCHSTRINGA = TV_FIRST + 23 +TVM_INSERTITEMW = TV_FIRST + 50 +TVM_GETITEMW = TV_FIRST + 62 +TVM_SETITEMW = TV_FIRST + 63 +TVM_GETISEARCHSTRINGW = TV_FIRST + 64 +TVM_EDITLABELW = TV_FIRST + 65 +TVM_INSERTITEM = TVM_INSERTITEMA +TVM_GETITEM = TVM_GETITEMA +TVM_SETITEM = TVM_SETITEMA +TVM_GETISEARCHSTRING = TVM_GETISEARCHSTRINGA +TVM_EDITLABEL = TVM_EDITLABELA + +; Tree view action flags + +TVE_COLLAPSE = 0001h +TVE_EXPAND = 0002h +TVE_TOGGLE = 0003h +TVE_EXPANDPARTIAL = 4000h +TVE_COLLAPSERESET = 8000h + +; Tree view image list types + +TVSIL_NORMAL = 0 +TVSIL_STATE = 2 + +; Tree view next item types + +TVGN_ROOT = 0 +TVGN_NEXT = 1 +TVGN_PREVIOUS = 2 +TVGN_PARENT = 3 +TVGN_CHILD = 4 +TVGN_FIRSTVISIBLE = 5 +TVGN_NEXTVISIBLE = 6 +TVGN_PREVIOUSVISIBLE = 7 +TVGN_DROPHILITE = 8 +TVGN_CARET = 9 + +; Tree view hit test flags + +TVHT_NOWHERE = 001h +TVHT_ONITEMICON = 002h +TVHT_ONITEMLABEL = 004h +TVHT_ONITEMINDENT = 008h +TVHT_ONITEMBUTTON = 010h +TVHT_ONITEMRIGHT = 020h +TVHT_ONITEMSTATEICON = 040h +TVHT_ONITEM = TVHT_ONITEMICON or TVHT_ONITEMLABEL or TVHT_ONITEMSTATEICON +TVHT_ABOVE = 100h +TVHT_BELOW = 200h +TVHT_TORIGHT = 400h +TVHT_TOLEFT = 800h + +; Tree view notifications + +TVN_SELCHANGINGA = TVN_FIRST - 1 +TVN_SELCHANGEDA = TVN_FIRST - 2 +TVN_GETDISPINFOA = TVN_FIRST - 3 +TVN_SETDISPINFOA = TVN_FIRST - 4 +TVN_ITEMEXPANDINGA = TVN_FIRST - 5 +TVN_ITEMEXPANDEDA = TVN_FIRST - 6 +TVN_BEGINDRAGA = TVN_FIRST - 7 +TVN_BEGINRDRAGA = TVN_FIRST - 8 +TVN_DELETEITEMA = TVN_FIRST - 9 +TVN_BEGINLABELEDITA = TVN_FIRST - 10 +TVN_ENDLABELEDITA = TVN_FIRST - 11 +TVN_KEYDOWN = TVN_FIRST - 12 +TVN_SELCHANGINGW = TVN_FIRST - 50 +TVN_SELCHANGEDW = TVN_FIRST - 51 +TVN_GETDISPINFOW = TVN_FIRST - 52 +TVN_SETDISPINFOW = TVN_FIRST - 53 +TVN_ITEMEXPANDINGW = TVN_FIRST - 54 +TVN_ITEMEXPANDEDW = TVN_FIRST - 55 +TVN_BEGINDRAGW = TVN_FIRST - 56 +TVN_BEGINRDRAGW = TVN_FIRST - 57 +TVN_DELETEITEMW = TVN_FIRST - 58 +TVN_BEGINLABELEDITW = TVN_FIRST - 59 +TVN_ENDLABELEDITW = TVN_FIRST - 60 +TVN_SELCHANGING = TVN_SELCHANGINGA +TVN_SELCHANGED = TVN_SELCHANGEDA +TVN_GETDISPINFO = TVN_GETDISPINFOA +TVN_SETDISPINFO = TVN_SETDISPINFOA +TVN_ITEMEXPANDING = TVN_ITEMEXPANDINGA +TVN_ITEMEXPANDED = TVN_ITEMEXPANDEDA +TVN_BEGINDRAG = TVN_BEGINDRAGA +TVN_BEGINRDRAG = TVN_BEGINRDRAGA +TVN_DELETEITEM = TVN_DELETEITEMA +TVN_BEGINLABELEDIT = TVN_BEGINLABELEDITA +TVN_ENDLABELEDIT = TVN_ENDLABELEDITA + +; Tree view action flags + +TVC_UNKNOWN = 0 +TVC_BYMOUSE = 1 +TVC_BYKEYBOARD = 2 + +; Tab control styles + +TCS_SCROLLOPPOSITE = 0001h +TCS_BOTTOM = 0002h +TCS_RIGHT = 0002h +TCS_FORCEICONLEFT = 0010h +TCS_FORCELABELLEFT = 0020h +TCS_HOTTRACK = 0040h +TCS_VERTICAL = 0080h +TCS_TABS = 0000h +TCS_BUTTONS = 0100h +TCS_SINGLELINE = 0000h +TCS_MULTILINE = 0200h +TCS_RIGHTJUSTIFY = 0000h +TCS_FIXEDWIDTH = 0400h +TCS_RAGGEDRIGHT = 0800h +TCS_FOCUSONBUTTONDOWN = 1000h +TCS_OWNERDRAWFIXED = 2000h +TCS_TOOLTIPS = 4000h +TCS_FOCUSNEVER = 8000h + +; Tab control messages + +TCM_GETIMAGELIST = TCM_FIRST + 2 +TCM_SETIMAGELIST = TCM_FIRST + 3 +TCM_GETITEMCOUNT = TCM_FIRST + 4 +TCM_GETITEMA = TCM_FIRST + 5 +TCM_SETITEMA = TCM_FIRST + 6 +TCM_INSERTITEMA = TCM_FIRST + 7 +TCM_DELETEITEM = TCM_FIRST + 8 +TCM_DELETEALLITEMS = TCM_FIRST + 9 +TCM_GETITEMRECT = TCM_FIRST + 10 +TCM_GETCURSEL = TCM_FIRST + 11 +TCM_SETCURSEL = TCM_FIRST + 12 +TCM_HITTEST = TCM_FIRST + 13 +TCM_SETITEMEXTRA = TCM_FIRST + 14 +TCM_ADJUSTRECT = TCM_FIRST + 40 +TCM_SETITEMSIZE = TCM_FIRST + 41 +TCM_REMOVEIMAGE = TCM_FIRST + 42 +TCM_SETPADDING = TCM_FIRST + 43 +TCM_GETROWCOUNT = TCM_FIRST + 44 +TCM_GETTOOLTIPS = TCM_FIRST + 45 +TCM_SETTOOLTIPS = TCM_FIRST + 46 +TCM_GETCURFOCUS = TCM_FIRST + 47 +TCM_SETCURFOCUS = TCM_FIRST + 48 +TCM_GETITEMW = TCM_FIRST + 60 +TCM_SETITEMW = TCM_FIRST + 61 +TCM_INSERTITEMW = TCM_FIRST + 62 +TCM_GETITEM = TCM_GETITEMA +TCM_SETITEM = TCM_SETITEMA +TCM_INSERTITEM = TCM_INSERTITEMA + +; Tab control item structure flags + +TCIF_TEXT = 1 +TCIF_IMAGE = 2 +TCIF_RTLREADING = 4 +TCIF_PARAM = 8 + +; Tab control hit test flags + +TCHT_NOWHERE = 1 +TCHT_ONITEMICON = 2 +TCHT_ONITEMLABEL = 4 +TCHT_ONITEM = TCHT_ONITEMICON or TCHT_ONITEMLABEL + +; Tab control notifications + +TCN_KEYDOWN = TCN_FIRST - 0 +TCN_SELCHANGE = TCN_FIRST - 1 +TCN_SELCHANGING = TCN_FIRST - 2 + +; Animation control styles + +ACS_CENTER = 1 +ACS_TRANSPARENT = 2 +ACS_AUTOPLAY = 4 +ACS_TIMER = 8 + +; Animation control messages + +ACM_OPENA = WM_USER + 100 +ACM_PLAY = WM_USER + 101 +ACM_STOP = WM_USER + 102 +ACM_OPENW = WM_USER + 103 +ACM_OPEN = ACM_OPENA + +; Animation control notifications + +ACN_START = 1 +ACN_STOP = 2 + +; Month calendar styles + +MCS_DAYSTATE = 1 +MCS_MULTISELECT = 2 +MCS_WEEKNUMBERS = 4 +MCS_NOTODAY_PRE_IE4 = 8 +MCS_NOTODAYCIRCLE = 8 +MCS_NOTODAY = 16 + +; Month calendar messages + +MCM_GETCURSEL = MCM_FIRST + 1 +MCM_SETCURSEL = MCM_FIRST + 2 +MCM_GETMAXSELCOUNT = MCM_FIRST + 3 +MCM_SETMAXSELCOUNT = MCM_FIRST + 4 +MCM_GETSELRANGE = MCM_FIRST + 5 +MCM_SETSELRANGE = MCM_FIRST + 6 +MCM_GETMONTHRANGE = MCM_FIRST + 7 +MCM_SETDAYSTATE = MCM_FIRST + 8 +MCM_GETMINREQRECT = MCM_FIRST + 9 +MCM_SETCOLOR = MCM_FIRST + 10 +MCM_GETCOLOR = MCM_FIRST + 11 +MCM_SETTODAY = MCM_FIRST + 12 +MCM_GETTODAY = MCM_FIRST + 13 +MCM_HITTEST = MCM_FIRST + 14 +MCM_SETFIRSTDAYOFWEEK = MCM_FIRST + 15 +MCM_GETFIRSTDAYOFWEEK = MCM_FIRST + 16 +MCM_GETRANGE = MCM_FIRST + 17 +MCM_SETRANGE = MCM_FIRST + 18 +MCM_GETMONTHDELTA = MCM_FIRST + 19 +MCM_SETMONTHDELTA = MCM_FIRST + 20 + +; Month calendar hit test flags + +MCHT_TITLE = 0010000h +MCHT_CALENDAR = 0020000h +MCHT_TODAYLINK = 0030000h +MCHT_NEXT = 1000000h +MCHT_PREV = 2000000h +MCHT_NOWHERE = 0000000h +MCHT_TITLEBK = MCHT_TITLE +MCHT_TITLEMONTH = MCHT_TITLE or 1 +MCHT_TITLEYEAR = MCHT_TITLE or 2 +MCHT_TITLEBTNNEXT = MCHT_TITLE or MCHT_NEXT or 3 +MCHT_TITLEBTNPREV = MCHT_TITLE or MCHT_PREV or 3 +MCHT_CALENDARBK = MCHT_CALENDAR +MCHT_CALENDARDATE = MCHT_CALENDAR or 1 +MCHT_CALENDARDATENEXT = MCHT_CALENDARDATE or MCHT_NEXT +MCHT_CALENDARDATEPREV = MCHT_CALENDARDATE or MCHT_PREV +MCHT_CALENDARDAY = MCHT_CALENDAR or 2 +MCHT_CALENDARWEEKNUM = MCHT_CALENDAR or 3 + +; Month calendar color codes + +MCSC_BACKGROUND = 0 +MCSC_TEXT = 1 +MCSC_TITLEBK = 2 +MCSC_TITLETEXT = 3 +MCSC_MONTHBK = 4 +MCSC_TRAILINGTEXT = 5 + +; Month calendar notifications + +MCN_SELCHANGE = MCN_FIRST + 1 +MCN_GETDAYSTATE = MCN_FIRST + 3 +MCN_SELECT = MCN_FIRST + 4 + +; Date-time pick control messages + +DTM_GETSYSTEMTIME = DTM_FIRST + 1 +DTM_SETSYSTEMTIME = DTM_FIRST + 2 +DTM_GETRANGE = DTM_FIRST + 3 +DTM_SETRANGE = DTM_FIRST + 4 +DTM_SETFORMATA = DTM_FIRST + 5 +DTM_SETMCCOLOR = DTM_FIRST + 6 +DTM_GETMCCOLOR = DTM_FIRST + 7 +DTM_GETMONTHCAL = DTM_FIRST + 8 +DTM_SETMCFONT = DTM_FIRST + 9 +DTM_GETMCFONT = DTM_FIRST + 10 +DTM_SETFORMATW = DTM_FIRST + 50 +DTM_SETFORMAT = DTM_SETFORMATA + +; Date-time pick control styles + +DTS_UPDOWN = 01h +DTS_SHOWNONE = 02h +DTS_SHORTDATEFORMAT = 00h +DTS_LONGDATEFORMAT = 04h +DTS_TIMEFORMAT = 09h +DTS_APPCANPARSE = 10h +DTS_RIGHTALIGN = 20h + +; Date-time pick control notifications + +DTN_DATETIMECHANGE = DTN_FIRST + 1 +DTN_USERSTRINGA = DTN_FIRST + 2 +DTN_WMKEYDOWNA = DTN_FIRST + 3 +DTN_FORMATA = DTN_FIRST + 4 +DTN_FORMATQUERYA = DTN_FIRST + 5 +DTN_DROPDOWN = DTN_FIRST + 6 +DTN_CLOSEUP = DTN_FIRST + 7 +DTN_USERSTRINGW = DTN_FIRST + 15 +DTN_WMKEYDOWNW = DTN_FIRST + 16 +DTN_FORMATW = DTN_FIRST + 17 +DTN_FORMATQUERYW = DTN_FIRST + 18 +DTN_USERSTRING = DTN_USERSTRINGA +DTN_WMKEYDOWN = DTN_WMKEYDOWNA +DTN_FORMAT = DTN_FORMATA +DTN_FORMATQUERY = DTN_FORMATQUERYA + +; ImageList_LoadImage types + +IMAGE_BITMAP = 0 +IMAGE_ICON = 1 +IMAGE_CURSOR = 2 +IMAGE_ENHMETAFILE = 3 + +; ImageList_LoadImage flags + +LR_DEFAULTCOLOR = 0000h +LR_MONOCHROME = 0001h +LR_COLOR = 0002h +LR_COPYRETURNORG = 0004h +LR_COPYDELETEORG = 0008h +LR_LOADFROMFILE = 0010h +LR_LOADTRANSPARENT = 0020h +LR_DEFAULTSIZE = 0040h +LR_VGACOLOR = 0080h +LR_LOADMAP3DCOLORS = 1000h +LR_CREATEDIBSECTION = 2000h +LR_COPYFROMRESOURCE = 4000h +LR_SHARED = 8000h + +; IP control messages + +IPM_CLEARADDRESS = WM_USER + 100 +IPM_SETADDRESS = WM_USER + 101 +IPM_GETADDRESS = WM_USER + 102 +IPM_SETRANGE = WM_USER + 103 +IPM_SETFOCUS = WM_USER + 104 +IPM_ISBLANK = WM_USER + 105 + +; Custom Draw flags + +CDRF_DODEFAULT = 0 +CDRF_NEWFONT = 2 +CDRF_SKIPDEFAULT = 4 +CDRF_NOTIFYPOSTPAINT = 10h +CDRF_NOTIFYITEMDRAW = 20h +CDRF_NOTIFYSUBITEMDRAW = 20h +CDRF_NOTIFYPOSTERASE = 40h +CDDS_PREPAINT = 1 +CDDS_POSTPAINT = 2 +CDDS_PREERASE = 3 +CDDS_POSTERASE = 4 +CDDS_ITEM = 10000h +CDDS_ITEMPREPAINT = CDDS_ITEM or CDDS_PREPAINT +CDDS_ITEMPOSTPAINT = CDDS_ITEM or CDDS_POSTPAINT +CDDS_ITEMPREERASE = CDDS_ITEM or CDDS_PREERASE +CDDS_ITEMPOSTERASE = CDDS_ITEM or CDDS_POSTERASE +CDDS_SUBITEM = 20000h +CDIS_SELECTED = 1 +CDIS_GRAYED = 2 +CDIS_DISABLED = 4 +CDIS_CHECKED = 8 +CDIS_FOCUS = 10h +CDIS_DEFAULT = 20h +CDIS_HOT = 40h +CDIS_MARKED = 80h +CDIS_INDETERMINATE = 100h diff --git a/toolchain/fasm2/include/equates/comctl64.inc b/toolchain/fasm2/include/equates/comctl64.inc new file mode 100644 index 0000000..ad819ca --- /dev/null +++ b/toolchain/fasm2/include/equates/comctl64.inc @@ -0,0 +1,1899 @@ + +; COMCTL32.DLL structures and constants + +struct PROPSHEETPAGE + dwSize dd ? + dwFlags dd ? + hInstance dq ? + pszTemplate dq ? + pszIcon dq ? + pszTitle dq ? + pfnDlgProc dq ? + lParam dd ? + dd ? + pfnCallback dq ? + pcRefParent dq ? +ends + +struct PROPSHEETHEADER + dwSize dd ? + dwFlags dd ? + hwndParent dq ? + hInstance dq ? + pszIcon dq ? + pszCaption dq ? + nPages dd ? + dd ? + pStartPage dq ? + ppsp dq ? + pfnCallback dq ? +ends + +struct IMAGEINFO + hbmImage dq ? + hbmMask dq ? + Unused1 dd ? + Unused2 dd ? + rcImage RECT +ends + +struct HD_ITEM + mask dd ? + cxy dd ? + pszText dq ? + hbm dq ? + cchTextMax dd ? + fmt dd ? + lParam dd ? + dd ? +ends + +struct HD_LAYOUT + prc dq ? + pwpos dq ? +ends + +struct HD_HITTESTINFO + pt POINT + flags dd ? + iItem dd ? +ends + +struct HD_NOTIFY + hdr NMHDR + iItem dd ? + iButton dd ? + pitem dq ? +ends + +struct TBBUTTON + iBitmap dd ? + idCommand dd ? + fsState db ? + fsStyle db ? + db 6 dup ? + dwData dq ? + iString dq ? +ends + +struct COLORMAP + from dd ? + to dd ? +ends + +struct TBADDBITMAP + hInst dq ? + nID dd ? + dd ? +ends + +struct TBSAVEPARAMS + hkr dq ? + pszSubKey dq ? + pszValueName dq ? +ends + +struct TBREPLACEBITMAP + hInstOld dq ? + nIDOld dq ? + hInstNew dq ? + nIDNew dq ? + nButtons dq ? +ends + +struct NMTOOLBAR + hdr NMHDR + iItem dd ? + dd ? + tbButton TBBUTTON + cchText dd ? + dd ? + pszText dq ? +ends + +struct REBARINFO + cbSize dd ? + fMask dd ? + himl dq ? +ends + +struct REBARBANDINFO + cbSize dd ? + fMask dd ? + fStyle dd ? + clrFore dd ? + clrBack dd ? + dd ? + lpText dq ? + cch dd ? + iImage dd ? + hwndChild dd ? + cxMinChild dd ? + cyMinChild dd ? + cx dd ? + hbmBack dq ? + wID dd ? + dd ? +ends + +struct TOOLINFO + cbSize dd ? + uFlags dd ? + hwnd dq ? + uId dq ? + rect RECT + hInst dq ? + lpszText dq ? + lParam dq ? + lpReserved dq ? +ends + +struct TTHITTESTINFO + hwnd dq ? + pt POINT + ti TOOLINFO +ends + +struct TOOLTIPTEXT + hdr NMHDR + lpszText dq ? + szText db 80 dup (?) + hinst dq ? + uFlags dd ? + dd ? +ends + +struct UDACCEL + nSec dd ? + nInc dd ? +ends + +struct NM_UPDOWN + hdr NMHDR + iPos dd ? + iDelta dd ? +ends + +struct LV_ITEM + mask dd ? + iItem dd ? + iSubItem dd ? + state dd ? + stateMask dd ? + dd ? + pszText dq ? + cchTextMax dd ? + iImage dd ? + lParam dd ? + iIndent dd ? +ends + +struct LV_FINDINFO + flags dd ? + dd ? + psz dq ? + lParam dq ? + pt POINT + vkDirection dd ? + dd ? +ends + +struct LV_HITTESTINFO + pt POINT + flags dd ? + iItem dd ? +ends + +struct LV_COLUMN + mask dd ? + fmt dd ? + cx dd ? + dd ? + pszText dq ? + cchTextMax dd ? + iSubItem dd ? +ends + +struct NM_LISTVIEW + hdr NMHDR + iItem dd ? + iSubItem dd ? + uNewState dd ? + uOldState dd ? + uChanged dd ? + ptAction POINT + dd ? + lParam dq ? +ends + +struct NM_CACHEHINT + hdr NMHDR + iFrom dd ? + iTo dd ? +ends + +struct NM_FINDITEM + hdr NMHDR + iStart dd ? + dd ? + lvfi LV_FINDINFO +ends + +struct LV_DISPINFO + hdr NMHDR + item LV_ITEM +ends + +struct LV_KEYDOWN + hdr NMHDR + wVKey dw ? + dw ? + flags dd ? +ends + +struct TV_ITEM + mask dd ? + dd ? + hItem dq ? + state dd ? + stateMask dd ? + pszText dq ? + cchTextMax dd ? + iImage dd ? + iSelectedImage dd ? + cChildren dd ? + lParam dd ? + dd ? +ends + +struct TV_INSERTSTRUCT + hParent dq ? + hInsertAfter dq ? + item TV_ITEM +ends + +struct TV_HITTESTINFO + pt POINT + flags dd ? + dd ? + hItem dq ? +ends + +struct TV_SORTCB + hParent dq ? + lpfnCompare dq ? + lParam dq ? +ends + +struct NM_TREEVIEW + hdr NMHDR + action dd ? + dd ? + itemOld TV_ITEM + itemNew TV_ITEM + ptDrag POINT +ends + +struct TV_DISPINFO + hdr NMHDR + item TV_ITEM +ends + +struct TV_KEYDOWN + hdr NMHDR + wVKey dw ? + dw ? + flags dd ? +ends + +struct TC_ITEMHEADER + mask dd ? + lpReserved1 dd ? + lpReserved2 dd ? + dd ? + pszText dq ? + cchTextMax dd ? + iImage dd ? +ends + +struct TC_ITEM + mask dd ? + lpReserved1 dd ? + lpReserved2 dd ? + dd ? + pszText dq ? + cchTextMax dd ? + iImage dd ? + lParam dd ? + dd ? +ends + +struct TC_HITTESTINFO + pt POINT + flags dd ? +ends + +struct TC_KEYDOWN + hdr NMHDR + wVKey dw ? + dw ? + flags dd ? +ends + +struct MC_HITTESTINFO + cbSize dd ? + pt POINT + uHit dd ? + st SYSTEMTIME +ends + +struct NM_SELCHANGE + nmhdr NMHDR + stSelStart SYSTEMTIME + stSelEnd SYSTEMTIME +ends + +struct NM_DAYSTATE + nmhdr NMHDR + stStart SYSTEMTIME + cDayState dd ? + prgDayState dd ? +ends + +struct NM_DATETIMECHANGE + nmhdr NMHDR + dwFlags dd ? + st SYSTEMTIME + dd ? +ends + +struct NM_DATETIMESTRING + nmhdr NMHDR + pszUserString dq ? + st SYSTEMTIME + dwFlags dd ? + dd ? +ends + +struct NM_DATETIMEWMKEYDOWN + nmhdr NMHDR + nVirtKey dd ? + dd ? + pszFormat dq ? + st SYSTEMTIME +ends + +struct NM_DATETIMEFORMAT + nmhdr NMHDR + pszFormat dq ? + st SYSTEMTIME + pszDisplay dq ? + szDisplay db 64 dup (?) +ends + +struct NM_DATETIMEFORMATQUERY + nmhdr NMHDR + pszFormat dq ? + szMax SIZE +ends + +struct INITCOMMONCONTROLSEX + dwSize dd ? + dwICC dd ? +ends + +; Common control window classes + +HOTKEY_CLASS equ 'msctls_hotkey32' +PROGRESS_CLASS equ 'msctls_progress32' +STATUS_CLASS equ 'msctls_statusbar32' +TRACKBAR_CLASS equ 'msctls_trackbar32' +UPDOWN_CLASS equ 'msctls_updown32' +TOOLTIPS_CLASS equ 'tooltips_class32' +ANIMATE_CLASS equ 'SysAnimate32' +HEADER_CLASS equ 'SysHeader32' +LISTVIEW_CLASS equ 'SysListView32' +TREEVIEW_CLASS equ 'SysTreeView32' +TABCONTROL_CLASS equ 'SysTabControl32' +MONTHCAL_CLASS equ 'SysMonthCal32' +DATETIMEPICK_CLASS equ 'SysDateTimePick32' +TOOLBAR_CLASS equ 'ToolbarWindow32' +REBAR_CLASS equ 'ReBarWindow32' + +; Ranges for control message IDs + +LVM_FIRST = 1000h +TV_FIRST = 1100h +HDM_FIRST = 1200h +TCM_FIRST = 1300h +MCM_FIRST = 1000h +DTM_FIRST = 1000h +CCM_FIRST = 2000h + +; Ranges for control notification IDs + +NM_FIRST = 0 +LVN_FIRST = -100 +PSN_FIRST = -200 +HDN_FIRST = -300 +TVN_FIRST = -400 +TTN_FIRST = -520 +TCN_FIRST = -550 +CDN_FIRST = -601 +TBN_FIRST = -700 +UDN_FIRST = -721 +MCN_FIRST = -750 +DTN_FIRST = -760 +CBEN_FIRST = -800 +RBN_FIRST = -831 + +; Generic notifications + +NM_OUTOFMEMORY = NM_FIRST - 1 +NM_CLICK = NM_FIRST - 2 +NM_DBLCLK = NM_FIRST - 3 +NM_RETURN = NM_FIRST - 4 +NM_RCLICK = NM_FIRST - 5 +NM_RDBLCLK = NM_FIRST - 6 +NM_SETFOCUS = NM_FIRST - 7 +NM_KILLFOCUS = NM_FIRST - 8 +NM_CUSTOMDRAW = NM_FIRST - 12 + +; Common control styles + +CCS_TOP = 01h +CCS_NOMOVEY = 02h +CCS_BOTTOM = 03h +CCS_NORESIZE = 04h +CCS_NOPARENTALIGN = 08h +CCS_ADJUSTABLE = 20h +CCS_NODIVIDER = 40h +CCS_VERT = 80h +CCS_LEFT = CCS_VERT or CCS_TOP +CCS_RIGHT = CCS_VERT or CCS_BOTTOM +CCS_NOMOVEX = CCS_VERT or CCS_NOMOVEY + +; Owner-drawn control types + +ODT_HEADER = 100 +ODT_TAB = 101 +ODT_LISTVIEW = 102 + +; InitCommonControlsEx classes + +ICC_ANIMATE_CLASS = 0080h +ICC_BAR_CLASSES = 0004h +ICC_COOL_CLASSES = 0400h +ICC_DATE_CLASSES = 0100h +ICC_HOTKEY_CLASS = 0040h +ICC_INTERNET_CLASSES = 0800h +ICC_LISTVIEW_CLASSES = 0001h +ICC_PAGESCROLLER_CLASS = 1000h +ICC_PROGRESS_CLASS = 0020h +ICC_TAB_CLASSES = 0008h +ICC_TREEVIEW_CLASSES = 0002h +ICC_UPDOWN_CLASS = 0010h +ICC_USEREX_CLASSES = 0200h +ICC_WIN95_CLASSES = 00FFh + +; Shared messages + +CCM_SETCOLORSCHEME = CCM_FIRST + 2 +CCM_GETCOLORSCHEME = CCM_FIRST + 3 +CCM_GETDROPTARGET = CCM_FIRST + 4 +CCM_SETUNICODEFORMAT = CCM_FIRST + 5 +CCM_GETUNICODEFORMAT = CCM_FIRST + 6 + +; Property sheet page flags + +PSP_DEFAULT = 0000h +PSP_DLGINDIRECT = 0001h +PSP_USEHICON = 0002h +PSP_USEICONID = 0004h +PSP_USETITLE = 0008h +PSP_HASHELP = 0020h +PSP_USEREFPARENT = 0040h +PSP_USECALLBACK = 0080h + +; Property sheet page actions + +PSPCB_RELEASE = 1 +PSPCB_CREATE = 2 + +; Property sheet header flags + +PSH_DEFAULT = 0000h +PSH_PROPTITLE = 0001h +PSH_USEHICON = 0002h +PSH_USEICONID = 0004h +PSH_PROPSHEETPAGE = 0008h +PSH_MULTILINETABS = 0010h +PSH_WIZARD = 0020h +PSH_USEPSTARTPAGE = 0040h +PSH_NOAPPLYNOW = 0080h +PSH_USECALLBACK = 0100h +PSH_HASHELP = 0200h +PSH_MODELESS = 0400h + +; Property sheet actions + +PSCB_INITIALIZED = 1 + +; Property sheet notifications + +PSN_SETACTIVE = PSN_FIRST - 0 +PSN_KILLACTIVE = PSN_FIRST - 1 +PSN_APPLY = PSN_FIRST - 2 +PSN_RESET = PSN_FIRST - 3 +PSN_HELP = PSN_FIRST - 5 +PSN_WIZBACK = PSN_FIRST - 6 +PSN_WIZNEXT = PSN_FIRST - 7 +PSN_WIZFINISH = PSN_FIRST - 8 +PSN_QUERYCANCEL = PSN_FIRST - 9 + +; Property sheet return values + +PSNRET_NOERROR = 0 +PSNRET_INVALID = 1 +PSNRET_INVALID_NOCHANGEPAGE = 2 + +; Property sheet messages + +PSM_SETCURSEL = WM_USER + 101 +PSM_REMOVEPAGE = WM_USER + 102 +PSM_ADDPAGE = WM_USER + 103 +PSM_CHANGED = WM_USER + 104 +PSM_RESTARTWINDOWS = WM_USER + 105 +PSM_REBOOTSYSTEM = WM_USER + 106 +PSM_CANCELTOCLOSE = WM_USER + 107 +PSM_QUERYSIBLINGS = WM_USER + 108 +PSM_UNCHANGED = WM_USER + 109 +PSM_APPLY = WM_USER + 110 +PSM_SETTITLE = WM_USER + 111 +PSM_SETTITLEW = WM_USER + 120 +PSM_SETWIZBUTTONS = WM_USER + 112 +PSM_PRESSBUTTON = WM_USER + 113 +PSM_SETCURSELID = WM_USER + 114 +PSM_SETFINISHTEXT = WM_USER + 115 +PSM_SETFINISHTEXTW = WM_USER + 121 +PSM_GETTABCONTROL = WM_USER + 116 +PSM_ISDIALOGMESSAGE = WM_USER + 117 + +; Property sheet buttons + +PSBTN_BACK = 0 +PSBTN_NEXT = 1 +PSBTN_FINISH = 2 +PSBTN_OK = 3 +PSBTN_APPLYNOW = 4 +PSBTN_CANCEL = 5 +PSBTN_HELP = 6 +PSWIZB_BACK = 1 +PSWIZB_NEXT = 2 +PSWIZB_FINISH = 4 +PSWIZB_DISABLEDFINISH = 8 +ID_PSRESTARTWINDOWS = 2 +ID_PSREBOOTSYSTEM = ID_PSRESTARTWINDOWS or 1 + +; Property sheet sizes + +PROP_SM_CXDLG = 212 +PROP_SM_CYDLG = 188 +PROP_MED_CXDLG = 227 +PROP_MED_CYDLG = 215 +PROP_LG_CXDLG = 252 +PROP_LG_CYDLG = 218 +WIZ_CXDLG = 276 +WIZ_CYDLG = 140 +WIZ_CXBMP = 80 +WIZ_BODYX = 92 +WIZ_BODYCX = 184 + +; Image list types + +ILC_MASK = 001h +ILC_COLOR = 0FEh +ILC_COLORDDB = 0FEh +ILC_COLOR4 = 004h +ILC_COLOR8 = 008h +ILC_COLOR16 = 010h +ILC_COLOR24 = 018h +ILC_COLOR32 = 020h +ILC_PALETTE = 800h + +; Image list color values + +CLR_NONE = 0FFFFFFFFh +CLR_DEFAULT = 0FF000000h +CLR_HILIGHT = CLR_DEFAULT + +; Image list drawing styles + +ILD_NORMAL = 0000h +ILD_TRANSPARENT = 0001h +ILD_MASK = 0010h +ILD_IMAGE = 0020h +ILD_BLEND25 = 0002h +ILD_BLEND50 = 0004h +ILD_OVERLAYMASK = 0F00h +ILD_SELECTED = ILD_BLEND50 +ILD_FOCUS = ILD_BLEND25 +ILD_BLEND = ILD_BLEND50 + +; Header control styles + +HDS_HORZ = 00h +HDS_BUTTONS = 02h +HDS_HOTTRACK = 04h +HDS_HIDDEN = 08h +HDS_DRAGDROP = 40h +HDS_FULLDRAG = 80h + +; Header control structure flags + +HDI_WIDTH = 01h +HDI_HEIGHT = HDI_WIDTH +HDI_TEXT = 02h +HDI_FORMAT = 04h +HDI_LPARAM = 08h +HDI_BITMAP = 10h + +; Header control flags + +HDF_LEFT = 0000h +HDF_RIGHT = 0001h +HDF_CENTER = 0002h +HDF_JUSTIFYMASK = 0003h +HDF_RTLREADING = 0004h +HDF_BITMAP = 2000h +HDF_STRING = 4000h +HDF_OWNERDRAW = 8000h + +; Header control messages + +HDM_GETITEMCOUNT = HDM_FIRST + 0 +HDM_INSERTITEMA = HDM_FIRST + 1 +HDM_DELETEITEM = HDM_FIRST + 2 +HDM_GETITEMA = HDM_FIRST + 3 +HDM_SETITEMA = HDM_FIRST + 4 +HDM_LAYOUT = HDM_FIRST + 5 +HDM_HITTEST = HDM_FIRST + 6 +HDM_INSERTITEMW = HDM_FIRST + 10 +HDM_GETITEMW = HDM_FIRST + 11 +HDM_SETITEMW = HDM_FIRST + 12 +HDM_INSERTITEM = HDM_INSERTITEMA +HDM_GETITEM = HDM_GETITEMA +HDM_SETITEM = HDM_SETITEMA + +; Hit test result flags + +HHT_NOWHERE = 001h +HHT_ONHEADER = 002h +HHT_ONDIVIDER = 004h +HHT_ONDIVOPEN = 008h +HHT_ABOVE = 100h +HHT_BELOW = 200h +HHT_TORIGHT = 400h +HHT_TOLEFT = 800h + +; Header control notifications + +HDN_ITEMCHANGINGA = HDN_FIRST - 0 +HDN_ITEMCHANGEDA = HDN_FIRST - 1 +HDN_ITEMCLICKA = HDN_FIRST - 2 +HDN_ITEMDBLCLICKA = HDN_FIRST - 3 +HDN_DIVIDERDBLCLICKA = HDN_FIRST - 5 +HDN_BEGINTRACKA = HDN_FIRST - 6 +HDN_ENDTRACKA = HDN_FIRST - 7 +HDN_TRACKA = HDN_FIRST - 8 +HDN_ITEMCHANGINGW = HDN_FIRST - 20 +HDN_ITEMCHANGEDW = HDN_FIRST - 21 +HDN_ITEMCLICKW = HDN_FIRST - 22 +HDN_ITEMDBLCLICKW = HDN_FIRST - 23 +HDN_DIVIDERDBLCLICKW = HDN_FIRST - 25 +HDN_BEGINTRACKW = HDN_FIRST - 26 +HDN_ENDTRACKW = HDN_FIRST - 27 +HDN_TRACKW = HDN_FIRST - 28 +HDN_ITEMCHANGING = HDN_ITEMCHANGINGA +HDN_ITEMCHANGED = HDN_ITEMCHANGEDA +HDN_ITEMCLICK = HDN_ITEMCLICKA +HDN_ITEMDBLCLICK = HDN_ITEMDBLCLICKA +HDN_DIVIDERDBLCLICK = HDN_DIVIDERDBLCLICKA +HDN_BEGINTRACK = HDN_BEGINTRACKA +HDN_ENDTRACK = HDN_ENDTRACKA +HDN_TRACK = HDN_TRACKA + +; Toolbar bitmap flags + +CMB_MASKED = 2 + +; Toolbar button states + +TBSTATE_CHECKED = 01h +TBSTATE_PRESSED = 02h +TBSTATE_ENABLED = 04h +TBSTATE_HIDDEN = 08h +TBSTATE_INDETERMINATE = 10h +TBSTATE_WRAP = 20h +TBSTATE_ELLIPSES = 40h + +; Toolbar button styles + +TBSTYLE_BUTTON = 0000h +TBSTYLE_SEP = 0001h +TBSTYLE_CHECK = 0002h +TBSTYLE_GROUP = 0004h +TBSTYLE_CHECKGROUP = TBSTYLE_GROUP or TBSTYLE_CHECK +TBSTYLE_DROPDOWN = 0008h +TBSTYLE_TOOLTIPS = 0100h +TBSTYLE_WRAPABLE = 0200h +TBSTYLE_ALTDRAG = 0400h +TBSTYLE_FLAT = 0800h +TBSTYLE_LIST = 1000h +TBSTYLE_CUSTOMERASE = 2000h +TBSTYLE_TRANSPARENT = 8000h + +; Toolbar button extended styles + +TBSTYLE_EX_DRAWDDARROWS = 0001h + +; Toolbar messages + +TB_ENABLEBUTTON = WM_USER + 1 +TB_CHECKBUTTON = WM_USER + 2 +TB_PRESSBUTTON = WM_USER + 3 +TB_HIDEBUTTON = WM_USER + 4 +TB_INDETERMINATE = WM_USER + 5 +TB_ISBUTTONENABLED = WM_USER + 9 +TB_ISBUTTONCHECKED = WM_USER + 10 +TB_ISBUTTONPRESSED = WM_USER + 11 +TB_ISBUTTONHIDDEN = WM_USER + 12 +TB_ISBUTTONINDETERMINATE = WM_USER + 13 +TB_SETSTATE = WM_USER + 17 +TB_GETSTATE = WM_USER + 18 +TB_ADDBITMAP = WM_USER + 19 +TB_ADDBUTTONS = WM_USER + 20 +TB_INSERTBUTTON = WM_USER + 21 +TB_DELETEBUTTON = WM_USER + 22 +TB_GETBUTTON = WM_USER + 23 +TB_BUTTONCOUNT = WM_USER + 24 +TB_COMMANDTOINDEX = WM_USER + 25 +TB_SAVERESTOREA = WM_USER + 26 +TB_ADDSTRINGA = WM_USER + 28 +TB_CUSTOMIZE = WM_USER + 27 +TB_GETITEMRECT = WM_USER + 29 +TB_BUTTONSTRUCTSIZE = WM_USER + 30 +TB_SETBUTTONSIZE = WM_USER + 31 +TB_SETBITMAPSIZE = WM_USER + 32 +TB_AUTOSIZE = WM_USER + 33 +TB_GETTOOLTIPS = WM_USER + 35 +TB_SETTOOLTIPS = WM_USER + 36 +TB_SETPARENT = WM_USER + 37 +TB_SETROWS = WM_USER + 39 +TB_GETROWS = WM_USER + 40 +TB_GETBITMAPFLAGS = WM_USER + 41 +TB_SETCMDID = WM_USER + 42 +TB_CHANGEBITMAP = WM_USER + 43 +TB_GETBITMAP = WM_USER + 44 +TB_GETBUTTONTEXTA = WM_USER + 45 +TB_REPLACEBITMAP = WM_USER + 46 +TB_SETINDENT = WM_USER + 47 +TB_SETIMAGELIST = WM_USER + 48 +TB_GETIMAGELIST = WM_USER + 49 +TB_LOADIMAGES = WM_USER + 50 +TB_GETRECT = WM_USER + 51 +TB_SETHOTIMAGELIST = WM_USER + 52 +TB_GETHOTIMAGELIST = WM_USER + 53 +TB_SETDISABLEDIMAGELIST = WM_USER + 54 +TB_GETDISABLEDIMAGELIST = WM_USER + 55 +TB_SETSTYLE = WM_USER + 56 +TB_GETSTYLE = WM_USER + 57 +TB_GETBUTTONSIZE = WM_USER + 58 +TB_SETBUTTONWIDTH = WM_USER + 59 +TB_SETMAXTEXTROWS = WM_USER + 60 +TB_GETTEXTROWS = WM_USER + 61 +TB_GETBUTTONTEXTW = WM_USER + 75 +TB_SAVERESTOREW = WM_USER + 76 +TB_ADDSTRINGW = WM_USER + 77 +TB_SETEXTENDEDSTYLE = WM_USER + 84 +TB_GETEXTENDEDSTYLE = WM_USER + 85 +TB_GETBUTTONTEXT = TB_GETBUTTONTEXTA +TB_SAVERESTORE = TB_SAVERESTOREA +TB_ADDSTRING = TB_ADDSTRINGA + +; System-defined button bitmaps + +HINST_COMMCTRL = -1 +IDB_STD_SMALL_COLOR = 0 +IDB_STD_LARGE_COLOR = 1 +IDB_VIEW_SMALL_COLOR = 4 +IDB_VIEW_LARGE_COLOR = 5 +IDB_HIST_SMALL_COLOR = 8 +IDB_HIST_LARGE_COLOR = 9 + +; Icon indexes for standard bitmap + +STD_CUT = 0 +STD_COPY = 1 +STD_PASTE = 2 +STD_UNDO = 3 +STD_REDOW = 4 +STD_DELETE = 5 +STD_FILENEW = 6 +STD_FILEOPEN = 7 +STD_FILESAVE = 8 +STD_PRINTPRE = 9 +STD_PROPERTIES = 10 +STD_HELP = 11 +STD_FIND = 12 +STD_REPLACE = 13 +STD_PRINT = 14 + +; Icon indexes for standard view bitmap + +VIEW_LARGEICONS = 0 +VIEW_SMALLICONS = 1 +VIEW_LIST = 2 +VIEW_DETAILS = 3 +VIEW_SORTNAME = 4 +VIEW_SORTSIZE = 5 +VIEW_SORTDATE = 6 +VIEW_SORTTYPE = 7 +VIEW_PARENTFOLDER = 8 +VIEW_NETCONNECT = 9 +VIEW_NETDISCONNECT = 10 +VIEW_NEWFOLDER = 11 + +; Icon indexes for history bitmap + +HIST_BACK = 0 +HIST_FORWARD = 1 +HIST_FAVORITES = 2 +HIST_ADDTOFAVORITES = 3 +HIST_VIEWTREE = 4 + +; Toolbar bitmap flags + +TBBF_LARGE = 1 + +; Toolbar notifications + +TBN_GETBUTTONINFOA = TBN_FIRST - 0 +TBN_BEGINDRAG = TBN_FIRST - 1 +TBN_ENDDRAG = TBN_FIRST - 2 +TBN_BEGINADJUST = TBN_FIRST - 3 +TBN_ENDADJUST = TBN_FIRST - 4 +TBN_RESET = TBN_FIRST - 5 +TBN_QUERYINSERT = TBN_FIRST - 6 +TBN_QUERYDELETE = TBN_FIRST - 7 +TBN_TOOLBARCHANGE = TBN_FIRST - 8 +TBN_CUSTHELP = TBN_FIRST - 9 +TBN_DROPDOWN = TBN_FIRST - 10 +TBN_CLOSEUP = TBN_FIRST - 11 +TBN_GETBUTTONINFOW = TBN_FIRST - 20 +TBN_GETBUTTONINFO = TBN_GETBUTTONINFOA + +; ReBar styles + +RBS_TOOLTIPS = 100h +RBS_VARHEIGHT = 200h +RBS_BANDBORDERS = 400h +RBS_FIXEDORDER = 800h +RBS_REGISTERDROP = 1000h +RBS_AUTOSIZE = 2000h +RBS_VERTICALGRIPPER = 4000h +RBS_DBLCLKTOGGLE = 8000h + +; ReBar band info structure flags + +RBBIM_STYLE = 001h +RBBIM_COLORS = 002h +RBBIM_TEXT = 004h +RBBIM_IMAGE = 008h +RBBIM_CHILD = 010h +RBBIM_CHILDSIZE = 020h +RBBIM_SIZE = 040h +RBBIM_BACKGROUND = 080h +RBBIM_ID = 100h +RBBIM_IDEALSIZE = 200h +RBBIM_LPARAM = 400h +RBBIM_HEADERSIZE = 800h + +; ReBar band styles + +RBBS_BREAK = 001h +RBBS_FIXEDSIZE = 002h +RBBS_CHILDEDGE = 004h +RBBS_HIDDEN = 008h +RBBS_NOVERT = 010h +RBBS_FIXEDBMP = 020h +RBBS_VARIABLEHEIGHT = 040h +RBBS_GRIPPERALWAYS = 080h +RBBS_NOGRIPPER = 100h + +; ReBar messages + +RB_INSERTBANDA = WM_USER + 1 +RB_DELETEBAND = WM_USER + 2 +RB_GETBARINFO = WM_USER + 3 +RB_SETBARINFO = WM_USER + 4 +RB_GETBANDINFO = WM_USER + 5 +RB_SETBANDINFOA = WM_USER + 6 +RB_SETPARENT = WM_USER + 7 +RB_INSERTBANDW = WM_USER + 10 +RB_SETBANDINFOW = WM_USER + 11 +RB_GETBANDCOUNT = WM_USER + 12 +RB_GETROWCOUNT = WM_USER + 13 +RB_GETROWHEIGHT = WM_USER + 14 +RB_IDTOINDEX = WM_USER + 16 +RB_GETTOOLTIPS = WM_USER + 17 +RB_SETTOOLTIPS = WM_USER + 18 +RB_SETBKCOLOR = WM_USER + 19 +RB_GETBKCOLOR = WM_USER + 20 +RB_SETTEXTCOLOR = WM_USER + 21 +RB_GETTEXTCOLOR = WM_USER + 22 +RB_SIZETORECT = WM_USER + 23 +RB_BEGINDRAG = WM_USER + 24 +RB_ENDDRAG = WM_USER + 25 +RB_DRAGMOVE = WM_USER + 26 +RB_GETBARHEIGHT = WM_USER + 27 +RB_GETBANDINFOW = WM_USER + 28 +RB_GETBANDINFOA = WM_USER + 29 +RB_MINIMIZEBAND = WM_USER + 30 +RB_MAXIMIZEBAND = WM_USER + 31 +RB_GETDROPTARGET = CCM_GETDROPTARGET +RB_GETBANDBORDERS = WM_USER + 34 +RB_SHOWBAND = WM_USER + 35 +RB_SETPALETTE = WM_USER + 37 +RB_GETPALETTE = WM_USER + 38 +RB_MOVEBAND = WM_USER + 39 +RB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT +RB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT +RB_INSERTBAND = RB_INSERTBANDA +RB_SETBANDINFO = RB_SETBANDINFOA + +; ReBar notifications + +RBN_HEIGHTCHANGE = RBN_FIRST - 0 +RBN_GETOBJECT = RBN_FIRST - 1 +RBN_LAYOUTCHANGED = RBN_FIRST - 2 +RBN_AUTOSIZE = RBN_FIRST - 3 +RBN_BEGINDRAG = RBN_FIRST - 4 +RBN_ENDDRAG = RBN_FIRST - 5 +RBN_DELETINGBAND = RBN_FIRST - 6 +RBN_DELETEDBAND = RBN_FIRST - 7 +RBN_CHILDSIZE = RBN_FIRST - 8 + +; Tooltip styles + +TTS_ALWAYSTIP = 1 +TTS_NOPREFIX = 2 + +; Tooltip flags + +TTF_IDISHWND = 01h +TTF_CENTERTIP = 02h +TTF_RTLREADING = 04h +TTF_SUBCLASS = 10h + +; Tooltip durations + +TTDT_AUTOMATIC = 0 +TTDT_RESHOW = 1 +TTDT_AUTOPOP = 2 +TTDT_INITIAL = 3 + +; Tooltip messages + +TTM_ACTIVATE = WM_USER + 1 +TTM_SETDELAYTIME = WM_USER + 3 +TTM_ADDTOOLA = WM_USER + 4 +TTM_DELTOOLA = WM_USER + 5 +TTM_NEWTOOLRECTA = WM_USER + 6 +TTM_RELAYEVENT = WM_USER + 7 +TTM_GETTOOLINFOA = WM_USER + 8 +TTM_SETTOOLINFOA = WM_USER + 9 +TTM_HITTESTA = WM_USER + 10 +TTM_GETTEXTA = WM_USER + 11 +TTM_UPDATETIPTEXTA = WM_USER + 12 +TTM_GETTOOLCOUNT = WM_USER + 13 +TTM_ENUMTOOLSA = WM_USER + 14 +TTM_GETCURRENTTOOLA = WM_USER + 15 +TTM_WINDOWFROMPOINT = WM_USER + 16 +TTM_ADDTOOLW = WM_USER + 50 +TTM_DELTOOLW = WM_USER + 51 +TTM_NEWTOOLRECTW = WM_USER + 52 +TTM_GETTOOLINFOW = WM_USER + 53 +TTM_SETTOOLINFOW = WM_USER + 54 +TTM_HITTESTW = WM_USER + 55 +TTM_GETTEXTW = WM_USER + 56 +TTM_UPDATETIPTEXTW = WM_USER + 57 +TTM_ENUMTOOLSW = WM_USER + 58 +TTM_GETCURRENTTOOLW = WM_USER + 59 +TTM_ADDTOOL = TTM_ADDTOOLA +TTM_DELTOOL = TTM_DELTOOLA +TTM_NEWTOOLRECT = TTM_NEWTOOLRECTA +TTM_GETTOOLINFO = TTM_GETTOOLINFOA +TTM_SETTOOLINFO = TTM_SETTOOLINFOA +TTM_HITTEST = TTM_HITTESTA +TTM_GETTEXT = TTM_GETTEXTA +TTM_UPDATETIPTEXT = TTM_UPDATETIPTEXTA +TTM_ENUMTOOLS = TTM_ENUMTOOLSA +TTM_GETCURRENTTOOL = TTM_GETCURRENTTOOLA + +; Tooltip notifications + +TTN_NEEDTEXTA = TTN_FIRST - 0 +TTN_SHOW = TTN_FIRST - 1 +TTN_POP = TTN_FIRST - 2 +TTN_NEEDTEXTW = TTN_FIRST - 10 +TTN_NEEDTEXT = TTN_NEEDTEXTA + +; Status bar styles + +SBARS_SIZEGRIP = 100h + +; Status bar messages + +SB_SETTEXTA = WM_USER + 1 +SB_GETTEXTA = WM_USER + 2 +SB_GETTEXTLENGTHA = WM_USER + 3 +SB_SETPARTS = WM_USER + 4 +SB_GETPARTS = WM_USER + 6 +SB_GETBORDERS = WM_USER + 7 +SB_SETMINHEIGHT = WM_USER + 8 +SB_SIMPLE = WM_USER + 9 +SB_GETRECT = WM_USER + 10 +SB_SETTEXTW = WM_USER + 11 +SB_GETTEXTW = WM_USER + 13 +SB_GETTEXTLENGTHW = WM_USER + 12 +SB_SETTEXT = SB_SETTEXTA +SB_GETTEXT = SB_GETTEXTA +SB_GETTEXTLENGTH = SB_GETTEXTLENGTHA + +; Status bar drawing types + +SBT_OWNERDRAW = 1000h +SBT_NOBORDERS = 0100h +SBT_POPOUT = 0200h +SBT_RTLREADING = 0400h + +; Trackbar styles + +TBS_AUTOTICKS = 01h +TBS_VERT = 02h +TBS_HORZ = 00h +TBS_TOP = 04h +TBS_BOTTOM = 00h +TBS_LEFT = 04h +TBS_RIGHT = 00h +TBS_BOTH = 08h +TBS_NOTICKS = 10h +TBS_ENABLESELRANGE = 20h +TBS_FIXEDLENGTH = 40h +TBS_NOTHUMB = 80h + +; Trackbar messages + +TBM_GETPOS = WM_USER + 0 +TBM_GETRANGEMIN = WM_USER + 1 +TBM_GETRANGEMAX = WM_USER + 2 +TBM_GETTIC = WM_USER + 3 +TBM_SETTIC = WM_USER + 4 +TBM_SETPOS = WM_USER + 5 +TBM_SETRANGE = WM_USER + 6 +TBM_SETRANGEMIN = WM_USER + 7 +TBM_SETRANGEMAX = WM_USER + 8 +TBM_CLEARTICS = WM_USER + 9 +TBM_SETSEL = WM_USER + 10 +TBM_SETSELSTART = WM_USER + 11 +TBM_SETSELEND = WM_USER + 12 +TBM_GETPTICS = WM_USER + 14 +TBM_GETTICPOS = WM_USER + 15 +TBM_GETNUMTICS = WM_USER + 16 +TBM_GETSELSTART = WM_USER + 17 +TBM_GETSELEND = WM_USER + 18 +TBM_CLEARSEL = WM_USER + 19 +TBM_SETTICFREQ = WM_USER + 20 +TBM_SETPAGESIZE = WM_USER + 21 +TBM_GETPAGESIZE = WM_USER + 22 +TBM_SETLINESIZE = WM_USER + 23 +TBM_GETLINESIZE = WM_USER + 24 +TBM_GETTHUMBRECT = WM_USER + 25 +TBM_GETCHANNELRECT = WM_USER + 26 +TBM_SETTHUMBLENGTH = WM_USER + 27 +TBM_GETTHUMBLENGTH = WM_USER + 28 + +; Trackbar notifications + +TB_LINEUP = 0 +TB_LINEDOWN = 1 +TB_PAGEUP = 2 +TB_PAGEDOWN = 3 +TB_THUMBPOSITION = 4 +TB_THUMBTRACK = 5 +TB_TOP = 6 +TB_BOTTOM = 7 +TB_ENDTRACK = 8 + +; Up-down control styles + +UDS_WRAP = 01h +UDS_SETBUDDYINT = 02h +UDS_ALIGNRIGHT = 04h +UDS_ALIGNLEFT = 08h +UDS_AUTOBUDDY = 10h +UDS_ARROWKEYS = 20h +UDS_HORZ = 40h +UDS_NOTHOUSANDS = 80h + +; Up-down control messages + +UDM_SETRANGE = WM_USER + 101 +UDM_GETRANGE = WM_USER + 102 +UDM_SETPOS = WM_USER + 103 +UDM_GETPOS = WM_USER + 104 +UDM_SETBUDDY = WM_USER + 105 +UDM_GETBUDDY = WM_USER + 106 +UDM_SETACCEL = WM_USER + 107 +UDM_GETACCEL = WM_USER + 108 +UDM_SETBASE = WM_USER + 109 +UDM_GETBASE = WM_USER + 110 + +; Up-down control notifications + +UDN_DELTAPOS = UDN_FIRST - 1 + +; Progress bar messages + +PBM_SETRANGE = WM_USER + 1 +PBM_SETPOS = WM_USER + 2 +PBM_DELTAPOS = WM_USER + 3 +PBM_SETSTEP = WM_USER + 4 +PBM_STEPIT = WM_USER + 5 +PBM_SETRANGE32 = WM_USER + 6 +PBM_GETRANGE = WM_USER + 7 +PBM_GETPOS = WM_USER + 8 + +; Hot-key control messages + +HKM_SETHOTKEY = WM_USER + 1 +HKM_GETHOTKEY = WM_USER + 2 +HKM_SETRULES = WM_USER + 3 + +; Hot key flags + +HOTKEYF_SHIFT = 1 +HOTKEYF_CONTROL = 2 +HOTKEYF_ALT = 4 +HOTKEYF_EXT = 8 + +; Key combination flags + +HKCOMB_NONE = 01h +HKCOMB_S = 02h +HKCOMB_C = 04h +HKCOMB_A = 08h +HKCOMB_SC = 10h +HKCOMB_SA = 20h +HKCOMB_CA = 40h +HKCOMB_SCA = 80h + +; List view styles + +LVS_ICON = 0000h +LVS_REPORT = 0001h +LVS_SMALLICON = 0002h +LVS_LIST = 0003h +LVS_TYPEMASK = 0003h +LVS_SINGLESEL = 0004h +LVS_SHOWSELALWAYS = 0008h +LVS_SORTASCENDING = 0010h +LVS_SORTDESCENDING = 0020h +LVS_SHAREIMAGELISTS = 0040h +LVS_NOLABELWRAP = 0080h +LVS_AUTOARRANGE = 0100h +LVS_EDITLABELS = 0200h +LVS_OWNERDATA = 1000h +LVS_NOSCROLL = 2000h +LVS_ALIGNTOP = 0000h +LVS_ALIGNLEFT = 0800h +LVS_OWNERDRAWFIXED = 0400h +LVS_NOCOLUMNHEADER = 4000h +LVS_NOSORTHEADER = 8000h + +; List view extended styles + +LVS_EX_GRIDLINES = 0001h +LVS_EX_SUBITEMIMAGES = 0002h +LVS_EX_CHECKBOXES = 0004h +LVS_EX_TRACKSELECT = 0008h +LVS_EX_HEADERDRAGDROP = 0010h +LVS_EX_FULLROWSELECT = 0020h +LVS_EX_ONECLICKACTIVATE = 0040h +LVS_EX_TWOCLICKACTIVATE = 0080h +LVS_EX_FLATSB = 0100h +LVS_EX_REGIONAL = 0200h +LVS_EX_INFOTIP = 0400h +LVS_EX_UNDERLINEHOT = 0800h +LVS_EX_UNDERLINECOLD = 1000h +LVS_EX_MULTIWORKAREAS = 2000h +LVS_EX_LABELTIP = 4000h + +; List view messages + +LVM_GETBKCOLOR = LVM_FIRST + 0 +LVM_SETBKCOLOR = LVM_FIRST + 1 +LVM_GETIMAGELIST = LVM_FIRST + 2 +LVM_SETIMAGELIST = LVM_FIRST + 3 +LVM_GETITEMCOUNT = LVM_FIRST + 4 +LVM_GETITEMA = LVM_FIRST + 5 +LVM_SETITEMA = LVM_FIRST + 6 +LVM_INSERTITEMA = LVM_FIRST + 7 +LVM_DELETEITEM = LVM_FIRST + 8 +LVM_DELETEALLITEMS = LVM_FIRST + 9 +LVM_GETCALLBACKMASK = LVM_FIRST + 10 +LVM_SETCALLBACKMASK = LVM_FIRST + 11 +LVM_GETNEXTITEM = LVM_FIRST + 12 +LVM_FINDITEMA = LVM_FIRST + 13 +LVM_GETITEMRECT = LVM_FIRST + 14 +LVM_SETITEMPOSITION = LVM_FIRST + 15 +LVM_GETITEMPOSITION = LVM_FIRST + 16 +LVM_GETSTRINGWIDTHA = LVM_FIRST + 17 +LVM_HITTEST = LVM_FIRST + 18 +LVM_ENSUREVISIBLE = LVM_FIRST + 19 +LVM_SCROLL = LVM_FIRST + 20 +LVM_REDRAWITEMS = LVM_FIRST + 21 +LVM_ARRANGE = LVM_FIRST + 22 +LVM_EDITLABELA = LVM_FIRST + 23 +LVM_GETEDITCONTROL = LVM_FIRST + 24 +LVM_GETCOLUMNA = LVM_FIRST + 25 +LVM_SETCOLUMNA = LVM_FIRST + 26 +LVM_INSERTCOLUMNA = LVM_FIRST + 27 +LVM_DELETECOLUMN = LVM_FIRST + 28 +LVM_GETCOLUMNWIDTH = LVM_FIRST + 29 +LVM_SETCOLUMNWIDTH = LVM_FIRST + 30 +LVM_CREATEDRAGIMAGE = LVM_FIRST + 33 +LVM_GETVIEWRECT = LVM_FIRST + 34 +LVM_GETTEXTCOLOR = LVM_FIRST + 35 +LVM_SETTEXTCOLOR = LVM_FIRST + 36 +LVM_GETTEXTBKCOLOR = LVM_FIRST + 37 +LVM_SETTEXTBKCOLOR = LVM_FIRST + 38 +LVM_GETTOPINDEX = LVM_FIRST + 39 +LVM_GETCOUNTPERPAGE = LVM_FIRST + 40 +LVM_GETORIGIN = LVM_FIRST + 41 +LVM_UPDATE = LVM_FIRST + 42 +LVM_SETITEMSTATE = LVM_FIRST + 43 +LVM_GETITEMSTATE = LVM_FIRST + 44 +LVM_GETITEMTEXTA = LVM_FIRST + 45 +LVM_SETITEMTEXTA = LVM_FIRST + 46 +LVM_SETITEMCOUNT = LVM_FIRST + 47 +LVM_SORTITEMS = LVM_FIRST + 48 +LVM_SETITEMPOSITION32 = LVM_FIRST + 49 +LVM_GETSELECTEDCOUNT = LVM_FIRST + 50 +LVM_GETITEMSPACING = LVM_FIRST + 51 +LVM_GETISEARCHSTRINGA = LVM_FIRST + 52 +LVM_SETICONSPACING = LVM_FIRST + 53 +LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 54 +LVM_GETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 55 +LVM_GETSUBITEMRECT = LVM_FIRST + 56 +LVM_SUBITEMHITTEST = LVM_FIRST + 57 +LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58 +LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59 +LVM_SETHOTITEM = LVM_FIRST + 60 +LVM_GETHOTITEM = LVM_FIRST + 61 +LVM_SETHOTCURSOR = LVM_FIRST + 62 +LVM_GETHOTCURSOR = LVM_FIRST + 63 +LVM_APPROXIMATEVIEWRECT = LVM_FIRST + 64 +LVM_SETWORKAREA = LVM_FIRST + 65 +LVM_GETITEMW = LVM_FIRST + 75 +LVM_SETITEMW = LVM_FIRST + 76 +LVM_INSERTITEMW = LVM_FIRST + 77 +LVM_FINDITEMW = LVM_FIRST + 83 +LVM_GETSTRINGWIDTHW = LVM_FIRST + 87 +LVM_GETCOLUMNW = LVM_FIRST + 95 +LVM_SETCOLUMNW = LVM_FIRST + 96 +LVM_INSERTCOLUMNW = LVM_FIRST + 97 +LVM_GETITEMTEXTW = LVM_FIRST + 115 +LVM_SETITEMTEXTW = LVM_FIRST + 116 +LVM_GETISEARCHSTRINGW = LVM_FIRST + 117 +LVM_EDITLABELW = LVM_FIRST + 118 +LVM_GETITEM = LVM_GETITEMA +LVM_SETITEM = LVM_SETITEMA +LVM_INSERTITEM = LVM_INSERTITEMA +LVM_FINDITEM = LVM_FINDITEMA +LVM_GETSTRINGWIDTH = LVM_GETSTRINGWIDTHA +LVM_GETCOLUMN = LVM_GETCOLUMNA +LVM_SETCOLUMN = LVM_SETCOLUMNA +LVM_INSERTCOLUMN = LVM_INSERTCOLUMNA +LVM_GETITEMTEXT = LVM_GETITEMTEXTA +LVM_SETITEMTEXT = LVM_SETITEMTEXTA +LVM_GETISEARCHSTRING = LVM_GETISEARCHSTRINGA +LVM_EDITLABEL = LVM_EDITLABELA + +; List view image list types + +LVSIL_NORMAL = 0 +LVSIL_SMALL = 1 +LVSIL_STATE = 2 + +; LVM_SETITEMCOUNT flags + +LVSICF_NOINVALIDATEALL = 1 +LVSICF_NOSCROLL = 2 + +; List view item structure flags + +LVIF_TEXT = 0001h +LVIF_IMAGE = 0002h +LVIF_PARAM = 0004h +LVIF_STATE = 0008h +LVIF_INDENT = 0010h +LVIF_NORECOMPUTE = 0800h +LVIF_DI_SETITEM = 1000h + +; List view item states + +LVIS_FOCUSED = 00001h +LVIS_SELECTED = 00002h +LVIS_CUT = 00004h +LVIS_DROPHILITED = 00008h +LVIS_ACTIVATING = 0020h +LVIS_OVERLAYMASK = 00F00h +LVIS_STATEIMAGEMASK = 0F000h + +; List view callback item values + +LPSTR_TEXTCALLBACK = -1 +I_IMAGECALLBACK = -1 +I_CHILDRENCALLBACK = -1 + +; List view next item relations + +LVNI_ALL = 000h +LVNI_FOCUSED = 001h +LVNI_SELECTED = 002h +LVNI_CUT = 004h +LVNI_DROPHILITED = 008h +LVNI_ABOVE = 100h +LVNI_BELOW = 200h +LVNI_TOLEFT = 400h +LVNI_TORIGHT = 800h + +; List view search types + +LVFI_PARAM = 01h +LVFI_STRING = 02h +LVFI_PARTIAL = 08h +LVFI_WRAP = 20h +LVFI_NEARESTXY = 40h + +; List view item rectangle types + +LVIR_BOUNDS = 0 +LVIR_ICON = 1 +LVIR_LABEL = 2 +LVIR_SELECTBOUNDS = 3 + +; List view hit test flags + +LVHT_NOWHERE = 01h +LVHT_ONITEMICON = 02h +LVHT_ONITEMLABEL = 04h +LVHT_ONITEMSTATEICON= 08h +LVHT_ONITEM = LVHT_ONITEMICON or LVHT_ONITEMLABEL or LVHT_ONITEMSTATEICON +LVHT_ABOVE = 08h +LVHT_BELOW = 10h +LVHT_TORIGHT = 20h +LVHT_TOLEFT = 40h + +; List view alignment values + +LVA_DEFAULT = 000h +LVA_ALIGNLEFT = 001h +LVA_ALIGNTOP = 002h +LVA_ALIGNRIGHT = 003h +LVA_ALIGNBOTTOM = 004h +LVA_SNAPTOGRID = 005h +LVA_SORTASCENDING = 100h +LVA_SORTDESCENDING = 200h + +; List view column structure flags + +LVCF_FMT = 1 +LVCF_WIDTH = 2 +LVCF_TEXT = 4 +LVCF_SUBITEM = 8 + +; List view column alignment values + +LVCFMT_LEFT = 0 +LVCFMT_RIGHT = 1 +LVCFMT_CENTER = 2 +LVCFMT_JUSTIFYMASK = 3 + +; List view column width values + +LVSCW_AUTOSIZE = -1 +LVSCW_AUTOSIZE_USEHEADER = -2 + +; List view notifications + +LVN_ITEMCHANGING = LVN_FIRST - 0 +LVN_ITEMCHANGED = LVN_FIRST - 1 +LVN_INSERTITEM = LVN_FIRST - 2 +LVN_DELETEITEM = LVN_FIRST - 3 +LVN_DELETEALLITEMS = LVN_FIRST - 4 +LVN_BEGINLABELEDITA = LVN_FIRST - 5 +LVN_ENDLABELEDITA = LVN_FIRST - 6 +LVN_COLUMNCLICK = LVN_FIRST - 8 +LVN_BEGINDRAG = LVN_FIRST - 9 +LVN_BEGINRDRAG = LVN_FIRST - 11 +LVN_ODCACHEHINT = LVN_FIRST - 13 +LVN_GETDISPINFOA = LVN_FIRST - 50 +LVN_SETDISPINFOA = LVN_FIRST - 51 +LVN_ODFINDITEMA = LVN_FIRST - 52 +LVN_KEYDOWN = LVN_FIRST - 55 +LVN_BEGINLABELEDITW = LVN_FIRST - 75 +LVN_ENDLABELEDITW = LVN_FIRST - 76 +LVN_GETDISPINFOW = LVN_FIRST - 77 +LVN_SETDISPINFOW = LVN_FIRST - 78 +LVN_ODFINDITEMW = LVN_FIRST - 79 +LVN_BEGINLABELEDIT = LVN_BEGINLABELEDITA +LVN_ENDLABELEDIT = LVN_ENDLABELEDITA +LVN_GETDISPINFO = LVN_GETDISPINFOA +LVN_SETDISPINFO = LVN_SETDISPINFOA +LVN_ODFINDITEM = LVN_ODFINDITEMA + +; Tree view styles + +TVS_HASBUTTONS = 0001h +TVS_HASLINES = 0002h +TVS_LINESATROOT = 0004h +TVS_EDITLABELS = 0008h +TVS_DISABLEDRAGDROP = 0010h +TVS_SHOWSELALWAYS = 0020h +TVS_RTLREADING = 0040h +TVS_NOTOOLTIPS = 0080h +TVS_CHECKBOXES = 0100h +TVS_TRACKSELECT = 0200h +TVS_SINGLEEXPAND = 0400h +TVS_INFOTIP = 0800h +TVS_FULLROWSELECT = 1000h +TVS_NOSCROLL = 2000h +TVS_NONEVENHEIGHT = 4000h + +; Tree view item structure flags + +TVIF_TEXT = 0001h +TVIF_IMAGE = 0002h +TVIF_PARAM = 0004h +TVIF_STATE = 0008h +TVIF_HANDLE = 0010h +TVIF_SELECTEDIMAGE = 0020h +TVIF_CHILDREN = 0040h +TVIF_DI_SETITEM = 1000h + +; Tree view item states + +TVIS_FOCUSED = 00001h +TVIS_SELECTED = 00002h +TVIS_CUT = 00004h +TVIS_DROPHILITED = 00008h +TVIS_BOLD = 00010h +TVIS_EXPANDED = 00020h +TVIS_EXPANDEDONCE = 00040h +TVIS_EXPANDPARTIAL = 00080h +TVIS_OVERLAYMASK = 00F00h +TVIS_STATEIMAGEMASK = 0F000h +TVIS_USERMASK = 0F000h + +; Tree view predefined item values + +TVI_ROOT = 0FFFF0000h +TVI_FIRST = 0FFFF0001h +TVI_LAST = 0FFFF0002h +TVI_SORT = 0FFFF0003h + +; Tree view messages + +TVM_INSERTITEMA = TV_FIRST + 0 +TVM_DELETEITEM = TV_FIRST + 1 +TVM_EXPAND = TV_FIRST + 2 +TVM_GETITEMRECT = TV_FIRST + 4 +TVM_GETCOUNT = TV_FIRST + 5 +TVM_GETINDENT = TV_FIRST + 6 +TVM_SETINDENT = TV_FIRST + 7 +TVM_GETIMAGELIST = TV_FIRST + 8 +TVM_SETIMAGELIST = TV_FIRST + 9 +TVM_GETNEXTITEM = TV_FIRST + 10 +TVM_SELECTITEM = TV_FIRST + 11 +TVM_GETITEMA = TV_FIRST + 12 +TVM_SETITEMA = TV_FIRST + 13 +TVM_EDITLABELA = TV_FIRST + 14 +TVM_GETEDITCONTROL = TV_FIRST + 15 +TVM_GETVISIBLECOUNT = TV_FIRST + 16 +TVM_HITTEST = TV_FIRST + 17 +TVM_CREATEDRAGIMAGE = TV_FIRST + 18 +TVM_SORTCHILDREN = TV_FIRST + 19 +TVM_ENSUREVISIBLE = TV_FIRST + 20 +TVM_SORTCHILDRENCB = TV_FIRST + 21 +TVM_ENDEDITLABELNOW = TV_FIRST + 22 +TVM_GETISEARCHSTRINGA = TV_FIRST + 23 +TVM_INSERTITEMW = TV_FIRST + 50 +TVM_GETITEMW = TV_FIRST + 62 +TVM_SETITEMW = TV_FIRST + 63 +TVM_GETISEARCHSTRINGW = TV_FIRST + 64 +TVM_EDITLABELW = TV_FIRST + 65 +TVM_INSERTITEM = TVM_INSERTITEMA +TVM_GETITEM = TVM_GETITEMA +TVM_SETITEM = TVM_SETITEMA +TVM_GETISEARCHSTRING = TVM_GETISEARCHSTRINGA +TVM_EDITLABEL = TVM_EDITLABELA + +; Tree view action flags + +TVE_COLLAPSE = 0001h +TVE_EXPAND = 0002h +TVE_TOGGLE = 0003h +TVE_EXPANDPARTIAL = 4000h +TVE_COLLAPSERESET = 8000h + +; Tree view image list types + +TVSIL_NORMAL = 0 +TVSIL_STATE = 2 + +; Tree view next item types + +TVGN_ROOT = 0 +TVGN_NEXT = 1 +TVGN_PREVIOUS = 2 +TVGN_PARENT = 3 +TVGN_CHILD = 4 +TVGN_FIRSTVISIBLE = 5 +TVGN_NEXTVISIBLE = 6 +TVGN_PREVIOUSVISIBLE = 7 +TVGN_DROPHILITE = 8 +TVGN_CARET = 9 + +; Tree view hit test flags + +TVHT_NOWHERE = 001h +TVHT_ONITEMICON = 002h +TVHT_ONITEMLABEL = 004h +TVHT_ONITEMINDENT = 008h +TVHT_ONITEMBUTTON = 010h +TVHT_ONITEMRIGHT = 020h +TVHT_ONITEMSTATEICON = 040h +TVHT_ONITEM = TVHT_ONITEMICON or TVHT_ONITEMLABEL or TVHT_ONITEMSTATEICON +TVHT_ABOVE = 100h +TVHT_BELOW = 200h +TVHT_TORIGHT = 400h +TVHT_TOLEFT = 800h + +; Tree view notifications + +TVN_SELCHANGINGA = TVN_FIRST - 1 +TVN_SELCHANGEDA = TVN_FIRST - 2 +TVN_GETDISPINFOA = TVN_FIRST - 3 +TVN_SETDISPINFOA = TVN_FIRST - 4 +TVN_ITEMEXPANDINGA = TVN_FIRST - 5 +TVN_ITEMEXPANDEDA = TVN_FIRST - 6 +TVN_BEGINDRAGA = TVN_FIRST - 7 +TVN_BEGINRDRAGA = TVN_FIRST - 8 +TVN_DELETEITEMA = TVN_FIRST - 9 +TVN_BEGINLABELEDITA = TVN_FIRST - 10 +TVN_ENDLABELEDITA = TVN_FIRST - 11 +TVN_KEYDOWN = TVN_FIRST - 12 +TVN_SELCHANGINGW = TVN_FIRST - 50 +TVN_SELCHANGEDW = TVN_FIRST - 51 +TVN_GETDISPINFOW = TVN_FIRST - 52 +TVN_SETDISPINFOW = TVN_FIRST - 53 +TVN_ITEMEXPANDINGW = TVN_FIRST - 54 +TVN_ITEMEXPANDEDW = TVN_FIRST - 55 +TVN_BEGINDRAGW = TVN_FIRST - 56 +TVN_BEGINRDRAGW = TVN_FIRST - 57 +TVN_DELETEITEMW = TVN_FIRST - 58 +TVN_BEGINLABELEDITW = TVN_FIRST - 59 +TVN_ENDLABELEDITW = TVN_FIRST - 60 +TVN_SELCHANGING = TVN_SELCHANGINGA +TVN_SELCHANGED = TVN_SELCHANGEDA +TVN_GETDISPINFO = TVN_GETDISPINFOA +TVN_SETDISPINFO = TVN_SETDISPINFOA +TVN_ITEMEXPANDING = TVN_ITEMEXPANDINGA +TVN_ITEMEXPANDED = TVN_ITEMEXPANDEDA +TVN_BEGINDRAG = TVN_BEGINDRAGA +TVN_BEGINRDRAG = TVN_BEGINRDRAGA +TVN_DELETEITEM = TVN_DELETEITEMA +TVN_BEGINLABELEDIT = TVN_BEGINLABELEDITA +TVN_ENDLABELEDIT = TVN_ENDLABELEDITA + +; Tree view action flags + +TVC_UNKNOWN = 0 +TVC_BYMOUSE = 1 +TVC_BYKEYBOARD = 2 + +; Tab control styles + +TCS_SCROLLOPPOSITE = 0001h +TCS_BOTTOM = 0002h +TCS_RIGHT = 0002h +TCS_FORCEICONLEFT = 0010h +TCS_FORCELABELLEFT = 0020h +TCS_HOTTRACK = 0040h +TCS_VERTICAL = 0080h +TCS_TABS = 0000h +TCS_BUTTONS = 0100h +TCS_SINGLELINE = 0000h +TCS_MULTILINE = 0200h +TCS_RIGHTJUSTIFY = 0000h +TCS_FIXEDWIDTH = 0400h +TCS_RAGGEDRIGHT = 0800h +TCS_FOCUSONBUTTONDOWN = 1000h +TCS_OWNERDRAWFIXED = 2000h +TCS_TOOLTIPS = 4000h +TCS_FOCUSNEVER = 8000h + +; Tab control messages + +TCM_GETIMAGELIST = TCM_FIRST + 2 +TCM_SETIMAGELIST = TCM_FIRST + 3 +TCM_GETITEMCOUNT = TCM_FIRST + 4 +TCM_GETITEMA = TCM_FIRST + 5 +TCM_SETITEMA = TCM_FIRST + 6 +TCM_INSERTITEMA = TCM_FIRST + 7 +TCM_DELETEITEM = TCM_FIRST + 8 +TCM_DELETEALLITEMS = TCM_FIRST + 9 +TCM_GETITEMRECT = TCM_FIRST + 10 +TCM_GETCURSEL = TCM_FIRST + 11 +TCM_SETCURSEL = TCM_FIRST + 12 +TCM_HITTEST = TCM_FIRST + 13 +TCM_SETITEMEXTRA = TCM_FIRST + 14 +TCM_ADJUSTRECT = TCM_FIRST + 40 +TCM_SETITEMSIZE = TCM_FIRST + 41 +TCM_REMOVEIMAGE = TCM_FIRST + 42 +TCM_SETPADDING = TCM_FIRST + 43 +TCM_GETROWCOUNT = TCM_FIRST + 44 +TCM_GETTOOLTIPS = TCM_FIRST + 45 +TCM_SETTOOLTIPS = TCM_FIRST + 46 +TCM_GETCURFOCUS = TCM_FIRST + 47 +TCM_SETCURFOCUS = TCM_FIRST + 48 +TCM_GETITEMW = TCM_FIRST + 60 +TCM_SETITEMW = TCM_FIRST + 61 +TCM_INSERTITEMW = TCM_FIRST + 62 +TCM_GETITEM = TCM_GETITEMA +TCM_SETITEM = TCM_SETITEMA +TCM_INSERTITEM = TCM_INSERTITEMA + +; Tab control item structure flags + +TCIF_TEXT = 1 +TCIF_IMAGE = 2 +TCIF_RTLREADING = 4 +TCIF_PARAM = 8 + +; Tab control hit test flags + +TCHT_NOWHERE = 1 +TCHT_ONITEMICON = 2 +TCHT_ONITEMLABEL = 4 +TCHT_ONITEM = TCHT_ONITEMICON or TCHT_ONITEMLABEL + +; Tab control notifications + +TCN_KEYDOWN = TCN_FIRST - 0 +TCN_SELCHANGE = TCN_FIRST - 1 +TCN_SELCHANGING = TCN_FIRST - 2 + +; Animation control styles + +ACS_CENTER = 1 +ACS_TRANSPARENT = 2 +ACS_AUTOPLAY = 4 +ACS_TIMER = 8 + +; Animation control messages + +ACM_OPENA = WM_USER + 100 +ACM_PLAY = WM_USER + 101 +ACM_STOP = WM_USER + 102 +ACM_OPENW = WM_USER + 103 +ACM_OPEN = ACM_OPENA + +; Animation control notifications + +ACN_START = 1 +ACN_STOP = 2 + +; Month calendar styles + +MCS_DAYSTATE = 1 +MCS_MULTISELECT = 2 +MCS_WEEKNUMBERS = 4 +MCS_NOTODAY_PRE_IE4 = 8 +MCS_NOTODAYCIRCLE = 8 +MCS_NOTODAY = 16 + +; Month calendar messages + +MCM_GETCURSEL = MCM_FIRST + 1 +MCM_SETCURSEL = MCM_FIRST + 2 +MCM_GETMAXSELCOUNT = MCM_FIRST + 3 +MCM_SETMAXSELCOUNT = MCM_FIRST + 4 +MCM_GETSELRANGE = MCM_FIRST + 5 +MCM_SETSELRANGE = MCM_FIRST + 6 +MCM_GETMONTHRANGE = MCM_FIRST + 7 +MCM_SETDAYSTATE = MCM_FIRST + 8 +MCM_GETMINREQRECT = MCM_FIRST + 9 +MCM_SETCOLOR = MCM_FIRST + 10 +MCM_GETCOLOR = MCM_FIRST + 11 +MCM_SETTODAY = MCM_FIRST + 12 +MCM_GETTODAY = MCM_FIRST + 13 +MCM_HITTEST = MCM_FIRST + 14 +MCM_SETFIRSTDAYOFWEEK = MCM_FIRST + 15 +MCM_GETFIRSTDAYOFWEEK = MCM_FIRST + 16 +MCM_GETRANGE = MCM_FIRST + 17 +MCM_SETRANGE = MCM_FIRST + 18 +MCM_GETMONTHDELTA = MCM_FIRST + 19 +MCM_SETMONTHDELTA = MCM_FIRST + 20 + +; Month calendar hit test flags + +MCHT_TITLE = 0010000h +MCHT_CALENDAR = 0020000h +MCHT_TODAYLINK = 0030000h +MCHT_NEXT = 1000000h +MCHT_PREV = 2000000h +MCHT_NOWHERE = 0000000h +MCHT_TITLEBK = MCHT_TITLE +MCHT_TITLEMONTH = MCHT_TITLE or 1 +MCHT_TITLEYEAR = MCHT_TITLE or 2 +MCHT_TITLEBTNNEXT = MCHT_TITLE or MCHT_NEXT or 3 +MCHT_TITLEBTNPREV = MCHT_TITLE or MCHT_PREV or 3 +MCHT_CALENDARBK = MCHT_CALENDAR +MCHT_CALENDARDATE = MCHT_CALENDAR or 1 +MCHT_CALENDARDATENEXT = MCHT_CALENDARDATE or MCHT_NEXT +MCHT_CALENDARDATEPREV = MCHT_CALENDARDATE or MCHT_PREV +MCHT_CALENDARDAY = MCHT_CALENDAR or 2 +MCHT_CALENDARWEEKNUM = MCHT_CALENDAR or 3 + +; Month calendar color codes + +MCSC_BACKGROUND = 0 +MCSC_TEXT = 1 +MCSC_TITLEBK = 2 +MCSC_TITLETEXT = 3 +MCSC_MONTHBK = 4 +MCSC_TRAILINGTEXT = 5 + +; Month calendar notifications + +MCN_SELCHANGE = MCN_FIRST + 1 +MCN_GETDAYSTATE = MCN_FIRST + 3 +MCN_SELECT = MCN_FIRST + 4 + +; Date-time pick control messages + +DTM_GETSYSTEMTIME = DTM_FIRST + 1 +DTM_SETSYSTEMTIME = DTM_FIRST + 2 +DTM_GETRANGE = DTM_FIRST + 3 +DTM_SETRANGE = DTM_FIRST + 4 +DTM_SETFORMATA = DTM_FIRST + 5 +DTM_SETMCCOLOR = DTM_FIRST + 6 +DTM_GETMCCOLOR = DTM_FIRST + 7 +DTM_GETMONTHCAL = DTM_FIRST + 8 +DTM_SETMCFONT = DTM_FIRST + 9 +DTM_GETMCFONT = DTM_FIRST + 10 +DTM_SETFORMATW = DTM_FIRST + 50 +DTM_SETFORMAT = DTM_SETFORMATA + +; Date-time pick control styles + +DTS_UPDOWN = 01h +DTS_SHOWNONE = 02h +DTS_SHORTDATEFORMAT = 00h +DTS_LONGDATEFORMAT = 04h +DTS_TIMEFORMAT = 09h +DTS_APPCANPARSE = 10h +DTS_RIGHTALIGN = 20h + +; Date-time pick control notifications + +DTN_DATETIMECHANGE = DTN_FIRST + 1 +DTN_USERSTRINGA = DTN_FIRST + 2 +DTN_WMKEYDOWNA = DTN_FIRST + 3 +DTN_FORMATA = DTN_FIRST + 4 +DTN_FORMATQUERYA = DTN_FIRST + 5 +DTN_DROPDOWN = DTN_FIRST + 6 +DTN_CLOSEUP = DTN_FIRST + 7 +DTN_USERSTRINGW = DTN_FIRST + 15 +DTN_WMKEYDOWNW = DTN_FIRST + 16 +DTN_FORMATW = DTN_FIRST + 17 +DTN_FORMATQUERYW = DTN_FIRST + 18 +DTN_USERSTRING = DTN_USERSTRINGA +DTN_WMKEYDOWN = DTN_WMKEYDOWNA +DTN_FORMAT = DTN_FORMATA +DTN_FORMATQUERY = DTN_FORMATQUERYA + +; ImageList_LoadImage types + +IMAGE_BITMAP = 0 +IMAGE_ICON = 1 +IMAGE_CURSOR = 2 +IMAGE_ENHMETAFILE = 3 + +; ImageList_LoadImage flags + +LR_DEFAULTCOLOR = 0000h +LR_MONOCHROME = 0001h +LR_COLOR = 0002h +LR_COPYRETURNORG = 0004h +LR_COPYDELETEORG = 0008h +LR_LOADFROMFILE = 0010h +LR_LOADTRANSPARENT = 0020h +LR_DEFAULTSIZE = 0040h +LR_VGACOLOR = 0080h +LR_LOADMAP3DCOLORS = 1000h +LR_CREATEDIBSECTION = 2000h +LR_COPYFROMRESOURCE = 4000h +LR_SHARED = 8000h + +; IP control messages + +IPM_CLEARADDRESS = WM_USER + 100 +IPM_SETADDRESS = WM_USER + 101 +IPM_GETADDRESS = WM_USER + 102 +IPM_SETRANGE = WM_USER + 103 +IPM_SETFOCUS = WM_USER + 104 +IPM_ISBLANK = WM_USER + 105 + +; Custom Draw flags + +CDRF_DODEFAULT = 0 +CDRF_NEWFONT = 2 +CDRF_SKIPDEFAULT = 4 +CDRF_NOTIFYPOSTPAINT = 10h +CDRF_NOTIFYITEMDRAW = 20h +CDRF_NOTIFYSUBITEMDRAW = 20h +CDRF_NOTIFYPOSTERASE = 40h +CDDS_PREPAINT = 1 +CDDS_POSTPAINT = 2 +CDDS_PREERASE = 3 +CDDS_POSTERASE = 4 +CDDS_ITEM = 10000h +CDDS_ITEMPREPAINT = CDDS_ITEM or CDDS_PREPAINT +CDDS_ITEMPOSTPAINT = CDDS_ITEM or CDDS_POSTPAINT +CDDS_ITEMPREERASE = CDDS_ITEM or CDDS_PREERASE +CDDS_ITEMPOSTERASE = CDDS_ITEM or CDDS_POSTERASE +CDDS_SUBITEM = 20000h +CDIS_SELECTED = 1 +CDIS_GRAYED = 2 +CDIS_DISABLED = 4 +CDIS_CHECKED = 8 +CDIS_FOCUS = 10h +CDIS_DEFAULT = 20h +CDIS_HOT = 40h +CDIS_MARKED = 80h +CDIS_INDETERMINATE = 100h diff --git a/toolchain/fasm2/include/equates/comdlg32.inc b/toolchain/fasm2/include/equates/comdlg32.inc new file mode 100644 index 0000000..4b27efc --- /dev/null +++ b/toolchain/fasm2/include/equates/comdlg32.inc @@ -0,0 +1,333 @@ + +; COMDLG32.DLL structures and constants + +struct OPENFILENAME + lStructSize dd ? + hwndOwner dd ? + hInstance dd ? + lpstrFilter dd ? + lpstrCustomFilter dd ? + nMaxCustFilter dd ? + nFilterIndex dd ? + lpstrFile dd ? + nMaxFile dd ? + lpstrFileTitle dd ? + nMaxFileTitle dd ? + lpstrInitialDir dd ? + lpstrTitle dd ? + Flags dd ? + nFileOffset dw ? + nFileExtension dw ? + lpstrDefExt dd ? + lCustData dd ? + lpfnHook dd ? + lpTemplateName dd ? +ends + +struct CHOOSECOLOR + lStructSize dd ? + hwndOwner dd ? + hInstance dd ? + rgbResult dd ? + lpCustColors dd ? + Flags dd ? + lCustData dd ? + lpfnHook dd ? + lpTemplateName dd ? +ends + +struct FINDREPLACE + lStructSize dd ? + hwndOwner dd ? + hInstance dd ? + Flags dd ? + lpstrFindWhat dd ? + lpstrReplaceWith dd ? + wFindWhatLen dw ? + wReplaceWithLen dw ? + lCustData dd ? + lpfnHook dd ? + lpTemplateName dd ? +ends + +struct CHOOSEFONT + lStructSize dd ? + hwndOwner dd ? + hDC dd ? + lpLogFont dd ? + iPointSize dd ? + Flags dd ? + rgbColors dd ? + lCustData dd ? + lpfnHook dd ? + lpTemplateName dd ? + hInstance dd ? + lpszStyle dd ? + nFontType dw ? + wReserved dw ? + nSizeMin dd ? + nSizeMax dd ? +ends + +struct PRINTDLG + lStructSize dd ? + hwndOwner dd ? + hDevMode dd ? + hDevNames dd ? + hDC dd ? + Flags dd ? + nFromPage dw ? + nToPage dw ? + nMinPage dw ? + nMaxPage dw ? + nCopies dw ? + hInstance dd ? + lCustData dd ? + lpfnPrintHook dd ? + lpfnSetupHook dd ? + lpPrintTemplateName dd ? + lpSetupTemplateName dd ? + hPrintTemplate dd ? + hSetupTemplate dd ? +ends + +struct DEVNAMES + wDriverOffset dw ? + wDeviceOffset dw ? + wOutputOffset dw ? + wDefault dw ? +ends + +struct PAGESETUPDLG + lStructSize dd ? + hwndOwner dd ? + hDevMode dd ? + hDevNames dd ? + Flags dd ? + ptPaperSize POINT + rtMinMargin RECT + rtMargin RECT + hInstance dd ? + lCustData dd ? + lpfnPageSetupHook dd ? + lpfnPagePaintHook dd ? + lpPageSetupTemplateName dd ? + hPageSetupTemplate dd ? +ends + +; OPENFILENAME flags + +OFN_READONLY = 000001h +OFN_OVERWRITEPROMPT = 000002h +OFN_HIDEREADONLY = 000004h +OFN_NOCHANGEDIR = 000008h +OFN_SHOWHELP = 000010h +OFN_ENABLEHOOK = 000020h +OFN_ENABLETEMPLATE = 000040h +OFN_ENABLETEMPLATEHANDLE = 000080h +OFN_NOVALIDATE = 000100h +OFN_ALLOWMULTISELECT = 000200h +OFN_EXTENSIONDIFFERENT = 000400h +OFN_PATHMUSTEXIST = 000800h +OFN_FILEMUSTEXIST = 001000h +OFN_CREATEPROMPT = 002000h +OFN_SHAREAWARE = 004000h +OFN_NOREADONLYRETURN = 008000h +OFN_NOTESTFILECREATE = 010000h +OFN_NONETWORKBUTTON = 020000h +OFN_NOLONGNAMES = 040000h +OFN_EXPLORER = 080000h +OFN_NODEREFERENCELINKS = 100000h +OFN_LONGNAMES = 200000h + +; Common dialog notifications + +CDN_FIRST = -601 +CDN_LAST = -699 +CDN_INITDONE = CDN_FIRST - 0 +CDN_SELCHANGE = CDN_FIRST - 1 +CDN_FOLDERCHANGE = CDN_FIRST - 2 +CDN_SHAREVIOLATION = CDN_FIRST - 3 +CDN_HELP = CDN_FIRST - 4 +CDN_FILEOK = CDN_FIRST - 5 +CDN_TYPECHANGE = CDN_FIRST - 6 + +; Common dialog messages + +CDM_FIRST = WM_USER + 100 +CDM_LAST = WM_USER + 200 +CDM_GETSPEC = CDM_FIRST + 0 +CDM_GETFILEPATH = CDM_FIRST + 1 +CDM_GETFOLDERPATH = CDM_FIRST + 2 +CDM_GETFOLDERIDLIST = CDM_FIRST + 3 +CDM_SETCONTROLTEXT = CDM_FIRST + 4 +CDM_HIDECONTROL = CDM_FIRST + 5 +CDM_SETDEFEXT = CDM_FIRST + 6 + +; CHOOSECOLOR flags + +CC_RGBINIT = 001h +CC_FULLOPEN = 002h +CC_PREVENTFULLOPEN = 004h +CC_SHOWHELP = 008h +CC_ENABLEHOOK = 010h +CC_ENABLETEMPLATE = 020h +CC_ENABLETEMPLATEHANDLE = 040h +CC_SOLIDCOLOR = 080h +CC_ANYCOLOR = 100h + +; FINDREPLACE flags + +FR_DOWN = 00001h +FR_WHOLEWORD = 00002h +FR_MATCHCASE = 00004h +FR_FINDNEXT = 00008h +FR_REPLACE = 00010h +FR_REPLACEALL = 00020h +FR_DIALOGTERM = 00040h +FR_SHOWHELP = 00080h +FR_ENABLEHOOK = 00100h +FR_ENABLETEMPLATE = 00200h +FR_NOUPDOWN = 00400h +FR_NOMATCHCASE = 00800h +FR_NOWHOLEWORD = 01000h +FR_ENABLETEMPLATEHANDLE = 02000h +FR_HIDEUPDOWN = 04000h +FR_HIDEMATCHCASE = 08000h +FR_HIDEWHOLEWORD = 10000h + +; CHOOSEFONT flags + +CF_SCREENFONTS = 0000001h +CF_PRINTERFONTS = 0000002h +CF_BOTH = CF_SCREENFONTS or CF_PRINTERFONTS +CF_SHOWHELP = 0000004h +CF_ENABLEHOOK = 0000008h +CF_ENABLETEMPLATE = 0000010h +CF_ENABLETEMPLATEHANDLE = 0000020h +CF_INITTOLOGFONTSTRUCT = 0000040h +CF_USESTYLE = 0000080h +CF_EFFECTS = 0000100h +CF_APPLY = 0000200h +CF_ANSIONLY = 0000400h +CF_SCRIPTSONLY = CF_ANSIONLY +CF_NOVECTORFONTS = 0000800h +CF_NOOEMFONTS = CF_NOVECTORFONTS +CF_NOSIMULATIONS = 0001000h +CF_LIMITSIZE = 0002000h +CF_FIXEDPITCHONLY = 0004000h +CF_WYSIWYG = 0008000h +CF_FORCEFONTEXIST = 0010000h +CF_SCALABLEONLY = 0020000h +CF_TTONLY = 0040000h +CF_NOFACESEL = 0080000h +CF_NOSTYLESEL = 0100000h +CF_NOSIZESEL = 0200000h +CF_SELECTSCRIPT = 0400000h +CF_NOSCRIPTSEL = 0800000h +CF_NOVERTFONTS = 1000000h + +; ChooseFont messages + +WM_CHOOSEFONT_GETLOGFONT = WM_USER + 1 +WM_CHOOSEFONT_SETLOGFONT = WM_USER + 101 +WM_CHOOSEFONT_SETFLAGS = WM_USER + 102 + +; PRINTDLG flags + +PD_ALLPAGES = 000000h +PD_SELECTION = 000001h +PD_PAGENUMS = 000002h +PD_NOSELECTION = 000004h +PD_NOPAGENUMS = 000008h +PD_COLLATE = 000010h +PD_PRINTTOFILE = 000020h +PD_PRINTSETUP = 000040h +PD_NOWARNING = 000080h +PD_RETURNDC = 000100h +PD_RETURNIC = 000200h +PD_RETURNDEFAULT = 000400h +PD_SHOWHELP = 000800h +PD_ENABLEPRINTHOOK = 001000h +PD_ENABLESETUPHOOK = 002000h +PD_ENABLEPRINTTEMPLATE = 004000h +PD_ENABLESETUPTEMPLATE = 008000h +PD_ENABLEPRINTTEMPLATEHANDLE = 010000h +PD_ENABLESETUPTEMPLATEHANDLE = 020000h +PD_USEDEVMODECOPIES = 040000h +PD_USEDEVMODECOPIESANDCOLLATE = 040000h +PD_DISABLEPRINTTOFILE = 080000h +PD_HIDEPRINTTOFILE = 100000h +PD_NONETWORKBUTTON = 200000h + +; PAGESETUPDLG flags + +PSD_DEFAULTMINMARGINS = 000000h +PSD_INWININIINTLMEASURE = 000000h +PSD_MINMARGINS = 000001h +PSD_MARGINS = 000002h +PSD_INTHOUSANDTHSOFINCHES = 000004h +PSD_INHUNDREDTHSOFMILLIMETERS = 000008h +PSD_DISABLEMARGINS = 000010h +PSD_DISABLEPRINTER = 000020h +PSD_NOWARNING = 000080h +PSD_DISABLEORIENTATION = 000100h +PSD_RETURNDEFAULT = 000400h +PSD_DISABLEPAPER = 000200h +PSD_SHOWHELP = 000800h +PSD_ENABLEPAGESETUPHOOK = 002000h +PSD_ENABLEPAGESETUPTEMPLATE = 008000h +PSD_ENABLEPAGESETUPTEMPLATEHANDLE = 020000h +PSD_ENABLEPAGEPAINTHOOK = 040000h +PSD_DISABLEPAGEPAINTING = 080000h +PSD_NONETWORKBUTTON = 200000h + +; PageSetupDlg messages + +WM_PSD_PAGESETUPDLG = WM_USER +WM_PSD_FULLPAGERECT = WM_USER + 1 +WM_PSD_MINMARGINRECT = WM_USER + 2 +WM_PSD_MARGINRECT = WM_USER + 3 +WM_PSD_GREEKTEXTRECT = WM_USER + 4 +WM_PSD_ENVSTAMPRECT = WM_USER + 5 +WM_PSD_YAFULLPAGERECT = WM_USER + 6 + +; Common dialog error codes + +CDERR_DIALOGFAILURE = 0FFFFh +CDERR_GENERALCODES = 00000h +CDERR_STRUCTSIZE = 00001h +CDERR_INITIALIZATION = 00002h +CDERR_NOTEMPLATE = 00003h +CDERR_NOHINSTANCE = 00004h +CDERR_LOADSTRFAILURE = 00005h +CDERR_FINDRESFAILURE = 00006h +CDERR_LOADRESFAILURE = 00007h +CDERR_LOCKRESFAILURE = 00008h +CDERR_MEMALLOCFAILURE = 00009h +CDERR_MEMLOCKFAILURE = 0000Ah +CDERR_NOHOOK = 0000Bh +CDERR_REGISTERMSGFAIL = 0000Ch +PDERR_PRINTERCODES = 01000h +PDERR_SETUPFAILURE = 01001h +PDERR_PARSEFAILURE = 01002h +PDERR_RETDEFFAILURE = 01003h +PDERR_LOADDRVFAILURE = 01004h +PDERR_GETDEVMODEFAIL = 01005h +PDERR_INITFAILURE = 01006h +PDERR_NODEVICES = 01007h +PDERR_NODEFAULTPRN = 01008h +PDERR_DNDMMISMATCH = 01009h +PDERR_CREATEICFAILURE = 0100Ah +PDERR_PRINTERNOTFOUND = 0100Bh +PDERR_DEFAULTDIFFERENT = 0100Ch +CFERR_CHOOSEFONTCODES = 02000h +CFERR_NOFONTS = 02001h +CFERR_MAXLESSTHANMIN = 02002h +FNERR_FILENAMECODES = 03000h +FNERR_SUBCLASSFAILURE = 03001h +FNERR_INVALIDFILENAME = 03002h +FNERR_BUFFERTOOSMALL = 03003h +FRERR_FINDREPLACECODES = 04000h +FRERR_BUFFERLENGTHZERO = 04001h +CCERR_CHOOSECOLORCODES = 05000h diff --git a/toolchain/fasm2/include/equates/comdlg64.inc b/toolchain/fasm2/include/equates/comdlg64.inc new file mode 100644 index 0000000..2c6743a --- /dev/null +++ b/toolchain/fasm2/include/equates/comdlg64.inc @@ -0,0 +1,343 @@ + +; COMDLG32.DLL structures and constants + +struct OPENFILENAME + lStructSize dq ? + hwndOwner dq ? + hInstance dq ? + lpstrFilter dq ? + lpstrCustomFilter dq ? + nMaxCustFilter dd ? + nFilterIndex dd ? + lpstrFile dq ? + nMaxFile dd ? + dd ? + lpstrFileTitle dq ? + nMaxFileTitle dd ? + dd ? + lpstrInitialDir dq ? + lpstrTitle dq ? + Flags dd ? + nFileOffset dw ? + nFileExtension dw ? + lpstrDefExt dq ? + lCustData dq ? + lpfnHook dq ? + lpTemplateName dq ? +ends + +struct CHOOSECOLOR + lStructSize dq ? + hwndOwner dq ? + hInstance dq ? + rgbResult dd ? + dd ? + lpCustColors dq ? + Flags dd ? + dd ? + lCustData dq ? + lpfnHook dq ? + lpTemplateName dq ? +ends + +struct FINDREPLACE + lStructSize dq ? + hwndOwner dq ? + hInstance dq ? + Flags dd ? + dd ? + lpstrFindWhat dq ? + lpstrReplaceWith dq ? + wFindWhatLen dw ? + wReplaceWithLen dw ? + dd ? + lCustData dq ? + lpfnHook dq ? + lpTemplateName dq ? +ends + +struct CHOOSEFONT + lStructSize dq ? + hwndOwner dq ? + hDC dq ? + lpLogFont dq ? + iPointSize dd ? + Flags dd ? + rgbColors dd ? + dd ? + lCustData dq ? + lpfnHook dq ? + lpTemplateName dq ? + hInstance dq ? + lpszStyle dq ? + nFontType dw ? + wReserved dw ? + nSizeMin dd ? + nSizeMax dd ? + dd ? +ends + +struct PRINTDLG + lStructSize dq ? + hwndOwner dq ? + hDevMode dq ? + hDevNames dq ? + hDC dq ? + Flags dd ? + nFromPage dw ? + nToPage dw ? + nMinPage dw ? + nMaxPage dw ? + nCopies dw ? + dw ? + hInstance dq ? + lCustData dq ? + lpfnPrintHook dq ? + lpfnSetupHook dq ? + lpPrintTemplateName dq ? + lpSetupTemplateName dq ? + hPrintTemplate dq ? + hSetupTemplate dq ? +ends + +struct DEVNAMES + wDriverOffset dw ? + wDeviceOffset dw ? + wOutputOffset dw ? + wDefault dw ? +ends + +struct PAGESETUPDLG + lStructSize dq ? + hwndOwner dq ? + hDevMode dq ? + hDevNames dq ? + Flags dd ? + ptPaperSize POINT + rtMinMargin RECT + rtMargin RECT + dd ? + hInstance dq ? + lCustData dq ? + lpfnPageSetupHook dq ? + lpfnPagePaintHook dq ? + lpPageSetupTemplateName dq ? + hPageSetupTemplate dq ? +ends + +; OPENFILENAME flags + +OFN_READONLY = 000001h +OFN_OVERWRITEPROMPT = 000002h +OFN_HIDEREADONLY = 000004h +OFN_NOCHANGEDIR = 000008h +OFN_SHOWHELP = 000010h +OFN_ENABLEHOOK = 000020h +OFN_ENABLETEMPLATE = 000040h +OFN_ENABLETEMPLATEHANDLE = 000080h +OFN_NOVALIDATE = 000100h +OFN_ALLOWMULTISELECT = 000200h +OFN_EXTENSIONDIFFERENT = 000400h +OFN_PATHMUSTEXIST = 000800h +OFN_FILEMUSTEXIST = 001000h +OFN_CREATEPROMPT = 002000h +OFN_SHAREAWARE = 004000h +OFN_NOREADONLYRETURN = 008000h +OFN_NOTESTFILECREATE = 010000h +OFN_NONETWORKBUTTON = 020000h +OFN_NOLONGNAMES = 040000h +OFN_EXPLORER = 080000h +OFN_NODEREFERENCELINKS = 100000h +OFN_LONGNAMES = 200000h + +; Common dialog notifications + +CDN_FIRST = -601 +CDN_LAST = -699 +CDN_INITDONE = CDN_FIRST - 0 +CDN_SELCHANGE = CDN_FIRST - 1 +CDN_FOLDERCHANGE = CDN_FIRST - 2 +CDN_SHAREVIOLATION = CDN_FIRST - 3 +CDN_HELP = CDN_FIRST - 4 +CDN_FILEOK = CDN_FIRST - 5 +CDN_TYPECHANGE = CDN_FIRST - 6 + +; Common dialog messages + +CDM_FIRST = WM_USER + 100 +CDM_LAST = WM_USER + 200 +CDM_GETSPEC = CDM_FIRST + 0 +CDM_GETFILEPATH = CDM_FIRST + 1 +CDM_GETFOLDERPATH = CDM_FIRST + 2 +CDM_GETFOLDERIDLIST = CDM_FIRST + 3 +CDM_SETCONTROLTEXT = CDM_FIRST + 4 +CDM_HIDECONTROL = CDM_FIRST + 5 +CDM_SETDEFEXT = CDM_FIRST + 6 + +; CHOOSECOLOR flags + +CC_RGBINIT = 001h +CC_FULLOPEN = 002h +CC_PREVENTFULLOPEN = 004h +CC_SHOWHELP = 008h +CC_ENABLEHOOK = 010h +CC_ENABLETEMPLATE = 020h +CC_ENABLETEMPLATEHANDLE = 040h +CC_SOLIDCOLOR = 080h +CC_ANYCOLOR = 100h + +; FINDREPLACE flags + +FR_DOWN = 00001h +FR_WHOLEWORD = 00002h +FR_MATCHCASE = 00004h +FR_FINDNEXT = 00008h +FR_REPLACE = 00010h +FR_REPLACEALL = 00020h +FR_DIALOGTERM = 00040h +FR_SHOWHELP = 00080h +FR_ENABLEHOOK = 00100h +FR_ENABLETEMPLATE = 00200h +FR_NOUPDOWN = 00400h +FR_NOMATCHCASE = 00800h +FR_NOWHOLEWORD = 01000h +FR_ENABLETEMPLATEHANDLE = 02000h +FR_HIDEUPDOWN = 04000h +FR_HIDEMATCHCASE = 08000h +FR_HIDEWHOLEWORD = 10000h + +; CHOOSEFONT flags + +CF_SCREENFONTS = 0000001h +CF_PRINTERFONTS = 0000002h +CF_BOTH = CF_SCREENFONTS or CF_PRINTERFONTS +CF_SHOWHELP = 0000004h +CF_ENABLEHOOK = 0000008h +CF_ENABLETEMPLATE = 0000010h +CF_ENABLETEMPLATEHANDLE = 0000020h +CF_INITTOLOGFONTSTRUCT = 0000040h +CF_USESTYLE = 0000080h +CF_EFFECTS = 0000100h +CF_APPLY = 0000200h +CF_ANSIONLY = 0000400h +CF_SCRIPTSONLY = CF_ANSIONLY +CF_NOVECTORFONTS = 0000800h +CF_NOOEMFONTS = CF_NOVECTORFONTS +CF_NOSIMULATIONS = 0001000h +CF_LIMITSIZE = 0002000h +CF_FIXEDPITCHONLY = 0004000h +CF_WYSIWYG = 0008000h +CF_FORCEFONTEXIST = 0010000h +CF_SCALABLEONLY = 0020000h +CF_TTONLY = 0040000h +CF_NOFACESEL = 0080000h +CF_NOSTYLESEL = 0100000h +CF_NOSIZESEL = 0200000h +CF_SELECTSCRIPT = 0400000h +CF_NOSCRIPTSEL = 0800000h +CF_NOVERTFONTS = 1000000h + +; ChooseFont messages + +WM_CHOOSEFONT_GETLOGFONT = WM_USER + 1 +WM_CHOOSEFONT_SETLOGFONT = WM_USER + 101 +WM_CHOOSEFONT_SETFLAGS = WM_USER + 102 + +; PRINTDLG flags + +PD_ALLPAGES = 000000h +PD_SELECTION = 000001h +PD_PAGENUMS = 000002h +PD_NOSELECTION = 000004h +PD_NOPAGENUMS = 000008h +PD_COLLATE = 000010h +PD_PRINTTOFILE = 000020h +PD_PRINTSETUP = 000040h +PD_NOWARNING = 000080h +PD_RETURNDC = 000100h +PD_RETURNIC = 000200h +PD_RETURNDEFAULT = 000400h +PD_SHOWHELP = 000800h +PD_ENABLEPRINTHOOK = 001000h +PD_ENABLESETUPHOOK = 002000h +PD_ENABLEPRINTTEMPLATE = 004000h +PD_ENABLESETUPTEMPLATE = 008000h +PD_ENABLEPRINTTEMPLATEHANDLE = 010000h +PD_ENABLESETUPTEMPLATEHANDLE = 020000h +PD_USEDEVMODECOPIES = 040000h +PD_USEDEVMODECOPIESANDCOLLATE = 040000h +PD_DISABLEPRINTTOFILE = 080000h +PD_HIDEPRINTTOFILE = 100000h +PD_NONETWORKBUTTON = 200000h + +; PAGESETUPDLG flags + +PSD_DEFAULTMINMARGINS = 000000h +PSD_INWININIINTLMEASURE = 000000h +PSD_MINMARGINS = 000001h +PSD_MARGINS = 000002h +PSD_INTHOUSANDTHSOFINCHES = 000004h +PSD_INHUNDREDTHSOFMILLIMETERS = 000008h +PSD_DISABLEMARGINS = 000010h +PSD_DISABLEPRINTER = 000020h +PSD_NOWARNING = 000080h +PSD_DISABLEORIENTATION = 000100h +PSD_RETURNDEFAULT = 000400h +PSD_DISABLEPAPER = 000200h +PSD_SHOWHELP = 000800h +PSD_ENABLEPAGESETUPHOOK = 002000h +PSD_ENABLEPAGESETUPTEMPLATE = 008000h +PSD_ENABLEPAGESETUPTEMPLATEHANDLE = 020000h +PSD_ENABLEPAGEPAINTHOOK = 040000h +PSD_DISABLEPAGEPAINTING = 080000h +PSD_NONETWORKBUTTON = 200000h + +; PageSetupDlg messages + +WM_PSD_PAGESETUPDLG = WM_USER +WM_PSD_FULLPAGERECT = WM_USER + 1 +WM_PSD_MINMARGINRECT = WM_USER + 2 +WM_PSD_MARGINRECT = WM_USER + 3 +WM_PSD_GREEKTEXTRECT = WM_USER + 4 +WM_PSD_ENVSTAMPRECT = WM_USER + 5 +WM_PSD_YAFULLPAGERECT = WM_USER + 6 + +; Common dialog error codes + +CDERR_DIALOGFAILURE = 0FFFFh +CDERR_GENERALCODES = 00000h +CDERR_STRUCTSIZE = 00001h +CDERR_INITIALIZATION = 00002h +CDERR_NOTEMPLATE = 00003h +CDERR_NOHINSTANCE = 00004h +CDERR_LOADSTRFAILURE = 00005h +CDERR_FINDRESFAILURE = 00006h +CDERR_LOADRESFAILURE = 00007h +CDERR_LOCKRESFAILURE = 00008h +CDERR_MEMALLOCFAILURE = 00009h +CDERR_MEMLOCKFAILURE = 0000Ah +CDERR_NOHOOK = 0000Bh +CDERR_REGISTERMSGFAIL = 0000Ch +PDERR_PRINTERCODES = 01000h +PDERR_SETUPFAILURE = 01001h +PDERR_PARSEFAILURE = 01002h +PDERR_RETDEFFAILURE = 01003h +PDERR_LOADDRVFAILURE = 01004h +PDERR_GETDEVMODEFAIL = 01005h +PDERR_INITFAILURE = 01006h +PDERR_NODEVICES = 01007h +PDERR_NODEFAULTPRN = 01008h +PDERR_DNDMMISMATCH = 01009h +PDERR_CREATEICFAILURE = 0100Ah +PDERR_PRINTERNOTFOUND = 0100Bh +PDERR_DEFAULTDIFFERENT = 0100Ch +CFERR_CHOOSEFONTCODES = 02000h +CFERR_NOFONTS = 02001h +CFERR_MAXLESSTHANMIN = 02002h +FNERR_FILENAMECODES = 03000h +FNERR_SUBCLASSFAILURE = 03001h +FNERR_INVALIDFILENAME = 03002h +FNERR_BUFFERTOOSMALL = 03003h +FRERR_FINDREPLACECODES = 04000h +FRERR_BUFFERLENGTHZERO = 04001h +CCERR_CHOOSECOLORCODES = 05000h diff --git a/toolchain/fasm2/include/equates/gdi32.inc b/toolchain/fasm2/include/equates/gdi32.inc new file mode 100644 index 0000000..77d556f --- /dev/null +++ b/toolchain/fasm2/include/equates/gdi32.inc @@ -0,0 +1,480 @@ + +; GDI32.DLL structures and constants + +struct SIZE + cx dd ? + cy dd ? +ends + +struct BITMAP + bmType dd ? + bmWidth dd ? + bmHeight dd ? + bmWidthBytes dd ? + bmPlanes dw ? + bmBitsPixel dw ? + bmBits dd ? +ends + +struct BITMAPCOREHEADER + bcSize dd ? + bcWidth dw ? + bcHeight dw ? + bcPlanes dw ? + bcBitCount dw ? +ends + +struct BITMAPINFOHEADER + biSize dd ? + biWidth dd ? + biHeight dd ? + biPlanes dw ? + biBitCount dw ? + biCompression dd ? + biSizeImage dd ? + biXPelsPerMeter dd ? + biYPelsPerMeter dd ? + biClrUsed dd ? + biClrImportant dd ? +ends + +struct BITMAPFILEHEADER + bfType dw ? + bfSize dd ? + bfReserved1 dw ? + bfReserved2 dw ? + bfOffBits dd ? +ends + +struct TEXTMETRIC + tmHeight dd ? + tmAscent dd ? + tmDescent dd ? + tmInternalLeading dd ? + tmExternalLeading dd ? + tmAveCharWidth dd ? + tmMaxCharWidth dd ? + tmWeight dd ? + tmOverhang dd ? + tmDigitizedAspectX dd ? + tmDigitizedAspectY dd ? + tmFirstChar TCHAR ? + tmLastChar TCHAR ? + tmDefaultChar TCHAR ? + tmBreakChar TCHAR ? + tmItalic db ? + tmUnderlined db ? + tmStruckOut db ? + tmPitchAndFamily db ? + tmCharSet db ? +ends + +struct LOGBRUSH + lbStyle dd ? + lbColor dd ? + lbHatch dd ? +ends + +struct LOGPEN + lopnStyle dd ? + lopnWidth POINT + lopnColor dd ? +ends + +struct EXTLOGPEN + elpPenStyle dd ? + elpWidth dd ? + elpBrushStyle dd ? + elpColor dd ? + elpHatch dd ? + elpNumEntries dd ? + elpStyleEntry dd ? +ends + +struct LOGFONT + lfHeight dd ? + lfWidth dd ? + lfEscapement dd ? + lfOrientation dd ? + lfWeight dd ? + lfItalic db ? + lfUnderline db ? + lfStrikeOut db ? + lfCharSet db ? + lfOutPrecision db ? + lfClipPrecision db ? + lfQuality db ? + lfPitchAndFamily db ? + lfFaceName TCHAR 32 dup (?) +ends + +struct ENUMLOGFONT + elfLogFont LOGFONT + elfFullName TCHAR 64 dup (?) + elfStyle TCHAR 32 dup (?) +ends + +struct ENUMLOGFONTEX + elfLogFont LOGFONT + elfFullName TCHAR 64 dup (?) + elfStyle TCHAR 32 dup (?) + elfScript TCHAR 32 dup (?) +ends + +struct PIXELFORMATDESCRIPTOR + nSize dw ? + nVersion dw ? + dwFlags dd ? + iPixelType db ? + cColorBits db ? + cRedBits db ? + cRedShift db ? + cGreenBits db ? + cGreenShift db ? + cBlueBits db ? + cBlueShift db ? + cAlphaBits db ? + cAlphaShift db ? + cAccumBits db ? + cAccumRedBits db ? + cAccumGreenBits db ? + cAccumBlueBits db ? + cAccumAlphaBits db ? + cDepthBits db ? + cStencilBits db ? + cAuxBuffers db ? + iLayerType db ? + bReserved db ? + dwLayerMask dd ? + dwVisibleMask dd ? + dwDamageMask dd ? +ends + +struct TRIVERTEX + x dd ? + y dd ? + Red dw ? + Green dw ? + Blue dw ? + Alpha dw ? +ends + +; General constants + +GDI_ERROR = 0FFFFFFFFh +HGDI_ERROR = 0FFFFFFFFh + +; Binary raster operations + +R2_BLACK = 1 +R2_NOTMERGEPEN = 2 +R2_MASKNOTPEN = 3 +R2_NOTCOPYPEN = 4 +R2_MASKPENNOT = 5 +R2_NOT = 6 +R2_XORPEN = 7 +R2_NOTMASKPEN = 8 +R2_MASKPEN = 9 +R2_NOTXORPEN = 10 +R2_NOP = 11 +R2_MERGENOTPEN = 12 +R2_COPYPEN = 13 +R2_MERGEPENNOT = 14 +R2_MERGEPEN = 15 +R2_WHITE = 16 + +; Raster operations + +SRCCOPY = 00CC0020h +SRCPAINT = 00EE0086h +SRCAND = 008800C6h +SRCINVERT = 00660046h +SRCERASE = 00440328h +NOTSRCCOPY = 00330008h +NOTSRCERASE = 001100A6h +MERGECOPY = 00C000CAh +MERGEPAINT = 00BB0226h +PATCOPY = 00F00021h +PATPAINT = 00FB0A09h +PATINVERT = 005A0049h +DSTINVERT = 00550009h +BLACKNESS = 00000042h +WHITENESS = 00FF0062h + +; Region flags + +ERROR = 0 +NULLREGION = 1 +SIMPLEREGION = 2 +COMPLEXREGION = 3 + +; CombineRgn styles + +RGN_AND = 1 +RGN_OR = 2 +RGN_XOR = 3 +RGN_DIFF = 4 +RGN_COPY = 5 + +; StretchBlt modes + +BLACKONWHITE = 1 +WHITEONBLACK = 2 +COLORONCOLOR = 3 +HALFTONE = 4 +STRETCH_ANDSCANS = BLACKONWHITE +STRETCH_ORSCANS = WHITEONBLACK +STRETCH_DELETESCANS = COLORONCOLOR +STRETCH_HALFTONE = HALFTONE + +; PolyFill modes + +ALTERNATE = 1 +WINDING = 2 + +; Background modes + +TRANSPARENT = 1 +OPAQUE = 2 + +; Point types + +PT_CLOSEFIGURE = 1 +PT_LINETO = 2 +PT_BEZIERTO = 4 +PT_MOVETO = 6 + +; Mapping modes + +MM_TEXT = 1 +MM_LOMETRIC = 2 +MM_HIMETRIC = 3 +MM_LOENGLISH = 4 +MM_HIENGLISH = 5 +MM_TWIPS = 6 +MM_ISOTROPIC = 7 +MM_ANISOTROPIC = 8 + +; Coordinate modes + +ABSOLUTE = 1 +RELATIVE = 2 + +; Stock logical objects + +WHITE_BRUSH = 0 +LTGRAY_BRUSH = 1 +GRAY_BRUSH = 2 +DKGRAY_BRUSH = 3 +BLACK_BRUSH = 4 +NULL_BRUSH = 5 +HOLLOW_BRUSH = NULL_BRUSH +WHITE_PEN = 6 +BLACK_PEN = 7 +NULL_PEN = 8 +OEM_FIXED_FONT = 10 +ANSI_FIXED_FONT = 11 +ANSI_VAR_FONT = 12 +SYSTEM_FONT = 13 +DEVICE_DEFAULT_FONT = 14 +DEFAULT_PALETTE = 15 +SYSTEM_FIXED_FONT = 16 +DEFAULT_GUI_FONT = 17 + +; Brush styles + +BS_SOLID = 0 +BS_NULL = 1 +BS_HOLLOW = BS_NULL +BS_HATCHED = 2 +BS_PATTERN = 3 +BS_INDEXED = 4 +BS_DIBPATTERN = 5 +BS_DIBPATTERNPT = 6 +BS_PATTERN8X8 = 7 +BS_DIBPATTERN8X8 = 8 +BS_MONOPATTERN = 9 + +; Hatch styles + +HS_HORIZONTAL = 0 +HS_VERTICAL = 1 +HS_FDIAGONAL = 2 +HS_BDIAGONAL = 3 +HS_CROSS = 4 +HS_DIAGCROSS = 5 + +; Pen styles + +PS_SOLID = 0 +PS_DASH = 1 +PS_DOT = 2 +PS_DASHDOT = 3 +PS_DASHDOTDOT = 4 +PS_NULL = 5 +PS_INSIDEFRAME = 6 +PS_USERSTYLE = 7 +PS_ALTERNATE = 8 +PS_ENDCAP_ROUND = 0 +PS_ENDCAP_SQUARE = 100h +PS_ENDCAP_FLAT = 200h +PS_JOIN_ROUND = 0 +PS_JOIN_BEVEL = 1000h +PS_JOIN_MITER = 2000h +PS_COSMETIC = 0 +PS_GEOMETRIC = 010000h + +; Arc directions + +AD_COUNTERCLOCKWISE = 1 +AD_CLOCKWISE = 2 + +; Text alignment options + +TA_NOUPDATECP = 0 +TA_UPDATECP = 1 +TA_LEFT = 0 +TA_RIGHT = 2 +TA_CENTER = 6 +TA_TOP = 0 +TA_BOTTOM = 8 +TA_BASELINE = 24 +TA_RTLREADING = 100h +VTA_BASELINE = TA_BASELINE +VTA_LEFT = TA_BOTTOM +VTA_RIGHT = TA_TOP +VTA_CENTER = TA_CENTER +VTA_BOTTOM = TA_RIGHT +VTA_TOP = TA_LEFT + +; ExtTextOut options + +ETO_OPAQUE = 0002h +ETO_CLIPPED = 0004h +ETO_GLYPH_INDEX = 0010h +ETO_RTLREADING = 0080h +ETO_IGNORELANGUAGE = 1000h + +; Bitmap compression types + +BI_RGB = 0 +BI_RLE8 = 1 +BI_RLE4 = 2 +BI_BITFIELDS = 3 + +; tmPitchAndFamily flags + +TMPF_FIXED_PITCH = 1 +TMPF_VECTOR = 2 +TMPF_TRUETYPE = 4 +TMPF_DEVICE = 8 + +; Font output precision values + +OUT_DEFAULT_PRECIS = 0 +OUT_STRING_PRECIS = 1 +OUT_CHARACTER_PRECIS = 2 +OUT_STROKE_PRECIS = 3 +OUT_TT_PRECIS = 4 +OUT_DEVICE_PRECIS = 5 +OUT_RASTER_PRECIS = 6 +OUT_TT_ONLY_PRECIS = 7 +OUT_OUTLINE_PRECIS = 8 +OUT_SCREEN_OUTLINE_PRECIS = 9 + +; Font clipping precision values + +CLIP_DEFAULT_PRECIS = 0 +CLIP_CHARACTER_PRECIS = 1 +CLIP_STROKE_PRECIS = 2 +CLIP_LH_ANGLES = 10h +CLIP_TT_ALWAYS = 20h +CLIP_EMBEDDED = 80h + +; Font output quality values + +DEFAULT_QUALITY = 0 +DRAFT_QUALITY = 1 +PROOF_QUALITY = 2 +NONANTIALIASED_QUALITY = 3 +ANTIALIASED_QUALITY = 4 + +; Font pitch values + +DEFAULT_PITCH = 0 +FIXED_PITCH = 1 +VARIABLE_PITCH = 2 +MONO_FONT = 8 + +; Font families + +FF_DONTCARE = 00h +FF_ROMAN = 10h +FF_SWISS = 20h +FF_MODERN = 30h +FF_SCRIPT = 40h +FF_DECORATIVE = 50h + +; Font weights + +FW_DONTCARE = 0 +FW_THIN = 100 +FW_EXTRALIGHT = 200 +FW_LIGHT = 300 +FW_NORMAL = 400 +FW_MEDIUM = 500 +FW_SEMIBOLD = 600 +FW_BOLD = 700 +FW_EXTRABOLD = 800 +FW_HEAVY = 900 +FW_ULTRALIGHT = FW_EXTRALIGHT +FW_REGULAR = FW_NORMAL +FW_DEMIBOLD = FW_SEMIBOLD +FW_ULTRABOLD = FW_EXTRABOLD +FW_BLACK = FW_HEAVY + +; Character set values + +ANSI_CHARSET = 0 +DEFAULT_CHARSET = 1 +SYMBOL_CHARSET = 2 +SHIFTJIS_CHARSET = 128 +HANGEUL_CHARSET = 129 +GB2312_CHARSET = 134 +CHINESEBIG5_CHARSET = 136 +OEM_CHARSET = 255 +JOHAB_CHARSET = 130 +HEBREW_CHARSET = 177 +ARABIC_CHARSET = 178 +GREEK_CHARSET = 161 +TURKISH_CHARSET = 162 +VIETNAMESE_CHARSET = 163 +THAI_CHARSET = 222 +EASTEUROPE_CHARSET = 238 +RUSSIAN_CHARSET = 204 +MAC_CHARSET = 77 +BALTIC_CHARSET = 186 + +; Pixel format constants + +PFD_TYPE_RGBA = 0 +PFD_TYPE_COLORINDEX = 1 +PFD_MAIN_PLANE = 0 +PFD_OVERLAY_PLANE = 1 +PFD_UNDERLAY_PLANE = -1 +PFD_DOUBLEBUFFER = 1 +PFD_STEREO = 2 +PFD_DRAW_TO_WINDOW = 4 +PFD_DRAW_TO_BITMAP = 8 +PFD_SUPPORT_GDI = 10h +PFD_SUPPORT_OPENGL = 20h +PFD_GENERIC_FORMAT = 40h +PFD_NEED_PALETTE = 80h +PFD_NEED_SYSTEM_PALETTE = 100h +PFD_SWAP_EXCHANGE = 200h +PFD_SWAP_COPY = 400h +PFD_SWAP_LAYER_BUFFERS = 800h +PFD_GENERIC_ACCELERATED = 1000h +PFD_DEPTH_DONTCARE = 20000000h +PFD_DOUBLEBUFFER_DONTCARE = 40000000h +PFD_STEREO_DONTCARE = 80000000h diff --git a/toolchain/fasm2/include/equates/gdi64.inc b/toolchain/fasm2/include/equates/gdi64.inc new file mode 100644 index 0000000..ec6c566 --- /dev/null +++ b/toolchain/fasm2/include/equates/gdi64.inc @@ -0,0 +1,482 @@ + +; GDI32.DLL structures and constants + +struct SIZE + cx dd ? + cy dd ? +ends + +struct BITMAP + bmType dd ? + bmWidth dd ? + bmHeight dd ? + bmWidthBytes dd ? + bmPlanes dw ? + bmBitsPixel dw ? + dd ? + bmBits dq ? +ends + +struct BITMAPCOREHEADER + bcSize dd ? + bcWidth dw ? + bcHeight dw ? + bcPlanes dw ? + bcBitCount dw ? +ends + +struct BITMAPINFOHEADER + biSize dd ? + biWidth dd ? + biHeight dd ? + biPlanes dw ? + biBitCount dw ? + biCompression dd ? + biSizeImage dd ? + biXPelsPerMeter dd ? + biYPelsPerMeter dd ? + biClrUsed dd ? + biClrImportant dd ? +ends + +struct BITMAPFILEHEADER, packed + bfType dw ? + bfSize dd ? + bfReserved1 dw ? + bfReserved2 dw ? + bfOffBits dd ? +ends + +struct TEXTMETRIC + tmHeight dd ? + tmAscent dd ? + tmDescent dd ? + tmInternalLeading dd ? + tmExternalLeading dd ? + tmAveCharWidth dd ? + tmMaxCharWidth dd ? + tmWeight dd ? + tmOverhang dd ? + tmDigitizedAspectX dd ? + tmDigitizedAspectY dd ? + tmFirstChar TCHAR ? + tmLastChar TCHAR ? + tmDefaultChar TCHAR ? + tmBreakChar TCHAR ? + tmItalic db ? + tmUnderlined db ? + tmStruckOut db ? + tmPitchAndFamily db ? + tmCharSet db ? + align 4 +ends + +struct LOGBRUSH + lbStyle dd ? + lbColor dd ? + lbHatch dd ? +ends + +struct LOGPEN + lopnStyle dd ? + lopnWidth POINT + lopnColor dd ? +ends + +struct EXTLOGPEN + elpPenStyle dd ? + elpWidth dd ? + elpBrushStyle dd ? + elpColor dd ? + elpHatch dd ? + elpNumEntries dd ? + elpStyleEntry dd ? +ends + +struct LOGFONT + lfHeight dd ? + lfWidth dd ? + lfEscapement dd ? + lfOrientation dd ? + lfWeight dd ? + lfItalic db ? + lfUnderline db ? + lfStrikeOut db ? + lfCharSet db ? + lfOutPrecision db ? + lfClipPrecision db ? + lfQuality db ? + lfPitchAndFamily db ? + lfFaceName TCHAR 32 dup (?) +ends + +struct ENUMLOGFONT + elfLogFont LOGFONT + elfFullName TCHAR 64 dup (?) + elfStyle TCHAR 32 dup (?) +ends + +struct ENUMLOGFONTEX + elfLogFont LOGFONT + elfFullName TCHAR 64 dup (?) + elfStyle TCHAR 32 dup (?) + elfScript TCHAR 32 dup (?) +ends + +struct PIXELFORMATDESCRIPTOR + nSize dw ? + nVersion dw ? + dwFlags dd ? + iPixelType db ? + cColorBits db ? + cRedBits db ? + cRedShift db ? + cGreenBits db ? + cGreenShift db ? + cBlueBits db ? + cBlueShift db ? + cAlphaBits db ? + cAlphaShift db ? + cAccumBits db ? + cAccumRedBits db ? + cAccumGreenBits db ? + cAccumBlueBits db ? + cAccumAlphaBits db ? + cDepthBits db ? + cStencilBits db ? + cAuxBuffers db ? + iLayerType db ? + bReserved db ? + dwLayerMask dd ? + dwVisibleMask dd ? + dwDamageMask dd ? +ends + +struct TRIVERTEX + x dd ? + y dd ? + Red dw ? + Green dw ? + Blue dw ? + Alpha dw ? +ends + +; General constants + +GDI_ERROR = 0FFFFFFFFh +HGDI_ERROR = 0FFFFFFFFh + +; Binary raster operations + +R2_BLACK = 1 +R2_NOTMERGEPEN = 2 +R2_MASKNOTPEN = 3 +R2_NOTCOPYPEN = 4 +R2_MASKPENNOT = 5 +R2_NOT = 6 +R2_XORPEN = 7 +R2_NOTMASKPEN = 8 +R2_MASKPEN = 9 +R2_NOTXORPEN = 10 +R2_NOP = 11 +R2_MERGENOTPEN = 12 +R2_COPYPEN = 13 +R2_MERGEPENNOT = 14 +R2_MERGEPEN = 15 +R2_WHITE = 16 + +; Raster operations + +SRCCOPY = 00CC0020h +SRCPAINT = 00EE0086h +SRCAND = 008800C6h +SRCINVERT = 00660046h +SRCERASE = 00440328h +NOTSRCCOPY = 00330008h +NOTSRCERASE = 001100A6h +MERGECOPY = 00C000CAh +MERGEPAINT = 00BB0226h +PATCOPY = 00F00021h +PATPAINT = 00FB0A09h +PATINVERT = 005A0049h +DSTINVERT = 00550009h +BLACKNESS = 00000042h +WHITENESS = 00FF0062h + +; Region flags + +ERROR = 0 +NULLREGION = 1 +SIMPLEREGION = 2 +COMPLEXREGION = 3 + +; CombineRgn styles + +RGN_AND = 1 +RGN_OR = 2 +RGN_XOR = 3 +RGN_DIFF = 4 +RGN_COPY = 5 + +; StretchBlt modes + +BLACKONWHITE = 1 +WHITEONBLACK = 2 +COLORONCOLOR = 3 +HALFTONE = 4 +STRETCH_ANDSCANS = BLACKONWHITE +STRETCH_ORSCANS = WHITEONBLACK +STRETCH_DELETESCANS = COLORONCOLOR +STRETCH_HALFTONE = HALFTONE + +; PolyFill modes + +ALTERNATE = 1 +WINDING = 2 + +; Background modes + +TRANSPARENT = 1 +OPAQUE = 2 + +; Point types + +PT_CLOSEFIGURE = 1 +PT_LINETO = 2 +PT_BEZIERTO = 4 +PT_MOVETO = 6 + +; Mapping modes + +MM_TEXT = 1 +MM_LOMETRIC = 2 +MM_HIMETRIC = 3 +MM_LOENGLISH = 4 +MM_HIENGLISH = 5 +MM_TWIPS = 6 +MM_ISOTROPIC = 7 +MM_ANISOTROPIC = 8 + +; Coordinate modes + +ABSOLUTE = 1 +RELATIVE = 2 + +; Stock logical objects + +WHITE_BRUSH = 0 +LTGRAY_BRUSH = 1 +GRAY_BRUSH = 2 +DKGRAY_BRUSH = 3 +BLACK_BRUSH = 4 +NULL_BRUSH = 5 +HOLLOW_BRUSH = NULL_BRUSH +WHITE_PEN = 6 +BLACK_PEN = 7 +NULL_PEN = 8 +OEM_FIXED_FONT = 10 +ANSI_FIXED_FONT = 11 +ANSI_VAR_FONT = 12 +SYSTEM_FONT = 13 +DEVICE_DEFAULT_FONT = 14 +DEFAULT_PALETTE = 15 +SYSTEM_FIXED_FONT = 16 +DEFAULT_GUI_FONT = 17 + +; Brush styles + +BS_SOLID = 0 +BS_NULL = 1 +BS_HOLLOW = BS_NULL +BS_HATCHED = 2 +BS_PATTERN = 3 +BS_INDEXED = 4 +BS_DIBPATTERN = 5 +BS_DIBPATTERNPT = 6 +BS_PATTERN8X8 = 7 +BS_DIBPATTERN8X8 = 8 +BS_MONOPATTERN = 9 + +; Hatch styles + +HS_HORIZONTAL = 0 +HS_VERTICAL = 1 +HS_FDIAGONAL = 2 +HS_BDIAGONAL = 3 +HS_CROSS = 4 +HS_DIAGCROSS = 5 + +; Pen styles + +PS_SOLID = 0 +PS_DASH = 1 +PS_DOT = 2 +PS_DASHDOT = 3 +PS_DASHDOTDOT = 4 +PS_NULL = 5 +PS_INSIDEFRAME = 6 +PS_USERSTYLE = 7 +PS_ALTERNATE = 8 +PS_ENDCAP_ROUND = 0 +PS_ENDCAP_SQUARE = 100h +PS_ENDCAP_FLAT = 200h +PS_JOIN_ROUND = 0 +PS_JOIN_BEVEL = 1000h +PS_JOIN_MITER = 2000h +PS_COSMETIC = 0 +PS_GEOMETRIC = 010000h + +; Arc directions + +AD_COUNTERCLOCKWISE = 1 +AD_CLOCKWISE = 2 + +; Text alignment options + +TA_NOUPDATECP = 0 +TA_UPDATECP = 1 +TA_LEFT = 0 +TA_RIGHT = 2 +TA_CENTER = 6 +TA_TOP = 0 +TA_BOTTOM = 8 +TA_BASELINE = 24 +TA_RTLREADING = 100h +VTA_BASELINE = TA_BASELINE +VTA_LEFT = TA_BOTTOM +VTA_RIGHT = TA_TOP +VTA_CENTER = TA_CENTER +VTA_BOTTOM = TA_RIGHT +VTA_TOP = TA_LEFT + +; ExtTextOut options + +ETO_OPAQUE = 0002h +ETO_CLIPPED = 0004h +ETO_GLYPH_INDEX = 0010h +ETO_RTLREADING = 0080h +ETO_IGNORELANGUAGE = 1000h + +; Bitmap compression types + +BI_RGB = 0 +BI_RLE8 = 1 +BI_RLE4 = 2 +BI_BITFIELDS = 3 + +; tmPitchAndFamily flags + +TMPF_FIXED_PITCH = 1 +TMPF_VECTOR = 2 +TMPF_TRUETYPE = 4 +TMPF_DEVICE = 8 + +; Font output precision values + +OUT_DEFAULT_PRECIS = 0 +OUT_STRING_PRECIS = 1 +OUT_CHARACTER_PRECIS = 2 +OUT_STROKE_PRECIS = 3 +OUT_TT_PRECIS = 4 +OUT_DEVICE_PRECIS = 5 +OUT_RASTER_PRECIS = 6 +OUT_TT_ONLY_PRECIS = 7 +OUT_OUTLINE_PRECIS = 8 +OUT_SCREEN_OUTLINE_PRECIS = 9 + +; Font clipping precision values + +CLIP_DEFAULT_PRECIS = 0 +CLIP_CHARACTER_PRECIS = 1 +CLIP_STROKE_PRECIS = 2 +CLIP_LH_ANGLES = 10h +CLIP_TT_ALWAYS = 20h +CLIP_EMBEDDED = 80h + +; Font output quality values + +DEFAULT_QUALITY = 0 +DRAFT_QUALITY = 1 +PROOF_QUALITY = 2 +NONANTIALIASED_QUALITY = 3 +ANTIALIASED_QUALITY = 4 + +; Font pitch values + +DEFAULT_PITCH = 0 +FIXED_PITCH = 1 +VARIABLE_PITCH = 2 +MONO_FONT = 8 + +; Font families + +FF_DONTCARE = 00h +FF_ROMAN = 10h +FF_SWISS = 20h +FF_MODERN = 30h +FF_SCRIPT = 40h +FF_DECORATIVE = 50h + +; Font weights + +FW_DONTCARE = 0 +FW_THIN = 100 +FW_EXTRALIGHT = 200 +FW_LIGHT = 300 +FW_NORMAL = 400 +FW_MEDIUM = 500 +FW_SEMIBOLD = 600 +FW_BOLD = 700 +FW_EXTRABOLD = 800 +FW_HEAVY = 900 +FW_ULTRALIGHT = FW_EXTRALIGHT +FW_REGULAR = FW_NORMAL +FW_DEMIBOLD = FW_SEMIBOLD +FW_ULTRABOLD = FW_EXTRABOLD +FW_BLACK = FW_HEAVY + +; Character set values + +ANSI_CHARSET = 0 +DEFAULT_CHARSET = 1 +SYMBOL_CHARSET = 2 +SHIFTJIS_CHARSET = 128 +HANGEUL_CHARSET = 129 +GB2312_CHARSET = 134 +CHINESEBIG5_CHARSET = 136 +OEM_CHARSET = 255 +JOHAB_CHARSET = 130 +HEBREW_CHARSET = 177 +ARABIC_CHARSET = 178 +GREEK_CHARSET = 161 +TURKISH_CHARSET = 162 +VIETNAMESE_CHARSET = 163 +THAI_CHARSET = 222 +EASTEUROPE_CHARSET = 238 +RUSSIAN_CHARSET = 204 +MAC_CHARSET = 77 +BALTIC_CHARSET = 186 + +; Pixel format constants + +PFD_TYPE_RGBA = 0 +PFD_TYPE_COLORINDEX = 1 +PFD_MAIN_PLANE = 0 +PFD_OVERLAY_PLANE = 1 +PFD_UNDERLAY_PLANE = -1 +PFD_DOUBLEBUFFER = 1 +PFD_STEREO = 2 +PFD_DRAW_TO_WINDOW = 4 +PFD_DRAW_TO_BITMAP = 8 +PFD_SUPPORT_GDI = 10h +PFD_SUPPORT_OPENGL = 20h +PFD_GENERIC_FORMAT = 40h +PFD_NEED_PALETTE = 80h +PFD_NEED_SYSTEM_PALETTE = 100h +PFD_SWAP_EXCHANGE = 200h +PFD_SWAP_COPY = 400h +PFD_SWAP_LAYER_BUFFERS = 800h +PFD_GENERIC_ACCELERATED = 1000h +PFD_DEPTH_DONTCARE = 20000000h +PFD_DOUBLEBUFFER_DONTCARE = 40000000h +PFD_STEREO_DONTCARE = 80000000h diff --git a/toolchain/fasm2/include/equates/kernel32.inc b/toolchain/fasm2/include/equates/kernel32.inc new file mode 100644 index 0000000..40b3569 --- /dev/null +++ b/toolchain/fasm2/include/equates/kernel32.inc @@ -0,0 +1,812 @@ + +; KERNEL32.DLL structures and constants + +struct SYSTEM_INFO + wProcessorArchitecture dw ? + wReserved dw ? + dwPageSize dd ? + lpMinimumApplicationAddress dd ? + lpMaximumApplicationAddress dd ? + dwActiveProcessorMask dd ? + dwNumberOfProcessors dd ? + dwProcessorType dd ? + dwAllocationGranularity dd ? + wProcessorLevel dw ? + wProcessorRevision dw ? +ends + +struct OSVERSIONINFO + dwOSVersionInfoSize dd ? + dwMajorVersion dd ? + dwMinorVersion dd ? + dwBuildNumber dd ? + dwPlatformId dd ? + szCSDVersion TCHAR 128 dup (?) +ends + +struct OSVERSIONINFOA + dwOSVersionInfoSize dd ? + dwMajorVersion dd ? + dwMinorVersion dd ? + dwBuildNumber dd ? + dwPlatformId dd ? + szCSDVersion db 128 dup (?) +ends + +struct OSVERSIONINFOW + dwOSVersionInfoSize dd ? + dwMajorVersion dd ? + dwMinorVersion dd ? + dwBuildNumber dd ? + dwPlatformId dd ? + szCSDVersion du 128 dup (?) +ends + +struct MEMORYSTATUS + dwLength dd ? + dwMemoryLoad dd ? + dwTotalPhys dd ? + dwAvailPhys dd ? + dwTotalPageFile dd ? + dwAvailPageFile dd ? + dwTotalVirtual dd ? + dwAvailVirtual dd ? +ends + +struct STARTUPINFO + cb dd ? + lpReserved dd ? + lpDesktop dd ? + lpTitle dd ? + dwX dd ? + dwY dd ? + dwXSize dd ? + dwYSize dd ? + dwXCountChars dd ? + dwYCountChars dd ? + dwFillAttribute dd ? + dwFlags dd ? + wShowWindow dw ? + cbReserved2 dw ? + lpReserved2 dd ? + hStdInput dd ? + hStdOutput dd ? + hStdError dd ? +ends + +struct PROCESS_INFORMATION + hProcess dd ? + hThread dd ? + dwProcessId dd ? + dwThreadId dd ? +ends + +struct FILETIME + dwLowDateTime dd ? + dwHighDateTime dd ? +ends + +struct SYSTEMTIME + wYear dw ? + wMonth dw ? + wDayOfWeek dw ? + wDay dw ? + wHour dw ? + wMinute dw ? + wSecond dw ? + wMilliseconds dw ? +ends + +struct BY_HANDLE_FILE_INFORMATION + dwFileAttributes dd ? + ftCreationTime FILETIME + ftLastAccessTime FILETIME + ftLastWriteTime FILETIME + dwVolumeSerialNumber dd ? + nFileSizeHigh dd ? + nFileSizeLow dd ? + nNumberOfLinks dd ? + nFileIndexHigh dd ? + nFileIndexLow dd ? +ends + +struct WIN32_FIND_DATA + dwFileAttributes dd ? + ftCreationTime FILETIME + ftLastAccessTime FILETIME + ftLastWriteTime FILETIME + nFileSizeHigh dd ? + nFileSizeLow dd ? + dwReserved0 dd ? + dwReserved1 dd ? + cFileName TCHAR MAX_PATH dup (?) + cAlternateFileName TCHAR 14 dup (?) +ends + +struct WIN32_FIND_DATAA + dwFileAttributes dd ? + ftCreationTime FILETIME + ftLastAccessTime FILETIME + ftLastWriteTime FILETIME + nFileSizeHigh dd ? + nFileSizeLow dd ? + dwReserved0 dd ? + dwReserved1 dd ? + cFileName db MAX_PATH dup (?) + cAlternateFileName db 14 dup (?) +ends + +struct WIN32_FIND_DATAW + dwFileAttributes dd ? + ftCreationTime FILETIME + ftLastAccessTime FILETIME + ftLastWriteTime FILETIME + nFileSizeHigh dd ? + nFileSizeLow dd ? + dwReserved0 dd ? + dwReserved1 dd ? + cFileName du MAX_PATH dup (?) + cAlternateFileName du 14 dup (?) +ends + +; General constants + +NULL = 0 +TRUE = 1 +FALSE = 0 + +; Maximum path length in characters + +MAX_PATH = 260 + +; Access rights + +DELETE_RIGHT = 00010000h +READ_CONTROL = 00020000h +WRITE_DAC = 00040000h +WRITE_OWNER = 00080000h +SYNCHRONIZE = 00100000h +STANDARD_RIGHTS_READ = READ_CONTROL +STANDARD_RIGHTS_WRITE = READ_CONTROL +STANDARD_RIGHTS_EXECUTE = READ_CONTROL +STANDARD_RIGHTS_REQUIRED = 000F0000h +STANDARD_RIGHTS_ALL = 001F0000h +SPECIFIC_RIGHTS_ALL = 0000FFFFh +ACCESS_SYSTEM_SECURITY = 01000000h +MAXIMUM_ALLOWED = 02000000h +GENERIC_READ = 80000000h +GENERIC_WRITE = 40000000h +GENERIC_EXECUTE = 20000000h +GENERIC_ALL = 10000000h +PROCESS_TERMINATE = 00000001h +PROCESS_CREATE_THREAD = 00000002h +PROCESS_VM_OPERATION = 00000008h +PROCESS_VM_READ = 00000010h +PROCESS_VM_WRITE = 00000020h +PROCESS_DUP_HANDLE = 00000040h +PROCESS_CREATE_PROCESS = 00000080h +PROCESS_SET_QUOTA = 00000100h +PROCESS_SET_INFORMATION = 00000200h +PROCESS_QUERY_INFORMATION = 00000400h +PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or 0FFFh +FILE_SHARE_READ = 00000001h +FILE_SHARE_WRITE = 00000002h +FILE_SHARE_DELETE = 00000004h + +; CreateFile actions + +CREATE_NEW = 1 +CREATE_ALWAYS = 2 +OPEN_EXISTING = 3 +OPEN_ALWAYS = 4 +TRUNCATE_EXISTING = 5 + +; OpenFile modes + +OF_READ = 0000h +OF_WRITE = 0001h +OF_READWRITE = 0002h +OF_SHARE_COMPAT = 0000h +OF_SHARE_EXCLUSIVE = 0010h +OF_SHARE_DENY_WRITE = 0020h +OF_SHARE_DENY_READ = 0030h +OF_SHARE_DENY_NONE = 0040h +OF_PARSE = 0100h +OF_DELETE = 0200h +OF_VERIFY = 0400h +OF_CANCEL = 0800h +OF_CREATE = 1000h +OF_PROMPT = 2000h +OF_EXIST = 4000h +OF_REOPEN = 8000h + +; SetFilePointer methods + +FILE_BEGIN = 0 +FILE_CURRENT = 1 +FILE_END = 2 + +; File attributes + +FILE_ATTRIBUTE_READONLY = 001h +FILE_ATTRIBUTE_HIDDEN = 002h +FILE_ATTRIBUTE_SYSTEM = 004h +FILE_ATTRIBUTE_DIRECTORY = 010h +FILE_ATTRIBUTE_ARCHIVE = 020h +FILE_ATTRIBUTE_NORMAL = 080h +FILE_ATTRIBUTE_TEMPORARY = 100h +FILE_ATTRIBUTE_COMPRESSED = 800h + +; File flags + +FILE_FLAG_WRITE_THROUGH = 80000000h +FILE_FLAG_OVERLAPPED = 40000000h +FILE_FLAG_NO_BUFFERING = 20000000h +FILE_FLAG_RANDOM_ACCESS = 10000000h +FILE_FLAG_SEQUENTIAL_SCAN = 08000000h +FILE_FLAG_DELETE_ON_CLOSE = 04000000h +FILE_FLAG_BACKUP_SEMANTICS = 02000000h +FILE_FLAG_POSIX_SEMANTICS = 01000000h + +; Notify filters + +FILE_NOTIFY_CHANGE_FILE_NAME = 001h +FILE_NOTIFY_CHANGE_DIR_NAME = 002h +FILE_NOTIFY_CHANGE_ATTRIBUTES = 004h +FILE_NOTIFY_CHANGE_SIZE = 008h +FILE_NOTIFY_CHANGE_LAST_WRITE = 010h +FILE_NOTIFY_CHANGE_SECURITY = 100h + +; File types + +FILE_TYPE_UNKNOWN = 0 +FILE_TYPE_DISK = 1 +FILE_TYPE_CHAR = 2 +FILE_TYPE_PIPE = 3 +FILE_TYPE_REMOTE = 8000h + +; LockFileEx flags + +LOCKFILE_FAIL_IMMEDIATELY = 1 +LOCKFILE_EXCLUSIVE_LOCK = 2 + +; MoveFileEx flags + +MOVEFILE_REPLACE_EXISTING = 1 +MOVEFILE_COPY_ALLOWED = 2 +MOVEFILE_DELAY_UNTIL_REBOOT = 4 +MOVEFILE_WRITE_THROUGH = 8 + +; FindFirstFileEx flags + +FIND_FIRST_EX_CASE_SENSITIVE = 1 + +; Device handles + +INVALID_HANDLE_VALUE = -1 +STD_INPUT_HANDLE = -10 +STD_OUTPUT_HANDLE = -11 +STD_ERROR_HANDLE = -12 + +; DuplicateHandle options + +DUPLICATE_CLOSE_SOURCE = 1 +DUPLICATE_SAME_ACCESS = 2 + +; File mapping acccess rights + +SECTION_QUERY = 01h +SECTION_MAP_WRITE = 02h +SECTION_MAP_READ = 04h +SECTION_MAP_EXECUTE = 08h +SECTION_EXTEND_SIZE = 10h +SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SECTION_QUERY or SECTION_MAP_WRITE or SECTION_MAP_READ or SECTION_MAP_EXECUTE or SECTION_EXTEND_SIZE +FILE_MAP_COPY = SECTION_QUERY +FILE_MAP_WRITE = SECTION_MAP_WRITE +FILE_MAP_READ = SECTION_MAP_READ +FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS + +; File system flags + +FILE_CASE_SENSITIVE_SEARCH = 0001h +FILE_CASE_PRESERVED_NAMES = 0002h +FILE_UNICODE_ON_DISK = 0004h +FILE_PERSISTENT_ACLS = 0008h +FILE_FILE_COMPRESSION = 0010h +FILE_VOLUME_IS_COMPRESSED = 8000h +FS_CASE_IS_PRESERVED = FILE_CASE_PRESERVED_NAMES +FS_CASE_SENSITIVE = FILE_CASE_SENSITIVE_SEARCH +FS_UNICODE_STORED_ON_DISK = FILE_UNICODE_ON_DISK +FS_PERSISTENT_ACLS = FILE_PERSISTENT_ACLS + +; Drive types + +DRIVE_UNKNOWN = 0 +DRIVE_NO_ROOT_DIR = 1 +DRIVE_REMOVABLE = 2 +DRIVE_FIXED = 3 +DRIVE_REMOTE = 4 +DRIVE_CDROM = 5 +DRIVE_RAMDISK = 6 + +; Pipe modes + +PIPE_ACCESS_INBOUND = 1 +PIPE_ACCESS_OUTBOUND = 2 +PIPE_ACCESS_DUPLEX = 3 +PIPE_CLIENT_END = 0 +PIPE_SERVER_END = 1 +PIPE_WAIT = 0 +PIPE_NOWAIT = 1 +PIPE_READMODE_BYTE = 0 +PIPE_READMODE_MESSAGE = 2 +PIPE_TYPE_BYTE = 0 +PIPE_TYPE_MESSAGE = 4 +PIPE_UNLIMITED_INSTANCES = 255 + +; Global memory flags + +GMEM_FIXED = 0000h +GMEM_MOVEABLE = 0002h +GMEM_NOCOMPACT = 0010h +GMEM_NODISCARD = 0020h +GMEM_ZEROINIT = 0040h +GMEM_MODIFY = 0080h +GMEM_DISCARDABLE = 0100h +GMEM_NOT_BANKED = 1000h +GMEM_SHARE = 2000h +GMEM_DDESHARE = 2000h +GMEM_NOTIFY = 4000h +GMEM_LOWER = GMEM_NOT_BANKED +GMEM_VALID_FLAGS = 7F72h +GMEM_INVALID_HANDLE = 8000h +GMEM_DISCARDED = 4000h +GMEM_LOCKCOUNT = 0FFh +GHND = GMEM_MOVEABLE + GMEM_ZEROINIT +GPTR = GMEM_FIXED + GMEM_ZEROINIT + +; Local memory flags + +LMEM_FIXED = 0000h +LMEM_MOVEABLE = 0002h +LMEM_NOCOMPACT = 0010h +LMEM_NODISCARD = 0020h +LMEM_ZEROINIT = 0040h +LMEM_MODIFY = 0080h +LMEM_DISCARDABLE = 0F00h +LMEM_VALID_FLAGS = 0F72h +LMEM_INVALID_HANDLE = 8000h +LHND = LMEM_MOVEABLE + LMEM_ZEROINIT +LPTR = LMEM_FIXED + LMEM_ZEROINIT +LMEM_DISCARDED = 4000h +LMEM_LOCKCOUNT = 00FFh + +; Page access flags + +PAGE_NOACCESS = 001h +PAGE_READONLY = 002h +PAGE_READWRITE = 004h +PAGE_WRITECOPY = 008h +PAGE_EXECUTE = 010h +PAGE_EXECUTE_READ = 020h +PAGE_EXECUTE_READWRITE = 040h +PAGE_EXECUTE_WRITECOPY = 080h +PAGE_GUARD = 100h +PAGE_NOCACHE = 200h + +; Memory allocation flags + +MEM_COMMIT = 001000h +MEM_RESERVE = 002000h +MEM_DECOMMIT = 004000h +MEM_RELEASE = 008000h +MEM_FREE = 010000h +MEM_PRIVATE = 020000h +MEM_MAPPED = 040000h +MEM_RESET = 080000h +MEM_TOP_DOWN = 100000h + +; Heap allocation flags + +HEAP_NO_SERIALIZE = 1 +HEAP_GENERATE_EXCEPTIONS = 4 +HEAP_ZERO_MEMORY = 8 + +; Platform identifiers + +VER_PLATFORM_WIN32s = 0 +VER_PLATFORM_WIN32_WINDOWS = 1 +VER_PLATFORM_WIN32_NT = 2 + +; GetBinaryType return values + +SCS_32BIT_BINARY = 0 +SCS_DOS_BINARY = 1 +SCS_WOW_BINARY = 2 +SCS_PIF_BINARY = 3 +SCS_POSIX_BINARY = 4 +SCS_OS216_BINARY = 5 + +; CreateProcess flags + +DEBUG_PROCESS = 001h +DEBUG_ONLY_THIS_PROCESS = 002h +CREATE_SUSPENDED = 004h +DETACHED_PROCESS = 008h +CREATE_NEW_CONSOLE = 010h +NORMAL_PRIORITY_CLASS = 020h +IDLE_PRIORITY_CLASS = 040h +HIGH_PRIORITY_CLASS = 080h +REALTIME_PRIORITY_CLASS = 100h +CREATE_NEW_PROCESS_GROUP = 200h +CREATE_SEPARATE_WOW_VDM = 800h + +; Thread priority values + +THREAD_BASE_PRIORITY_MIN = -2 +THREAD_BASE_PRIORITY_MAX = 2 +THREAD_BASE_PRIORITY_LOWRT = 15 +THREAD_BASE_PRIORITY_IDLE = -15 +THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN +THREAD_PRIORITY_BELOW_NORMAL = THREAD_PRIORITY_LOWEST + 1 +THREAD_PRIORITY_NORMAL = 0 +THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX +THREAD_PRIORITY_ABOVE_NORMAL = THREAD_PRIORITY_HIGHEST - 1 +THREAD_PRIORITY_ERROR_RETURN = 7FFFFFFFh +THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT +THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE + +; Startup flags + +STARTF_USESHOWWINDOW = 001h +STARTF_USESIZE = 002h +STARTF_USEPOSITION = 004h +STARTF_USECOUNTCHARS = 008h +STARTF_USEFILLATTRIBUTE = 010h +STARTF_RUNFULLSCREEN = 020h +STARTF_FORCEONFEEDBACK = 040h +STARTF_FORCEOFFFEEDBACK = 080h +STARTF_USESTDHANDLES = 100h + +; Shutdown flags + +SHUTDOWN_NORETRY = 1h + +; LoadLibraryEx flags + +DONT_RESOLVE_DLL_REFERENCES = 1 +LOAD_LIBRARY_AS_DATAFILE = 2 +LOAD_WITH_ALTERED_SEARCH_PATH = 8 + +; DLL entry-point calls + +DLL_PROCESS_DETACH = 0 +DLL_PROCESS_ATTACH = 1 +DLL_THREAD_ATTACH = 2 +DLL_THREAD_DETACH = 3 + +; Status codes + +STATUS_WAIT_0 = 000000000h +STATUS_ABANDONED_WAIT_0 = 000000080h +STATUS_USER_APC = 0000000C0h +STATUS_TIMEOUT = 000000102h +STATUS_PENDING = 000000103h +STATUS_DATATYPE_MISALIGNMENT = 080000002h +STATUS_BREAKPOINT = 080000003h +STATUS_SINGLE_STEP = 080000004h +STATUS_ACCESS_VIOLATION = 0C0000005h +STATUS_IN_PAGE_ERROR = 0C0000006h +STATUS_NO_MEMORY = 0C0000017h +STATUS_ILLEGAL_INSTRUCTION = 0C000001Dh +STATUS_NONCONTINUABLE_EXCEPTION = 0C0000025h +STATUS_INVALID_DISPOSITION = 0C0000026h +STATUS_ARRAY_BOUNDS_EXCEEDED = 0C000008Ch +STATUS_FLOAT_DENORMAL_OPERAND = 0C000008Dh +STATUS_FLOAT_DIVIDE_BY_ZERO = 0C000008Eh +STATUS_FLOAT_INEXACT_RESULT = 0C000008Fh +STATUS_FLOAT_INVALID_OPERATION = 0C0000090h +STATUS_FLOAT_OVERFLOW = 0C0000091h +STATUS_FLOAT_STACK_CHECK = 0C0000092h +STATUS_FLOAT_UNDERFLOW = 0C0000093h +STATUS_INTEGER_DIVIDE_BY_ZERO = 0C0000094h +STATUS_INTEGER_OVERFLOW = 0C0000095h +STATUS_PRIVILEGED_INSTRUCTION = 0C0000096h +STATUS_STACK_OVERFLOW = 0C00000FDh +STATUS_CONTROL_C_EXIT = 0C000013Ah +WAIT_FAILED = -1 +WAIT_OBJECT_0 = STATUS_WAIT_0 +WAIT_ABANDONED = STATUS_ABANDONED_WAIT_0 +WAIT_ABANDONED_0 = STATUS_ABANDONED_WAIT_0 +WAIT_TIMEOUT = STATUS_TIMEOUT +WAIT_IO_COMPLETION = STATUS_USER_APC +STILL_ACTIVE = STATUS_PENDING + +; Exception codes + +EXCEPTION_CONTINUABLE = 0 +EXCEPTION_NONCONTINUABLE = 1 +EXCEPTION_ACCESS_VIOLATION = STATUS_ACCESS_VIOLATION +EXCEPTION_DATATYPE_MISALIGNMENT = STATUS_DATATYPE_MISALIGNMENT +EXCEPTION_BREAKPOINT = STATUS_BREAKPOINT +EXCEPTION_SINGLE_STEP = STATUS_SINGLE_STEP +EXCEPTION_ARRAY_BOUNDS_EXCEEDED = STATUS_ARRAY_BOUNDS_EXCEEDED +EXCEPTION_FLT_DENORMAL_OPERAND = STATUS_FLOAT_DENORMAL_OPERAND +EXCEPTION_FLT_DIVIDE_BY_ZERO = STATUS_FLOAT_DIVIDE_BY_ZERO +EXCEPTION_FLT_INEXACT_RESULT = STATUS_FLOAT_INEXACT_RESULT +EXCEPTION_FLT_INVALID_OPERATION = STATUS_FLOAT_INVALID_OPERATION +EXCEPTION_FLT_OVERFLOW = STATUS_FLOAT_OVERFLOW +EXCEPTION_FLT_STACK_CHECK = STATUS_FLOAT_STACK_CHECK +EXCEPTION_FLT_UNDERFLOW = STATUS_FLOAT_UNDERFLOW +EXCEPTION_INT_DIVIDE_BY_ZERO = STATUS_INTEGER_DIVIDE_BY_ZERO +EXCEPTION_INT_OVERFLOW = STATUS_INTEGER_OVERFLOW +EXCEPTION_ILLEGAL_INSTRUCTION = STATUS_ILLEGAL_INSTRUCTION +EXCEPTION_PRIV_INSTRUCTION = STATUS_PRIVILEGED_INSTRUCTION +EXCEPTION_IN_PAGE_ERROR = STATUS_IN_PAGE_ERROR + +; Registry options + +REG_OPTION_RESERVED = 0 +REG_OPTION_NON_VOLATILE = 0 +REG_OPTION_VOLATILE = 1 +REG_OPTION_CREATE_LINK = 2 +REG_OPTION_BACKUP_RESTORE = 4 +REG_CREATED_NEW_KEY = 1 +REG_OPENED_EXISTING_KEY = 2 +REG_WHOLE_HIVE_VOLATILE = 1 +REG_REFRESH_HIVE = 2 +REG_NOTIFY_CHANGE_NAME = 1 +REG_NOTIFY_CHANGE_ATTRIBUTES = 2 +REG_NOTIFY_CHANGE_LAST_SET = 4 +REG_NOTIFY_CHANGE_SECURITY = 8 +REG_LEGAL_CHANGE_FILTER = REG_NOTIFY_CHANGE_NAME or REG_NOTIFY_CHANGE_ATTRIBUTES or REG_NOTIFY_CHANGE_LAST_SET or REG_NOTIFY_CHANGE_SECURITY +REG_LEGAL_OPTION = REG_OPTION_RESERVED or REG_OPTION_NON_VOLATILE or REG_OPTION_VOLATILE or REG_OPTION_CREATE_LINK or REG_OPTION_BACKUP_RESTORE +REG_NONE = 0 +REG_SZ = 1 +REG_EXPAND_SZ = 2 +REG_BINARY = 3 +REG_DWORD = 4 +REG_DWORD_LITTLE_ENDIAN = 4 +REG_DWORD_BIG_ENDIAN = 5 +REG_LINK = 6 +REG_MULTI_SZ = 7 +REG_RESOURCE_LIST = 8 +REG_FULL_RESOURCE_DESCRIPTOR = 9 +REG_RESOURCE_REQUIREMENTS_LIST = 10 + +; Registry access modes + +KEY_QUERY_VALUE = 1 +KEY_SET_VALUE = 2 +KEY_CREATE_SUB_KEY = 4 +KEY_ENUMERATE_SUB_KEYS = 8 +KEY_NOTIFY = 10h +KEY_CREATE_LINK = 20h +KEY_READ = STANDARD_RIGHTS_READ or KEY_QUERY_VALUE or KEY_ENUMERATE_SUB_KEYS or KEY_NOTIFY and not SYNCHRONIZE +KEY_WRITE = STANDARD_RIGHTS_WRITE or KEY_SET_VALUE or KEY_CREATE_SUB_KEY and not SYNCHRONIZE +KEY_EXECUTE = KEY_READ +KEY_ALL_ACCESS = STANDARD_RIGHTS_ALL or KEY_QUERY_VALUE or KEY_SET_VALUE or KEY_CREATE_SUB_KEY or KEY_ENUMERATE_SUB_KEYS or KEY_NOTIFY or KEY_CREATE_LINK and not SYNCHRONIZE + +; Predefined registry keys + +HKEY_CLASSES_ROOT = 80000000h +HKEY_CURRENT_USER = 80000001h +HKEY_LOCAL_MACHINE = 80000002h +HKEY_USERS = 80000003h +HKEY_PERFORMANCE_DATA = 80000004h +HKEY_CURRENT_CONFIG = 80000005h +HKEY_DYN_DATA = 80000006h + +; FormatMessage flags + +FORMAT_MESSAGE_ALLOCATE_BUFFER = 0100h +FORMAT_MESSAGE_IGNORE_INSERTS = 0200h +FORMAT_MESSAGE_FROM_STRING = 0400h +FORMAT_MESSAGE_FROM_HMODULE = 0800h +FORMAT_MESSAGE_FROM_SYSTEM = 1000h +FORMAT_MESSAGE_ARGUMENT_ARRAY = 2000h +FORMAT_MESSAGE_MAX_WIDTH_MASK = 00FFh + +; Language identifiers + +LANG_NEUTRAL = 00h +LANG_BULGARIAN = 02h +LANG_CHINESE = 04h +LANG_CROATIAN = 1Ah +LANG_CZECH = 05h +LANG_DANISH = 06h +LANG_DUTCH = 13h +LANG_ENGLISH = 09h +LANG_FINNISH = 0Bh +LANG_FRENCH = 0Ch +LANG_GERMAN = 07h +LANG_GREEK = 08h +LANG_HUNGARIAN = 0Eh +LANG_ICELANDIC = 0Fh +LANG_ITALIAN = 10h +LANG_JAPANESE = 11h +LANG_KOREAN = 12h +LANG_NORWEGIAN = 14h +LANG_POLISH = 15h +LANG_PORTUGUESE = 16h +LANG_ROMANIAN = 18h +LANG_RUSSIAN = 19h +LANG_SLOVAK = 1Bh +LANG_SLOVENIAN = 24h +LANG_SPANISH = 0Ah +LANG_SWEDISH = 1Dh +LANG_THAI = 1Eh +LANG_TURKISH = 1Fh + +; Sublanguage identifiers + +SUBLANG_NEUTRAL = 00h shl 10 +SUBLANG_DEFAULT = 01h shl 10 +SUBLANG_SYS_DEFAULT = 02h shl 10 +SUBLANG_CHINESE_TRADITIONAL = 01h shl 10 +SUBLANG_CHINESE_SIMPLIFIED = 02h shl 10 +SUBLANG_CHINESE_HONGKONG = 03h shl 10 +SUBLANG_CHINESE_SINGAPORE = 04h shl 10 +SUBLANG_DUTCH = 01h shl 10 +SUBLANG_DUTCH_BELGIAN = 02h shl 10 +SUBLANG_ENGLISH_US = 01h shl 10 +SUBLANG_ENGLISH_UK = 02h shl 10 +SUBLANG_ENGLISH_AUS = 03h shl 10 +SUBLANG_ENGLISH_CAN = 04h shl 10 +SUBLANG_ENGLISH_NZ = 05h shl 10 +SUBLANG_ENGLISH_EIRE = 06h shl 10 +SUBLANG_FRENCH = 01h shl 10 +SUBLANG_FRENCH_BELGIAN = 02h shl 10 +SUBLANG_FRENCH_CANADIAN = 03h shl 10 +SUBLANG_FRENCH_SWISS = 04h shl 10 +SUBLANG_GERMAN = 01h shl 10 +SUBLANG_GERMAN_SWISS = 02h shl 10 +SUBLANG_GERMAN_AUSTRIAN = 03h shl 10 +SUBLANG_ITALIAN = 01h shl 10 +SUBLANG_ITALIAN_SWISS = 02h shl 10 +SUBLANG_NORWEGIAN_BOKMAL = 01h shl 10 +SUBLANG_NORWEGIAN_NYNORSK = 02h shl 10 +SUBLANG_PORTUGUESE = 02h shl 10 +SUBLANG_PORTUGUESE_BRAZILIAN = 01h shl 10 +SUBLANG_SPANISH = 01h shl 10 +SUBLANG_SPANISH_MEXICAN = 02h shl 10 +SUBLANG_SPANISH_MODERN = 03h shl 10 + +; Sorting identifiers + +SORT_DEFAULT = 0 shl 16 +SORT_JAPANESE_XJIS = 0 shl 16 +SORT_JAPANESE_UNICODE = 1 shl 16 +SORT_CHINESE_BIG5 = 0 shl 16 +SORT_CHINESE_PRCP = 0 shl 16 +SORT_CHINESE_UNICODE = 1 shl 16 +SORT_CHINESE_PRC = 2 shl 16 +SORT_CHINESE_BOPOMOFO = 3 shl 16 +SORT_KOREAN_KSC = 0 shl 16 +SORT_KOREAN_UNICODE = 1 shl 16 +SORT_GERMAN_PHONE_BOOK = 1 shl 16 +SORT_HUNGARIAN_DEFAULT = 0 shl 16 +SORT_HUNGARIAN_TECHNICAL = 1 shl 16 + +; Code pages + +CP_ACP = 0 ; default to ANSI code page +CP_OEMCP = 1 ; default to OEM code page +CP_MACCP = 2 ; default to MAC code page +CP_THREAD_ACP = 3 ; current thread's ANSI code page +CP_SYMBOL = 42 ; SYMBOL translations +CP_UTF7 = 65000 ; UTF-7 translation +CP_UTF8 = 65001 ; UTF-8 translation + +; Resource types + +RT_CURSOR = 1 +RT_BITMAP = 2 +RT_ICON = 3 +RT_MENU = 4 +RT_DIALOG = 5 +RT_STRING = 6 +RT_FONTDIR = 7 +RT_FONT = 8 +RT_ACCELERATOR = 9 +RT_RCDATA = 10 +RT_MESSAGETABLE = 11 +RT_GROUP_CURSOR = 12 +RT_GROUP_ICON = 14 +RT_VERSION = 16 +RT_DLGINCLUDE = 17 +RT_PLUGPLAY = 19 +RT_VXD = 20 +RT_ANICURSOR = 21 +RT_ANIICON = 22 +RT_HTML = 23 +RT_MANIFEST = 24 + +; Clipboard formats + +CF_TEXT = 001h +CF_BITMAP = 002h +CF_METAFILEPICT = 003h +CF_SYLK = 004h +CF_DIF = 005h +CF_TIFF = 006h +CF_OEMTEXT = 007h +CF_DIB = 008h +CF_PALETTE = 009h +CF_PENDATA = 00Ah +CF_RIFF = 00Bh +CF_WAVE = 00Ch +CF_UNICODETEXT = 00Dh +CF_ENHMETAFILE = 00Eh +CF_HDROP = 00Fh +CF_LOCALE = 010h +CF_OWNERDISPLAY = 080h +CF_DSPTEXT = 081h +CF_DSPBITMAP = 082h +CF_DSPMETAFILEPICT = 083h +CF_DSPENHMETAFILE = 08Eh +CF_PRIVATEFIRST = 200h +CF_PRIVATELAST = 2FFh +CF_GDIOBJFIRST = 300h +CF_GDIOBJLAST = 3FFh + +; OS types for version info + +VOS_UNKNOWN = 00000000h +VOS_DOS = 00010000h +VOS_OS216 = 00020000h +VOS_OS232 = 00030000h +VOS_NT = 00040000h +VOS__BASE = 00000000h +VOS__WINDOWS16 = 00000001h +VOS__PM16 = 00000002h +VOS__PM32 = 00000003h +VOS__WINDOWS32 = 00000004h +VOS_DOS_WINDOWS16 = 00010001h +VOS_DOS_WINDOWS32 = 00010004h +VOS_OS216_PM16 = 00020002h +VOS_OS232_PM32 = 00030003h +VOS_NT_WINDOWS32 = 00040004h + +; File types for version info + +VFT_UNKNOWN = 00000000h +VFT_APP = 00000001h +VFT_DLL = 00000002h +VFT_DRV = 00000003h +VFT_FONT = 00000004h +VFT_VXD = 00000005h +VFT_STATIC_LIB = 00000007h + +; File subtypes for version info + +VFT2_UNKNOWN = 00000000h +VFT2_DRV_PRINTER = 00000001h +VFT2_DRV_KEYBOARD = 00000002h +VFT2_DRV_LANGUAGE = 00000003h +VFT2_DRV_DISPLAY = 00000004h +VFT2_DRV_MOUSE = 00000005h +VFT2_DRV_NETWORK = 00000006h +VFT2_DRV_SYSTEM = 00000007h +VFT2_DRV_INSTALLABLE = 00000008h +VFT2_DRV_SOUND = 00000009h +VFT2_DRV_COMM = 0000000Ah +VFT2_DRV_INPUTMETHOD = 0000000Bh +VFT2_DRV_VERSIONED_PRINTER = 0000000Ch +VFT2_FONT_RASTER = 00000001h +VFT2_FONT_VECTOR = 00000002h +VFT2_FONT_TRUETYPE = 00000003h + +; Console control signals + +CTRL_C_EVENT = 0 +CTRL_BREAK_EVENT = 1 +CTRL_CLOSE_EVENT = 2 +CTRL_LOGOFF_EVENT = 5 +CTRL_SHUTDOWN_EVENT = 6 + +; Standard file handles + +STD_INPUT_HANDLE = 0FFFFFFF6h +STD_OUTPUT_HANDLE = 0FFFFFFF5h +STD_ERROR_HANDLE = 0FFFFFFF4h diff --git a/toolchain/fasm2/include/equates/kernel64.inc b/toolchain/fasm2/include/equates/kernel64.inc new file mode 100644 index 0000000..5ebe242 --- /dev/null +++ b/toolchain/fasm2/include/equates/kernel64.inc @@ -0,0 +1,810 @@ + +; KERNEL32.DLL structures and constants + +struct SYSTEM_INFO + wProcessorArchitecture dw ? + wReserved dw ? + dwPageSize dd ? + lpMinimumApplicationAddress dq ? + lpMaximumApplicationAddress dq ? + dwActiveProcessorMask dq ? + dwNumberOfProcessors dd ? + dwProcessorType dd ? + dwAllocationGranularity dd ? + wProcessorLevel dw ? + wProcessorRevision dw ? +ends + +struct OSVERSIONINFO + dwOSVersionInfoSize dd ? + dwMajorVersion dd ? + dwMinorVersion dd ? + dwBuildNumber dd ? + dwPlatformId dd ? + szCSDVersion TCHAR 128 dup (?) +ends + +struct OSVERSIONINFOA + dwOSVersionInfoSize dd ? + dwMajorVersion dd ? + dwMinorVersion dd ? + dwBuildNumber dd ? + dwPlatformId dd ? + szCSDVersion db 128 dup (?) +ends + +struct OSVERSIONINFOW + dwOSVersionInfoSize dd ? + dwMajorVersion dd ? + dwMinorVersion dd ? + dwBuildNumber dd ? + dwPlatformId dd ? + szCSDVersion du 128 dup (?) +ends + +struct MEMORYSTATUS + dwLength dd ? + dwMemoryLoad dd ? + dwTotalPhys dq ? + dwAvailPhys dq ? + dwTotalPageFile dq ? + dwAvailPageFile dq ? + dwTotalVirtual dq ? + dwAvailVirtual dq ? +ends + +struct STARTUPINFO + cb dd ? + dd ? + lpReserved dq ? + lpDesktop dq ? + lpTitle dq ? + dwX dd ? + dwY dd ? + dwXSize dd ? + dwYSize dd ? + dwXCountChars dd ? + dwYCountChars dd ? + dwFillAttribute dd ? + dwFlags dd ? + wShowWindow dw ? + cbReserved2 dw ? + dd ? + lpReserved2 dq ? + hStdInput dq ? + hStdOutput dq ? + hStdError dq ? +ends + +struct PROCESS_INFORMATION + hProcess dq ? + hThread dq ? + dwProcessId dd ? + dwThreadId dd ? +ends + +struct FILETIME + dwLowDateTime dd ? + dwHighDateTime dd ? +ends + +struct SYSTEMTIME + wYear dw ? + wMonth dw ? + wDayOfWeek dw ? + wDay dw ? + wHour dw ? + wMinute dw ? + wSecond dw ? + wMilliseconds dw ? +ends + +struct BY_HANDLE_FILE_INFORMATION + dwFileAttributes dd ? + ftCreationTime FILETIME + ftLastAccessTime FILETIME + ftLastWriteTime FILETIME + dwVolumeSerialNumber dd ? + nFileSizeHigh dd ? + nFileSizeLow dd ? + nNumberOfLinks dd ? + nFileIndexHigh dd ? + nFileIndexLow dd ? +ends + +struct WIN32_FIND_DATA + dwFileAttributes dd ? + ftCreationTime FILETIME + ftLastAccessTime FILETIME + ftLastWriteTime FILETIME + nFileSizeHigh dd ? + nFileSizeLow dd ? + dwReserved0 dd ? + dwReserved1 dd ? + cFileName TCHAR MAX_PATH dup (?) + cAlternateFileName TCHAR 14 dup (?) + align 4 +ends + +struct WIN32_FIND_DATAA + dwFileAttributes dd ? + ftCreationTime FILETIME + ftLastAccessTime FILETIME + ftLastWriteTime FILETIME + nFileSizeHigh dd ? + nFileSizeLow dd ? + dwReserved0 dd ? + dwReserved1 dd ? + cFileName db MAX_PATH dup (?) + cAlternateFileName db 14 dup (?) + align 4 +ends + +struct WIN32_FIND_DATAW + dwFileAttributes dd ? + ftCreationTime FILETIME + ftLastAccessTime FILETIME + ftLastWriteTime FILETIME + nFileSizeHigh dd ? + nFileSizeLow dd ? + dwReserved0 dd ? + dwReserved1 dd ? + cFileName du MAX_PATH dup (?) + cAlternateFileName du 14 dup (?) +ends + +; General constants + +NULL = 0 +TRUE = 1 +FALSE = 0 + +; Maximum path length in characters + +MAX_PATH = 260 + +; Access rights + +DELETE_RIGHT = 00010000h +READ_CONTROL = 00020000h +WRITE_DAC = 00040000h +WRITE_OWNER = 00080000h +SYNCHRONIZE = 00100000h +STANDARD_RIGHTS_READ = READ_CONTROL +STANDARD_RIGHTS_WRITE = READ_CONTROL +STANDARD_RIGHTS_EXECUTE = READ_CONTROL +STANDARD_RIGHTS_REQUIRED = 000F0000h +STANDARD_RIGHTS_ALL = 001F0000h +SPECIFIC_RIGHTS_ALL = 0000FFFFh +ACCESS_SYSTEM_SECURITY = 01000000h +MAXIMUM_ALLOWED = 02000000h +GENERIC_READ = 80000000h +GENERIC_WRITE = 40000000h +GENERIC_EXECUTE = 20000000h +GENERIC_ALL = 10000000h +PROCESS_TERMINATE = 00000001h +PROCESS_CREATE_THREAD = 00000002h +PROCESS_VM_OPERATION = 00000008h +PROCESS_VM_READ = 00000010h +PROCESS_VM_WRITE = 00000020h +PROCESS_DUP_HANDLE = 00000040h +PROCESS_CREATE_PROCESS = 00000080h +PROCESS_SET_QUOTA = 00000100h +PROCESS_SET_INFORMATION = 00000200h +PROCESS_QUERY_INFORMATION = 00000400h +PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or 0FFFh +FILE_SHARE_READ = 00000001h +FILE_SHARE_WRITE = 00000002h +FILE_SHARE_DELETE = 00000004h + +; CreateFile actions + +CREATE_NEW = 1 +CREATE_ALWAYS = 2 +OPEN_EXISTING = 3 +OPEN_ALWAYS = 4 +TRUNCATE_EXISTING = 5 + +; OpenFile modes + +OF_READ = 0000h +OF_WRITE = 0001h +OF_READWRITE = 0002h +OF_SHARE_COMPAT = 0000h +OF_SHARE_EXCLUSIVE = 0010h +OF_SHARE_DENY_WRITE = 0020h +OF_SHARE_DENY_READ = 0030h +OF_SHARE_DENY_NONE = 0040h +OF_PARSE = 0100h +OF_DELETE = 0200h +OF_VERIFY = 0400h +OF_CANCEL = 0800h +OF_CREATE = 1000h +OF_PROMPT = 2000h +OF_EXIST = 4000h +OF_REOPEN = 8000h + +; SetFilePointer methods + +FILE_BEGIN = 0 +FILE_CURRENT = 1 +FILE_END = 2 + +; File attributes + +FILE_ATTRIBUTE_READONLY = 001h +FILE_ATTRIBUTE_HIDDEN = 002h +FILE_ATTRIBUTE_SYSTEM = 004h +FILE_ATTRIBUTE_DIRECTORY = 010h +FILE_ATTRIBUTE_ARCHIVE = 020h +FILE_ATTRIBUTE_NORMAL = 080h +FILE_ATTRIBUTE_TEMPORARY = 100h +FILE_ATTRIBUTE_COMPRESSED = 800h + +; File flags + +FILE_FLAG_WRITE_THROUGH = 80000000h +FILE_FLAG_OVERLAPPED = 40000000h +FILE_FLAG_NO_BUFFERING = 20000000h +FILE_FLAG_RANDOM_ACCESS = 10000000h +FILE_FLAG_SEQUENTIAL_SCAN = 08000000h +FILE_FLAG_DELETE_ON_CLOSE = 04000000h +FILE_FLAG_BACKUP_SEMANTICS = 02000000h +FILE_FLAG_POSIX_SEMANTICS = 01000000h + +; Notify filters + +FILE_NOTIFY_CHANGE_FILE_NAME = 001h +FILE_NOTIFY_CHANGE_DIR_NAME = 002h +FILE_NOTIFY_CHANGE_ATTRIBUTES = 004h +FILE_NOTIFY_CHANGE_SIZE = 008h +FILE_NOTIFY_CHANGE_LAST_WRITE = 010h +FILE_NOTIFY_CHANGE_SECURITY = 100h + +; File types + +FILE_TYPE_UNKNOWN = 0 +FILE_TYPE_DISK = 1 +FILE_TYPE_CHAR = 2 +FILE_TYPE_PIPE = 3 +FILE_TYPE_REMOTE = 8000h + +; LockFileEx flags + +LOCKFILE_FAIL_IMMEDIATELY = 1 +LOCKFILE_EXCLUSIVE_LOCK = 2 + +; MoveFileEx flags + +MOVEFILE_REPLACE_EXISTING = 1 +MOVEFILE_COPY_ALLOWED = 2 +MOVEFILE_DELAY_UNTIL_REBOOT = 4 +MOVEFILE_WRITE_THROUGH = 8 + +; FindFirstFileEx flags + +FIND_FIRST_EX_CASE_SENSITIVE = 1 + +; Device handles + +INVALID_HANDLE_VALUE = -1 +STD_INPUT_HANDLE = -10 +STD_OUTPUT_HANDLE = -11 +STD_ERROR_HANDLE = -12 + +; DuplicateHandle options + +DUPLICATE_CLOSE_SOURCE = 1 +DUPLICATE_SAME_ACCESS = 2 + +; File mapping acccess rights + +SECTION_QUERY = 01h +SECTION_MAP_WRITE = 02h +SECTION_MAP_READ = 04h +SECTION_MAP_EXECUTE = 08h +SECTION_EXTEND_SIZE = 10h +SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SECTION_QUERY or SECTION_MAP_WRITE or SECTION_MAP_READ or SECTION_MAP_EXECUTE or SECTION_EXTEND_SIZE +FILE_MAP_COPY = SECTION_QUERY +FILE_MAP_WRITE = SECTION_MAP_WRITE +FILE_MAP_READ = SECTION_MAP_READ +FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS + +; File system flags + +FILE_CASE_SENSITIVE_SEARCH = 0001h +FILE_CASE_PRESERVED_NAMES = 0002h +FILE_UNICODE_ON_DISK = 0004h +FILE_PERSISTENT_ACLS = 0008h +FILE_FILE_COMPRESSION = 0010h +FILE_VOLUME_IS_COMPRESSED = 8000h +FS_CASE_IS_PRESERVED = FILE_CASE_PRESERVED_NAMES +FS_CASE_SENSITIVE = FILE_CASE_SENSITIVE_SEARCH +FS_UNICODE_STORED_ON_DISK = FILE_UNICODE_ON_DISK +FS_PERSISTENT_ACLS = FILE_PERSISTENT_ACLS + +; Drive types + +DRIVE_UNKNOWN = 0 +DRIVE_NO_ROOT_DIR = 1 +DRIVE_REMOVABLE = 2 +DRIVE_FIXED = 3 +DRIVE_REMOTE = 4 +DRIVE_CDROM = 5 +DRIVE_RAMDISK = 6 + +; Pipe modes + +PIPE_ACCESS_INBOUND = 1 +PIPE_ACCESS_OUTBOUND = 2 +PIPE_ACCESS_DUPLEX = 3 +PIPE_CLIENT_END = 0 +PIPE_SERVER_END = 1 +PIPE_WAIT = 0 +PIPE_NOWAIT = 1 +PIPE_READMODE_BYTE = 0 +PIPE_READMODE_MESSAGE = 2 +PIPE_TYPE_BYTE = 0 +PIPE_TYPE_MESSAGE = 4 +PIPE_UNLIMITED_INSTANCES = 255 + +; Global memory flags + +GMEM_FIXED = 0000h +GMEM_MOVEABLE = 0002h +GMEM_NOCOMPACT = 0010h +GMEM_NODISCARD = 0020h +GMEM_ZEROINIT = 0040h +GMEM_MODIFY = 0080h +GMEM_DISCARDABLE = 0100h +GMEM_NOT_BANKED = 1000h +GMEM_SHARE = 2000h +GMEM_DDESHARE = 2000h +GMEM_NOTIFY = 4000h +GMEM_LOWER = GMEM_NOT_BANKED +GMEM_VALID_FLAGS = 7F72h +GMEM_INVALID_HANDLE = 8000h +GMEM_DISCARDED = 4000h +GMEM_LOCKCOUNT = 0FFh +GHND = GMEM_MOVEABLE + GMEM_ZEROINIT +GPTR = GMEM_FIXED + GMEM_ZEROINIT + +; Local memory flags + +LMEM_FIXED = 0000h +LMEM_MOVEABLE = 0002h +LMEM_NOCOMPACT = 0010h +LMEM_NODISCARD = 0020h +LMEM_ZEROINIT = 0040h +LMEM_MODIFY = 0080h +LMEM_DISCARDABLE = 0F00h +LMEM_VALID_FLAGS = 0F72h +LMEM_INVALID_HANDLE = 8000h +LHND = LMEM_MOVEABLE + LMEM_ZEROINIT +LPTR = LMEM_FIXED + LMEM_ZEROINIT +LMEM_DISCARDED = 4000h +LMEM_LOCKCOUNT = 00FFh + +; Page access flags + +PAGE_NOACCESS = 001h +PAGE_READONLY = 002h +PAGE_READWRITE = 004h +PAGE_WRITECOPY = 008h +PAGE_EXECUTE = 010h +PAGE_EXECUTE_READ = 020h +PAGE_EXECUTE_READWRITE = 040h +PAGE_EXECUTE_WRITECOPY = 080h +PAGE_GUARD = 100h +PAGE_NOCACHE = 200h + +; Memory allocation flags + +MEM_COMMIT = 001000h +MEM_RESERVE = 002000h +MEM_DECOMMIT = 004000h +MEM_RELEASE = 008000h +MEM_FREE = 010000h +MEM_PRIVATE = 020000h +MEM_MAPPED = 040000h +MEM_RESET = 080000h +MEM_TOP_DOWN = 100000h + +; Heap allocation flags + +HEAP_NO_SERIALIZE = 1 +HEAP_GENERATE_EXCEPTIONS = 4 +HEAP_ZERO_MEMORY = 8 + +; Platform identifiers + +VER_PLATFORM_WIN32s = 0 +VER_PLATFORM_WIN32_WINDOWS = 1 +VER_PLATFORM_WIN32_NT = 2 + +; GetBinaryType return values + +SCS_32BIT_BINARY = 0 +SCS_DOS_BINARY = 1 +SCS_WOW_BINARY = 2 +SCS_PIF_BINARY = 3 +SCS_POSIX_BINARY = 4 +SCS_OS216_BINARY = 5 + +; CreateProcess flags + +DEBUG_PROCESS = 001h +DEBUG_ONLY_THIS_PROCESS = 002h +CREATE_SUSPENDED = 004h +DETACHED_PROCESS = 008h +CREATE_NEW_CONSOLE = 010h +NORMAL_PRIORITY_CLASS = 020h +IDLE_PRIORITY_CLASS = 040h +HIGH_PRIORITY_CLASS = 080h +REALTIME_PRIORITY_CLASS = 100h +CREATE_NEW_PROCESS_GROUP = 200h +CREATE_SEPARATE_WOW_VDM = 800h + +; Thread priority values + +THREAD_BASE_PRIORITY_MIN = -2 +THREAD_BASE_PRIORITY_MAX = 2 +THREAD_BASE_PRIORITY_LOWRT = 15 +THREAD_BASE_PRIORITY_IDLE = -15 +THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN +THREAD_PRIORITY_BELOW_NORMAL = THREAD_PRIORITY_LOWEST + 1 +THREAD_PRIORITY_NORMAL = 0 +THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX +THREAD_PRIORITY_ABOVE_NORMAL = THREAD_PRIORITY_HIGHEST - 1 +THREAD_PRIORITY_ERROR_RETURN = 7FFFFFFFh +THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT +THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE + +; Startup flags + +STARTF_USESHOWWINDOW = 001h +STARTF_USESIZE = 002h +STARTF_USEPOSITION = 004h +STARTF_USECOUNTCHARS = 008h +STARTF_USEFILLATTRIBUTE = 010h +STARTF_RUNFULLSCREEN = 020h +STARTF_FORCEONFEEDBACK = 040h +STARTF_FORCEOFFFEEDBACK = 080h +STARTF_USESTDHANDLES = 100h + +; Shutdown flags + +SHUTDOWN_NORETRY = 1h + +; LoadLibraryEx flags + +DONT_RESOLVE_DLL_REFERENCES = 1 +LOAD_LIBRARY_AS_DATAFILE = 2 +LOAD_WITH_ALTERED_SEARCH_PATH = 8 + +; DLL entry-point calls + +DLL_PROCESS_DETACH = 0 +DLL_PROCESS_ATTACH = 1 +DLL_THREAD_ATTACH = 2 +DLL_THREAD_DETACH = 3 + +; Status codes + +STATUS_WAIT_0 = 000000000h +STATUS_ABANDONED_WAIT_0 = 000000080h +STATUS_USER_APC = 0000000C0h +STATUS_TIMEOUT = 000000102h +STATUS_PENDING = 000000103h +STATUS_DATATYPE_MISALIGNMENT = 080000002h +STATUS_BREAKPOINT = 080000003h +STATUS_SINGLE_STEP = 080000004h +STATUS_ACCESS_VIOLATION = 0C0000005h +STATUS_IN_PAGE_ERROR = 0C0000006h +STATUS_NO_MEMORY = 0C0000017h +STATUS_ILLEGAL_INSTRUCTION = 0C000001Dh +STATUS_NONCONTINUABLE_EXCEPTION = 0C0000025h +STATUS_INVALID_DISPOSITION = 0C0000026h +STATUS_ARRAY_BOUNDS_EXCEEDED = 0C000008Ch +STATUS_FLOAT_DENORMAL_OPERAND = 0C000008Dh +STATUS_FLOAT_DIVIDE_BY_ZERO = 0C000008Eh +STATUS_FLOAT_INEXACT_RESULT = 0C000008Fh +STATUS_FLOAT_INVALID_OPERATION = 0C0000090h +STATUS_FLOAT_OVERFLOW = 0C0000091h +STATUS_FLOAT_STACK_CHECK = 0C0000092h +STATUS_FLOAT_UNDERFLOW = 0C0000093h +STATUS_INTEGER_DIVIDE_BY_ZERO = 0C0000094h +STATUS_INTEGER_OVERFLOW = 0C0000095h +STATUS_PRIVILEGED_INSTRUCTION = 0C0000096h +STATUS_STACK_OVERFLOW = 0C00000FDh +STATUS_CONTROL_C_EXIT = 0C000013Ah +WAIT_FAILED = -1 +WAIT_OBJECT_0 = STATUS_WAIT_0 +WAIT_ABANDONED = STATUS_ABANDONED_WAIT_0 +WAIT_ABANDONED_0 = STATUS_ABANDONED_WAIT_0 +WAIT_TIMEOUT = STATUS_TIMEOUT +WAIT_IO_COMPLETION = STATUS_USER_APC +STILL_ACTIVE = STATUS_PENDING + +; Exception codes + +EXCEPTION_CONTINUABLE = 0 +EXCEPTION_NONCONTINUABLE = 1 +EXCEPTION_ACCESS_VIOLATION = STATUS_ACCESS_VIOLATION +EXCEPTION_DATATYPE_MISALIGNMENT = STATUS_DATATYPE_MISALIGNMENT +EXCEPTION_BREAKPOINT = STATUS_BREAKPOINT +EXCEPTION_SINGLE_STEP = STATUS_SINGLE_STEP +EXCEPTION_ARRAY_BOUNDS_EXCEEDED = STATUS_ARRAY_BOUNDS_EXCEEDED +EXCEPTION_FLT_DENORMAL_OPERAND = STATUS_FLOAT_DENORMAL_OPERAND +EXCEPTION_FLT_DIVIDE_BY_ZERO = STATUS_FLOAT_DIVIDE_BY_ZERO +EXCEPTION_FLT_INEXACT_RESULT = STATUS_FLOAT_INEXACT_RESULT +EXCEPTION_FLT_INVALID_OPERATION = STATUS_FLOAT_INVALID_OPERATION +EXCEPTION_FLT_OVERFLOW = STATUS_FLOAT_OVERFLOW +EXCEPTION_FLT_STACK_CHECK = STATUS_FLOAT_STACK_CHECK +EXCEPTION_FLT_UNDERFLOW = STATUS_FLOAT_UNDERFLOW +EXCEPTION_INT_DIVIDE_BY_ZERO = STATUS_INTEGER_DIVIDE_BY_ZERO +EXCEPTION_INT_OVERFLOW = STATUS_INTEGER_OVERFLOW +EXCEPTION_ILLEGAL_INSTRUCTION = STATUS_ILLEGAL_INSTRUCTION +EXCEPTION_PRIV_INSTRUCTION = STATUS_PRIVILEGED_INSTRUCTION +EXCEPTION_IN_PAGE_ERROR = STATUS_IN_PAGE_ERROR + +; Registry options + +REG_OPTION_RESERVED = 0 +REG_OPTION_NON_VOLATILE = 0 +REG_OPTION_VOLATILE = 1 +REG_OPTION_CREATE_LINK = 2 +REG_OPTION_BACKUP_RESTORE = 4 +REG_CREATED_NEW_KEY = 1 +REG_OPENED_EXISTING_KEY = 2 +REG_WHOLE_HIVE_VOLATILE = 1 +REG_REFRESH_HIVE = 2 +REG_NOTIFY_CHANGE_NAME = 1 +REG_NOTIFY_CHANGE_ATTRIBUTES = 2 +REG_NOTIFY_CHANGE_LAST_SET = 4 +REG_NOTIFY_CHANGE_SECURITY = 8 +REG_LEGAL_CHANGE_FILTER = REG_NOTIFY_CHANGE_NAME or REG_NOTIFY_CHANGE_ATTRIBUTES or REG_NOTIFY_CHANGE_LAST_SET or REG_NOTIFY_CHANGE_SECURITY +REG_LEGAL_OPTION = REG_OPTION_RESERVED or REG_OPTION_NON_VOLATILE or REG_OPTION_VOLATILE or REG_OPTION_CREATE_LINK or REG_OPTION_BACKUP_RESTORE +REG_NONE = 0 +REG_SZ = 1 +REG_EXPAND_SZ = 2 +REG_BINARY = 3 +REG_DWORD = 4 +REG_DWORD_LITTLE_ENDIAN = 4 +REG_DWORD_BIG_ENDIAN = 5 +REG_LINK = 6 +REG_MULTI_SZ = 7 +REG_RESOURCE_LIST = 8 +REG_FULL_RESOURCE_DESCRIPTOR = 9 +REG_RESOURCE_REQUIREMENTS_LIST = 10 + +; Registry access modes + +KEY_QUERY_VALUE = 1 +KEY_SET_VALUE = 2 +KEY_CREATE_SUB_KEY = 4 +KEY_ENUMERATE_SUB_KEYS = 8 +KEY_NOTIFY = 10h +KEY_CREATE_LINK = 20h +KEY_READ = STANDARD_RIGHTS_READ or KEY_QUERY_VALUE or KEY_ENUMERATE_SUB_KEYS or KEY_NOTIFY and not SYNCHRONIZE +KEY_WRITE = STANDARD_RIGHTS_WRITE or KEY_SET_VALUE or KEY_CREATE_SUB_KEY and not SYNCHRONIZE +KEY_EXECUTE = KEY_READ +KEY_ALL_ACCESS = STANDARD_RIGHTS_ALL or KEY_QUERY_VALUE or KEY_SET_VALUE or KEY_CREATE_SUB_KEY or KEY_ENUMERATE_SUB_KEYS or KEY_NOTIFY or KEY_CREATE_LINK and not SYNCHRONIZE + +; Predefined registry keys + +HKEY_CLASSES_ROOT = 80000000h +HKEY_CURRENT_USER = 80000001h +HKEY_LOCAL_MACHINE = 80000002h +HKEY_USERS = 80000003h +HKEY_PERFORMANCE_DATA = 80000004h +HKEY_CURRENT_CONFIG = 80000005h +HKEY_DYN_DATA = 80000006h + +; FormatMessage flags + +FORMAT_MESSAGE_ALLOCATE_BUFFER = 0100h +FORMAT_MESSAGE_IGNORE_INSERTS = 0200h +FORMAT_MESSAGE_FROM_STRING = 0400h +FORMAT_MESSAGE_FROM_HMODULE = 0800h +FORMAT_MESSAGE_FROM_SYSTEM = 1000h +FORMAT_MESSAGE_ARGUMENT_ARRAY = 2000h +FORMAT_MESSAGE_MAX_WIDTH_MASK = 00FFh + +; Language identifiers + +LANG_NEUTRAL = 00h +LANG_BULGARIAN = 02h +LANG_CHINESE = 04h +LANG_CROATIAN = 1Ah +LANG_CZECH = 05h +LANG_DANISH = 06h +LANG_DUTCH = 13h +LANG_ENGLISH = 09h +LANG_FINNISH = 0Bh +LANG_FRENCH = 0Ch +LANG_GERMAN = 07h +LANG_GREEK = 08h +LANG_HUNGARIAN = 0Eh +LANG_ICELANDIC = 0Fh +LANG_ITALIAN = 10h +LANG_JAPANESE = 11h +LANG_KOREAN = 12h +LANG_NORWEGIAN = 14h +LANG_POLISH = 15h +LANG_PORTUGUESE = 16h +LANG_ROMANIAN = 18h +LANG_RUSSIAN = 19h +LANG_SLOVAK = 1Bh +LANG_SLOVENIAN = 24h +LANG_SPANISH = 0Ah +LANG_SWEDISH = 1Dh +LANG_THAI = 1Eh +LANG_TURKISH = 1Fh + +; Sublanguage identifiers + +SUBLANG_NEUTRAL = 00h shl 10 +SUBLANG_DEFAULT = 01h shl 10 +SUBLANG_SYS_DEFAULT = 02h shl 10 +SUBLANG_CHINESE_TRADITIONAL = 01h shl 10 +SUBLANG_CHINESE_SIMPLIFIED = 02h shl 10 +SUBLANG_CHINESE_HONGKONG = 03h shl 10 +SUBLANG_CHINESE_SINGAPORE = 04h shl 10 +SUBLANG_DUTCH = 01h shl 10 +SUBLANG_DUTCH_BELGIAN = 02h shl 10 +SUBLANG_ENGLISH_US = 01h shl 10 +SUBLANG_ENGLISH_UK = 02h shl 10 +SUBLANG_ENGLISH_AUS = 03h shl 10 +SUBLANG_ENGLISH_CAN = 04h shl 10 +SUBLANG_ENGLISH_NZ = 05h shl 10 +SUBLANG_ENGLISH_EIRE = 06h shl 10 +SUBLANG_FRENCH = 01h shl 10 +SUBLANG_FRENCH_BELGIAN = 02h shl 10 +SUBLANG_FRENCH_CANADIAN = 03h shl 10 +SUBLANG_FRENCH_SWISS = 04h shl 10 +SUBLANG_GERMAN = 01h shl 10 +SUBLANG_GERMAN_SWISS = 02h shl 10 +SUBLANG_GERMAN_AUSTRIAN = 03h shl 10 +SUBLANG_ITALIAN = 01h shl 10 +SUBLANG_ITALIAN_SWISS = 02h shl 10 +SUBLANG_NORWEGIAN_BOKMAL = 01h shl 10 +SUBLANG_NORWEGIAN_NYNORSK = 02h shl 10 +SUBLANG_PORTUGUESE = 02h shl 10 +SUBLANG_PORTUGUESE_BRAZILIAN = 01h shl 10 +SUBLANG_SPANISH = 01h shl 10 +SUBLANG_SPANISH_MEXICAN = 02h shl 10 +SUBLANG_SPANISH_MODERN = 03h shl 10 + +; Sorting identifiers + +SORT_DEFAULT = 0 shl 16 +SORT_JAPANESE_XJIS = 0 shl 16 +SORT_JAPANESE_UNICODE = 1 shl 16 +SORT_CHINESE_BIG5 = 0 shl 16 +SORT_CHINESE_PRCP = 0 shl 16 +SORT_CHINESE_UNICODE = 1 shl 16 +SORT_CHINESE_PRC = 2 shl 16 +SORT_CHINESE_BOPOMOFO = 3 shl 16 +SORT_KOREAN_KSC = 0 shl 16 +SORT_KOREAN_UNICODE = 1 shl 16 +SORT_GERMAN_PHONE_BOOK = 1 shl 16 +SORT_HUNGARIAN_DEFAULT = 0 shl 16 +SORT_HUNGARIAN_TECHNICAL = 1 shl 16 + +; Code pages + +CP_ACP = 0 ; default to ANSI code page +CP_OEMCP = 1 ; default to OEM code page +CP_MACCP = 2 ; default to MAC code page +CP_THREAD_ACP = 3 ; current thread's ANSI code page +CP_SYMBOL = 42 ; SYMBOL translations +CP_UTF7 = 65000 ; UTF-7 translation +CP_UTF8 = 65001 ; UTF-8 translation + +; Resource types + +RT_CURSOR = 1 +RT_BITMAP = 2 +RT_ICON = 3 +RT_MENU = 4 +RT_DIALOG = 5 +RT_STRING = 6 +RT_FONTDIR = 7 +RT_FONT = 8 +RT_ACCELERATOR = 9 +RT_RCDATA = 10 +RT_MESSAGETABLE = 11 +RT_GROUP_CURSOR = 12 +RT_GROUP_ICON = 14 +RT_VERSION = 16 +RT_DLGINCLUDE = 17 +RT_PLUGPLAY = 19 +RT_VXD = 20 +RT_ANICURSOR = 21 +RT_ANIICON = 22 +RT_HTML = 23 +RT_MANIFEST = 24 + +; Clipboard formats + +CF_TEXT = 001h +CF_BITMAP = 002h +CF_METAFILEPICT = 003h +CF_SYLK = 004h +CF_DIF = 005h +CF_TIFF = 006h +CF_OEMTEXT = 007h +CF_DIB = 008h +CF_PALETTE = 009h +CF_PENDATA = 00Ah +CF_RIFF = 00Bh +CF_WAVE = 00Ch +CF_UNICODETEXT = 00Dh +CF_ENHMETAFILE = 00Eh +CF_HDROP = 00Fh +CF_LOCALE = 010h +CF_OWNERDISPLAY = 080h +CF_DSPTEXT = 081h +CF_DSPBITMAP = 082h +CF_DSPMETAFILEPICT = 083h +CF_DSPENHMETAFILE = 08Eh +CF_PRIVATEFIRST = 200h +CF_PRIVATELAST = 2FFh +CF_GDIOBJFIRST = 300h +CF_GDIOBJLAST = 3FFh + +; OS types for version info + +VOS_UNKNOWN = 00000000h +VOS_DOS = 00010000h +VOS_OS216 = 00020000h +VOS_OS232 = 00030000h +VOS_NT = 00040000h +VOS__BASE = 00000000h +VOS__WINDOWS16 = 00000001h +VOS__PM16 = 00000002h +VOS__PM32 = 00000003h +VOS__WINDOWS32 = 00000004h +VOS_DOS_WINDOWS16 = 00010001h +VOS_DOS_WINDOWS32 = 00010004h +VOS_OS216_PM16 = 00020002h +VOS_OS232_PM32 = 00030003h +VOS_NT_WINDOWS32 = 00040004h + +; File types for version info + +VFT_UNKNOWN = 00000000h +VFT_APP = 00000001h +VFT_DLL = 00000002h +VFT_DRV = 00000003h +VFT_FONT = 00000004h +VFT_VXD = 00000005h +VFT_STATIC_LIB = 00000007h + +; File subtypes for version info + +VFT2_UNKNOWN = 00000000h +VFT2_DRV_PRINTER = 00000001h +VFT2_DRV_KEYBOARD = 00000002h +VFT2_DRV_LANGUAGE = 00000003h +VFT2_DRV_DISPLAY = 00000004h +VFT2_DRV_MOUSE = 00000005h +VFT2_DRV_NETWORK = 00000006h +VFT2_DRV_SYSTEM = 00000007h +VFT2_DRV_INSTALLABLE = 00000008h +VFT2_DRV_SOUND = 00000009h +VFT2_DRV_COMM = 0000000Ah +VFT2_DRV_INPUTMETHOD = 0000000Bh +VFT2_DRV_VERSIONED_PRINTER = 0000000Ch +VFT2_FONT_RASTER = 00000001h +VFT2_FONT_VECTOR = 00000002h +VFT2_FONT_TRUETYPE = 00000003h + +; Console control signals + +CTRL_C_EVENT = 0 +CTRL_BREAK_EVENT = 1 +CTRL_CLOSE_EVENT = 2 +CTRL_LOGOFF_EVENT = 5 +CTRL_SHUTDOWN_EVENT = 6 diff --git a/toolchain/fasm2/include/equates/shell32.inc b/toolchain/fasm2/include/equates/shell32.inc new file mode 100644 index 0000000..aa2b0ad --- /dev/null +++ b/toolchain/fasm2/include/equates/shell32.inc @@ -0,0 +1,128 @@ + +; SHELL32.DLL structures and constants + +struct NOTIFYICONDATA + cbSize dd ? + hWnd dd ? + uID dd ? + uFlags dd ? + uCallbackMessage dd ? + hIcon dd ? + szTip TCHAR 64 dup (?) +ends + +struct NOTIFYICONDATAA + cbSize dd ? + hWnd dd ? + uID dd ? + uFlags dd ? + uCallbackMessage dd ? + hIcon dd ? + szTip db 64 dup (?) +ends + +struct NOTIFYICONDATAW + cbSize dd ? + hWnd dd ? + uID dd ? + uFlags dd ? + uCallbackMessage dd ? + hIcon dd ? + szTip du 64 dup (?) +ends + +struct BROWSEINFO + hwndOwner dd ? + pidlRoot dd ? + pszDisplayName dd ? + lpszTitle dd ? + ulFlags dd ? + lpfn dd ? + lParam dd ? + iImage dd ? +ends + +; Taskbar icon messages + +NIM_ADD = 0 +NIM_MODIFY = 1 +NIM_DELETE = 2 +NIM_SETFOCUS = 3 +NIM_SETVERSION = 4 + +; Taskbar icon flags + +NIF_MESSAGE = 01h +NIF_ICON = 02h +NIF_TIP = 04h +NIF_STATE = 08h +NIF_INFO = 10h +NIF_GUID = 20h + +; Constant Special Item ID List + +CSIDL_DESKTOP = 0x0000 +CSIDL_INTERNET = 0x0001 +CSIDL_PROGRAMS = 0x0002 +CSIDL_CONTROLS = 0x0003 +CSIDL_PRINTERS = 0x0004 +CSIDL_PERSONAL = 0x0005 +CSIDL_FAVORITES = 0x0006 +CSIDL_STARTUP = 0x0007 +CSIDL_RECENT = 0x0008 +CSIDL_SENDTO = 0x0009 +CSIDL_BITBUCKET = 0x000A +CSIDL_STARTMENU = 0x000B +CSIDL_MYDOCUMENTS = 0x000C +CSIDL_MYMUSIC = 0x000D +CSIDL_MYVIDEO = 0x000E +CSIDL_DESKTOPDIRECTORY = 0x0010 +CSIDL_DRIVES = 0x0011 +CSIDL_NETWORK = 0x0012 +CSIDL_NETHOOD = 0x0013 +CSIDL_FONTS = 0x0014 +CSIDL_TEMPLATES = 0x0015 +CSIDL_COMMON_STARTMENU = 0x0016 +CSIDL_COMMON_PROGRAMS = 0x0017 +CSIDL_COMMON_STARTUP = 0x0018 +CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019 +CSIDL_APPDATA = 0x001A +CSIDL_PRINTHOOD = 0x001B +CSIDL_LOCAL_APPDATA = 0x001C +CSIDL_ALTSTARTUP = 0x001D +CSIDL_COMMON_ALTSTARTUP = 0x001E +CSIDL_COMMON_FAVORITES = 0x001F +CSIDL_INTERNET_CACHE = 0x0020 +CSIDL_COOKIES = 0x0021 +CSIDL_HISTORY = 0x0022 +CSIDL_COMMON_APPDATA = 0x0023 +CSIDL_WINDOWS = 0x0024 +CSIDL_SYSTEM = 0x0025 +CSIDL_PROGRAM_FILES = 0x0026 +CSIDL_MYPICTURES = 0x0027 +CSIDL_PROFILE = 0x0028 +CSIDL_SYSTEMX86 = 0x0029 +CSIDL_PROGRAM_FILESX86 = 0x002A +CSIDL_PROGRAM_FILES_COMMON = 0x002B +CSIDL_PROGRAM_FILES_COMMONX86 = 0x002C +CSIDL_COMMON_TEMPLATES = 0x002D +CSIDL_COMMON_DOCUMENTS = 0x002E +CSIDL_COMMON_ADMINTOOLS = 0x002F +CSIDL_ADMINTOOLS = 0x0030 +CSIDL_CONNECTIONS = 0x0031 +CSIDL_COMMON_MUSIC = 0x0035 +CSIDL_COMMON_PICTURES = 0x0036 +CSIDL_COMMON_VIDEO = 0x0037 +CSIDL_RESOURCES = 0x0038 +CSIDL_RESOURCES_LOCALIZED = 0x0039 +CSIDL_COMMON_OEM_LINKS = 0x003A +CSIDL_CDBURN_AREA = 0x003B +CSIDL_COMPUTERSNEARME = 0x003D +CSIDL_PROFILES = 0x003E +CSIDL_FOLDER_MASK = 0x00FF +CSIDL_FLAG_PER_USER_INIT = 0x0800 +CSIDL_FLAG_NO_ALIAS = 0x1000 +CSIDL_FLAG_DONT_VERIFY = 0x4000 +CSIDL_FLAG_CREATE = 0x8000 +CSIDL_FLAG_MASK = 0xFF00 + \ No newline at end of file diff --git a/toolchain/fasm2/include/equates/shell64.inc b/toolchain/fasm2/include/equates/shell64.inc new file mode 100644 index 0000000..c528004 --- /dev/null +++ b/toolchain/fasm2/include/equates/shell64.inc @@ -0,0 +1,134 @@ + +; SHELL32.DLL structures and constants + +struct NOTIFYICONDATA + cbSize dd ? + dd ? + hWnd dq ? + uID dd ? + uFlags dd ? + uCallbackMessage dd ? + dd ? + hIcon dq ? + szTip TCHAR 64 dup (?) +ends + +struct NOTIFYICONDATAA + cbSize dd ? + dd ? + hWnd dq ? + uID dd ? + uFlags dd ? + uCallbackMessage dd ? + dd ? + hIcon dq ? + szTip db 64 dup (?) +ends + +struct NOTIFYICONDATAW + cbSize dd ? + dd ? + hWnd dq ? + uID dd ? + uFlags dd ? + uCallbackMessage dd ? + dd ? + hIcon dq ? + szTip du 64 dup (?) +ends + +struct BROWSEINFO + hwndOwner dq ? + pidlRoot dq ? + pszDisplayName dq ? + lpszTitle dq ? + ulFlags dd ? + dd ? + lpfn dq ? + lParam dq ? + iImage dq ? +ends + +; Taskbar icon messages + +NIM_ADD = 0 +NIM_MODIFY = 1 +NIM_DELETE = 2 +NIM_SETFOCUS = 3 +NIM_SETVERSION = 4 + +; Taskbar icon flags + +NIF_MESSAGE = 01h +NIF_ICON = 02h +NIF_TIP = 04h +NIF_STATE = 08h +NIF_INFO = 10h +NIF_GUID = 20h + +; Constant Special Item ID List + +CSIDL_DESKTOP = 0x0000 +CSIDL_INTERNET = 0x0001 +CSIDL_PROGRAMS = 0x0002 +CSIDL_CONTROLS = 0x0003 +CSIDL_PRINTERS = 0x0004 +CSIDL_PERSONAL = 0x0005 +CSIDL_FAVORITES = 0x0006 +CSIDL_STARTUP = 0x0007 +CSIDL_RECENT = 0x0008 +CSIDL_SENDTO = 0x0009 +CSIDL_BITBUCKET = 0x000A +CSIDL_STARTMENU = 0x000B +CSIDL_MYDOCUMENTS = 0x000C +CSIDL_MYMUSIC = 0x000D +CSIDL_MYVIDEO = 0x000E +CSIDL_DESKTOPDIRECTORY = 0x0010 +CSIDL_DRIVES = 0x0011 +CSIDL_NETWORK = 0x0012 +CSIDL_NETHOOD = 0x0013 +CSIDL_FONTS = 0x0014 +CSIDL_TEMPLATES = 0x0015 +CSIDL_COMMON_STARTMENU = 0x0016 +CSIDL_COMMON_PROGRAMS = 0x0017 +CSIDL_COMMON_STARTUP = 0x0018 +CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019 +CSIDL_APPDATA = 0x001A +CSIDL_PRINTHOOD = 0x001B +CSIDL_LOCAL_APPDATA = 0x001C +CSIDL_ALTSTARTUP = 0x001D +CSIDL_COMMON_ALTSTARTUP = 0x001E +CSIDL_COMMON_FAVORITES = 0x001F +CSIDL_INTERNET_CACHE = 0x0020 +CSIDL_COOKIES = 0x0021 +CSIDL_HISTORY = 0x0022 +CSIDL_COMMON_APPDATA = 0x0023 +CSIDL_WINDOWS = 0x0024 +CSIDL_SYSTEM = 0x0025 +CSIDL_PROGRAM_FILES = 0x0026 +CSIDL_MYPICTURES = 0x0027 +CSIDL_PROFILE = 0x0028 +CSIDL_SYSTEMX86 = 0x0029 +CSIDL_PROGRAM_FILESX86 = 0x002A +CSIDL_PROGRAM_FILES_COMMON = 0x002B +CSIDL_PROGRAM_FILES_COMMONX86 = 0x002C +CSIDL_COMMON_TEMPLATES = 0x002D +CSIDL_COMMON_DOCUMENTS = 0x002E +CSIDL_COMMON_ADMINTOOLS = 0x002F +CSIDL_ADMINTOOLS = 0x0030 +CSIDL_CONNECTIONS = 0x0031 +CSIDL_COMMON_MUSIC = 0x0035 +CSIDL_COMMON_PICTURES = 0x0036 +CSIDL_COMMON_VIDEO = 0x0037 +CSIDL_RESOURCES = 0x0038 +CSIDL_RESOURCES_LOCALIZED = 0x0039 +CSIDL_COMMON_OEM_LINKS = 0x003A +CSIDL_CDBURN_AREA = 0x003B +CSIDL_COMPUTERSNEARME = 0x003D +CSIDL_PROFILES = 0x003E +CSIDL_FOLDER_MASK = 0x00FF +CSIDL_FLAG_PER_USER_INIT = 0x0800 +CSIDL_FLAG_NO_ALIAS = 0x1000 +CSIDL_FLAG_DONT_VERIFY = 0x4000 +CSIDL_FLAG_CREATE = 0x8000 +CSIDL_FLAG_MASK = 0xFF00 diff --git a/toolchain/fasm2/include/equates/user32.inc b/toolchain/fasm2/include/equates/user32.inc new file mode 100644 index 0000000..512c6d4 --- /dev/null +++ b/toolchain/fasm2/include/equates/user32.inc @@ -0,0 +1,1934 @@ + +; USER32.DLL structures and constants + +struct POINT + x dd ? + y dd ? +ends + +struct POINTS + x dw ? + y dw ? +ends + +struct RECT + left dd ? + top dd ? + right dd ? + bottom dd ? +ends + +struct WNDCLASS + style dd ? + lpfnWndProc dd ? + cbClsExtra dd ? + cbWndExtra dd ? + hInstance dd ? + hIcon dd ? + hCursor dd ? + hbrBackground dd ? + lpszMenuName dd ? + lpszClassName dd ? +ends + +struct WNDCLASSEX + cbSize dd ? + style dd ? + lpfnWndProc dd ? + cbClsExtra dd ? + cbWndExtra dd ? + hInstance dd ? + hIcon dd ? + hCursor dd ? + hbrBackground dd ? + lpszMenuName dd ? + lpszClassName dd ? + hIconSm dd ? +ends + +struct CREATESTRUCT + lpCreateParams dd ? + hInstance dd ? + hMenu dd ? + hwndParent dd ? + cy dd ? + cx dd ? + y dd ? + x dd ? + style dd ? + lpszName dd ? + lpszClass dd ? + dwExStyle dd ? +ends + +struct CLIENTCREATESTRUCT + hWindowMenu dd ? + idFirstChild dd ? +ends + +struct MDICREATESTRUCT + szClass dd ? + szTitle dd ? + hOwner dd ? + x dd ? + y dd ? + cx dd ? + cy dd ? + style dd ? + lParam dd ? +ends + +struct SCROLLINFO + cbSize dd ? + fMask dd ? + nMin dd ? + nMax dd ? + nPage dd ? + nPos dd ? + nTrackPos dd ? +ends + +struct MSG + hwnd dd ? + message dd ? + wParam dd ? + lParam dd ? + time dd ? + pt POINT +ends + +struct MINMAXINFO + ptReserved POINT + ptMaxSize POINT + ptMaxPosition POINT + ptMinTrackSize POINT + ptMaxTrackSize POINT +ends + +struct WINDOWPLACEMENT + length dd ? + flags dd ? + showCmd dd ? + ptMinPosition POINT + ptMaxPosition POINT + rcNormalPosition RECT +ends + +struct WINDOWPOS + hwnd dd ? + hwndInsertAfter dd ? + x dd ? + y dd ? + cx dd ? + cy dd ? + flags dd ? +ends + +struct NMHDR + hwndFrom dd ? + idFrom dd ? + code dd ? +ends + +struct COPYDATASTRUCT + dwData dd ? + cbData dd ? + lpData dd ? +ends + +struct ACCEL + fVirt dw ? + key dw ? + cmd dw ? +ends + +struct PAINTSTRUCT + hdc dd ? + fErase dd ? + rcPaint RECT + fRestore dd ? + fIncUpdate dd ? + rgbReserved db 32 dup (?) +ends + +struct DRAWTEXTPARAMS + cbSize dd ? + iTabLength dd ? + iLeftMargin dd ? + iRightMargin dd ? + uiLengthDrawn dd ? +ends + +struct DRAWITEMSTRUCT + CtlType dd ? + CtlID dd ? + itemID dd ? + itemAction dd ? + itemState dd ? + hwndItem dd ? + hDC dd ? + rcItem RECT + itemData dd ? +ends + +struct MENUITEMINFO + cbSize dd ? + fMask dd ? + fType dd ? + fState dd ? + wID dd ? + hSubMenu dd ? + hbmpChecked dd ? + hbmpUnchecked dd ? + dwItemData dd ? + dwTypeData dd ? + cch dd ? + hbmpItem dd ? +ends + +struct MEASUREITEMSTRUCT + CtlType dd ? + CtlID dd ? + itemID dd ? + itemWidth dd ? + itemHeight dd ? + itemData dd ? +ends + +struct MSGBOXPARAMS + cbSize dd ? + hwndOwner dd ? + hInstance dd ? + lpszText dd ? + lpszCaption dd ? + dwStyle dd ? + lpszIcon dd ? + dwContextHelpId dd ? + lpfnMsgBoxCallback dd ? + dwLanguageId dd ? +ends + +struct GESTURECONFIG + dwID dd ? + dwWant dd ? + dwBlock dd ? +ends + +struct GESTUREINFO + cbSize dd ? + dwFlags dd ? + dwID dd ? + hwndTarget dd ? + ptsLocation POINTS + dwInstanceID dd ? + dwSequenceID dd ?,? + ullArguments dq ? + cbExtraArgs dd ?,? +ends + +; MessageBox type flags + +MB_OK = 000000h +MB_OKCANCEL = 000001h +MB_ABORTRETRYIGNORE = 000002h +MB_YESNOCANCEL = 000003h +MB_YESNO = 000004h +MB_RETRYCANCEL = 000005h +MB_ICONHAND = 000010h +MB_ICONQUESTION = 000020h +MB_ICONEXCLAMATION = 000030h +MB_ICONASTERISK = 000040h +MB_USERICON = 000080h +MB_ICONWARNING = MB_ICONEXCLAMATION +MB_ICONERROR = MB_ICONHAND +MB_ICONINFORMATION = MB_ICONASTERISK +MB_ICONSTOP = MB_ICONHAND +MB_DEFBUTTON1 = 000000h +MB_DEFBUTTON2 = 000100h +MB_DEFBUTTON3 = 000200h +MB_DEFBUTTON4 = 000300h +MB_APPLMODAL = 000000h +MB_SYSTEMMODAL = 001000h +MB_TASKMODAL = 002000h +MB_HELP = 004000h +MB_NOFOCUS = 008000h +MB_SETFOREGROUND = 010000h +MB_DEFAULT_DESKTOP_ONLY = 020000h +MB_TOPMOST = 040000h +MB_RIGHT = 080000h +MB_RTLREADING = 100000h +MB_SERVICE_NOTIFICATION = 200000h + +; Conventional dialog box and message box command IDs + +IDOK = 1 +IDCANCEL = 2 +IDABORT = 3 +IDRETRY = 4 +IDIGNORE = 5 +IDYES = 6 +IDNO = 7 +IDCLOSE = 8 +IDHELP = 9 + +; Class styles + +CS_VREDRAW = 00001h +CS_HREDRAW = 00002h +CS_KEYCVTWINDOW = 00004h +CS_DBLCLKS = 00008h +CS_OWNDC = 00020h +CS_CLASSDC = 00040h +CS_PARENTDC = 00080h +CS_NOKEYCVT = 00100h +CS_SAVEBITS = 00800h +CS_NOCLOSE = 00200h +CS_BYTEALIGNCLIENT = 01000h +CS_BYTEALIGNWINDOW = 02000h +CS_PUBLICCLASS = 04000h +CS_GLOBALCLASS = CS_PUBLICCLASS +CS_IME = 10000h + +; Windows styles + +WS_OVERLAPPED = 000000000h +WS_ICONICPOPUP = 0C0000000h +WS_POPUP = 080000000h +WS_CHILD = 040000000h +WS_MINIMIZE = 020000000h +WS_VISIBLE = 010000000h +WS_DISABLED = 008000000h +WS_CLIPSIBLINGS = 004000000h +WS_CLIPCHILDREN = 002000000h +WS_MAXIMIZE = 001000000h +WS_CAPTION = 000C00000h +WS_BORDER = 000800000h +WS_DLGFRAME = 000400000h +WS_VSCROLL = 000200000h +WS_HSCROLL = 000100000h +WS_SYSMENU = 000080000h +WS_THICKFRAME = 000040000h +WS_HREDRAW = 000020000h +WS_VREDRAW = 000010000h +WS_GROUP = 000020000h +WS_TABSTOP = 000010000h +WS_MINIMIZEBOX = 000020000h +WS_MAXIMIZEBOX = 000010000h + +; Common Window Styles + +WS_OVERLAPPEDWINDOW = WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX +WS_POPUPWINDOW = WS_POPUP or WS_BORDER or WS_SYSMENU +WS_CHILDWINDOW = WS_CHILD +WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW +WS_TILED = WS_OVERLAPPED +WS_ICONIC = WS_MINIMIZE +WS_SIZEBOX = WS_THICKFRAME + +; Extended Window Styles + +WS_EX_DLGMODALFRAME = 00001h +WS_EX_DRAGOBJECT = 00002h +WS_EX_NOPARENTNOTIFY = 00004h +WS_EX_TOPMOST = 00008h +WS_EX_ACCEPTFILES = 00010h +WS_EX_TRANSPARENT = 00020h +WS_EX_MDICHILD = 00040h +WS_EX_TOOLWINDOW = 00080h +WS_EX_WINDOWEDGE = 00100h +WS_EX_CLIENTEDGE = 00200h +WS_EX_CONTEXTHELP = 00400h +WS_EX_RIGHT = 01000h +WS_EX_LEFT = 00000h +WS_EX_RTLREADING = 02000h +WS_EX_LTRREADING = 00000h +WS_EX_LEFTSCROLLBAR = 04000h +WS_EX_RIGHTSCROLLBAR = 00000h +WS_EX_CONTROLPARENT = 10000h +WS_EX_STATICEDGE = 20000h +WS_EX_APPWINDOW = 40000h +WS_EX_LAYERED = 80000h +WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE +WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE or WS_EX_TOOLWINDOW or WS_EX_TOPMOST + +; MDI client style bits + +MDIS_ALLCHILDSTYLES = 1 + +; Special CreateWindow position value + +CW_USEDEFAULT = 80000000h + +; Predefined window handle + +HWND_DESKTOP = 0 + +; ShowWindow commands + +SW_HIDE = 0 +SW_SHOWNORMAL = 1 +SW_NORMAL = 1 +SW_SHOWMINIMIZED = 2 +SW_SHOWMAXIMIZED = 3 +SW_MAXIMIZE = 3 +SW_SHOWNOACTIVATE = 4 +SW_SHOW = 5 +SW_MINIMIZE = 6 +SW_SHOWMINNOACTIVE = 7 +SW_SHOWNA = 8 +SW_RESTORE = 9 +SW_SHOWDEFAULT = 10 + +; SetWindowPos flags + +SWP_NOSIZE = 0001h +SWP_NOMOVE = 0002h +SWP_NOZORDER = 0004h +SWP_NOREDRAW = 0008h +SWP_NOACTIVATE = 0010h +SWP_DRAWFRAME = 0020h +SWP_SHOWWINDOW = 0040h +SWP_HIDEWINDOW = 0080h +SWP_NOCOPYBITS = 0100h +SWP_NOREPOSITION = 0200h +SWP_DEFERERASE = 2000h +SWP_ASYNCWINDOWPOS = 4000h + +; SetWindowPos special handle values + +HWND_TOP = 0 +HWND_BOTTOM = 1 +HWND_TOPMOST = -1 +HWND_NOTOPMOST = -2 + +; GetWindow flags + +GW_HWNDFIRST = 0 +GW_HWNDLAST = 1 +GW_HWNDNEXT = 2 +GW_HWNDPREV = 3 +GW_OWNER = 4 +GW_CHILD = 5 + +; RedrawWindow flags + +RDW_INVALIDATE = 0001h +RDW_INTERNALPAINT = 0002h +RDW_ERASE = 0004h +RDW_VALIDATE = 0008h +RDW_NOINTERNALPAINT = 0010h +RDW_NOERASE = 0020h +RDW_NOCHILDREN = 0040h +RDW_ALLCHILDREN = 0080h +RDW_UPDATENOW = 0100h +RDW_ERASENOW = 0200h +RDW_FRAME = 0400h +RDW_NOFRAME = 0800h + +; PeekMessage Options + +PM_NOREMOVE = 0000h +PM_REMOVE = 0001h +PM_NOYIELD = 0002h + +; Window state messages + +WM_STATE = 0000h +WM_NULL = 0000h +WM_CREATE = 0001h +WM_DESTROY = 0002h +WM_MOVE = 0003h +WM_SIZE = 0005h +WM_ACTIVATE = 0006h +WM_SETFOCUS = 0007h +WM_KILLFOCUS = 0008h +WM_ENABLE = 000Ah +WM_SETREDRAW = 000Bh +WM_SETTEXT = 000Ch +WM_GETTEXT = 000Dh +WM_GETTEXTLENGTH = 000Eh +WM_PAINT = 000Fh +WM_CLOSE = 0010h +WM_QUERYENDSESSION = 0011h +WM_QUIT = 0012h +WM_QUERYOPEN = 0013h +WM_ERASEBKGND = 0014h +WM_SYSCOLORCHANGE = 0015h +WM_ENDSESSION = 0016h +WM_SYSTEMERROR = 0017h +WM_SHOWWINDOW = 0018h +WM_CTLCOLOR = 0019h +WM_WININICHANGE = 001Ah +WM_DEVMODECHANGE = 001Bh +WM_ACTIVATEAPP = 001Ch +WM_FONTCHANGE = 001Dh +WM_TIMECHANGE = 001Eh +WM_CANCELMODE = 001Fh +WM_SETCURSOR = 0020h +WM_MOUSEACTIVATE = 0021h +WM_CHILDACTIVATE = 0022h +WM_QUEUESYNC = 0023h +WM_GETMINMAXINFO = 0024h +WM_PAINTICON = 0026h +WM_ICONERASEBKGND = 0027h +WM_NEXTDLGCTL = 0028h +WM_SPOOLERSTATUS = 002Ah +WM_DRAWITEM = 002Bh +WM_MEASUREITEM = 002Ch +WM_DELETEITEM = 002Dh +WM_VKEYTOITEM = 002Eh +WM_CHARTOITEM = 002Fh +WM_SETFONT = 0030h +WM_GETFONT = 0031h +WM_SETHOTKEY = 0032h +WM_QUERYDRAGICON = 0037h +WM_COMPAREITEM = 0039h +WM_COMPACTING = 0041h +WM_COMMNOTIFY = 0044h +WM_WINDOWPOSCHANGING = 0046h +WM_WINDOWPOSCHANGED = 0047h +WM_POWER = 0048h +WM_COPYDATA = 004Ah +WM_CANCELJOURNAL = 004Bh +WM_NOTIFY = 004Eh +WM_INPUTLANGCHANGEREQUEST = 0050h +WM_INPUTLANGCHANGE = 0051h +WM_TCARD = 0052h +WM_HELP = 0053h +WM_USERCHANGED = 0054h +WM_NOTIFYFORMAT = 0055h +WM_CONTEXTMENU = 007Bh +WM_STYLECHANGING = 007Ch +WM_STYLECHANGED = 007Dh +WM_DISPLAYCHANGE = 007Eh +WM_GETICON = 007Fh +WM_SETICON = 0080h +WM_NCCREATE = 0081h +WM_NCDESTROY = 0082h +WM_NCCALCSIZE = 0083h +WM_NCHITTEST = 0084h +WM_NCPAINT = 0085h +WM_NCACTIVATE = 0086h +WM_GETDLGCODE = 0087h +WM_NCMOUSEMOVE = 00A0h +WM_NCLBUTTONDOWN = 00A1h +WM_NCLBUTTONUP = 00A2h +WM_NCLBUTTONDBLCLK = 00A3h +WM_NCRBUTTONDOWN = 00A4h +WM_NCRBUTTONUP = 00A5h +WM_NCRBUTTONDBLCLK = 00A6h +WM_NCMBUTTONDOWN = 00A7h +WM_NCMBUTTONUP = 00A8h +WM_NCMBUTTONDBLCLK = 00A9h +WM_KEYFIRST = 0100h +WM_KEYDOWN = 0100h +WM_KEYUP = 0101h +WM_CHAR = 0102h +WM_DEADCHAR = 0103h +WM_SYSKEYDOWN = 0104h +WM_SYSKEYUP = 0105h +WM_SYSCHAR = 0106h +WM_SYSDEADCHAR = 0107h +WM_KEYLAST = 0108h +WM_INITDIALOG = 0110h +WM_COMMAND = 0111h +WM_SYSCOMMAND = 0112h +WM_TIMER = 0113h +WM_HSCROLL = 0114h +WM_VSCROLL = 0115h +WM_INITMENU = 0116h +WM_INITMENUPOPUP = 0117h +WM_GESTURE = 0119h +WM_GESTURENOTIFY = 011Ah +WM_MENUSELECT = 011Fh +WM_MENUCHAR = 0120h +WM_ENTERIDLE = 0121h +WM_MENURBUTTONUP = 0122h +WM_MENUDRAG = 0123h +WM_MENUGETOBJECT = 0124h +WM_UNINITMENUPOPUP = 0125h +WM_MENUCOMMAND = 0126h +WM_CTLCOLORMSGBOX = 0132h +WM_CTLCOLOREDIT = 0133h +WM_CTLCOLORLISTBOX = 0134h +WM_CTLCOLORBTN = 0135h +WM_CTLCOLORDLG = 0136h +WM_CTLCOLORSCROLLBAR = 0137h +WM_CTLCOLORSTATIC = 0138h +WM_MOUSEFIRST = 0200h +WM_MOUSEMOVE = 0200h +WM_LBUTTONDOWN = 0201h +WM_LBUTTONUP = 0202h +WM_LBUTTONDBLCLK = 0203h +WM_RBUTTONDOWN = 0204h +WM_RBUTTONUP = 0205h +WM_RBUTTONDBLCLK = 0206h +WM_MBUTTONDOWN = 0207h +WM_MBUTTONUP = 0208h +WM_MBUTTONDBLCLK = 0209h +WM_MOUSEWHEEL = 020Ah +WM_MOUSELAST = 020Ah +WM_PARENTNOTIFY = 0210h +WM_ENTERMENULOOP = 0211h +WM_EXITMENULOOP = 0212h +WM_NEXTMENU = 0213h +WM_SIZING = 0214h +WM_CAPTURECHANGED = 0215h +WM_MOVING = 0216h +WM_POWERBROADCAST = 0218h +WM_DEVICECHANGE = 0219h +WM_MDICREATE = 0220h +WM_MDIDESTROY = 0221h +WM_MDIACTIVATE = 0222h +WM_MDIRESTORE = 0223h +WM_MDINEXT = 0224h +WM_MDIMAXIMIZE = 0225h +WM_MDITILE = 0226h +WM_MDICASCADE = 0227h +WM_MDIICONARRANGE = 0228h +WM_MDIGETACTIVE = 0229h +WM_MDISETMENU = 0230h +WM_ENTERSIZEMOVE = 0231h +WM_EXITSIZEMOVE = 0232h +WM_DROPFILES = 0233h +WM_MDIREFRESHMENU = 0234h +WM_IME_SETCONTEXT = 0281h +WM_IME_NOTIFY = 0282h +WM_IME_CONTROL = 0283h +WM_IME_COMPOSITIONFULL = 0284h +WM_IME_SELECT = 0285h +WM_IME_CHAR = 0286h +WM_IME_KEYDOWN = 0290h +WM_IME_KEYUP = 0291h +WM_MOUSEHOVER = 02A1h +WM_MOUSELEAVE = 02A3h +WM_CUT = 0300h +WM_COPY = 0301h +WM_PASTE = 0302h +WM_CLEAR = 0303h +WM_UNDO = 0304h +WM_RENDERFORMAT = 0305h +WM_RENDERALLFORMATS = 0306h +WM_DESTROYCLIPBOARD = 0307h +WM_DRAWCLIPBOARD = 0308h +WM_PAINTCLIPBOARD = 0309h +WM_VSCROLLCLIPBOARD = 030Ah +WM_SIZECLIPBOARD = 030Bh +WM_ASKCBFORMATNAME = 030Ch +WM_CHANGECBCHAIN = 030Dh +WM_HSCROLLCLIPBOARD = 030Eh +WM_QUERYNEWPALETTE = 030Fh +WM_PALETTEISCHANGING = 0310h +WM_PALETTECHANGED = 0311h +WM_HOTKEY = 0312h +WM_PRINT = 0317h +WM_PRINTCLIENT = 0318h +WM_HANDHELDFIRST = 0358h +WM_HANDHELDLAST = 035Fh +WM_AFXFIRST = 0360h +WM_AFXLAST = 037Fh +WM_PENWINFIRST = 0380h +WM_PENWINLAST = 038Fh +WM_COALESCE_FIRST = 0390h +WM_COALESCE_LAST = 039Fh +WM_USER = 0400h + +; WM_SIZE commands + +SIZE_RESTORED = 0 +SIZE_MINIMIZED = 1 +SIZE_MAXIMIZED = 2 +SIZE_MAXSHOW = 3 +SIZE_MAXHIDE = 4 + +; WM_ACTIVATE states + +WA_INACTIVE = 0 +WA_ACTIVE = 1 +WA_CLICKACTIVE = 2 + +; WM_SHOWWINDOW identifiers + +SW_PARENTCLOSING = 1 +SW_OTHERZOOM = 2 +SW_PARENTOPENING = 3 +SW_OTHERUNZOOM = 4 + +; WM_MOUSEACTIVATE return codes + +MA_ACTIVATE = 1 +MA_ACTIVATEANDEAT = 2 +MA_NOACTIVATE = 3 +MA_NOACTIVATEANDEAT = 4 + +; WM_MDITILE flags + +MDITILE_VERTICAL = 0 +MDITILE_HORIZONTAL = 1 +MDITILE_SKIPDISABLED = 2 + +; WM_NOTIFY codes + +NM_OUTOFMEMORY = -1 +NM_CLICK = -2 +NM_DBLCLICK = -3 +NM_RETURN = -4 +NM_RCLICK = -5 +NM_RDBLCLK = -6 +NM_SETFOCUS = -7 +NM_KILLFOCUS = -8 + +; WM_SETICON types + +ICON_SMALL = 0 +ICON_BIG = 1 + +; WM_HOTKEY commands + +HOTKEYF_SHIFT = 01h +HOTKEYF_CONTROL = 02h +HOTKEYF_ALT = 04h +HOTKEYF_EXT = 08h + +; Keystroke flags + +KF_EXTENDED = 0100h +KF_DLGMODE = 0800h +KF_MENUMODE = 1000h +KF_ALTDOWN = 2000h +KF_REPEAT = 4000h +KF_UP = 8000h + +; Key state masks for mouse messages + +MK_LBUTTON = 01h +MK_RBUTTON = 02h +MK_SHIFT = 04h +MK_CONTROL = 08h +MK_MBUTTON = 10h + +; WM_SIZING codes + +WMSZ_LEFT = 1 +WMSZ_RIGHT = 2 +WMSZ_TOP = 3 +WMSZ_TOPLEFT = 4 +WMSZ_TOPRIGHT = 5 +WMSZ_BOTTOM = 6 +WMSZ_BOTTOMLEFT = 7 +WMSZ_BOTTOMRIGHT = 8 + +; WM_HOTKEY modifiers + +MOD_ALT = 1 +MOD_CONTROL = 2 +MOD_SHIFT = 4 +MOD_WIN = 8 + +; WM_PRINT flags + +PRF_CHECKVISIBLE = 01h +PRF_NONCLIENT = 02h +PRF_CLIENT = 04h +PRF_ERASEBKGND = 08h +PRF_CHILDREN = 10h +PRF_OWNED = 20h + +; Virtual key codes + +VK_LBUTTON = 001h +VK_CANCEL = 003h +VK_RBUTTON = 002h +VK_MBUTTON = 004h +VK_BACK = 008h +VK_TAB = 009h +VK_CLEAR = 00Ch +VK_RETURN = 00Dh +VK_SHIFT = 010h +VK_CONTROL = 011h +VK_MENU = 012h +VK_PAUSE = 013h +VK_CAPITAL = 014h +VK_ESCAPE = 01Bh +VK_SPACE = 020h +VK_PRIOR = 021h +VK_PGUP = 021h +VK_PGDN = 022h +VK_NEXT = 022h +VK_END = 023h +VK_HOME = 024h +VK_LEFT = 025h +VK_UP = 026h +VK_RIGHT = 027h +VK_DOWN = 028h +VK_SELECT = 029h +VK_PRINT = 02Ah +VK_EXECUTE = 02Bh +VK_SNAPSHOT = 02Ch +VK_INSERT = 02Dh +VK_DELETE = 02Eh +VK_HELP = 02Fh +VK_LWIN = 05Bh +VK_RWIN = 05Ch +VK_APPS = 05Dh +VK_NUMPAD0 = 060h +VK_NUMPAD1 = 061h +VK_NUMPAD2 = 062h +VK_NUMPAD3 = 063h +VK_NUMPAD4 = 064h +VK_NUMPAD5 = 065h +VK_NUMPAD6 = 066h +VK_NUMPAD7 = 067h +VK_NUMPAD8 = 068h +VK_NUMPAD9 = 069h +VK_MULTIPLY = 06Ah +VK_ADD = 06Bh +VK_SEPARATOR = 06Ch +VK_SUBTRACT = 06Dh +VK_DECIMAL = 06Eh +VK_DIVIDE = 06Fh +VK_F1 = 070h +VK_F2 = 071h +VK_F3 = 072h +VK_F4 = 073h +VK_F5 = 074h +VK_F6 = 075h +VK_F7 = 076h +VK_F8 = 077h +VK_F9 = 078h +VK_F10 = 079h +VK_F11 = 07Ah +VK_F12 = 07Bh +VK_F13 = 07Ch +VK_F14 = 07Dh +VK_F15 = 07Eh +VK_F16 = 07Fh +VK_F17 = 080h +VK_F18 = 081h +VK_F19 = 082h +VK_F20 = 083h +VK_F21 = 084h +VK_F22 = 085h +VK_F23 = 086h +VK_F24 = 087h +VK_NUMLOCK = 090h +VK_SCROLL = 091h +VK_LSHIFT = 0A0h +VK_RSHIFT = 0A1h +VK_LCONTROL = 0A2h +VK_RCONTROL = 0A3h +VK_LMENU = 0A4h +VK_RMENU = 0A5h +VK_ATTN = 0F6h +VK_CRSEL = 0F7h +VK_EXSEL = 0F8h +VK_EREOF = 0F9h +VK_PLAY = 0FAh +VK_ZOOM = 0FBh +VK_NONAME = 0FCh +VK_PA1 = 0FDh +VK_OEM_CLEAR = 0FEh + +; Accelerator flags + +FVIRTKEY = 01h +FNOINVERT = 02h +FSHIFT = 04h +FCONTROL = 08h +FALT = 10h + +; GetClassLong offsets + +GCL_MENUNAME = -8 +GCL_HBRBACKGROUND = -10 +GCL_HCURSOR = -12 +GCL_HICON = -14 +GCL_HMODULE = -16 +GCL_CBWNDEXTRA = -18 +GCL_CBCLSEXTRA = -20 +GCL_WNDPROC = -24 +GCL_STYLE = -26 +GCW_ATOM = -32 +GCL_HICONSM = -34 + +; WNDCLASS parameters + +DLGWINDOWEXTRA = 30 + +; GetWindowLong offsets + +GWL_WNDPROC = -4 +GWL_HINSTANCE = -6 +GWL_HWNDPARENT = -8 +GWL_STYLE = -16 +GWL_EXSTYLE = -20 +GWL_USERDATA = -21 +GWL_ID = -12 +DWL_MSGRESULT = 0 +DWL_DLGPROC = 4 +DWL_USER = 8 + +; GetSystemMetrics codes + +SM_CXSCREEN = 0 +SM_CYSCREEN = 1 +SM_CXVSCROLL = 2 +SM_CYHSCROLL = 3 +SM_CYCAPTION = 4 +SM_CXBORDER = 5 +SM_CYBORDER = 6 +SM_CXDLGFRAME = 7 +SM_CYDLGFRAME = 8 +SM_CYVTHUMB = 9 +SM_CXHTHUMB = 10 +SM_CXICON = 11 +SM_CYICON = 12 +SM_CXCURSOR = 13 +SM_CYCURSOR = 14 +SM_CYMENU = 15 +SM_CXFULLSCREEN = 16 +SM_CYFULLSCREEN = 17 +SM_CYKANJIWINDOW = 18 +SM_MOUSEPRESENT = 19 +SM_CYVSCROLL = 20 +SM_CXHSCROLL = 21 +SM_DEBUG = 22 +SM_SWAPBUTTON = 23 +SM_RESERVED1 = 24 +SM_RESERVED2 = 25 +SM_RESERVED3 = 26 +SM_RESERVED4 = 27 +SM_CXMIN = 28 +SM_CYMIN = 29 +SM_CXSIZE = 30 +SM_CYSIZE = 31 +SM_CXFRAME = 32 +SM_CYFRAME = 33 +SM_CXMINTRACK = 34 +SM_CYMINTRACK = 35 +SM_CXDOUBLECLK = 36 +SM_CYDOUBLECLK = 37 +SM_CXICONSPACING = 38 +SM_CYICONSPACING = 39 +SM_MENUDROPALIGNMENT = 40 +SM_PENWINDOWS = 41 +SM_DBCSENABLED = 42 +SM_CMOUSEBUTTONS = 43 +SM_CXFIXEDFRAME = SM_CXDLGFRAME +SM_CYFIXEDFRAME = SM_CYDLGFRAME +SM_CXSIZEFRAME = SM_CXFRAME +SM_CYSIZEFRAME = SM_CYFRAME +SM_SECURE = 44 +SM_CXEDGE = 45 +SM_CYEDGE = 46 +SM_CXMINSPACING = 47 +SM_CYMINSPACING = 48 +SM_CXSMICON = 49 +SM_CYSMICON = 50 +SM_CYSMCAPTION = 51 +SM_CXSMSIZE = 52 +SM_CYSMSIZE = 53 +SM_CXMENUSIZE = 54 +SM_CYMENUSIZE = 55 +SM_ARRANGE = 56 +SM_CXMINIMIZED = 57 +SM_CYMINIMIZED = 58 +SM_CXMAXTRACK = 59 +SM_CYMAXTRACK = 60 +SM_CXMAXIMIZED = 61 +SM_CYMAXIMIZED = 62 +SM_NETWORK = 63 +SM_CLEANBOOT = 67 +SM_CXDRAG = 68 +SM_CYDRAG = 69 +SM_SHOWSOUNDS = 70 +SM_CXMENUCHECK = 71 +SM_CYMENUCHECK = 72 +SM_SLOWMACHINE = 73 +SM_MIDEASTENABLED = 74 +SM_MOUSEWHEELPRESENT = 75 +SM_CMETRICS = 76 + +; Predefined cursor identifiers + +IDC_ARROW = 32512 +IDC_IBEAM = 32513 +IDC_WAIT = 32514 +IDC_CROSS = 32515 +IDC_UPARROW = 32516 +IDC_SIZE = 32640 +IDC_ICON = 32641 +IDC_SIZENWSE = 32642 +IDC_SIZENESW = 32643 +IDC_SIZEWE = 32644 +IDC_SIZENS = 32645 +IDC_NO = 32648 +IDC_HAND = 32649 +IDC_APPSTARTING = 32650 +IDC_HELP = 32651 + +; Predefined icon identifiers + +IDI_APPLICATION = 32512 +IDI_HAND = 32513 +IDI_QUESTION = 32514 +IDI_EXCLAMATION = 32515 +IDI_ASTERISK = 32516 +IDI_WINLOGO = 32517 + +; System colors + +COLOR_SCROLLBAR = 0 +COLOR_BACKGROUND = 1 +COLOR_ACTIVECAPTION = 2 +COLOR_INACTIVECAPTION = 3 +COLOR_MENU = 4 +COLOR_WINDOW = 5 +COLOR_WINDOWFRAME = 6 +COLOR_MENUTEXT = 7 +COLOR_WINDOWTEXT = 8 +COLOR_CAPTIONTEXT = 9 +COLOR_ACTIVEBORDER = 10 +COLOR_INACTIVEBORDER = 11 +COLOR_APPWORKSPACE = 12 +COLOR_HIGHLIGHT = 13 +COLOR_HIGHLIGHTTEXT = 14 +COLOR_BTNFACE = 15 +COLOR_BTNSHADOW = 16 +COLOR_GRAYTEXT = 17 +COLOR_BTNTEXT = 18 +COLOR_INACTIVECAPTIONTEXT = 19 +COLOR_BTNHIGHLIGHT = 20 +COLOR_3DDKSHADOW = 21 +COLOR_3DLIGHT = 22 +COLOR_INFOTEXT = 23 +COLOR_INFOBK = 24 +COLOR_HOTLIGHT = 26 +COLOR_GRADIENTACTIVECAPTION = 27 +COLOR_GRADIENTINACTIVECAPTION = 28 + +; Button messages + +BM_GETCHECK = 00F0h +BM_SETCHECK = 00F1h +BM_GETSTATE = 00F2h +BM_SETSTATE = 00F3h +BM_SETSTYLE = 00F4h +BM_CLICK = 00F5h +BM_GETIMAGE = 00F6h +BM_SETIMAGE = 00F7h + +; Button notifications + +BN_CLICKED = 0 +BN_PAINT = 1 +BN_HILITE = 2 +BN_UNHILITE = 3 +BN_DISABLE = 4 +BN_DOUBLECLICKED = 5 +BN_SETFOCUS = 6 +BN_KILLFOCUS = 7 +BN_PUSHED = BN_HILITE +BN_UNPUSHED = BN_UNHILITE +BN_DBLCLK = BN_DOUBLECLICKED + +; Button styles + +BS_PUSHBUTTON = 0000h +BS_DEFPUSHBUTTON = 0001h +BS_CHECKBOX = 0002h +BS_AUTOCHECKBOX = 0003h +BS_RADIOBUTTON = 0004h +BS_3STATE = 0005h +BS_AUTO3STATE = 0006h +BS_GROUPBOX = 0007h +BS_USERBUTTON = 0008h +BS_AUTORADIOBUTTON = 0009h +BS_OWNERDRAW = 000Bh +BS_TEXT = 0000h +BS_LEFTTEXT = 0020h +BS_RIGHTBUTTON = BS_LEFTTEXT +BS_ICON = 0040h +BS_BITMAP = 0080h +BS_LEFT = 0100h +BS_RIGHT = 0200h +BS_CENTER = 0300h +BS_TOP = 0400h +BS_BOTTOM = 0800h +BS_VCENTER = 0C00h +BS_PUSHLIKE = 1000h +BS_MULTILINE = 2000h +BS_NOTIFY = 4000h +BS_FLAT = 8000h + +; Button states + +BST_UNCHECKED = 0 +BST_CHECKED = 1 +BST_INDETERMINATE = 2 +BST_PUSHED = 4 +BST_FOCUS = 8 + +; List box messages + +LB_ADDSTRING = 0180h +LB_INSERTSTRING = 0181h +LB_DELETESTRING = 0182h +LB_SELITEMRANGEEX = 0183h +LB_RESETCONTENT = 0184h +LB_SETSEL = 0185h +LB_SETCURSEL = 0186h +LB_GETSEL = 0187h +LB_GETCURSEL = 0188h +LB_GETTEXT = 0189h +LB_GETTEXTLEN = 018Ah +LB_GETCOUNT = 018Bh +LB_SELECTSTRING = 018Ch +LB_DIR = 018Dh +LB_GETTOPINDEX = 018Eh +LB_FINDSTRING = 018Fh +LB_GETSELCOUNT = 0190h +LB_GETSELITEMS = 0191h +LB_SETTABSTOPS = 0192h +LB_GETHORIZONTALEXTENT = 0193h +LB_SETHORIZONTALEXTENT = 0194h +LB_SETCOLUMNWIDTH = 0195h +LB_ADDFILE = 0196h +LB_SETTOPINDEX = 0197h +LB_GETITEMRECT = 0198h +LB_GETITEMDATA = 0199h +LB_SETITEMDATA = 019Ah +LB_SELITEMRANGE = 019Bh +LB_SETANCHORINDEX = 019Ch +LB_GETANCHORINDEX = 019Dh +LB_SETCARETINDEX = 019Eh +LB_GETCARETINDEX = 019Fh +LB_SETITEMHEIGHT = 01A0h +LB_GETITEMHEIGHT = 01A1h +LB_FINDSTRINGEXACT = 01A2h +LB_SETLOCALE = 01A5h +LB_GETLOCALE = 01A6h +LB_SETCOUNT = 01A7h +LB_INITSTORAGE = 01A8h +LB_ITEMFROMPOINT = 01A9h + +; List box notifications + +LBN_ERRSPACE = -2 +LBN_SELCHANGE = 1 +LBN_DBLCLK = 2 +LBN_SELCANCEL = 3 +LBN_SETFOCUS = 4 +LBN_KILLFOCUS = 5 + +; List box styles + +LBS_NOTIFY = 0001h +LBS_SORT = 0002h +LBS_NOREDRAW = 0004h +LBS_MULTIPLESEL = 0008h +LBS_OWNERDRAWFIXED = 0010h +LBS_OWNERDRAWVARIABLE = 0020h +LBS_HASSTRINGS = 0040h +LBS_USETABSTOPS = 0080h +LBS_NOINTEGRALHEIGHT = 0100h +LBS_MULTICOLUMN = 0200h +LBS_WANTKEYBOARDINPUT = 0400h +LBS_EXTENDEDSEL = 0800h +LBS_DISABLENOSCROLL = 1000h +LBS_NODATA = 2000h +LBS_NOSEL = 4000h +LBS_STANDARD = LBS_NOTIFY or LBS_SORT or WS_VSCROLL or WS_BORDER + +; List box return values + +LB_OKAY = 0 +LB_ERR = -1 +LB_ERRSPACE = -2 + +; Combo box messages + +CB_GETEDITSEL = 0140h +CB_LIMITTEXT = 0141h +CB_SETEDITSEL = 0142h +CB_ADDSTRING = 0143h +CB_DELETESTRING = 0144h +CB_DIR = 0145h +CB_GETCOUNT = 0146h +CB_GETCURSEL = 0147h +CB_GETLBTEXT = 0148h +CB_GETLBTEXTLEN = 0149h +CB_INSERTSTRING = 014Ah +CB_RESETCONTENT = 014Bh +CB_FINDSTRING = 014Ch +CB_SELECTSTRING = 014Dh +CB_SETCURSEL = 014Eh +CB_SHOWDROPDOWN = 014Fh +CB_GETITEMDATA = 0150h +CB_SETITEMDATA = 0151h +CB_GETDROPPEDCONTROLRECT = 0152h +CB_SETITEMHEIGHT = 0153h +CB_GETITEMHEIGHT = 0154h +CB_SETEXTENDEDUI = 0155h +CB_GETEXTENDEDUI = 0156h +CB_GETDROPPEDSTATE = 0157h +CB_FINDSTRINGEXACT = 0158h +CB_SETLOCALE = 0159h +CB_GETLOCALE = 015Ah +CB_GETTOPINDEX = 015Bh +CB_SETTOPINDEX = 015Ch +CB_GETHORIZONTALEXTENT = 015Dh +CB_SETHORIZONTALEXTENT = 015Eh +CB_GETDROPPEDWIDTH = 015Fh +CB_SETDROPPEDWIDTH = 0160h +CB_INITSTORAGE = 0161h + +; Combo box notifications + +CBN_ERRSPACE = -1 +CBN_SELCHANGE = 1 +CBN_DBLCLK = 2 +CBN_SETFOCUS = 3 +CBN_KILLFOCUS = 4 +CBN_EDITCHANGE = 5 +CBN_EDITUPDATE = 6 +CBN_DROPDOWN = 7 +CBN_CLOSEUP = 8 +CBN_SELENDOK = 9 +CBN_SELENDCANCEL = 10 + +; Combo box styles + +CBS_SIMPLE = 0001h +CBS_DROPDOWN = 0002h +CBS_DROPDOWNLIST = 0003h +CBS_OWNERDRAWFIXED = 0010h +CBS_OWNERDRAWVARIABLE = 0020h +CBS_AUTOHSCROLL = 0040h +CBS_OEMCONVERT = 0080h +CBS_SORT = 0100h +CBS_HASSTRINGS = 0200h +CBS_NOINTEGRALHEIGHT = 0400h +CBS_DISABLENOSCROLL = 0800h +CBS_UPPERCASE = 2000h +CBS_LOWERCASE = 4000h + +; Combo box return values + +CB_OKAY = 0 +CB_ERR = -1 +CB_ERRSPACE = -2 + +; Edit control messages + +EM_GETSEL = 00B0h +EM_SETSEL = 00B1h +EM_GETRECT = 00B2h +EM_SETRECT = 00B3h +EM_SETRECTNP = 00B4h +EM_SCROLL = 00B5h +EM_LINESCROLL = 00B6h +EM_SCROLLCARET = 00B7h +EM_GETMODIFY = 00B8h +EM_SETMODIFY = 00B9h +EM_GETLINECOUNT = 00BAh +EM_LINEINDEX = 00BBh +EM_SETHANDLE = 00BCh +EM_GETHANDLE = 00BDh +EM_GETTHUMB = 00BEh +EM_LINELENGTH = 00C1h +EM_REPLACESEL = 00C2h +EM_GETLINE = 00C4h +EM_LIMITTEXT = 00C5h +EM_CANUNDO = 00C6h +EM_UNDO = 00C7h +EM_FMTLINES = 00C8h +EM_LINEFROMCHAR = 00C9h +EM_SETTABSTOPS = 00CBh +EM_SETPASSWORDCHAR = 00CCh +EM_EMPTYUNDOBUFFER = 00CDh +EM_GETFIRSTVISIBLELINE = 00CEh +EM_SETREADONLY = 00CFh +EM_SETWORDBREAKPROC = 00D0h +EM_GETWORDBREAKPROC = 00D1h +EM_GETPASSWORDCHAR = 00D2h +EM_SETMARGINS = 00D3h +EM_GETMARGINS = 00D4h +EM_SETLIMITTEXT = EM_LIMITTEXT +EM_GETLIMITTEXT = 00D5h +EM_POSFROMCHAR = 00D6h +EM_CHARFROMPOS = 00D7h + +; Edit control EM_SETMARGIN parameters + +EC_LEFTMARGIN = 1 +EC_RIGHTMARGIN = 2 +EC_USEFONTINFO = 0FFFFh + +; Edit control notifications + +EN_SETFOCUS = 0100h +EN_KILLFOCUS = 0200h +EN_CHANGE = 0300h +EN_UPDATE = 0400h +EN_ERRSPACE = 0500h +EN_MAXTEXT = 0501h +EN_HSCROLL = 0601h +EN_VSCROLL = 0602h + +; Edit control styles + +ES_LEFT = 0000h +ES_CENTER = 0001h +ES_RIGHT = 0002h +ES_MULTILINE = 0004h +ES_UPPERCASE = 0008h +ES_LOWERCASE = 0010h +ES_PASSWORD = 0020h +ES_AUTOVSCROLL = 0040h +ES_AUTOHSCROLL = 0080h +ES_NOHIDESEL = 0100h +ES_OEMCONVERT = 0400h +ES_READONLY = 0800h +ES_WANTRETURN = 1000h +ES_NUMBER = 2000h + +; Static window messages + +STM_SETICON = 0170h +STM_GETICON = 0171h +STM_SETIMAGE = 0172h +STM_GETIMAGE = 0173h + +; Static window notifications + +STN_CLICKED = 0 +STN_DBLCLK = 1 +STN_ENABLE = 2 +STN_DISABLE = 3 + +; Static window styles + +SS_LEFT = 0000h +SS_CENTER = 0001h +SS_RIGHT = 0002h +SS_ICON = 0003h +SS_BLACKRECT = 0004h +SS_GRAYRECT = 0005h +SS_WHITERECT = 0006h +SS_BLACKFRAME = 0007h +SS_GRAYFRAME = 0008h +SS_WHITEFRAME = 0009h +SS_USERITEM = 000Ah +SS_SIMPLE = 000Bh +SS_LEFTNOWORDWRAP = 000Ch +SS_BITMAP = 000Eh +SS_OWNERDRAW = 000Dh +SS_ENHMETAFILE = 000Fh +SS_ETCHEDHORZ = 0010h +SS_ETCHEDVERT = 0011h +SS_ETCHEDFRAME = 0012h +SS_TYPEMASK = 001Fh +SS_NOPREFIX = 0080h +SS_NOTIFY = 0100h +SS_CENTERIMAGE = 0200h +SS_RIGHTJUST = 0400h +SS_REALSIZEIMAGE = 0800h +SS_SUNKEN = 1000h + +; Scroll bar constants + +SB_HORZ = 0 +SB_VERT = 1 +SB_CTL = 2 +SB_BOTH = 3 + +; Scroll bar messages + +SBM_SETPOS = 00E0h +SBM_GETPOS = 00E1h +SBM_SETRANGE = 00E2h +SBM_SETRANGEREDRAW = 00E6h +SBM_GETRANGE = 00E3h +SBM_ENABLE_ARROWS = 00E4h +SBM_SETSCROLLINFO = 00E9h +SBM_GETSCROLLINFO = 00EAh + +; Scroll bar commands + +SB_LINEUP = 0 +SB_LINELEFT = 0 +SB_LINEDOWN = 1 +SB_LINERIGHT = 1 +SB_PAGEUP = 2 +SB_PAGELEFT = 2 +SB_PAGEDOWN = 3 +SB_PAGERIGHT = 3 +SB_THUMBPOSITION = 4 +SB_THUMBTRACK = 5 +SB_TOP = 6 +SB_LEFT = 6 +SB_BOTTOM = 7 +SB_RIGHT = 7 +SB_ENDSCROLL = 8 + +; Scroll bar styles + +SBS_HORZ = 0000h +SBS_VERT = 0001h +SBS_TOPALIGN = 0002h +SBS_LEFTALIGN = 0002h +SBS_BOTTOMALIGN = 0004h +SBS_RIGHTALIGN = 0004h +SBS_SIZEBOXTOPLEFTALIGN = 0002h +SBS_SIZEBOXBOTTOMRIGHTALIGN = 0004h +SBS_SIZEBOX = 0008h +SBS_SIZEGRIP = 0010h + +; Scroll bar info flags + +SIF_RANGE = 0001h +SIF_PAGE = 0002h +SIF_POS = 0004h +SIF_DISABLENOSCROLL = 0008h +SIF_TRACKPOS = 0010h +SIF_ALL = SIF_RANGE or SIF_PAGE or SIF_POS or SIF_TRACKPOS + +; Dialog styles + +DS_ABSALIGN = 0001h +DS_SYSMODAL = 0002h +DS_3DLOOK = 0004h +DS_FIXEDSYS = 0008h +DS_NOFAILCREATE = 0010h +DS_LOCALEDIT = 0020h +DS_SETFONT = 0040h +DS_MODALFRAME = 0080h +DS_NOIDLEMSG = 0100h +DS_SETFOREGROUND = 0200h +DS_CONTROL = 0400h +DS_CENTER = 0800h +DS_CENTERMOUSE = 1000h +DS_CONTEXTHELP = 2000h + +; Dialog codes + +DLGC_WANTARROWS = 0001h +DLGC_WANTTAB = 0002h +DLGC_WANTALLKEYS = 0004h +DLGC_WANTMESSAGE = 0004h +DLGC_HASSETSEL = 0008h +DLGC_DEFPUSHBUTTON = 0010h +DLGC_UNDEFPUSHBUTTON = 0020h +DLGC_RADIOBUTTON = 0040h +DLGC_WANTCHARS = 0080h +DLGC_STATIC = 0100h +DLGC_BUTTON = 2000h + +; Menu flags + +MF_INSERT = 0000h +MF_CHANGE = 0080h +MF_APPEND = 0100h +MF_DELETE = 0200h +MF_REMOVE = 1000h +MF_BYCOMMAND = 0000h +MF_BYPOSITION = 0400h +MF_SEPARATOR = 0800h +MF_UNCHECKED = 0000h +MF_ENABLED = 0000h +MF_GRAYED = 0001h +MF_DISABLED = 0002h +MF_CHECKED = 0008h +MF_USECHECKBITMAPS = 0200h +MF_STRING = 0000h +MF_BITMAP = 0004h +MF_OWNERDRAW = 0100h +MF_POPUP = 0010h +MF_MENUBARBREAK = 0020h +MF_MENUBREAK = 0040h +MF_UNHILITE = 0000h +MF_HILITE = 0080h +MF_DEFAULT = 1000h +MF_SYSMENU = 2000h +MF_HELP = 4000h +MF_RIGHTJUSTIFY = 4000h +MF_MOUSESELECT = 8000h +MF_END = 0080h +MFT_STRING = MF_STRING +MFT_BITMAP = MF_BITMAP +MFT_MENUBARBREAK = MF_MENUBARBREAK +MFT_MENUBREAK = MF_MENUBREAK +MFT_OWNERDRAW = MF_OWNERDRAW +MFT_RADIOCHECK = 0200h +MFT_SEPARATOR = MF_SEPARATOR +MFT_RIGHTORDER = 2000h +MFT_RIGHTJUSTIFY = MF_RIGHTJUSTIFY +MFS_GRAYED = 0003h +MFS_DISABLED = MFS_GRAYED +MFS_CHECKED = MF_CHECKED +MFS_HILITE = MF_HILITE +MFS_ENABLED = MF_ENABLED +MFS_UNCHECKED = MF_UNCHECKED +MFS_UNHILITE = MF_UNHILITE +MFS_DEFAULT = MF_DEFAULT +MFR_POPUP = 0001h +MFR_END = MF_END + +; System menu command values + +SC_SIZE = 61440 +SC_MOVE = 61456 +SC_MINIMIZE = 61472 +SC_MAXIMIZE = 61488 +SC_NEXTWINDOW = 61504 +SC_PREVWINDOW = 61520 +SC_CLOSE = 61536 +SC_VSCROLL = 61552 +SC_HSCROLL = 61568 +SC_MOUSEMENU = 61584 +SC_KEYMENU = 61696 +SC_ARRANGE = 61712 +SC_RESTORE = 61728 +SC_TASKLIST = 61744 +SC_SCREENSAVE = 61760 +SC_HOTKEY = 61776 +SC_DEFAULT = 61792 +SC_MONITORPOWER = 61808 +SC_CONTEXTHELP = 61824 +SC_SEPARATOR = 61455 + +; Border types + +BDR_RAISEDOUTER = 01h +BDR_SUNKENOUTER = 02h +BDR_RAISEDINNER = 04h +BDR_SUNKENINNER = 08h +BDR_OUTER = 03h +BDR_INNER = 0Ch +BDR_RAISED = 05h +BDR_SUNKEN = 0Ah +EDGE_RAISED = BDR_RAISEDOUTER or BDR_RAISEDINNER +EDGE_SUNKEN = BDR_SUNKENOUTER or BDR_SUNKENINNER +EDGE_ETCHED = BDR_SUNKENOUTER or BDR_RAISEDINNER +EDGE_BUMP = BDR_RAISEDOUTER or BDR_SUNKENINNER + +; Border flags + +BF_LEFT = 0001h +BF_TOP = 0002h +BF_RIGHT = 0004h +BF_BOTTOM = 0008h +BF_TOPLEFT = BF_TOP or BF_LEFT +BF_TOPRIGHT = BF_TOP or BF_RIGHT +BF_BOTTOMLEFT = BF_BOTTOM or BF_LEFT +BF_BOTTOMRIGHT = BF_BOTTOM or BF_RIGHT +BF_RECT = BF_LEFT or BF_TOP or BF_RIGHT or BF_BOTTOM +BF_DIAGONAL = 0010h +BF_DIAGONAL_ENDTOPRIGHT = BF_DIAGONAL or BF_TOP or BF_RIGHT +BF_DIAGONAL_ENDTOPLEFT = BF_DIAGONAL or BF_TOP or BF_LEFT +BF_DIAGONAL_ENDBOTTOMLEFT = BF_DIAGONAL or BF_BOTTOM or BF_LEFT +BF_DIAGONAL_ENDBOTTOMRIGHT = BF_DIAGONAL or BF_BOTTOM or BF_RIGHT +BF_MIDDLE = 0800h +BF_SOFT = 1000h +BF_ADJUST = 2000h +BF_FLAT = 4000h +BF_MONO = 8000h + +; Frame control types + +DFC_CAPTION = 1 +DFC_MENU = 2 +DFC_SCROLL = 3 +DFC_BUTTON = 4 +DFC_POPUPMENU = 5 + +; Frame control states + +DFCS_CAPTIONCLOSE = 0000h +DFCS_CAPTIONMIN = 0001h +DFCS_CAPTIONMAX = 0002h +DFCS_CAPTIONRESTORE = 0003h +DFCS_CAPTIONHELP = 0004h +DFCS_MENUARROW = 0000h +DFCS_MENUCHECK = 0001h +DFCS_MENUBULLET = 0002h +DFCS_MENUARROWRIGHT = 0004h +DFCS_SCROLLUP = 0000h +DFCS_SCROLLDOWN = 0001h +DFCS_SCROLLLEFT = 0002h +DFCS_SCROLLRIGHT = 0003h +DFCS_SCROLLCOMBOBOX = 0005h +DFCS_SCROLLSIZEGRIP = 0008h +DFCS_SCROLLSIZEGRIPRIGHT = 0010h +DFCS_BUTTONCHECK = 0000h +DFCS_BUTTONRADIOIMAGE = 0001h +DFCS_BUTTONRADIOMASK = 0002h +DFCS_BUTTONRADIO = 0004h +DFCS_BUTTON3STATE = 0008h +DFCS_BUTTONPUSH = 0010h +DFCS_INACTIVE = 0100h +DFCS_PUSHED = 0200h +DFCS_CHECKED = 0400h +DFCS_TRANSPARENT = 0800h +DFCS_HOT = 1000h +DFCS_ADJUSTRECT = 2000h +DFCS_FLAT = 4000h +DFCS_MONO = 8000h + +; DrawCaption flags + +DC_ACTIVE = 01h +DC_SMALLCAP = 02h +DC_ICON = 04h +DC_TEXT = 08h +DC_INBUTTON = 10h + +; DrawIconEx options + +DI_MASK = 1 +DI_IMAGE = 2 +DI_NORMAL = 3 +DI_COMPAT = 4 +DI_DEFAULTSIZE = 8 + +; DrawText parameters + +DT_TOP = 00000h +DT_LEFT = 00000h +DT_CENTER = 00001h +DT_RIGHT = 00002h +DT_VCENTER = 00004h +DT_BOTTOM = 00008h +DT_WORDBREAK = 00010h +DT_SINGLELINE = 00020h +DT_EXPANDTABS = 00040h +DT_TABSTOP = 00080h +DT_NOCLIP = 00100h +DT_EXTERNALLEADING = 00200h +DT_CALCRECT = 00400h +DT_NOPREFIX = 00800h +DT_INTERNAL = 01000h +DT_EDITCONTROL = 02000h +DT_PATH_ELLIPSIS = 04000h +DT_END_ELLIPSIS = 08000h +DT_MODIFYSTRING = 10000h +DT_RTLREADING = 20000h +DT_WORD_ELLIPSIS = 40000h + +; GetDCEx flags + +DCX_WINDOW = 000001h +DCX_CACHE = 000002h +DCX_NORESETATTRS = 000004h +DCX_CLIPCHILDREN = 000008h +DCX_CLIPSIBLINGS = 000010h +DCX_PARENTCLIP = 000020h +DCX_EXCLUDERGN = 000040h +DCX_INTERSECTRGN = 000080h +DCX_EXCLUDEUPDATE = 000100h +DCX_INTERSECTUPDATE = 000200h +DCX_LOCKWINDOWUPDATE = 000400h +DCX_VALIDATE = 200000h + +; SetWindowsHook codes + +WH_MSGFILTER = -1 +WH_JOURNALRECORD = 0 +WH_JOURNALPLAYBACK = 1 +WH_KEYBOARD = 2 +WH_GETMESSAGE = 3 +WH_CALLWNDPROC = 4 +WH_CBT = 5 +WH_SYSMSGFILTER = 6 +WH_MOUSE = 7 +WH_HARDWARE = 8 +WH_DEBUG = 9 +WH_SHELL = 10 +WH_FOREGROUNDIDLE = 11 +WH_CALLWNDPROCRET = 12 +WH_KEYBOARD_LL = 13 +WH_MOUSE_LL = 14 + +; Hook codes + +HC_ACTION = 0 +HC_GETNEXT = 1 +HC_SKIP = 2 +HC_NOREMOVE = 3 +HC_SYSMODALON = 4 +HC_SYSMODALOFF = 5 + +; CBT hook codes + +HCBT_MOVESIZE = 0 +HCBT_MINMAX = 1 +HCBT_QS = 2 +HCBT_CREATEWND = 3 +HCBT_DESTROYWND = 4 +HCBT_ACTIVATE = 5 +HCBT_CLICKSKIPPED = 6 +HCBT_KEYSKIPPED = 7 +HCBT_SYSCOMMAND = 8 +HCBT_SETFOCUS = 9 + +; ExitWindowsEx flags + +EWX_LOGOFF = 0 +EWX_SHUTDOWN = 1 +EWX_REBOOT = 2 +EWX_FORCE = 4 +EWX_POWEROFF = 8 + +; WinHelp commands + +HELP_CONTEXT = 001h +HELP_QUIT = 002h +HELP_INDEX = 003h +HELP_CONTENTS = 003h +HELP_HELPONHELP = 004h +HELP_SETINDEX = 005h +HELP_SETCONTENTS = 005h +HELP_CONTEXTPOPUP = 008h +HELP_FORCEFILE = 009h +HELP_CONTEXTMENU = 00Ah +HELP_FINDER = 00Bh +HELP_WM_HELP = 00Ch +HELP_SETPOPUP_POS = 00Dh +HELP_KEY = 101h +HELP_COMMAND = 102h +HELP_PARTIALKEY = 105h +HELP_MULTIKEY = 201h +HELP_SETWINPOS = 203h + +; keybd_event flags + +KEYEVENTF_EXTENDEDKEY = 1h +KEYEVENTF_KEYUP = 2h + +; mouse_event flags + +MOUSEEVENTF_MOVE = 0001h +MOUSEEVENTF_LEFTDOWN = 0002h +MOUSEEVENTF_LEFTUP = 0004h +MOUSEEVENTF_RIGHTDOWN = 0008h +MOUSEEVENTF_RIGHTUP = 0010h +MOUSEEVENTF_MIDDLEDOWN = 0020h +MOUSEEVENTF_MIDDLEUP = 0040h +MOUSEEVENTF_WHEEL = 0800h +MOUSEEVENTF_ABSOLUTE = 8000h + +; TrackPopupMenu flags + +TPM_LEFTBUTTON = 0000h +TPM_RIGHTBUTTON = 0002h +TPM_LEFTALIGN = 0000h +TPM_CENTERALIGN = 0004h +TPM_RIGHTALIGN = 0008h +TPM_TOPALIGN = 0000h +TPM_VCENTERALIGN = 0010h +TPM_BOTTOMALIGN = 0020h +TPM_HORIZONTAL = 0000h +TPM_VERTICAL = 0040h +TPM_NONOTIFY = 0080h +TPM_RETURNCMD = 0100h +TPM_RECURSE = 0001h +TPM_HORPOSANIMATION = 0400h +TPM_HORNEGANIMATION = 0800h +TPM_VERPOSANIMATION = 1000h +TPM_VERNEGANIMATION = 2000h +TPM_NOANIMATION = 4000h +TPM_LAYOUTRTL = 8000h + +; Menu item info mask values + +MIIM_STATE = 001h +MIIM_ID = 002h +MIIM_SUBMENU = 004h +MIIM_CHECKMARKS = 008h +MIIM_TYPE = 010h +MIIM_DATA = 020h +MIIM_STRING = 040h +MIIM_BITMAP = 080h +MIIM_FTYPE = 100h + +; DRAWITEMSTRUCT control types + +ODT_MENU = 1 +ODT_LISTBOX = 2 +ODT_COMBOBOX = 3 +ODT_BUTTON = 4 +ODT_STATIC = 5 + +; DRAWITEMSTRUCT actions + +ODA_DRAWENTIRE = 1 +ODA_SELECT = 2 +ODA_FOCUS = 4 + +; DRAWITEMSTRUCT states + +ODS_SELECTED = 0001h +ODS_GRAYED = 0002h +ODS_DISABLED = 0004h +ODS_CHECKED = 0008h +ODS_FOCUS = 0010h +ODS_DEFAULT = 0020h +ODS_COMBOBOXEDIT = 1000h +ODS_HOTLIGHT = 0040h +ODS_INACTIVE = 0080h + +; WINDOWPLACEMENT flags + +WPF_SETMINPOSITION = 1 +WPF_RESTORETOMAXIMIZED = 2 + +; Layered window attributes + +LWA_COLORKEY = 1 +LWA_ALPHA = 2 + +; UpdateLayeredWindow flags + +ULW_COLORKEY = 1 +ULW_ALPHA = 2 +ULW_OPAQUE = 4 + +; SystemParametersInfo parameters + +SPI_GETACCESSTIMEOUT = 60 +SPI_GETANIMATION = 72 +SPI_GETBEEP = 1 +SPI_GETBORDER = 5 +SPI_GETDEFAULTINPUTLANG = 89 +SPI_GETDRAGFULLWINDOWS = 38 +SPI_GETFASTTASKSWITCH = 35 +SPI_GETFILTERKEYS = 50 +SPI_GETFONTSMOOTHING = 74 +SPI_GETGRIDGRANULARITY = 18 +SPI_GETHIGHCONTRAST = 66 +SPI_GETICONMETRICS = 45 +SPI_GETICONTITLELOGFONT = 31 +SPI_GETICONTITLEWRAP = 25 +SPI_GETKEYBOARDDELAY = 22 +SPI_GETKEYBOARDPREF = 68 +SPI_GETKEYBOARDSPEED = 10 +SPI_GETLOWPOWERACTIVE = 83 +SPI_GETLOWPOWERTIMEOUT = 79 +SPI_GETMENUDROPALIGNMENT = 27 +SPI_GETMINIMIZEDMETRICS = 43 +SPI_GETMOUSE = 3 +SPI_GETMOUSEKEYS = 54 +SPI_GETMOUSETRAILS = 94 +SPI_GETNONCLIENTMETRICS = 41 +SPI_GETPOWEROFFACTIVE = 84 +SPI_GETPOWEROFFTIMEOUT = 80 +SPI_GETSCREENREADER = 70 +SPI_GETSCREENSAVEACTIVE = 16 +SPI_GETSCREENSAVETIMEOUT = 14 +SPI_GETSERIALKEYS = 62 +SPI_GETSHOWSOUNDS = 56 +SPI_GETSOUNDSENTRY = 64 +SPI_GETSTICKYKEYS = 58 +SPI_GETTOGGLEKEYS = 52 +SPI_GETWINDOWSEXTENSION = 92 +SPI_GETWORKAREA = 48 +SPI_ICONHORIZONTALSPACING = 13 +SPI_ICONVERTICALSPACING = 24 +SPI_LANGDRIVER = 12 +SPI_SCREENSAVERRUNNING = 97 +SPI_SETACCESSTIMEOUT = 61 +SPI_SETANIMATION = 73 +SPI_SETBEEP = 2 +SPI_SETBORDER = 6 +SPI_SETDEFAULTINPUTLANG = 90 +SPI_SETDESKPATTERN = 21 +SPI_SETDESKWALLPAPER = 20 +SPI_SETDOUBLECLICKTIME = 32 +SPI_SETDOUBLECLKHEIGHT = 30 +SPI_SETDOUBLECLKWIDTH = 29 +SPI_SETDRAGFULLWINDOWS = 37 +SPI_SETDRAGHEIGHT = 77 +SPI_SETDRAGWIDTH = 76 +SPI_SETFASTTASKSWITCH = 36 +SPI_SETFILTERKEYS = 51 +SPI_SETFONTSMOOTHING = 75 +SPI_SETGRIDGRANULARITY = 19 +SPI_SETHANDHELD = 78 +SPI_SETHIGHCONTRAST = 67 +SPI_SETICONMETRICS = 46 +SPI_SETICONTITLELOGFONT = 34 +SPI_SETICONTITLEWRAP = 26 +SPI_SETKEYBOARDDELAY = 23 +SPI_SETKEYBOARDPREF = 69 +SPI_SETKEYBOARDSPEED = 11 +SPI_SETLANGTOGGLE = 91 +SPI_SETLOWPOWERACTIVE = 85 +SPI_SETLOWPOWERTIMEOUT = 81 +SPI_SETMENUDROPALIGNMENT = 28 +SPI_SETMINIMIZEDMETRICS = 44 +SPI_SETMOUSE = 4 +SPI_SETMOUSEBUTTONSWAP = 33 +SPI_SETMOUSEKEYS = 55 +SPI_SETMOUSETRAILS = 93 +SPI_SETNONCLIENTMETRICS = 42 +SPI_SETPENWINDOWS = 49 +SPI_SETPOWEROFFACTIVE = 86 +SPI_SETPOWEROFFTIMEOUT = 82 +SPI_SETSCREENREADER = 71 +SPI_SETSCREENSAVEACTIVE = 17 +SPI_SETSCREENSAVERRUNNING = 97 +SPI_SETSCREENSAVETIMEOUT = 15 +SPI_SETSERIALKEYS = 63 +SPI_SETSHOWSOUNDS = 57 +SPI_SETSOUNDSENTRY = 65 +SPI_SETSTICKYKEYS = 59 +SPI_SETTOGGLEKEYS = 53 +SPI_SETWORKAREA = 47 + +; SystemParametersInfo flags + +SPIF_UPDATEINIFILE = 1 +SPIF_SENDWININICHANGE = 2 + +; Gesture Information Flags + +GF_BEGIN = 1 +GF_INERTIA = 2 +GF_END = 4 + +; Gesture IDs + +GID_BEGIN = 1 +GID_END = 2 +GID_ZOOM = 3 +GID_PAN = 4 +GID_ROTATE = 5 +GID_TWOFINGERTAP = 6 +GID_PRESSANDTAP = 7 +GID_ROLLOVER = GID_PRESSANDTAP + +; Zoom Gesture Confiration Flags + +GC_ZOOM = 0x00000001 + +; Pan Gesture Configuration Flags + +GC_PAN = 0x00000001 +GC_PAN_WITH_SINGLE_FINGER_VERTICALLY = 0x00000002 +GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY = 0x00000004 +GC_PAN_WITH_GUTTER = 0x00000008 +GC_PAN_WITH_INERTIA = 0x00000010 + +; Rotate Gesture Configuration Flags + +GC_ROTATE = 0x00000001 + +; Two finger tap configuration flags + +GC_TWOFINGERTAP = 0x00000001 + +; Press and tap Configuration Flags + +GC_PRESSANDTAP = 0x00000001 +GC_ROLLOVER = GC_PRESSANDTAP diff --git a/toolchain/fasm2/include/equates/user64.inc b/toolchain/fasm2/include/equates/user64.inc new file mode 100644 index 0000000..eeb3c42 --- /dev/null +++ b/toolchain/fasm2/include/equates/user64.inc @@ -0,0 +1,1956 @@ + +; USER32.DLL structures and constants + +struct POINT + x dd ? + y dd ? +ends + +struct POINTS + x dw ? + y dw ? +ends + +struct RECT + left dd ? + top dd ? + right dd ? + bottom dd ? +ends + +struct WNDCLASS + style dd ? + dd ? + lpfnWndProc dq ? + cbClsExtra dd ? + cbWndExtra dd ? + hInstance dq ? + hIcon dq ? + hCursor dq ? + hbrBackground dq ? + lpszMenuName dq ? + lpszClassName dq ? +ends + +struct WNDCLASSEX + cbSize dd ? + style dd ? + lpfnWndProc dq ? + cbClsExtra dd ? + cbWndExtra dd ? + hInstance dq ? + hIcon dq ? + hCursor dq ? + hbrBackground dq ? + lpszMenuName dq ? + lpszClassName dq ? + hIconSm dq ? +ends + +struct CREATESTRUCT + lpCreateParams dq ? + hInstance dq ? + hMenu dq ? + hwndParent dq ? + cy dd ? + cx dd ? + y dd ? + x dd ? + style dd ? + dd ? + lpszName dq ? + lpszClass dq ? + dwExStyle dd ? + dd ? +ends + +struct CLIENTCREATESTRUCT + hWindowMenu dq ? + idFirstChild dd ? + dd ? +ends + +struct MDICREATESTRUCT + szClass dq ? + szTitle dq ? + hOwner dq ? + x dd ? + y dd ? + cx dd ? + cy dd ? + style dd ? + lParam dd ? +ends + +struct SCROLLINFO + cbSize dd ? + fMask dd ? + nMin dd ? + nMax dd ? + nPage dd ? + nPos dd ? + nTrackPos dd ? +ends + +struct MSG + hwnd dq ? + message dd ? + dd ? + wParam dq ? + lParam dq ? + time dd ? + pt POINT + dd ? +ends + +struct MINMAXINFO + ptReserved POINT + ptMaxSize POINT + ptMaxPosition POINT + ptMinTrackSize POINT + ptMaxTrackSize POINT +ends + +struct WINDOWPLACEMENT + length dd ? + flags dd ? + showCmd dd ? + ptMinPosition POINT + ptMaxPosition POINT + rcNormalPosition RECT +ends + +struct WINDOWPOS + hwnd dq ? + hwndInsertAfter dq ? + x dd ? + y dd ? + cx dd ? + cy dd ? + flags dd ? + dd ? +ends + +struct NMHDR + hwndFrom dq ? + idFrom dq ? + code dd ? + dd ? +ends + +struct COPYDATASTRUCT + dwData dq ? + cbData dd ? + dd ? + lpData dq ? +ends + +struct ACCEL + fVirt dw ? + key dw ? + cmd dw ? +ends + +struct PAINTSTRUCT + hdc dq ? + fErase dd ? + rcPaint RECT + fRestore dd ? + fIncUpdate dd ? + rgbReserved db 36 dup (?) +ends + +struct DRAWTEXTPARAMS + cbSize dd ? + iTabLength dd ? + iLeftMargin dd ? + iRightMargin dd ? + uiLengthDrawn dd ? + dd ? +ends + +struct DRAWITEMSTRUCT + CtlType dd ? + CtlID dd ? + itemID dd ? + itemAction dd ? + itemState dd ? + dd ? + hwndItem dq ? + hDC dq ? + rcItem RECT + itemData dd ? + dd ? +ends + +struct MENUITEMINFO + cbSize dd ? + fMask dd ? + fType dd ? + fState dd ? + wID dd ? + dd ? + hSubMenu dq ? + hbmpChecked dq ? + hbmpUnchecked dq ? + dwItemData dq ? + dwTypeData dq ? + cch dd ? + dd ? + hbmpItem dq ? +ends + +struct MEASUREITEMSTRUCT + CtlType dd ? + CtlID dd ? + itemID dd ? + itemWidth dd ? + itemHeight dd ? + dd ? + itemData dq ? +ends + +struct MSGBOXPARAMS + cbSize dd ? + dd ? + hwndOwner dq ? + hInstance dq ? + lpszText dd ? + lpszCaption dd ? + dwStyle dd ? + dd ? + lpszIcon dq ? + dwContextHelpId dd ? + dd ? + lpfnMsgBoxCallback dq ? + dwLanguageId dd ? + dd ? +ends + +struct GESTURECONFIG + dwID dd ? + dwWant dd ? + dwBlock dd ? +ends + +struct GESTUREINFO + cbSize dd ? + dwFlags dd ? + dwID dd ? + dd ? + hwndTarget dq ? + ptsLocation POINTS + dwInstanceID dd ? + dwSequenceID dd ? + dd ? + ullArguments dq ? + cbExtraArgs dd ? + dd ? +ends + +; MessageBox type flags + +MB_OK = 000000h +MB_OKCANCEL = 000001h +MB_ABORTRETRYIGNORE = 000002h +MB_YESNOCANCEL = 000003h +MB_YESNO = 000004h +MB_RETRYCANCEL = 000005h +MB_ICONHAND = 000010h +MB_ICONQUESTION = 000020h +MB_ICONEXCLAMATION = 000030h +MB_ICONASTERISK = 000040h +MB_USERICON = 000080h +MB_ICONWARNING = MB_ICONEXCLAMATION +MB_ICONERROR = MB_ICONHAND +MB_ICONINFORMATION = MB_ICONASTERISK +MB_ICONSTOP = MB_ICONHAND +MB_DEFBUTTON1 = 000000h +MB_DEFBUTTON2 = 000100h +MB_DEFBUTTON3 = 000200h +MB_DEFBUTTON4 = 000300h +MB_APPLMODAL = 000000h +MB_SYSTEMMODAL = 001000h +MB_TASKMODAL = 002000h +MB_HELP = 004000h +MB_NOFOCUS = 008000h +MB_SETFOREGROUND = 010000h +MB_DEFAULT_DESKTOP_ONLY = 020000h +MB_TOPMOST = 040000h +MB_RIGHT = 080000h +MB_RTLREADING = 100000h +MB_SERVICE_NOTIFICATION = 200000h + +; Conventional dialog box and message box command IDs + +IDOK = 1 +IDCANCEL = 2 +IDABORT = 3 +IDRETRY = 4 +IDIGNORE = 5 +IDYES = 6 +IDNO = 7 +IDCLOSE = 8 +IDHELP = 9 + +; Class styles + +CS_VREDRAW = 00001h +CS_HREDRAW = 00002h +CS_KEYCVTWINDOW = 00004h +CS_DBLCLKS = 00008h +CS_OWNDC = 00020h +CS_CLASSDC = 00040h +CS_PARENTDC = 00080h +CS_NOKEYCVT = 00100h +CS_SAVEBITS = 00800h +CS_NOCLOSE = 00200h +CS_BYTEALIGNCLIENT = 01000h +CS_BYTEALIGNWINDOW = 02000h +CS_PUBLICCLASS = 04000h +CS_GLOBALCLASS = CS_PUBLICCLASS +CS_IME = 10000h + +; Windows styles + +WS_OVERLAPPED = 000000000h +WS_ICONICPOPUP = 0C0000000h +WS_POPUP = 080000000h +WS_CHILD = 040000000h +WS_MINIMIZE = 020000000h +WS_VISIBLE = 010000000h +WS_DISABLED = 008000000h +WS_CLIPSIBLINGS = 004000000h +WS_CLIPCHILDREN = 002000000h +WS_MAXIMIZE = 001000000h +WS_CAPTION = 000C00000h +WS_BORDER = 000800000h +WS_DLGFRAME = 000400000h +WS_VSCROLL = 000200000h +WS_HSCROLL = 000100000h +WS_SYSMENU = 000080000h +WS_THICKFRAME = 000040000h +WS_HREDRAW = 000020000h +WS_VREDRAW = 000010000h +WS_GROUP = 000020000h +WS_TABSTOP = 000010000h +WS_MINIMIZEBOX = 000020000h +WS_MAXIMIZEBOX = 000010000h + +; Common Window Styles + +WS_OVERLAPPEDWINDOW = WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX +WS_POPUPWINDOW = WS_POPUP or WS_BORDER or WS_SYSMENU +WS_CHILDWINDOW = WS_CHILD +WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW +WS_TILED = WS_OVERLAPPED +WS_ICONIC = WS_MINIMIZE +WS_SIZEBOX = WS_THICKFRAME + +; Extended Window Styles + +WS_EX_DLGMODALFRAME = 00001h +WS_EX_DRAGOBJECT = 00002h +WS_EX_NOPARENTNOTIFY = 00004h +WS_EX_TOPMOST = 00008h +WS_EX_ACCEPTFILES = 00010h +WS_EX_TRANSPARENT = 00020h +WS_EX_MDICHILD = 00040h +WS_EX_TOOLWINDOW = 00080h +WS_EX_WINDOWEDGE = 00100h +WS_EX_CLIENTEDGE = 00200h +WS_EX_CONTEXTHELP = 00400h +WS_EX_RIGHT = 01000h +WS_EX_LEFT = 00000h +WS_EX_RTLREADING = 02000h +WS_EX_LTRREADING = 00000h +WS_EX_LEFTSCROLLBAR = 04000h +WS_EX_RIGHTSCROLLBAR = 00000h +WS_EX_CONTROLPARENT = 10000h +WS_EX_STATICEDGE = 20000h +WS_EX_APPWINDOW = 40000h +WS_EX_LAYERED = 80000h +WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE +WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE or WS_EX_TOOLWINDOW or WS_EX_TOPMOST + +; MDI client style bits + +MDIS_ALLCHILDSTYLES = 1 + +; Special CreateWindow position value + +CW_USEDEFAULT = 80000000h + +; Predefined window handle + +HWND_DESKTOP = 0 + +; ShowWindow commands + +SW_HIDE = 0 +SW_SHOWNORMAL = 1 +SW_NORMAL = 1 +SW_SHOWMINIMIZED = 2 +SW_SHOWMAXIMIZED = 3 +SW_MAXIMIZE = 3 +SW_SHOWNOACTIVATE = 4 +SW_SHOW = 5 +SW_MINIMIZE = 6 +SW_SHOWMINNOACTIVE = 7 +SW_SHOWNA = 8 +SW_RESTORE = 9 +SW_SHOWDEFAULT = 10 + +; SetWindowPos flags + +SWP_NOSIZE = 0001h +SWP_NOMOVE = 0002h +SWP_NOZORDER = 0004h +SWP_NOREDRAW = 0008h +SWP_NOACTIVATE = 0010h +SWP_DRAWFRAME = 0020h +SWP_SHOWWINDOW = 0040h +SWP_HIDEWINDOW = 0080h +SWP_NOCOPYBITS = 0100h +SWP_NOREPOSITION = 0200h +SWP_DEFERERASE = 2000h +SWP_ASYNCWINDOWPOS = 4000h + +; SetWindowPos special handle values + +HWND_TOP = 0 +HWND_BOTTOM = 1 +HWND_TOPMOST = -1 +HWND_NOTOPMOST = -2 + +; GetWindow flags + +GW_HWNDFIRST = 0 +GW_HWNDLAST = 1 +GW_HWNDNEXT = 2 +GW_HWNDPREV = 3 +GW_OWNER = 4 +GW_CHILD = 5 + +; RedrawWindow flags + +RDW_INVALIDATE = 0001h +RDW_INTERNALPAINT = 0002h +RDW_ERASE = 0004h +RDW_VALIDATE = 0008h +RDW_NOINTERNALPAINT = 0010h +RDW_NOERASE = 0020h +RDW_NOCHILDREN = 0040h +RDW_ALLCHILDREN = 0080h +RDW_UPDATENOW = 0100h +RDW_ERASENOW = 0200h +RDW_FRAME = 0400h +RDW_NOFRAME = 0800h + +; PeekMessage Options + +PM_NOREMOVE = 0000h +PM_REMOVE = 0001h +PM_NOYIELD = 0002h + +; Window state messages + +WM_STATE = 0000h +WM_NULL = 0000h +WM_CREATE = 0001h +WM_DESTROY = 0002h +WM_MOVE = 0003h +WM_SIZE = 0005h +WM_ACTIVATE = 0006h +WM_SETFOCUS = 0007h +WM_KILLFOCUS = 0008h +WM_ENABLE = 000Ah +WM_SETREDRAW = 000Bh +WM_SETTEXT = 000Ch +WM_GETTEXT = 000Dh +WM_GETTEXTLENGTH = 000Eh +WM_PAINT = 000Fh +WM_CLOSE = 0010h +WM_QUERYENDSESSION = 0011h +WM_QUIT = 0012h +WM_QUERYOPEN = 0013h +WM_ERASEBKGND = 0014h +WM_SYSCOLORCHANGE = 0015h +WM_ENDSESSION = 0016h +WM_SYSTEMERROR = 0017h +WM_SHOWWINDOW = 0018h +WM_CTLCOLOR = 0019h +WM_WININICHANGE = 001Ah +WM_DEVMODECHANGE = 001Bh +WM_ACTIVATEAPP = 001Ch +WM_FONTCHANGE = 001Dh +WM_TIMECHANGE = 001Eh +WM_CANCELMODE = 001Fh +WM_SETCURSOR = 0020h +WM_MOUSEACTIVATE = 0021h +WM_CHILDACTIVATE = 0022h +WM_QUEUESYNC = 0023h +WM_GETMINMAXINFO = 0024h +WM_PAINTICON = 0026h +WM_ICONERASEBKGND = 0027h +WM_NEXTDLGCTL = 0028h +WM_SPOOLERSTATUS = 002Ah +WM_DRAWITEM = 002Bh +WM_MEASUREITEM = 002Ch +WM_DELETEITEM = 002Dh +WM_VKEYTOITEM = 002Eh +WM_CHARTOITEM = 002Fh +WM_SETFONT = 0030h +WM_GETFONT = 0031h +WM_SETHOTKEY = 0032h +WM_QUERYDRAGICON = 0037h +WM_COMPAREITEM = 0039h +WM_COMPACTING = 0041h +WM_COMMNOTIFY = 0044h +WM_WINDOWPOSCHANGING = 0046h +WM_WINDOWPOSCHANGED = 0047h +WM_POWER = 0048h +WM_COPYDATA = 004Ah +WM_CANCELJOURNAL = 004Bh +WM_NOTIFY = 004Eh +WM_INPUTLANGCHANGEREQUEST = 0050h +WM_INPUTLANGCHANGE = 0051h +WM_TCARD = 0052h +WM_HELP = 0053h +WM_USERCHANGED = 0054h +WM_NOTIFYFORMAT = 0055h +WM_CONTEXTMENU = 007Bh +WM_STYLECHANGING = 007Ch +WM_STYLECHANGED = 007Dh +WM_DISPLAYCHANGE = 007Eh +WM_GETICON = 007Fh +WM_SETICON = 0080h +WM_NCCREATE = 0081h +WM_NCDESTROY = 0082h +WM_NCCALCSIZE = 0083h +WM_NCHITTEST = 0084h +WM_NCPAINT = 0085h +WM_NCACTIVATE = 0086h +WM_GETDLGCODE = 0087h +WM_NCMOUSEMOVE = 00A0h +WM_NCLBUTTONDOWN = 00A1h +WM_NCLBUTTONUP = 00A2h +WM_NCLBUTTONDBLCLK = 00A3h +WM_NCRBUTTONDOWN = 00A4h +WM_NCRBUTTONUP = 00A5h +WM_NCRBUTTONDBLCLK = 00A6h +WM_NCMBUTTONDOWN = 00A7h +WM_NCMBUTTONUP = 00A8h +WM_NCMBUTTONDBLCLK = 00A9h +WM_KEYFIRST = 0100h +WM_KEYDOWN = 0100h +WM_KEYUP = 0101h +WM_CHAR = 0102h +WM_DEADCHAR = 0103h +WM_SYSKEYDOWN = 0104h +WM_SYSKEYUP = 0105h +WM_SYSCHAR = 0106h +WM_SYSDEADCHAR = 0107h +WM_KEYLAST = 0108h +WM_INITDIALOG = 0110h +WM_COMMAND = 0111h +WM_SYSCOMMAND = 0112h +WM_TIMER = 0113h +WM_HSCROLL = 0114h +WM_VSCROLL = 0115h +WM_INITMENU = 0116h +WM_INITMENUPOPUP = 0117h +WM_GESTURE = 0119h +WM_GESTURENOTIFY = 011Ah +WM_MENUSELECT = 011Fh +WM_MENUCHAR = 0120h +WM_ENTERIDLE = 0121h +WM_MENURBUTTONUP = 0122h +WM_MENUDRAG = 0123h +WM_MENUGETOBJECT = 0124h +WM_UNINITMENUPOPUP = 0125h +WM_MENUCOMMAND = 0126h +WM_CTLCOLORMSGBOX = 0132h +WM_CTLCOLOREDIT = 0133h +WM_CTLCOLORLISTBOX = 0134h +WM_CTLCOLORBTN = 0135h +WM_CTLCOLORDLG = 0136h +WM_CTLCOLORSCROLLBAR = 0137h +WM_CTLCOLORSTATIC = 0138h +WM_MOUSEFIRST = 0200h +WM_MOUSEMOVE = 0200h +WM_LBUTTONDOWN = 0201h +WM_LBUTTONUP = 0202h +WM_LBUTTONDBLCLK = 0203h +WM_RBUTTONDOWN = 0204h +WM_RBUTTONUP = 0205h +WM_RBUTTONDBLCLK = 0206h +WM_MBUTTONDOWN = 0207h +WM_MBUTTONUP = 0208h +WM_MBUTTONDBLCLK = 0209h +WM_MOUSEWHEEL = 020Ah +WM_MOUSELAST = 020Ah +WM_PARENTNOTIFY = 0210h +WM_ENTERMENULOOP = 0211h +WM_EXITMENULOOP = 0212h +WM_NEXTMENU = 0213h +WM_SIZING = 0214h +WM_CAPTURECHANGED = 0215h +WM_MOVING = 0216h +WM_POWERBROADCAST = 0218h +WM_DEVICECHANGE = 0219h +WM_MDICREATE = 0220h +WM_MDIDESTROY = 0221h +WM_MDIACTIVATE = 0222h +WM_MDIRESTORE = 0223h +WM_MDINEXT = 0224h +WM_MDIMAXIMIZE = 0225h +WM_MDITILE = 0226h +WM_MDICASCADE = 0227h +WM_MDIICONARRANGE = 0228h +WM_MDIGETACTIVE = 0229h +WM_MDISETMENU = 0230h +WM_ENTERSIZEMOVE = 0231h +WM_EXITSIZEMOVE = 0232h +WM_DROPFILES = 0233h +WM_MDIREFRESHMENU = 0234h +WM_IME_SETCONTEXT = 0281h +WM_IME_NOTIFY = 0282h +WM_IME_CONTROL = 0283h +WM_IME_COMPOSITIONFULL = 0284h +WM_IME_SELECT = 0285h +WM_IME_CHAR = 0286h +WM_IME_KEYDOWN = 0290h +WM_IME_KEYUP = 0291h +WM_MOUSEHOVER = 02A1h +WM_MOUSELEAVE = 02A3h +WM_CUT = 0300h +WM_COPY = 0301h +WM_PASTE = 0302h +WM_CLEAR = 0303h +WM_UNDO = 0304h +WM_RENDERFORMAT = 0305h +WM_RENDERALLFORMATS = 0306h +WM_DESTROYCLIPBOARD = 0307h +WM_DRAWCLIPBOARD = 0308h +WM_PAINTCLIPBOARD = 0309h +WM_VSCROLLCLIPBOARD = 030Ah +WM_SIZECLIPBOARD = 030Bh +WM_ASKCBFORMATNAME = 030Ch +WM_CHANGECBCHAIN = 030Dh +WM_HSCROLLCLIPBOARD = 030Eh +WM_QUERYNEWPALETTE = 030Fh +WM_PALETTEISCHANGING = 0310h +WM_PALETTECHANGED = 0311h +WM_HOTKEY = 0312h +WM_PRINT = 0317h +WM_PRINTCLIENT = 0318h +WM_HANDHELDFIRST = 0358h +WM_HANDHELDLAST = 035Fh +WM_AFXFIRST = 0360h +WM_AFXLAST = 037Fh +WM_PENWINFIRST = 0380h +WM_PENWINLAST = 038Fh +WM_COALESCE_FIRST = 0390h +WM_COALESCE_LAST = 039Fh +WM_USER = 0400h + +; WM_SIZE commands + +SIZE_RESTORED = 0 +SIZE_MINIMIZED = 1 +SIZE_MAXIMIZED = 2 +SIZE_MAXSHOW = 3 +SIZE_MAXHIDE = 4 + +; WM_ACTIVATE states + +WA_INACTIVE = 0 +WA_ACTIVE = 1 +WA_CLICKACTIVE = 2 + +; WM_SHOWWINDOW identifiers + +SW_PARENTCLOSING = 1 +SW_OTHERZOOM = 2 +SW_PARENTOPENING = 3 +SW_OTHERUNZOOM = 4 + +; WM_MOUSEACTIVATE return codes + +MA_ACTIVATE = 1 +MA_ACTIVATEANDEAT = 2 +MA_NOACTIVATE = 3 +MA_NOACTIVATEANDEAT = 4 + +; WM_MDITILE flags + +MDITILE_VERTICAL = 0 +MDITILE_HORIZONTAL = 1 +MDITILE_SKIPDISABLED = 2 + +; WM_NOTIFY codes + +NM_OUTOFMEMORY = -1 +NM_CLICK = -2 +NM_DBLCLICK = -3 +NM_RETURN = -4 +NM_RCLICK = -5 +NM_RDBLCLK = -6 +NM_SETFOCUS = -7 +NM_KILLFOCUS = -8 + +; WM_SETICON types + +ICON_SMALL = 0 +ICON_BIG = 1 + +; WM_HOTKEY commands + +HOTKEYF_SHIFT = 01h +HOTKEYF_CONTROL = 02h +HOTKEYF_ALT = 04h +HOTKEYF_EXT = 08h + +; Keystroke flags + +KF_EXTENDED = 0100h +KF_DLGMODE = 0800h +KF_MENUMODE = 1000h +KF_ALTDOWN = 2000h +KF_REPEAT = 4000h +KF_UP = 8000h + +; Key state masks for mouse messages + +MK_LBUTTON = 01h +MK_RBUTTON = 02h +MK_SHIFT = 04h +MK_CONTROL = 08h +MK_MBUTTON = 10h + +; WM_SIZING codes + +WMSZ_LEFT = 1 +WMSZ_RIGHT = 2 +WMSZ_TOP = 3 +WMSZ_TOPLEFT = 4 +WMSZ_TOPRIGHT = 5 +WMSZ_BOTTOM = 6 +WMSZ_BOTTOMLEFT = 7 +WMSZ_BOTTOMRIGHT = 8 + +; WM_HOTKEY modifiers + +MOD_ALT = 1 +MOD_CONTROL = 2 +MOD_SHIFT = 4 +MOD_WIN = 8 + +; WM_PRINT flags + +PRF_CHECKVISIBLE = 01h +PRF_NONCLIENT = 02h +PRF_CLIENT = 04h +PRF_ERASEBKGND = 08h +PRF_CHILDREN = 10h +PRF_OWNED = 20h + +; Virtual key codes + +VK_LBUTTON = 001h +VK_CANCEL = 003h +VK_RBUTTON = 002h +VK_MBUTTON = 004h +VK_BACK = 008h +VK_TAB = 009h +VK_CLEAR = 00Ch +VK_RETURN = 00Dh +VK_SHIFT = 010h +VK_CONTROL = 011h +VK_MENU = 012h +VK_PAUSE = 013h +VK_CAPITAL = 014h +VK_ESCAPE = 01Bh +VK_SPACE = 020h +VK_PRIOR = 021h +VK_PGUP = 021h +VK_PGDN = 022h +VK_NEXT = 022h +VK_END = 023h +VK_HOME = 024h +VK_LEFT = 025h +VK_UP = 026h +VK_RIGHT = 027h +VK_DOWN = 028h +VK_SELECT = 029h +VK_PRINT = 02Ah +VK_EXECUTE = 02Bh +VK_SNAPSHOT = 02Ch +VK_INSERT = 02Dh +VK_DELETE = 02Eh +VK_HELP = 02Fh +VK_LWIN = 05Bh +VK_RWIN = 05Ch +VK_APPS = 05Dh +VK_NUMPAD0 = 060h +VK_NUMPAD1 = 061h +VK_NUMPAD2 = 062h +VK_NUMPAD3 = 063h +VK_NUMPAD4 = 064h +VK_NUMPAD5 = 065h +VK_NUMPAD6 = 066h +VK_NUMPAD7 = 067h +VK_NUMPAD8 = 068h +VK_NUMPAD9 = 069h +VK_MULTIPLY = 06Ah +VK_ADD = 06Bh +VK_SEPARATOR = 06Ch +VK_SUBTRACT = 06Dh +VK_DECIMAL = 06Eh +VK_DIVIDE = 06Fh +VK_F1 = 070h +VK_F2 = 071h +VK_F3 = 072h +VK_F4 = 073h +VK_F5 = 074h +VK_F6 = 075h +VK_F7 = 076h +VK_F8 = 077h +VK_F9 = 078h +VK_F10 = 079h +VK_F11 = 07Ah +VK_F12 = 07Bh +VK_F13 = 07Ch +VK_F14 = 07Dh +VK_F15 = 07Eh +VK_F16 = 07Fh +VK_F17 = 080h +VK_F18 = 081h +VK_F19 = 082h +VK_F20 = 083h +VK_F21 = 084h +VK_F22 = 085h +VK_F23 = 086h +VK_F24 = 087h +VK_NUMLOCK = 090h +VK_SCROLL = 091h +VK_LSHIFT = 0A0h +VK_RSHIFT = 0A1h +VK_LCONTROL = 0A2h +VK_RCONTROL = 0A3h +VK_LMENU = 0A4h +VK_RMENU = 0A5h +VK_ATTN = 0F6h +VK_CRSEL = 0F7h +VK_EXSEL = 0F8h +VK_EREOF = 0F9h +VK_PLAY = 0FAh +VK_ZOOM = 0FBh +VK_NONAME = 0FCh +VK_PA1 = 0FDh +VK_OEM_CLEAR = 0FEh + +; Accelerator flags + +FVIRTKEY = 01h +FNOINVERT = 02h +FSHIFT = 04h +FCONTROL = 08h +FALT = 10h + +; GetClassLong offsets + +GCL_MENUNAME = -8 +GCL_HBRBACKGROUND = -10 +GCL_HCURSOR = -12 +GCL_HICON = -14 +GCL_HMODULE = -16 +GCL_CBWNDEXTRA = -18 +GCL_CBCLSEXTRA = -20 +GCL_WNDPROC = -24 +GCL_STYLE = -26 +GCW_ATOM = -32 +GCL_HICONSM = -34 + +; WNDCLASS parameters + +DLGWINDOWEXTRA = 30 + +; GetWindowLong offsets + +GWLP_WNDPROC = -4 +GWLP_HINSTANCE = -6 +GWLP_HWNDPARENT = -8 +GWLP_ID = -12 +GWLP_STYLE = -16 +GWLP_EXSTYLE = -20 +GWLP_USERDATA = -21 +DWLP_MSGRESULT = 0 +DWLP_DLGPROC = 8 +DWLP_USER = 16 + +; GetSystemMetrics codes + +SM_CXSCREEN = 0 +SM_CYSCREEN = 1 +SM_CXVSCROLL = 2 +SM_CYHSCROLL = 3 +SM_CYCAPTION = 4 +SM_CXBORDER = 5 +SM_CYBORDER = 6 +SM_CXDLGFRAME = 7 +SM_CYDLGFRAME = 8 +SM_CYVTHUMB = 9 +SM_CXHTHUMB = 10 +SM_CXICON = 11 +SM_CYICON = 12 +SM_CXCURSOR = 13 +SM_CYCURSOR = 14 +SM_CYMENU = 15 +SM_CXFULLSCREEN = 16 +SM_CYFULLSCREEN = 17 +SM_CYKANJIWINDOW = 18 +SM_MOUSEPRESENT = 19 +SM_CYVSCROLL = 20 +SM_CXHSCROLL = 21 +SM_DEBUG = 22 +SM_SWAPBUTTON = 23 +SM_RESERVED1 = 24 +SM_RESERVED2 = 25 +SM_RESERVED3 = 26 +SM_RESERVED4 = 27 +SM_CXMIN = 28 +SM_CYMIN = 29 +SM_CXSIZE = 30 +SM_CYSIZE = 31 +SM_CXFRAME = 32 +SM_CYFRAME = 33 +SM_CXMINTRACK = 34 +SM_CYMINTRACK = 35 +SM_CXDOUBLECLK = 36 +SM_CYDOUBLECLK = 37 +SM_CXICONSPACING = 38 +SM_CYICONSPACING = 39 +SM_MENUDROPALIGNMENT = 40 +SM_PENWINDOWS = 41 +SM_DBCSENABLED = 42 +SM_CMOUSEBUTTONS = 43 +SM_CXFIXEDFRAME = SM_CXDLGFRAME +SM_CYFIXEDFRAME = SM_CYDLGFRAME +SM_CXSIZEFRAME = SM_CXFRAME +SM_CYSIZEFRAME = SM_CYFRAME +SM_SECURE = 44 +SM_CXEDGE = 45 +SM_CYEDGE = 46 +SM_CXMINSPACING = 47 +SM_CYMINSPACING = 48 +SM_CXSMICON = 49 +SM_CYSMICON = 50 +SM_CYSMCAPTION = 51 +SM_CXSMSIZE = 52 +SM_CYSMSIZE = 53 +SM_CXMENUSIZE = 54 +SM_CYMENUSIZE = 55 +SM_ARRANGE = 56 +SM_CXMINIMIZED = 57 +SM_CYMINIMIZED = 58 +SM_CXMAXTRACK = 59 +SM_CYMAXTRACK = 60 +SM_CXMAXIMIZED = 61 +SM_CYMAXIMIZED = 62 +SM_NETWORK = 63 +SM_CLEANBOOT = 67 +SM_CXDRAG = 68 +SM_CYDRAG = 69 +SM_SHOWSOUNDS = 70 +SM_CXMENUCHECK = 71 +SM_CYMENUCHECK = 72 +SM_SLOWMACHINE = 73 +SM_MIDEASTENABLED = 74 +SM_MOUSEWHEELPRESENT = 75 +SM_CMETRICS = 76 + +; Predefined cursor identifiers + +IDC_ARROW = 32512 +IDC_IBEAM = 32513 +IDC_WAIT = 32514 +IDC_CROSS = 32515 +IDC_UPARROW = 32516 +IDC_SIZE = 32640 +IDC_ICON = 32641 +IDC_SIZENWSE = 32642 +IDC_SIZENESW = 32643 +IDC_SIZEWE = 32644 +IDC_SIZENS = 32645 +IDC_NO = 32648 +IDC_HAND = 32649 +IDC_APPSTARTING = 32650 +IDC_HELP = 32651 + +; Predefined icon identifiers + +IDI_APPLICATION = 32512 +IDI_HAND = 32513 +IDI_QUESTION = 32514 +IDI_EXCLAMATION = 32515 +IDI_ASTERISK = 32516 +IDI_WINLOGO = 32517 + +; System colors + +COLOR_SCROLLBAR = 0 +COLOR_BACKGROUND = 1 +COLOR_ACTIVECAPTION = 2 +COLOR_INACTIVECAPTION = 3 +COLOR_MENU = 4 +COLOR_WINDOW = 5 +COLOR_WINDOWFRAME = 6 +COLOR_MENUTEXT = 7 +COLOR_WINDOWTEXT = 8 +COLOR_CAPTIONTEXT = 9 +COLOR_ACTIVEBORDER = 10 +COLOR_INACTIVEBORDER = 11 +COLOR_APPWORKSPACE = 12 +COLOR_HIGHLIGHT = 13 +COLOR_HIGHLIGHTTEXT = 14 +COLOR_BTNFACE = 15 +COLOR_BTNSHADOW = 16 +COLOR_GRAYTEXT = 17 +COLOR_BTNTEXT = 18 +COLOR_INACTIVECAPTIONTEXT = 19 +COLOR_BTNHIGHLIGHT = 20 +COLOR_3DDKSHADOW = 21 +COLOR_3DLIGHT = 22 +COLOR_INFOTEXT = 23 +COLOR_INFOBK = 24 +COLOR_HOTLIGHT = 26 +COLOR_GRADIENTACTIVECAPTION = 27 +COLOR_GRADIENTINACTIVECAPTION = 28 + +; Button messages + +BM_GETCHECK = 00F0h +BM_SETCHECK = 00F1h +BM_GETSTATE = 00F2h +BM_SETSTATE = 00F3h +BM_SETSTYLE = 00F4h +BM_CLICK = 00F5h +BM_GETIMAGE = 00F6h +BM_SETIMAGE = 00F7h + +; Button notifications + +BN_CLICKED = 0 +BN_PAINT = 1 +BN_HILITE = 2 +BN_UNHILITE = 3 +BN_DISABLE = 4 +BN_DOUBLECLICKED = 5 +BN_SETFOCUS = 6 +BN_KILLFOCUS = 7 +BN_PUSHED = BN_HILITE +BN_UNPUSHED = BN_UNHILITE +BN_DBLCLK = BN_DOUBLECLICKED + +; Button styles + +BS_PUSHBUTTON = 0000h +BS_DEFPUSHBUTTON = 0001h +BS_CHECKBOX = 0002h +BS_AUTOCHECKBOX = 0003h +BS_RADIOBUTTON = 0004h +BS_3STATE = 0005h +BS_AUTO3STATE = 0006h +BS_GROUPBOX = 0007h +BS_USERBUTTON = 0008h +BS_AUTORADIOBUTTON = 0009h +BS_OWNERDRAW = 000Bh +BS_TEXT = 0000h +BS_LEFTTEXT = 0020h +BS_RIGHTBUTTON = BS_LEFTTEXT +BS_ICON = 0040h +BS_BITMAP = 0080h +BS_LEFT = 0100h +BS_RIGHT = 0200h +BS_CENTER = 0300h +BS_TOP = 0400h +BS_BOTTOM = 0800h +BS_VCENTER = 0C00h +BS_PUSHLIKE = 1000h +BS_MULTILINE = 2000h +BS_NOTIFY = 4000h +BS_FLAT = 8000h + +; Button states + +BST_UNCHECKED = 0 +BST_CHECKED = 1 +BST_INDETERMINATE = 2 +BST_PUSHED = 4 +BST_FOCUS = 8 + +; List box messages + +LB_ADDSTRING = 0180h +LB_INSERTSTRING = 0181h +LB_DELETESTRING = 0182h +LB_SELITEMRANGEEX = 0183h +LB_RESETCONTENT = 0184h +LB_SETSEL = 0185h +LB_SETCURSEL = 0186h +LB_GETSEL = 0187h +LB_GETCURSEL = 0188h +LB_GETTEXT = 0189h +LB_GETTEXTLEN = 018Ah +LB_GETCOUNT = 018Bh +LB_SELECTSTRING = 018Ch +LB_DIR = 018Dh +LB_GETTOPINDEX = 018Eh +LB_FINDSTRING = 018Fh +LB_GETSELCOUNT = 0190h +LB_GETSELITEMS = 0191h +LB_SETTABSTOPS = 0192h +LB_GETHORIZONTALEXTENT = 0193h +LB_SETHORIZONTALEXTENT = 0194h +LB_SETCOLUMNWIDTH = 0195h +LB_ADDFILE = 0196h +LB_SETTOPINDEX = 0197h +LB_GETITEMRECT = 0198h +LB_GETITEMDATA = 0199h +LB_SETITEMDATA = 019Ah +LB_SELITEMRANGE = 019Bh +LB_SETANCHORINDEX = 019Ch +LB_GETANCHORINDEX = 019Dh +LB_SETCARETINDEX = 019Eh +LB_GETCARETINDEX = 019Fh +LB_SETITEMHEIGHT = 01A0h +LB_GETITEMHEIGHT = 01A1h +LB_FINDSTRINGEXACT = 01A2h +LB_SETLOCALE = 01A5h +LB_GETLOCALE = 01A6h +LB_SETCOUNT = 01A7h +LB_INITSTORAGE = 01A8h +LB_ITEMFROMPOINT = 01A9h + +; List box notifications + +LBN_ERRSPACE = -2 +LBN_SELCHANGE = 1 +LBN_DBLCLK = 2 +LBN_SELCANCEL = 3 +LBN_SETFOCUS = 4 +LBN_KILLFOCUS = 5 + +; List box styles + +LBS_NOTIFY = 0001h +LBS_SORT = 0002h +LBS_NOREDRAW = 0004h +LBS_MULTIPLESEL = 0008h +LBS_OWNERDRAWFIXED = 0010h +LBS_OWNERDRAWVARIABLE = 0020h +LBS_HASSTRINGS = 0040h +LBS_USETABSTOPS = 0080h +LBS_NOINTEGRALHEIGHT = 0100h +LBS_MULTICOLUMN = 0200h +LBS_WANTKEYBOARDINPUT = 0400h +LBS_EXTENDEDSEL = 0800h +LBS_DISABLENOSCROLL = 1000h +LBS_NODATA = 2000h +LBS_NOSEL = 4000h +LBS_STANDARD = LBS_NOTIFY or LBS_SORT or WS_VSCROLL or WS_BORDER + +; List box return values + +LB_OKAY = 0 +LB_ERR = -1 +LB_ERRSPACE = -2 + +; Combo box messages + +CB_GETEDITSEL = 0140h +CB_LIMITTEXT = 0141h +CB_SETEDITSEL = 0142h +CB_ADDSTRING = 0143h +CB_DELETESTRING = 0144h +CB_DIR = 0145h +CB_GETCOUNT = 0146h +CB_GETCURSEL = 0147h +CB_GETLBTEXT = 0148h +CB_GETLBTEXTLEN = 0149h +CB_INSERTSTRING = 014Ah +CB_RESETCONTENT = 014Bh +CB_FINDSTRING = 014Ch +CB_SELECTSTRING = 014Dh +CB_SETCURSEL = 014Eh +CB_SHOWDROPDOWN = 014Fh +CB_GETITEMDATA = 0150h +CB_SETITEMDATA = 0151h +CB_GETDROPPEDCONTROLRECT = 0152h +CB_SETITEMHEIGHT = 0153h +CB_GETITEMHEIGHT = 0154h +CB_SETEXTENDEDUI = 0155h +CB_GETEXTENDEDUI = 0156h +CB_GETDROPPEDSTATE = 0157h +CB_FINDSTRINGEXACT = 0158h +CB_SETLOCALE = 0159h +CB_GETLOCALE = 015Ah +CB_GETTOPINDEX = 015Bh +CB_SETTOPINDEX = 015Ch +CB_GETHORIZONTALEXTENT = 015Dh +CB_SETHORIZONTALEXTENT = 015Eh +CB_GETDROPPEDWIDTH = 015Fh +CB_SETDROPPEDWIDTH = 0160h +CB_INITSTORAGE = 0161h + +; Combo box notifications + +CBN_ERRSPACE = -1 +CBN_SELCHANGE = 1 +CBN_DBLCLK = 2 +CBN_SETFOCUS = 3 +CBN_KILLFOCUS = 4 +CBN_EDITCHANGE = 5 +CBN_EDITUPDATE = 6 +CBN_DROPDOWN = 7 +CBN_CLOSEUP = 8 +CBN_SELENDOK = 9 +CBN_SELENDCANCEL = 10 + +; Combo box styles + +CBS_SIMPLE = 0001h +CBS_DROPDOWN = 0002h +CBS_DROPDOWNLIST = 0003h +CBS_OWNERDRAWFIXED = 0010h +CBS_OWNERDRAWVARIABLE = 0020h +CBS_AUTOHSCROLL = 0040h +CBS_OEMCONVERT = 0080h +CBS_SORT = 0100h +CBS_HASSTRINGS = 0200h +CBS_NOINTEGRALHEIGHT = 0400h +CBS_DISABLENOSCROLL = 0800h +CBS_UPPERCASE = 2000h +CBS_LOWERCASE = 4000h + +; Combo box return values + +CB_OKAY = 0 +CB_ERR = -1 +CB_ERRSPACE = -2 + +; Edit control messages + +EM_GETSEL = 00B0h +EM_SETSEL = 00B1h +EM_GETRECT = 00B2h +EM_SETRECT = 00B3h +EM_SETRECTNP = 00B4h +EM_SCROLL = 00B5h +EM_LINESCROLL = 00B6h +EM_SCROLLCARET = 00B7h +EM_GETMODIFY = 00B8h +EM_SETMODIFY = 00B9h +EM_GETLINECOUNT = 00BAh +EM_LINEINDEX = 00BBh +EM_SETHANDLE = 00BCh +EM_GETHANDLE = 00BDh +EM_GETTHUMB = 00BEh +EM_LINELENGTH = 00C1h +EM_REPLACESEL = 00C2h +EM_GETLINE = 00C4h +EM_LIMITTEXT = 00C5h +EM_CANUNDO = 00C6h +EM_UNDO = 00C7h +EM_FMTLINES = 00C8h +EM_LINEFROMCHAR = 00C9h +EM_SETTABSTOPS = 00CBh +EM_SETPASSWORDCHAR = 00CCh +EM_EMPTYUNDOBUFFER = 00CDh +EM_GETFIRSTVISIBLELINE = 00CEh +EM_SETREADONLY = 00CFh +EM_SETWORDBREAKPROC = 00D0h +EM_GETWORDBREAKPROC = 00D1h +EM_GETPASSWORDCHAR = 00D2h +EM_SETMARGINS = 00D3h +EM_GETMARGINS = 00D4h +EM_SETLIMITTEXT = EM_LIMITTEXT +EM_GETLIMITTEXT = 00D5h +EM_POSFROMCHAR = 00D6h +EM_CHARFROMPOS = 00D7h + +; Edit control EM_SETMARGIN parameters + +EC_LEFTMARGIN = 1 +EC_RIGHTMARGIN = 2 +EC_USEFONTINFO = 0FFFFh + +; Edit control notifications + +EN_SETFOCUS = 0100h +EN_KILLFOCUS = 0200h +EN_CHANGE = 0300h +EN_UPDATE = 0400h +EN_ERRSPACE = 0500h +EN_MAXTEXT = 0501h +EN_HSCROLL = 0601h +EN_VSCROLL = 0602h + +; Edit control styles + +ES_LEFT = 0000h +ES_CENTER = 0001h +ES_RIGHT = 0002h +ES_MULTILINE = 0004h +ES_UPPERCASE = 0008h +ES_LOWERCASE = 0010h +ES_PASSWORD = 0020h +ES_AUTOVSCROLL = 0040h +ES_AUTOHSCROLL = 0080h +ES_NOHIDESEL = 0100h +ES_OEMCONVERT = 0400h +ES_READONLY = 0800h +ES_WANTRETURN = 1000h +ES_NUMBER = 2000h + +; Static window messages + +STM_SETICON = 0170h +STM_GETICON = 0171h +STM_SETIMAGE = 0172h +STM_GETIMAGE = 0173h + +; Static window notifications + +STN_CLICKED = 0 +STN_DBLCLK = 1 +STN_ENABLE = 2 +STN_DISABLE = 3 + +; Static window styles + +SS_LEFT = 0000h +SS_CENTER = 0001h +SS_RIGHT = 0002h +SS_ICON = 0003h +SS_BLACKRECT = 0004h +SS_GRAYRECT = 0005h +SS_WHITERECT = 0006h +SS_BLACKFRAME = 0007h +SS_GRAYFRAME = 0008h +SS_WHITEFRAME = 0009h +SS_USERITEM = 000Ah +SS_SIMPLE = 000Bh +SS_LEFTNOWORDWRAP = 000Ch +SS_BITMAP = 000Eh +SS_OWNERDRAW = 000Dh +SS_ENHMETAFILE = 000Fh +SS_ETCHEDHORZ = 0010h +SS_ETCHEDVERT = 0011h +SS_ETCHEDFRAME = 0012h +SS_TYPEMASK = 001Fh +SS_NOPREFIX = 0080h +SS_NOTIFY = 0100h +SS_CENTERIMAGE = 0200h +SS_RIGHTJUST = 0400h +SS_REALSIZEIMAGE = 0800h +SS_SUNKEN = 1000h + +; Scroll bar constants + +SB_HORZ = 0 +SB_VERT = 1 +SB_CTL = 2 +SB_BOTH = 3 + +; Scroll bar messages + +SBM_SETPOS = 00E0h +SBM_GETPOS = 00E1h +SBM_SETRANGE = 00E2h +SBM_SETRANGEREDRAW = 00E6h +SBM_GETRANGE = 00E3h +SBM_ENABLE_ARROWS = 00E4h +SBM_SETSCROLLINFO = 00E9h +SBM_GETSCROLLINFO = 00EAh + +; Scroll bar commands + +SB_LINEUP = 0 +SB_LINELEFT = 0 +SB_LINEDOWN = 1 +SB_LINERIGHT = 1 +SB_PAGEUP = 2 +SB_PAGELEFT = 2 +SB_PAGEDOWN = 3 +SB_PAGERIGHT = 3 +SB_THUMBPOSITION = 4 +SB_THUMBTRACK = 5 +SB_TOP = 6 +SB_LEFT = 6 +SB_BOTTOM = 7 +SB_RIGHT = 7 +SB_ENDSCROLL = 8 + +; Scroll bar styles + +SBS_HORZ = 0000h +SBS_VERT = 0001h +SBS_TOPALIGN = 0002h +SBS_LEFTALIGN = 0002h +SBS_BOTTOMALIGN = 0004h +SBS_RIGHTALIGN = 0004h +SBS_SIZEBOXTOPLEFTALIGN = 0002h +SBS_SIZEBOXBOTTOMRIGHTALIGN = 0004h +SBS_SIZEBOX = 0008h +SBS_SIZEGRIP = 0010h + +; Scroll bar info flags + +SIF_RANGE = 0001h +SIF_PAGE = 0002h +SIF_POS = 0004h +SIF_DISABLENOSCROLL = 0008h +SIF_TRACKPOS = 0010h +SIF_ALL = SIF_RANGE or SIF_PAGE or SIF_POS or SIF_TRACKPOS + +; Dialog styles + +DS_ABSALIGN = 0001h +DS_SYSMODAL = 0002h +DS_3DLOOK = 0004h +DS_FIXEDSYS = 0008h +DS_NOFAILCREATE = 0010h +DS_LOCALEDIT = 0020h +DS_SETFONT = 0040h +DS_MODALFRAME = 0080h +DS_NOIDLEMSG = 0100h +DS_SETFOREGROUND = 0200h +DS_CONTROL = 0400h +DS_CENTER = 0800h +DS_CENTERMOUSE = 1000h +DS_CONTEXTHELP = 2000h + +; Dialog codes + +DLGC_WANTARROWS = 0001h +DLGC_WANTTAB = 0002h +DLGC_WANTALLKEYS = 0004h +DLGC_WANTMESSAGE = 0004h +DLGC_HASSETSEL = 0008h +DLGC_DEFPUSHBUTTON = 0010h +DLGC_UNDEFPUSHBUTTON = 0020h +DLGC_RADIOBUTTON = 0040h +DLGC_WANTCHARS = 0080h +DLGC_STATIC = 0100h +DLGC_BUTTON = 2000h + +; Menu flags + +MF_INSERT = 0000h +MF_CHANGE = 0080h +MF_APPEND = 0100h +MF_DELETE = 0200h +MF_REMOVE = 1000h +MF_BYCOMMAND = 0000h +MF_BYPOSITION = 0400h +MF_SEPARATOR = 0800h +MF_UNCHECKED = 0000h +MF_ENABLED = 0000h +MF_GRAYED = 0001h +MF_DISABLED = 0002h +MF_CHECKED = 0008h +MF_USECHECKBITMAPS = 0200h +MF_STRING = 0000h +MF_BITMAP = 0004h +MF_OWNERDRAW = 0100h +MF_POPUP = 0010h +MF_MENUBARBREAK = 0020h +MF_MENUBREAK = 0040h +MF_UNHILITE = 0000h +MF_HILITE = 0080h +MF_DEFAULT = 1000h +MF_SYSMENU = 2000h +MF_HELP = 4000h +MF_RIGHTJUSTIFY = 4000h +MF_MOUSESELECT = 8000h +MF_END = 0080h +MFT_STRING = MF_STRING +MFT_BITMAP = MF_BITMAP +MFT_MENUBARBREAK = MF_MENUBARBREAK +MFT_MENUBREAK = MF_MENUBREAK +MFT_OWNERDRAW = MF_OWNERDRAW +MFT_RADIOCHECK = 0200h +MFT_SEPARATOR = MF_SEPARATOR +MFT_RIGHTORDER = 2000h +MFT_RIGHTJUSTIFY = MF_RIGHTJUSTIFY +MFS_GRAYED = 0003h +MFS_DISABLED = MFS_GRAYED +MFS_CHECKED = MF_CHECKED +MFS_HILITE = MF_HILITE +MFS_ENABLED = MF_ENABLED +MFS_UNCHECKED = MF_UNCHECKED +MFS_UNHILITE = MF_UNHILITE +MFS_DEFAULT = MF_DEFAULT +MFR_POPUP = 0001h +MFR_END = MF_END + +; System menu command values + +SC_SIZE = 61440 +SC_MOVE = 61456 +SC_MINIMIZE = 61472 +SC_MAXIMIZE = 61488 +SC_NEXTWINDOW = 61504 +SC_PREVWINDOW = 61520 +SC_CLOSE = 61536 +SC_VSCROLL = 61552 +SC_HSCROLL = 61568 +SC_MOUSEMENU = 61584 +SC_KEYMENU = 61696 +SC_ARRANGE = 61712 +SC_RESTORE = 61728 +SC_TASKLIST = 61744 +SC_SCREENSAVE = 61760 +SC_HOTKEY = 61776 +SC_DEFAULT = 61792 +SC_MONITORPOWER = 61808 +SC_CONTEXTHELP = 61824 +SC_SEPARATOR = 61455 + +; Border types + +BDR_RAISEDOUTER = 01h +BDR_SUNKENOUTER = 02h +BDR_RAISEDINNER = 04h +BDR_SUNKENINNER = 08h +BDR_OUTER = 03h +BDR_INNER = 0Ch +BDR_RAISED = 05h +BDR_SUNKEN = 0Ah +EDGE_RAISED = BDR_RAISEDOUTER or BDR_RAISEDINNER +EDGE_SUNKEN = BDR_SUNKENOUTER or BDR_SUNKENINNER +EDGE_ETCHED = BDR_SUNKENOUTER or BDR_RAISEDINNER +EDGE_BUMP = BDR_RAISEDOUTER or BDR_SUNKENINNER + +; Border flags + +BF_LEFT = 0001h +BF_TOP = 0002h +BF_RIGHT = 0004h +BF_BOTTOM = 0008h +BF_TOPLEFT = BF_TOP or BF_LEFT +BF_TOPRIGHT = BF_TOP or BF_RIGHT +BF_BOTTOMLEFT = BF_BOTTOM or BF_LEFT +BF_BOTTOMRIGHT = BF_BOTTOM or BF_RIGHT +BF_RECT = BF_LEFT or BF_TOP or BF_RIGHT or BF_BOTTOM +BF_DIAGONAL = 0010h +BF_DIAGONAL_ENDTOPRIGHT = BF_DIAGONAL or BF_TOP or BF_RIGHT +BF_DIAGONAL_ENDTOPLEFT = BF_DIAGONAL or BF_TOP or BF_LEFT +BF_DIAGONAL_ENDBOTTOMLEFT = BF_DIAGONAL or BF_BOTTOM or BF_LEFT +BF_DIAGONAL_ENDBOTTOMRIGHT = BF_DIAGONAL or BF_BOTTOM or BF_RIGHT +BF_MIDDLE = 0800h +BF_SOFT = 1000h +BF_ADJUST = 2000h +BF_FLAT = 4000h +BF_MONO = 8000h + +; Frame control types + +DFC_CAPTION = 1 +DFC_MENU = 2 +DFC_SCROLL = 3 +DFC_BUTTON = 4 +DFC_POPUPMENU = 5 + +; Frame control states + +DFCS_CAPTIONCLOSE = 0000h +DFCS_CAPTIONMIN = 0001h +DFCS_CAPTIONMAX = 0002h +DFCS_CAPTIONRESTORE = 0003h +DFCS_CAPTIONHELP = 0004h +DFCS_MENUARROW = 0000h +DFCS_MENUCHECK = 0001h +DFCS_MENUBULLET = 0002h +DFCS_MENUARROWRIGHT = 0004h +DFCS_SCROLLUP = 0000h +DFCS_SCROLLDOWN = 0001h +DFCS_SCROLLLEFT = 0002h +DFCS_SCROLLRIGHT = 0003h +DFCS_SCROLLCOMBOBOX = 0005h +DFCS_SCROLLSIZEGRIP = 0008h +DFCS_SCROLLSIZEGRIPRIGHT = 0010h +DFCS_BUTTONCHECK = 0000h +DFCS_BUTTONRADIOIMAGE = 0001h +DFCS_BUTTONRADIOMASK = 0002h +DFCS_BUTTONRADIO = 0004h +DFCS_BUTTON3STATE = 0008h +DFCS_BUTTONPUSH = 0010h +DFCS_INACTIVE = 0100h +DFCS_PUSHED = 0200h +DFCS_CHECKED = 0400h +DFCS_TRANSPARENT = 0800h +DFCS_HOT = 1000h +DFCS_ADJUSTRECT = 2000h +DFCS_FLAT = 4000h +DFCS_MONO = 8000h + +; DrawCaption flags + +DC_ACTIVE = 01h +DC_SMALLCAP = 02h +DC_ICON = 04h +DC_TEXT = 08h +DC_INBUTTON = 10h + +; DrawIconEx options + +DI_MASK = 1 +DI_IMAGE = 2 +DI_NORMAL = 3 +DI_COMPAT = 4 +DI_DEFAULTSIZE = 8 + +; DrawText parameters + +DT_TOP = 00000h +DT_LEFT = 00000h +DT_CENTER = 00001h +DT_RIGHT = 00002h +DT_VCENTER = 00004h +DT_BOTTOM = 00008h +DT_WORDBREAK = 00010h +DT_SINGLELINE = 00020h +DT_EXPANDTABS = 00040h +DT_TABSTOP = 00080h +DT_NOCLIP = 00100h +DT_EXTERNALLEADING = 00200h +DT_CALCRECT = 00400h +DT_NOPREFIX = 00800h +DT_INTERNAL = 01000h +DT_EDITCONTROL = 02000h +DT_PATH_ELLIPSIS = 04000h +DT_END_ELLIPSIS = 08000h +DT_MODIFYSTRING = 10000h +DT_RTLREADING = 20000h +DT_WORD_ELLIPSIS = 40000h + +; GetDCEx flags + +DCX_WINDOW = 000001h +DCX_CACHE = 000002h +DCX_NORESETATTRS = 000004h +DCX_CLIPCHILDREN = 000008h +DCX_CLIPSIBLINGS = 000010h +DCX_PARENTCLIP = 000020h +DCX_EXCLUDERGN = 000040h +DCX_INTERSECTRGN = 000080h +DCX_EXCLUDEUPDATE = 000100h +DCX_INTERSECTUPDATE = 000200h +DCX_LOCKWINDOWUPDATE = 000400h +DCX_VALIDATE = 200000h + +; SetWindowsHook codes + +WH_MSGFILTER = -1 +WH_JOURNALRECORD = 0 +WH_JOURNALPLAYBACK = 1 +WH_KEYBOARD = 2 +WH_GETMESSAGE = 3 +WH_CALLWNDPROC = 4 +WH_CBT = 5 +WH_SYSMSGFILTER = 6 +WH_MOUSE = 7 +WH_HARDWARE = 8 +WH_DEBUG = 9 +WH_SHELL = 10 +WH_FOREGROUNDIDLE = 11 +WH_CALLWNDPROCRET = 12 +WH_KEYBOARD_LL = 13 +WH_MOUSE_LL = 14 + +; Hook codes + +HC_ACTION = 0 +HC_GETNEXT = 1 +HC_SKIP = 2 +HC_NOREMOVE = 3 +HC_SYSMODALON = 4 +HC_SYSMODALOFF = 5 + +; CBT hook codes + +HCBT_MOVESIZE = 0 +HCBT_MINMAX = 1 +HCBT_QS = 2 +HCBT_CREATEWND = 3 +HCBT_DESTROYWND = 4 +HCBT_ACTIVATE = 5 +HCBT_CLICKSKIPPED = 6 +HCBT_KEYSKIPPED = 7 +HCBT_SYSCOMMAND = 8 +HCBT_SETFOCUS = 9 + +; ExitWindowsEx flags + +EWX_LOGOFF = 0 +EWX_SHUTDOWN = 1 +EWX_REBOOT = 2 +EWX_FORCE = 4 +EWX_POWEROFF = 8 + +; WinHelp commands + +HELP_CONTEXT = 001h +HELP_QUIT = 002h +HELP_INDEX = 003h +HELP_CONTENTS = 003h +HELP_HELPONHELP = 004h +HELP_SETINDEX = 005h +HELP_SETCONTENTS = 005h +HELP_CONTEXTPOPUP = 008h +HELP_FORCEFILE = 009h +HELP_CONTEXTMENU = 00Ah +HELP_FINDER = 00Bh +HELP_WM_HELP = 00Ch +HELP_SETPOPUP_POS = 00Dh +HELP_KEY = 101h +HELP_COMMAND = 102h +HELP_PARTIALKEY = 105h +HELP_MULTIKEY = 201h +HELP_SETWINPOS = 203h + +; keybd_event flags + +KEYEVENTF_EXTENDEDKEY = 1h +KEYEVENTF_KEYUP = 2h + +; mouse_event flags + +MOUSEEVENTF_MOVE = 0001h +MOUSEEVENTF_LEFTDOWN = 0002h +MOUSEEVENTF_LEFTUP = 0004h +MOUSEEVENTF_RIGHTDOWN = 0008h +MOUSEEVENTF_RIGHTUP = 0010h +MOUSEEVENTF_MIDDLEDOWN = 0020h +MOUSEEVENTF_MIDDLEUP = 0040h +MOUSEEVENTF_WHEEL = 0800h +MOUSEEVENTF_ABSOLUTE = 8000h + +; TrackPopupMenu flags + +TPM_LEFTBUTTON = 0000h +TPM_RIGHTBUTTON = 0002h +TPM_LEFTALIGN = 0000h +TPM_CENTERALIGN = 0004h +TPM_RIGHTALIGN = 0008h +TPM_TOPALIGN = 0000h +TPM_VCENTERALIGN = 0010h +TPM_BOTTOMALIGN = 0020h +TPM_HORIZONTAL = 0000h +TPM_VERTICAL = 0040h +TPM_NONOTIFY = 0080h +TPM_RETURNCMD = 0100h +TPM_RECURSE = 0001h +TPM_HORPOSANIMATION = 0400h +TPM_HORNEGANIMATION = 0800h +TPM_VERPOSANIMATION = 1000h +TPM_VERNEGANIMATION = 2000h +TPM_NOANIMATION = 4000h +TPM_LAYOUTRTL = 8000h + +; Menu item info mask values + +MIIM_STATE = 001h +MIIM_ID = 002h +MIIM_SUBMENU = 004h +MIIM_CHECKMARKS = 008h +MIIM_TYPE = 010h +MIIM_DATA = 020h +MIIM_STRING = 040h +MIIM_BITMAP = 080h +MIIM_FTYPE = 100h + +; DRAWITEMSTRUCT control types + +ODT_MENU = 1 +ODT_LISTBOX = 2 +ODT_COMBOBOX = 3 +ODT_BUTTON = 4 +ODT_STATIC = 5 + +; DRAWITEMSTRUCT actions + +ODA_DRAWENTIRE = 1 +ODA_SELECT = 2 +ODA_FOCUS = 4 + +; DRAWITEMSTRUCT states + +ODS_SELECTED = 0001h +ODS_GRAYED = 0002h +ODS_DISABLED = 0004h +ODS_CHECKED = 0008h +ODS_FOCUS = 0010h +ODS_DEFAULT = 0020h +ODS_COMBOBOXEDIT = 1000h +ODS_HOTLIGHT = 0040h +ODS_INACTIVE = 0080h + +; WINDOWPLACEMENT flags + +WPF_SETMINPOSITION = 1 +WPF_RESTORETOMAXIMIZED = 2 + +; Layered window attributes + +LWA_COLORKEY = 1 +LWA_ALPHA = 2 + +; UpdateLayeredWindow flags + +ULW_COLORKEY = 1 +ULW_ALPHA = 2 +ULW_OPAQUE = 4 + +; SystemParametersInfo parameters + +SPI_GETACCESSTIMEOUT = 60 +SPI_GETANIMATION = 72 +SPI_GETBEEP = 1 +SPI_GETBORDER = 5 +SPI_GETDEFAULTINPUTLANG = 89 +SPI_GETDRAGFULLWINDOWS = 38 +SPI_GETFASTTASKSWITCH = 35 +SPI_GETFILTERKEYS = 50 +SPI_GETFONTSMOOTHING = 74 +SPI_GETGRIDGRANULARITY = 18 +SPI_GETHIGHCONTRAST = 66 +SPI_GETICONMETRICS = 45 +SPI_GETICONTITLELOGFONT = 31 +SPI_GETICONTITLEWRAP = 25 +SPI_GETKEYBOARDDELAY = 22 +SPI_GETKEYBOARDPREF = 68 +SPI_GETKEYBOARDSPEED = 10 +SPI_GETLOWPOWERACTIVE = 83 +SPI_GETLOWPOWERTIMEOUT = 79 +SPI_GETMENUDROPALIGNMENT = 27 +SPI_GETMINIMIZEDMETRICS = 43 +SPI_GETMOUSE = 3 +SPI_GETMOUSEKEYS = 54 +SPI_GETMOUSETRAILS = 94 +SPI_GETNONCLIENTMETRICS = 41 +SPI_GETPOWEROFFACTIVE = 84 +SPI_GETPOWEROFFTIMEOUT = 80 +SPI_GETSCREENREADER = 70 +SPI_GETSCREENSAVEACTIVE = 16 +SPI_GETSCREENSAVETIMEOUT = 14 +SPI_GETSERIALKEYS = 62 +SPI_GETSHOWSOUNDS = 56 +SPI_GETSOUNDSENTRY = 64 +SPI_GETSTICKYKEYS = 58 +SPI_GETTOGGLEKEYS = 52 +SPI_GETWINDOWSEXTENSION = 92 +SPI_GETWORKAREA = 48 +SPI_ICONHORIZONTALSPACING = 13 +SPI_ICONVERTICALSPACING = 24 +SPI_LANGDRIVER = 12 +SPI_SCREENSAVERRUNNING = 97 +SPI_SETACCESSTIMEOUT = 61 +SPI_SETANIMATION = 73 +SPI_SETBEEP = 2 +SPI_SETBORDER = 6 +SPI_SETDEFAULTINPUTLANG = 90 +SPI_SETDESKPATTERN = 21 +SPI_SETDESKWALLPAPER = 20 +SPI_SETDOUBLECLICKTIME = 32 +SPI_SETDOUBLECLKHEIGHT = 30 +SPI_SETDOUBLECLKWIDTH = 29 +SPI_SETDRAGFULLWINDOWS = 37 +SPI_SETDRAGHEIGHT = 77 +SPI_SETDRAGWIDTH = 76 +SPI_SETFASTTASKSWITCH = 36 +SPI_SETFILTERKEYS = 51 +SPI_SETFONTSMOOTHING = 75 +SPI_SETGRIDGRANULARITY = 19 +SPI_SETHANDHELD = 78 +SPI_SETHIGHCONTRAST = 67 +SPI_SETICONMETRICS = 46 +SPI_SETICONTITLELOGFONT = 34 +SPI_SETICONTITLEWRAP = 26 +SPI_SETKEYBOARDDELAY = 23 +SPI_SETKEYBOARDPREF = 69 +SPI_SETKEYBOARDSPEED = 11 +SPI_SETLANGTOGGLE = 91 +SPI_SETLOWPOWERACTIVE = 85 +SPI_SETLOWPOWERTIMEOUT = 81 +SPI_SETMENUDROPALIGNMENT = 28 +SPI_SETMINIMIZEDMETRICS = 44 +SPI_SETMOUSE = 4 +SPI_SETMOUSEBUTTONSWAP = 33 +SPI_SETMOUSEKEYS = 55 +SPI_SETMOUSETRAILS = 93 +SPI_SETNONCLIENTMETRICS = 42 +SPI_SETPENWINDOWS = 49 +SPI_SETPOWEROFFACTIVE = 86 +SPI_SETPOWEROFFTIMEOUT = 82 +SPI_SETSCREENREADER = 71 +SPI_SETSCREENSAVEACTIVE = 17 +SPI_SETSCREENSAVERRUNNING = 97 +SPI_SETSCREENSAVETIMEOUT = 15 +SPI_SETSERIALKEYS = 63 +SPI_SETSHOWSOUNDS = 57 +SPI_SETSOUNDSENTRY = 65 +SPI_SETSTICKYKEYS = 59 +SPI_SETTOGGLEKEYS = 53 +SPI_SETWORKAREA = 47 + +; SystemParametersInfo flags + +SPIF_UPDATEINIFILE = 1 +SPIF_SENDWININICHANGE = 2 + +; Gesture Information Flags + +GF_BEGIN = 1 +GF_INERTIA = 2 +GF_END = 4 + +; Gesture IDs + +GID_BEGIN = 1 +GID_END = 2 +GID_ZOOM = 3 +GID_PAN = 4 +GID_ROTATE = 5 +GID_TWOFINGERTAP = 6 +GID_PRESSANDTAP = 7 +GID_ROLLOVER = GID_PRESSANDTAP + +; Zoom Gesture Confiration Flags + +GC_ZOOM = 0x00000001 + +; Pan Gesture Configuration Flags + +GC_PAN = 0x00000001 +GC_PAN_WITH_SINGLE_FINGER_VERTICALLY = 0x00000002 +GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY = 0x00000004 +GC_PAN_WITH_GUTTER = 0x00000008 +GC_PAN_WITH_INERTIA = 0x00000010 + +; Rotate Gesture Configuration Flags + +GC_ROTATE = 0x00000001 + +; Two finger tap configuration flags + +GC_TWOFINGERTAP = 0x00000001 + +; Press and tap Configuration Flags + +GC_PRESSANDTAP = 0x00000001 +GC_ROLLOVER = GC_PRESSANDTAP diff --git a/toolchain/fasm2/include/equates/wsock32.inc b/toolchain/fasm2/include/equates/wsock32.inc new file mode 100644 index 0000000..4b16b8e --- /dev/null +++ b/toolchain/fasm2/include/equates/wsock32.inc @@ -0,0 +1,124 @@ + +; WSOCK32.DLL structures and constants + +struct WSADATA + wVersion dw ? + wHighVersion dw ? + szDescription db 256+1 dup (?) + szSystemStatus db 128+1 dup (?) + iMaxSockets dw ? + iMaxUdpDg dw ? + _padding_ db 2 dup (?) + lpVendorInfo dd ? +ends + +struct hostent + h_name dd ? + h_aliases dd ? + h_addrtype dw ? + h_length dw ? + h_addr_list dd ? +ends + +struct sockaddr_in + sin_family dw ? + sin_port dw ? + sin_addr dd ? + sin_zero db 8 dup (?) +ends + +struct sockaddr + sa_family dw ? + sa_data db 14 dup (?) +ends + +; Socket types + +SOCK_STREAM = 1 +SOCK_DGRAM = 2 +SOCK_RAW = 3 +SOCK_RDM = 4 +SOCK_SEQPACKET = 5 + +; Address formats + +AF_UNSPEC = 0 +AF_UNIX = 1 +AF_INET = 2 +AF_IMPLINK = 3 +AF_PUP = 4 +AF_CHAOS = 5 +AF_NS = 6 +AF_IPX = 6 +AF_ISO = 7 +AF_OSI = AF_ISO +AF_ECMA = 8 +AF_DATAKIT = 9 +AF_CCITT = 10 +AF_SNA = 11 +AF_DECnet = 12 +AF_DLI = 13 +AF_LAT = 14 +AF_HYLINK = 15 +AF_APPLETALK = 16 +AF_NETBIOS = 17 + +; Protocol formats + +PF_UNSPEC = 0 +PF_UNIX = 1 +PF_INET = 2 +PF_IMPLINK = 3 +PF_PUP = 4 +PF_CHAOS = 5 +PF_NS = 6 +PF_IPX = 6 +PF_ISO = 7 +PF_OSI = PF_ISO +PF_ECMA = 8 +PF_DATAKIT = 9 +PF_CCITT = 10 +PF_SNA = 11 +PF_DECnet = 12 +PF_DLI = 13 +PF_LAT = 14 +PF_HYLINK = 15 +PF_APPLETALK = 16 +PF_NETBIOS = 17 + +; IP Ports + +IPPORT_ECHO = 7 +IPPORT_DISCARD = 9 +IPPORT_SYSTAT = 11 +IPPORT_DAYTIME = 13 +IPPORT_NETSTAT = 15 +IPPORT_FTP = 21 +IPPORT_TELNET = 23 +IPPORT_SMTP = 25 +IPPORT_TIMESERVER = 37 +IPPORT_NAMESERVER = 42 +IPPORT_WHOIS = 43 +IPPORT_MTP = 57 +IPPORT_TFTP = 69 +IPPORT_RJE = 77 +IPPORT_FINGER = 79 +IPPORT_TTYLINK = 87 +IPPORT_SUPDUP = 95 +IPPORT_EXECSERVER = 512 +IPPORT_LOGINSERVER = 513 +IPPORT_CMDSERVER = 514 +IPPORT_EFSSERVER = 520 +IPPORT_BIFFUDP = 512 +IPPORT_WHOSERVER = 513 +IPPORT_ROUTESERVER = 520 +IPPORT_RESERVED = 1024 + +; Notifications + +FD_READ = 01h +FD_WRITE = 02h +FD_OOB = 04h +FD_ACCEPT = 08h +FD_CONNECT = 10h +FD_CLOSE = 20h diff --git a/toolchain/fasm2/include/fasm2.inc b/toolchain/fasm2/include/fasm2.inc new file mode 100644 index 0000000..b1b7d85 --- /dev/null +++ b/toolchain/fasm2/include/fasm2.inc @@ -0,0 +1,9 @@ +include 'dd.inc' +include 'align.inc' +include 'format.inc' +include 'x86-2.inc' +use everything + +include '@@.inc' +include 'times.inc' +include 'fix.inc' \ No newline at end of file diff --git a/toolchain/fasm2/include/fix.inc b/toolchain/fasm2/include/fix.inc new file mode 100644 index 0000000..c7b4ef0 --- /dev/null +++ b/toolchain/fasm2/include/fix.inc @@ -0,0 +1,31 @@ + +define fix? fix? + +fix... = 0 + +calminstruction (name) fix? &value& + arrange name, fix.name + publish name, value + check fix... + jyes done + compute fix..., 1 + arrange name, fix.=enable + assemble name + done: +end calminstruction + +macro fix?.enable? chain + chain + macro include?! file*, head + include file, fix.enable head + purge ?, include? + end macro + calminstruction ?! &line& + local any + match any =fix? any?, line + jyes skip + transform line, fix + skip: + assemble line + end calminstruction +end macro diff --git a/toolchain/fasm2/include/format.inc b/toolchain/fasm2/include/format.inc new file mode 100644 index 0000000..1b87a34 --- /dev/null +++ b/toolchain/fasm2/include/format.inc @@ -0,0 +1,381 @@ + +define format? format.extension + +calminstruction format? statement* + local ext + match statement =as? ext, statement + jno pass + publish format:, ext + pass: + arrange statement, =format statement + assemble statement +end calminstruction + +postpone + if definite format + format.binary as format + end if +end postpone + +macro local_include? instr + local pos,chr,path + pos = lengthof __FILE__ + while pos + chr = (__FILE__ shr (8*(pos-1))) and 0FFh + if chr = '/' | chr = '\' + break + end if + pos = pos - 1 + end while + path = string __FILE__ and not ( (-1) shl (8*pos) ) + macro instr file + include path bappend file + end macro +end macro + +local_include __include + +macro format?.MZ? + if ~ definite format + format binary as 'exe' + end if + __include 'format/mz.inc' +end macro + +macro format?.PE? settings + PE.Settings.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED + PE.Settings.DllCharacteristics = 0 + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI + local seq + define seq settings: + while 1 + match :, seq + break + else match =DLL? more, seq + PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_DLL + redefine seq more + else match =large? more, seq + PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_LARGE_ADDRESS_AWARE + redefine seq more + else match =WDM? more, seq + PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_WDM_DRIVER + redefine seq more + else match =NX? more, seq + PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_NX_COMPAT + redefine seq more + else match =at? base =on? stub :, seq + PE.Settings.ImageBase = base + PE.Settings.Stub = stub + break + else match =at? base :, seq + PE.Settings.ImageBase = base + break + else match =on? stub :, seq + PE.Settings.Stub = stub + break + else + match =GUI? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI + redefine seq more + else match =console? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI + redefine seq more + else match =native? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_NATIVE + PE.Settings.SectionAlignment = 32 + PE.Settings.FileAlignment = 32 + redefine seq more + else match =EFI? more, seq + PE.Settings.Magic = 0x20B + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION + redefine seq more + else match =EFIboot? more, seq + PE.Settings.Magic = 0x20B + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER + redefine seq more + else match =EFIruntime? more, seq + PE.Settings.Magic = 0x20B + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER + redefine seq more + else + err 'invalid argument' + break + end match + match V.v more, seq + PE.Settings.MajorSubsystemVersion = V + PE.Settings.MinorSubsystemVersion = v + redefine seq more + end match + end match + end while + if ~ definite format + if PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION | PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER | PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER + format binary as 'efi' + else if PE.Settings.Characteristics and IMAGE_FILE_DLL + format binary as 'dll' + else + format binary as 'exe' + end if + end if + __include 'format/pe.inc' + use32 +end macro + +macro format?.PE64? settings + PE.Settings.Magic = 0x20B + PE.Settings.Machine = IMAGE_FILE_MACHINE_AMD64 + PE.Settings.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_LARGE_ADDRESS_AWARE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED + PE.Settings.DllCharacteristics = 0 + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI + PE.Settings.MajorSubsystemVersion = 5 + PE.Settings.MinorSubsystemVersion = 0 + local seq + define seq settings: + while 1 + match :, seq + break + else match =DLL? more, seq + PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_DLL + redefine seq more + else match =WDM? more, seq + PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_WDM_DRIVER + redefine seq more + else match =NX? more, seq + PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_NX_COMPAT + redefine seq more + else match =at? base =on? stub :, seq + PE.Settings.ImageBase = base + PE.Settings.Stub = stub + break + else match =at? base :, seq + PE.Settings.ImageBase = base + break + else match =on? stub :, seq + PE.Settings.Stub = stub + break + else + match =GUI? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI + redefine seq more + else match =console? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI + redefine seq more + else match =native? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_NATIVE + PE.Settings.SectionAlignment = 32 + PE.Settings.FileAlignment = 32 + redefine seq more + else match =EFI? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION + redefine seq more + else match =EFIboot? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER + redefine seq more + else match =EFIruntime? more, seq + PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER + redefine seq more + else + err 'invalid argument' + break + end match + match V.v more, seq + PE.Settings.MajorSubsystemVersion = V + PE.Settings.MinorSubsystemVersion = v + redefine seq more + end match + end match + end while + if ~ definite format + if PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION | PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER | PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER + format binary as 'efi' + else if PE.Settings.Characteristics and IMAGE_FILE_DLL + format binary as 'dll' + else + format binary as 'exe' + end if + end if + __include 'format/pe.inc' + use64 +end macro + +macro format?.ELF? variant + match , variant + if ~ definite format + format binary as 'o' + end if + __include 'format/elf32.inc' + use32 + else match =executable? settings, variant: + match brand =at? base:, settings + ELF.Settings.ABI = brand + ELF.Settings.BaseAddress = base + else match =at? base:, settings + ELF.Settings.BaseAddress = base + else match brand:, settings + ELF.Settings.ABI = brand + end match + __include 'format/elfexe.inc' + use32 + else match =dynamic? settings, variant: + ELF.Settings.Type = ET_DYN + match brand =at? base:, settings + ELF.Settings.ABI = brand + ELF.Settings.BaseAddress = base + else match =at? base:, settings + ELF.Settings.BaseAddress = base + else match brand:, settings + ELF.Settings.ABI = brand + end match + __include 'format/elfexe.inc' + use32 + else + err 'invalid argument' + end match +end macro + +macro format?.ELF64? variant + match , variant + if ~ definite format + format binary as 'o' + end if + __include 'format/elf64.inc' + use64 + else match =executable? settings, variant: + ELF.Settings.Class = ELFCLASS64 + ELF.Settings.Machine = EM_X86_64 + ELF.Settings.BaseAddress = 400000h + match brand =at? base:, settings + ELF.Settings.ABI = brand + ELF.Settings.BaseAddress = base + else match =at? base:, settings + ELF.Settings.BaseAddress = base + else match brand:, settings + ELF.Settings.ABI = brand + end match + __include 'format/elfexe.inc' + use64 + else match =dynamic? settings, variant: + ELF.Settings.Class = ELFCLASS64 + ELF.Settings.Type = ET_DYN + ELF.Settings.Machine = EM_X86_64 + ELF.Settings.BaseAddress = 400000h + match brand =at? base:, settings + ELF.Settings.ABI = brand + ELF.Settings.BaseAddress = base + else match =at? base:, settings + ELF.Settings.BaseAddress = base + else match brand:, settings + ELF.Settings.ABI = brand + end match + __include 'format/elfexe.inc' + use64 + else + err 'invalid argument' + end match +end macro + +macro format?.ELFx32? variant + match , variant + if ~ definite format + format binary as 'o' + end if + ELF.Settings.Machine = EM_X86_64 + __include 'format/elf32.inc' + use64 + else match =executable? settings, variant: + ELF.Settings.Class = ELFCLASS32 + ELF.Settings.Machine = EM_X86_64 + ELF.Settings.BaseAddress = 400000h + match brand =at? base:, settings + ELF.Settings.ABI = brand + ELF.Settings.BaseAddress = base + else match =at? base:, settings + ELF.Settings.BaseAddress = base + else match brand:, settings + ELF.Settings.ABI = brand + end match + __include 'format/elfexe.inc' + use64 + else + err 'invalid argument' + end match +end macro + +macro format?.COFF? + if ~ definite format + format binary as 'obj' + end if + __include 'format/coff.inc' + use32 +end macro + +macro format?.MS? variant + match =COFF?, variant + if ~ definite format + format binary as 'obj' + end if + COFF.Settings.Characteristics = IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_BYTES_REVERSED_LO + __include 'format/coffms.inc' + use32 + else + err 'invalid argument' + end match +end macro + +macro format?.MS64? variant + match =COFF?, variant + if ~ definite format + format binary as 'obj' + end if + COFF.Settings.Machine = IMAGE_FILE_MACHINE_AMD64 + COFF.Settings.Characteristics = IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_BYTES_REVERSED_LO + __include 'format/coffms.inc' + use64 + else + err 'invalid argument' + end match +end macro + +macro format?.MachO? variant + match , variant + if ~ definite format + format binary as 'o' + end if + MachO.Settings.FileType equ MH_OBJECT + __include 'format/macho.inc' + use32 + else match =executable?, variant + MachO.Settings.BaseAddress = 0x1000 + __include 'format/macho.inc' + use32 + else match =executable? at? base, variant + MachO.Settings.BaseAddress = base + __include 'format/macho.inc' + use32 + else + err 'invalid argument' + end match +end macro + +macro format?.MachO64? variant + MachO.Settings.ProcessorType equ CPU_TYPE_X86_64 + MachO.Settings.ProcessorSubtype equ CPU_SUBTYPE_X86_64_ALL + match , variant + if ~ definite format + format binary as 'o' + end if + MachO.Settings.FileType equ MH_OBJECT + __include 'format/macho.inc' + use64 + else match =executable?, variant + MachO.Settings.BaseAddress = 0x100000000 + __include 'format/macho.inc' + use64 + else match =executable? =at? base, variant + MachO.Settings.BaseAddress = base + __include 'format/macho.inc' + use64 + else + err 'invalid argument' + end match +end macro diff --git a/toolchain/fasm2/include/format/coff.inc b/toolchain/fasm2/include/format/coff.inc new file mode 100644 index 0000000..3dc7824 --- /dev/null +++ b/toolchain/fasm2/include/format/coff.inc @@ -0,0 +1,403 @@ + +macro struct? name + macro end?.struct?! + end namespace + esc end struc + virtual at 0 + name name + sizeof.name = $ + end virtual + purge end?.struct? + end macro + esc struc name + label . : sizeof.name + namespace . +end macro + +struct SCNHDR + s_name db 8 dup ? + s_paddr dd ? + s_vaddr dd ? + s_size dd ? + s_scnptr dd ? + s_relptr dd ? + s_lnnoptr dd ? + s_nreloc dw ? + s_nlnno dw ? + s_flags dd ? +end struct + +SCNHSZ = sizeof SCNHDR + +struct RELOC + r_vaddr dd ? + r_symndx dd ? + r_type dw ? +end struct + +RELSZ = sizeof RELOC + +struct SYMENT + e_name db 8 dup ? + virtual at e_name + e_zeroes dd ? + e_offset dd ? + end virtual + e_value dd ? + e_scnum dw ? + e_type dw ? + e_sclass db ? + e_numaux db ? +end struct + +SYMESZ = sizeof SYMENT + +I386MAGIC = 0x14c + +F_RELFLG = 0x0001 +F_EXEC = 0x0002 +F_LNNO = 0x0004 +F_LSYMS = 0x0008 +F_AR32WR = 0x0100 + +STYP_TEXT = 0x0020 +STYP_DATA = 0x0040 +STYP_BSS = 0x0080 + +N_UNDEF = 0 +N_ABS = -1 +N_DEBUG = -2 + +T_NULL = 0000b +T_VOID = 0001b +T_CHAR = 0010b +T_SHORT = 0011b +T_INT = 0100b +T_LONG = 0101b +T_FLOAT = 0110b +T_DOUBLE = 0111b +T_STRUCT = 1000b +T_UNION = 1001b +T_ENUM = 1010b +T_MOE = 1011b +T_UCHAR = 1100b +T_USHORT = 1101b +T_UINT = 1110b +T_ULONG = 1111b +T_LNGDBL = 01_0000b + +DT_NON = 00b +DT_PTR = 01b +DT_FCN = 10b +DT_ARY = 11b + +C_NULL = 0 +C_AUTO = 1 +C_EXT = 2 +C_STAT = 3 +C_REG = 4 +C_EXTDEF = 5 +C_LABEL = 6 +C_ULABEL = 7 +C_MOS = 8 +C_ARG = 9 +C_STRTAG = 10 +C_MOU = 11 +C_UNTAG = 12 +C_TPDEF = 13 +C_USTATIC = 14 +C_ENTAG = 15 +C_MOE = 16 +C_REGPARM = 17 +C_FIELD = 18 +C_AUTOARG = 19 +C_LASTENT = 20 +C_BLOCK = 100 +C_FCN = 101 +C_EOS = 102 +C_FILE = 103 +C_LINE = 104 +C_ALIAS = 105 +C_HIDDEN = 106 +C_EFCN = 255 + +RELOC_ADDR32 = 6 +RELOC_REL32 = 20 + +COFF:: + +namespace COFF + + Header: + + f_magic dw I386MAGIC + f_nscns dw NUMBER_OF_SECTIONS + f_timdat dd __TIME__ + f_symptr dd SYMBOL_TABLE_OFFSET + f_nsyms dd NUMBER_OF_SYMBOLS + f_opthdr dw 0 + f_flags dw F_AR32WR + F_LNNO + + Sections: db NUMBER_OF_SECTIONS * SCNHSZ dup 0 + + virtual at 0 + symbol_table:: rb NUMBER_OF_SYMBOLS * SYMESZ + end virtual + + virtual at 0 + string_table:: dd STRING_TABLE_SIZE + STRING_POSITION = $ + rb STRING_TABLE_SIZE - $ + end virtual + + virtual at 0 + relocations:: rb NUMBER_OF_RELOCATIONS * RELSZ + end virtual + + element relocatable? + + macro section_start + local sym + element sym : relocatable * (1+SECTION_INDEX) + SYMBOL_INDEX + SECTION_BASE = sym + org sym + align.assume sym, SECTION_ALIGN + if DEFINED_SECTION | defined DEFAULT_SECTION + store SECTION_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name + store C_STAT at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass + store 1+SECTION_INDEX at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_scnum + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end if + end macro + + RELOCATION_INDEX = 0 + SECTION_INDEX = 0 + SECTION_RELOCATION_INDEX = RELOCATION_INDEX + SYMBOL_INDEX = 0 + + SECTION_OFFSET = $% + SECTION_ALIGN = 4 + SECTION_NAME = '.flat' + SECTION_FLAGS = STYP_TEXT + STYP_DATA + DEFINED_SECTION = 0 + section_start + +end namespace + +macro section? + namespace COFF + + SECTION_SIZE = $% - SECTION_OFFSET + + if DEFINED_SECTION | SECTION_SIZE > 0 + + if ~ DEFINED_SECTION + DEFAULT_SECTION := 1 + end if + + if $%% = SECTION_OFFSET + SECTION_FLAGS = SECTION_FLAGS or STYP_BSS + SECTION_OFFSET = 0 + section $ + else + UNINITIALIZED_LENGTH = $% - $%% + section $ + db UNINITIALIZED_LENGTH dup 0 + end if + + store SECTION_NAME : 8 at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_name + store SECTION_OFFSET at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_scnptr + store SECTION_SIZE at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_size + store SECTION_FLAGS at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_flags + + if RELOCATION_INDEX > SECTION_RELOCATION_INDEX + store RELOCATION_INDEX - SECTION_RELOCATION_INDEX at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_nreloc + store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * RELSZ at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_relptr + end if + + SECTION_INDEX = SECTION_INDEX + 1 + + end if + + end namespace +end macro + +macro section? declaration* + namespace COFF + + section + + DEFINED_SECTION = 1 + SECTION_FLAGS = 0 + SECTION_OFFSET = $% + SECTION_ALIGN = 4 + + match name attributes, declaration + + SECTION_NAME = name + + local seq,list + define seq attributes + while 1 + match car cdr, seq + define list car + define seq cdr + else + match any, seq + define list any + end match + break + end match + end while + irpv attribute, list + match =code?, attribute + SECTION_FLAGS = SECTION_FLAGS or STYP_TEXT + else match =data?, attribute + SECTION_FLAGS = SECTION_FLAGS or STYP_DATA + else + err 'unknown attribute "',`attribute,'"' + end match + end irpv + + else + + SECTION_NAME = declaration + + end match + + section_start + + SECTION_RELOCATION_INDEX = RELOCATION_INDEX + + end namespace +end macro + +macro public? declaration* + namespace COFF + match =static? value =as? str, declaration + SYMBOL_VALUE = value + SYMBOL_NAME = string str + SYMBOL_CLASS = C_STAT + else match value =as? str, declaration + SYMBOL_VALUE = value + SYMBOL_NAME = string str + SYMBOL_CLASS = C_EXT + else match =static? value, declaration + SYMBOL_VALUE = value + SYMBOL_NAME = `value + SYMBOL_CLASS = C_STAT + else + SYMBOL_VALUE = declaration + SYMBOL_NAME = `declaration + SYMBOL_CLASS = C_EXT + end match + if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & 1 scaleof (1 metadataof SYMBOL_VALUE) > 0 + SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE) + SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE + else + SYMBOL_SECTION_INDEX = N_ABS + end if + if lengthof SYMBOL_NAME > 8 + store 0 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_zeroes + store STRING_POSITION at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_offset + store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION + STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1 + else + store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name + end if + store SYMBOL_VALUE at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_value + store SYMBOL_SECTION_INDEX at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_scnum + store SYMBOL_CLASS at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end namespace +end macro + +macro extrn? declaration* + namespace COFF + local sym,psym + element sym : relocatable * (-1) + SYMBOL_INDEX + match str =as? name:size, declaration + label name:size at sym + SYMBOL_NAME = string str + else match name:size, declaration + label name:size at sym + SYMBOL_NAME = `name + else match str =as? name, declaration + label name at sym + SYMBOL_NAME = string str + else + label declaration at sym + SYMBOL_NAME = `declaration + end match + if lengthof SYMBOL_NAME > 8 + store 0 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_zeroes + store STRING_POSITION at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_offset + store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION + STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1 + else + store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name + end if + store C_EXT at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end namespace +end macro + +calminstruction dword? value + compute value, value + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable + jyes addr32 + check ~ value relativeto 0 & (value + COFF.SECTION_BASE) relativeto 1 elementof (value + COFF.SECTION_BASE) + jno plain + check 1 elementof (1 metadataof (value + COFF.SECTION_BASE)) relativeto COFF.relocatable + jyes rel32 + plain: + emit 4, value + exit + local offset, symndx, type + addr32: + compute symndx, 0 scaleof (1 metadataof value) + compute type, RELOC_ADDR32 + jump add_relocation + rel32: + compute value, value + COFF.SECTION_BASE + compute symndx, 0 scaleof (1 metadataof value) + compute type, RELOC_REL32 + jump add_relocation + add_relocation: + compute offset, $% + emit 4, 0 scaleof value + check $% > offset + jno done + compute offset, offset - COFF.SECTION_OFFSET + local reloc + compute reloc, COFF.RELOCATION_INDEX * RELSZ + asm store offset at COFF.relocations : reloc + RELOC.r_vaddr + asm store symndx at COFF.relocations : reloc + RELOC.r_symndx + asm store type at COFF.relocations : reloc + RELOC.r_type + compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1 + done: +end calminstruction + +postpone + purge section? + section + namespace COFF + + NUMBER_OF_SECTIONS := SECTION_INDEX + STRING_TABLE_SIZE := STRING_POSITION + NUMBER_OF_SYMBOLS := SYMBOL_INDEX + NUMBER_OF_RELOCATIONS := RELOCATION_INDEX + + RELOCATIONS_OFFSET = $% + load byte_sequence : NUMBER_OF_RELOCATIONS * RELSZ from relocations:0 + db byte_sequence + + SYMBOL_TABLE_OFFSET = $% + load byte_sequence : NUMBER_OF_SYMBOLS * SYMESZ from symbol_table:0 + db byte_sequence + + load byte_sequence : STRING_TABLE_SIZE from string_table:0 + db byte_sequence + + end namespace +end postpone diff --git a/toolchain/fasm2/include/format/coffms.inc b/toolchain/fasm2/include/format/coffms.inc new file mode 100644 index 0000000..89d9a9c --- /dev/null +++ b/toolchain/fasm2/include/format/coffms.inc @@ -0,0 +1,684 @@ + +macro struct? name + macro end?.struct?! + end namespace + esc end struc + virtual at 0 + name name + sizeof.name = $ + end virtual + purge end?.struct? + end macro + esc struc name + label . : sizeof.name + namespace . +end macro + +struct IMAGE_SECTION_HEADER + Name db 8 dup ? + VirtualSize dd ? + VirtualAddress dd ? + SizeOfRawData dd ? + PointerToRawData dd ? + PointerToRelocations dd ? + PointerToLinenumbers dd ? + NumberOfRelocations dw ? + NumberOfLinenumbers dw ? + Characteristics dd ? +end struct + +struct IMAGE_RELOCATION + VirtualAddress dd ? + SymbolTableIndex dd ? + Type dw ? +end struct + +struct IMAGE_SYMBOL + ShortName db 8 dup ? + virtual at ShortName + Zeroes dd ? + Offset dd ? + end virtual + Value dd ? + SectionNumber dw ? + Type dw ? + StorageClass db ? + NumberOfAuxSymbols db ? +end struct + +IMAGE_FILE_MACHINE_UNKNOWN = 0x0 +IMAGE_FILE_MACHINE_AM33 = 0x1D3 +IMAGE_FILE_MACHINE_AMD64 = 0x8664 +IMAGE_FILE_MACHINE_ARM = 0x1C0 +IMAGE_FILE_MACHINE_ARMNT = 0x1C4 +IMAGE_FILE_MACHINE_ARM64 = 0xAA64 +IMAGE_FILE_MACHINE_EBC = 0xEBC +IMAGE_FILE_MACHINE_I386 = 0x14C +IMAGE_FILE_MACHINE_IA64 = 0x200 +IMAGE_FILE_MACHINE_M32R = 0x9041 +IMAGE_FILE_MACHINE_MIPS16 = 0x266 +IMAGE_FILE_MACHINE_MIPSFPU = 0x366 +IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466 +IMAGE_FILE_MACHINE_POWERPC = 0x1F0 +IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1 +IMAGE_FILE_MACHINE_R4000 = 0x166 +IMAGE_FILE_MACHINE_SH3 = 0x1A2 +IMAGE_FILE_MACHINE_SH3DSP = 0x1A3 +IMAGE_FILE_MACHINE_SH4 = 0x1A6 +IMAGE_FILE_MACHINE_SH5 = 0x1A8 +IMAGE_FILE_MACHINE_THUMB = 0x1C2 +IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169 + +IMAGE_FILE_RELOCS_STRIPPED = 0x0001 +IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 +IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 +IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 +IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010 +IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 +IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 +IMAGE_FILE_32BIT_MACHINE = 0x0100 +IMAGE_FILE_DEBUG_STRIPPED = 0x0200 +IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 +IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 +IMAGE_FILE_SYSTEM = 0x1000 +IMAGE_FILE_DLL = 0x2000 +IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 +IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 + +IMAGE_SCN_TYPE_NO_PAD = 0x00000008 +IMAGE_SCN_CNT_CODE = 0x00000020 +IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 +IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 +IMAGE_SCN_LNK_OTHER = 0x00000100 +IMAGE_SCN_LNK_INFO = 0x00000200 +IMAGE_SCN_LNK_REMOVE = 0x00000800 +IMAGE_SCN_LNK_COMDAT = 0x00001000 +IMAGE_SCN_GPREL = 0x00008000 +IMAGE_SCN_MEM_PURGEABLE = 0x00020000 +IMAGE_SCN_MEM_16BIT = 0x00020000 +IMAGE_SCN_MEM_LOCKED = 0x00040000 +IMAGE_SCN_MEM_PRELOAD = 0x00080000 +IMAGE_SCN_ALIGN_1BYTES = 0x00100000 +IMAGE_SCN_ALIGN_2BYTES = 0x00200000 +IMAGE_SCN_ALIGN_4BYTES = 0x00300000 +IMAGE_SCN_ALIGN_8BYTES = 0x00400000 +IMAGE_SCN_ALIGN_16BYTES = 0x00500000 +IMAGE_SCN_ALIGN_32BYTES = 0x00600000 +IMAGE_SCN_ALIGN_64BYTES = 0x00700000 +IMAGE_SCN_ALIGN_128BYTES = 0x00800000 +IMAGE_SCN_ALIGN_256BYTES = 0x00900000 +IMAGE_SCN_ALIGN_512BYTES = 0x00A00000 +IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000 +IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000 +IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000 +IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000 +IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000 +IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 +IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 +IMAGE_SCN_MEM_NOT_PAGED = 0x08000000 +IMAGE_SCN_MEM_SHARED = 0x10000000 +IMAGE_SCN_MEM_EXECUTE = 0x20000000 +IMAGE_SCN_MEM_READ = 0x40000000 +IMAGE_SCN_MEM_WRITE = 0x80000000 + +IMAGE_REL_AMD64_ABSOLUTE = 0x0000 +IMAGE_REL_AMD64_ADDR64 = 0x0001 +IMAGE_REL_AMD64_ADDR32 = 0x0002 +IMAGE_REL_AMD64_ADDR32NB = 0x0003 +IMAGE_REL_AMD64_REL32 = 0x0004 +IMAGE_REL_AMD64_REL32_1 = 0x0005 +IMAGE_REL_AMD64_REL32_2 = 0x0006 +IMAGE_REL_AMD64_REL32_3 = 0x0007 +IMAGE_REL_AMD64_REL32_4 = 0x0008 +IMAGE_REL_AMD64_REL32_5 = 0x0009 +IMAGE_REL_AMD64_SECTION = 0x000A +IMAGE_REL_AMD64_SECREL = 0x000B +IMAGE_REL_AMD64_SECREL7 = 0x000C +IMAGE_REL_AMD64_TOKEN = 0x000D +IMAGE_REL_AMD64_SREL32 = 0x000E +IMAGE_REL_AMD64_PAIR = 0x000F +IMAGE_REL_AMD64_SSPAN32 = 0x0010 + +IMAGE_REL_I386_ABSOLUTE = 0x0000 +IMAGE_REL_I386_DIR16 = 0x0001 +IMAGE_REL_I386_REL16 = 0x0002 +IMAGE_REL_I386_DIR32 = 0x0006 +IMAGE_REL_I386_DIR32NB = 0x0007 +IMAGE_REL_I386_SEG12 = 0x0009 +IMAGE_REL_I386_SECTION = 0x000A +IMAGE_REL_I386_SECREL = 0x000B +IMAGE_REL_I386_TOKEN = 0x000C +IMAGE_REL_I386_SECREL7 = 0x000D +IMAGE_REL_I386_REL32 = 0x0014 + +IMAGE_SYM_UNDEFINED = 0 +IMAGE_SYM_ABSOLUTE = -1 +IMAGE_SYM_DEBUG = -2 + +IMAGE_SYM_TYPE_NULL = 0 +IMAGE_SYM_TYPE_VOID = 1 +IMAGE_SYM_TYPE_CHAR = 2 +IMAGE_SYM_TYPE_SHORT = 3 +IMAGE_SYM_TYPE_INT = 4 +IMAGE_SYM_TYPE_LONG = 5 +IMAGE_SYM_TYPE_FLOAT = 6 +IMAGE_SYM_TYPE_DOUBLE = 7 +IMAGE_SYM_TYPE_STRUCT = 8 +IMAGE_SYM_TYPE_UNION = 9 +IMAGE_SYM_TYPE_ENUM = 10 +IMAGE_SYM_TYPE_MOE = 11 +IMAGE_SYM_TYPE_BYTE = 12 +IMAGE_SYM_TYPE_WORD = 13 +IMAGE_SYM_TYPE_UINT = 14 +IMAGE_SYM_TYPE_DWORD = 15 + +IMAGE_SYM_DTYPE_NULL = 0 +IMAGE_SYM_DTYPE_POINTER = 1 +IMAGE_SYM_DTYPE_FUNCTION = 2 +IMAGE_SYM_DTYPE_ARRAY = 3 + +IMAGE_SYM_CLASS_END_OF_FUNCTION = -1 +IMAGE_SYM_CLASS_NULL = 0 +IMAGE_SYM_CLASS_AUTOMATIC = 1 +IMAGE_SYM_CLASS_EXTERNAL = 2 +IMAGE_SYM_CLASS_STATIC = 3 +IMAGE_SYM_CLASS_REGISTER = 4 +IMAGE_SYM_CLASS_EXTERNAL_DEF = 5 +IMAGE_SYM_CLASS_LABEL = 6 +IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7 +IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8 +IMAGE_SYM_CLASS_ARGUMENT = 9 +IMAGE_SYM_CLASS_STRUCT_TAG = 10 +IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11 +IMAGE_SYM_CLASS_UNION_TAG = 12 +IMAGE_SYM_CLASS_TYPE_DEFINITION = 13 +IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14 +IMAGE_SYM_CLASS_ENUM_TAG = 15 +IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16 +IMAGE_SYM_CLASS_REGISTER_PARAM = 17 +IMAGE_SYM_CLASS_BIT_FIELD = 18 +IMAGE_SYM_CLASS_BLOCK = 100 +IMAGE_SYM_CLASS_FUNCTION = 101 +IMAGE_SYM_CLASS_END_OF_STRUCT = 102 +IMAGE_SYM_CLASS_FILE = 103 +IMAGE_SYM_CLASS_SECTION = 104 +IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105 +IMAGE_SYM_CLASS_CLR_TOKEN = 107 + +IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1 +IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2 +IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 + +COFF:: + +namespace COFF + + if defined Settings.Machine + MACHINE := Settings.Machine + else + MACHINE := IMAGE_FILE_MACHINE_I386 + end if + + if defined Settings.Characteristics + CHARACTERISTICS = Settings.Characteristics + else + CHARACTERISTICS = IMAGE_FILE_32BIT_MACHINE + end if + + Header: + + Machine dw MACHINE + NumberOfSections dw NUMBER_OF_SECTIONS + TimeDateStamp dd __TIME__ + PointerToSymbolTable dd SYMBOL_TABLE_OFFSET + NumberOfSymbols dd NUMBER_OF_SYMBOLS + SizeOfOptionalHeader dw 0 + Characteristics dw CHARACTERISTICS + + Sections: db NUMBER_OF_SECTIONS * sizeof IMAGE_SECTION_HEADER dup 0 + + virtual at 0 + symbol_table:: rb NUMBER_OF_SYMBOLS * sizeof IMAGE_SYMBOL + end virtual + + virtual at 0 + string_table:: dd STRING_TABLE_SIZE + STRING_POSITION = $ + rb STRING_TABLE_SIZE - $ + end virtual + + virtual at 0 + relocations:: rb NUMBER_OF_RELOCATIONS * sizeof IMAGE_RELOCATION + end virtual + + element relocatable? + + macro section_start + local sym + element sym : relocatable * (1+SECTION_INDEX) + SYMBOL_INDEX + SECTION_BASE = sym + org sym + align.assume sym, SECTION_ALIGN + if DEFINED_SECTION | defined DEFAULT_SECTION + store SECTION_NAME : 8 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.ShortName + store IMAGE_SYM_CLASS_STATIC at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.StorageClass + store 1+SECTION_INDEX at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.SectionNumber + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end if + end macro + + RELOCATION_INDEX = 0 + SECTION_INDEX = 0 + SECTION_RELOCATION_INDEX = RELOCATION_INDEX + SYMBOL_INDEX = 0 + + SECTION_OFFSET = $% + SECTION_ALIGN = 4 + SECTION_NAME = '.flat' + SECTION_FLAGS = IMAGE_SCN_CNT_CODE + IMAGE_SCN_CNT_INITIALIZED_DATA + IMAGE_SCN_MEM_EXECUTE + IMAGE_SCN_MEM_READ + IMAGE_SCN_MEM_WRITE + DEFINED_SECTION = 0 + + section_start + +end namespace + +macro section? + namespace COFF + + SECTION_SIZE = $% - SECTION_OFFSET + + if DEFINED_SECTION | SECTION_SIZE > 0 + + if ~ DEFINED_SECTION + DEFAULT_SECTION := 1 + end if + + if $%% = SECTION_OFFSET + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_CNT_UNINITIALIZED_DATA + SECTION_OFFSET = 0 + section $ + else + UNINITIALIZED_LENGTH = $% - $%% + section $ + db UNINITIALIZED_LENGTH dup 0 + end if + + if RELOCATION_INDEX > SECTION_RELOCATION_INDEX + store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.PointerToRelocations + if RELOCATION_INDEX - SECTION_RELOCATION_INDEX > 65535 + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_LNK_NRELOC_OVFL + store 0FFFFh at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.NumberOfRelocations + load RELOCATIONS : (RELOCATION_INDEX - SECTION_RELOCATION_INDEX) * sizeof IMAGE_RELOCATION from relocations : SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION + store RELOCATIONS : (RELOCATION_INDEX - SECTION_RELOCATION_INDEX) * sizeof IMAGE_RELOCATION at relocations : (SECTION_RELOCATION_INDEX+1) * sizeof IMAGE_RELOCATION + RELOCATION_INDEX = RELOCATION_INDEX + 1 + store RELOCATION_INDEX - SECTION_RELOCATION_INDEX at relocations : SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION + IMAGE_RELOCATION.VirtualAddress + store 0 at relocations : SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION + IMAGE_RELOCATION.SymbolTableIndex + store 0 at relocations : SECTION_RELOCATION_INDEX * sizeof IMAGE_RELOCATION + IMAGE_RELOCATION.Type + else + store RELOCATION_INDEX - SECTION_RELOCATION_INDEX at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.NumberOfRelocations + end if + end if + + store SECTION_NAME : 8 at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.Name + store SECTION_OFFSET at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.PointerToRawData + store SECTION_SIZE at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.SizeOfRawData + store SECTION_FLAGS at COFF:Sections + SECTION_INDEX * sizeof IMAGE_SECTION_HEADER + IMAGE_SECTION_HEADER.Characteristics + + SECTION_INDEX = SECTION_INDEX + 1 + + end if + + end namespace +end macro + +macro section? declaration* + namespace COFF + + section + + DEFINED_SECTION = 1 + SECTION_FLAGS = 0 + SECTION_OFFSET = $% + SECTION_ALIGN = 4 + + match name attributes, declaration + + SECTION_NAME = name + + local seq,list + match flags =align? boundary, attributes + SECTION_ALIGN = boundary + define seq flags + else match =align? boundary, attributes + SECTION_ALIGN = boundary + define seq + else + define seq attributes + end match + while 1 + match car cdr, seq + define list car + define seq cdr + else + match any, seq + define list any + end match + break + end match + end while + irpv attribute, list + match =code?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_CNT_CODE + else match =data?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_CNT_INITIALIZED_DATA + else match =readable?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_READ + else match =writeable?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_WRITE + else match =executable?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_EXECUTE + else match =shareable?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_SHARED + else match =discardable?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_DISCARDABLE + else match =notpageable?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_MEM_NOT_PAGED + else match =linkremove?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_LNK_REMOVE + else match =linkinfo?, attribute + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_LNK_INFO + else + err 'unknown attribute "',`attribute,'"' + end match + end irpv + + else + + SECTION_NAME = declaration + + end match + + repeat 1, i:SECTION_ALIGN + if defined IMAGE_SCN_ALIGN_#i#BYTES + SECTION_FLAGS = SECTION_FLAGS or IMAGE_SCN_ALIGN_#i#BYTES + else + err 'invalid section alignment' + end if + end repeat + + section_start + + SECTION_RELOCATION_INDEX = RELOCATION_INDEX + + end namespace +end macro + +macro public? declaration* + namespace COFF + match =static? value =as? str, declaration + SYMBOL_VALUE = value + SYMBOL_NAME = string str + SYMBOL_CLASS = IMAGE_SYM_CLASS_STATIC + else match value =as? str, declaration + SYMBOL_VALUE = value + SYMBOL_NAME = string str + SYMBOL_CLASS = IMAGE_SYM_CLASS_EXTERNAL + else match =static? value, declaration + SYMBOL_VALUE = value + SYMBOL_NAME = `value + SYMBOL_CLASS = IMAGE_SYM_CLASS_STATIC + else + SYMBOL_VALUE = declaration + SYMBOL_NAME = `declaration + SYMBOL_CLASS = IMAGE_SYM_CLASS_EXTERNAL + end match + if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & SYMBOL_CLASS = IMAGE_SYM_CLASS_EXTERNAL + if 1 scaleof (1 metadataof SYMBOL_VALUE) > 0 + SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE) + SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE + else + SYMBOL_SECTION_INDEX = IMAGE_SYM_UNDEFINED + SYMBOL_VALUE = 0 + SYMBOL_CLASS = IMAGE_SYM_CLASS_WEAK_EXTERNAL + SYMBOL_TAG = 0 scaleof (1 metadataof SYMBOL_VALUE) + end if + else + SYMBOL_SECTION_INDEX = IMAGE_SYM_ABSOLUTE + end if + if lengthof SYMBOL_NAME > 8 + store 0 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Zeroes + store STRING_POSITION at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Offset + store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION + STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1 + else + store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.ShortName + end if + store SYMBOL_VALUE at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Value + store SYMBOL_SECTION_INDEX at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.SectionNumber + store SYMBOL_CLASS at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.StorageClass + if SYMBOL_CLASS = IMAGE_SYM_CLASS_WEAK_EXTERNAL + store 1 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.NumberOfAuxSymbols + SYMBOL_INDEX = SYMBOL_INDEX + 1 + store SYMBOL_TAG : 4 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + store IMAGE_WEAK_EXTERN_SEARCH_ALIAS : 4 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + 4 + end if + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end namespace +end macro + +macro extrn? declaration* + namespace COFF + local sym,psym + element sym : relocatable * (-1) + SYMBOL_INDEX + match str =as? name:size, declaration + label name:size at sym + SYMBOL_NAME = string str + else match name:size, declaration + label name:size at sym + SYMBOL_NAME = `name + else match str =as? name, declaration + label name at sym + SYMBOL_NAME = string str + else + label declaration at sym + SYMBOL_NAME = `declaration + end match + if lengthof SYMBOL_NAME > 8 + store 0 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Zeroes + store STRING_POSITION at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.Offset + store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION + STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1 + else + store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.ShortName + end if + store IMAGE_SYM_CLASS_EXTERNAL at symbol_table : SYMBOL_INDEX * sizeof IMAGE_SYMBOL + IMAGE_SYMBOL.StorageClass + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end namespace +end macro + +element COFF.IMAGE_BASE +RVA? equ -COFF.IMAGE_BASE+ + +if COFF.MACHINE = IMAGE_FILE_MACHINE_I386 + + calminstruction dword? value + compute value, value + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable + jyes dir32 + check ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable + jyes dir32nb + check ~ value relativeto 0 & (value + COFF.SECTION_BASE) relativeto 1 elementof (value + COFF.SECTION_BASE) + jno plain + check 1 elementof (1 metadataof (value + COFF.SECTION_BASE)) relativeto COFF.relocatable + jyes rel32 + plain: + emit 4, value + exit + local offset, symndx, type + dir32: + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_I386_DIR32 + jump add_relocation + dir32nb: + compute value, value + COFF.IMAGE_BASE + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_I386_DIR32NB + jump add_relocation + rel32: + compute value, value + (COFF.SECTION_BASE + $% + 4 - COFF.SECTION_OFFSET) + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_I386_REL32 + jump add_relocation + add_relocation: + compute offset, $% + emit 4, 0 scaleof value + check $% > offset + jno done + compute offset, offset - COFF.SECTION_OFFSET + local relocation + compute relocation, COFF.RELOCATION_INDEX * sizeof IMAGE_RELOCATION + asm store offset at COFF.relocations : relocation + IMAGE_RELOCATION.VirtualAddress + asm store symndx at COFF.relocations : relocation + IMAGE_RELOCATION.SymbolTableIndex + asm store type at COFF.relocations : relocation + IMAGE_RELOCATION.Type + compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1 + done: + end calminstruction + + calminstruction qword? value + compute value, value + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable + jyes dir32 + check ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable + jyes dir32nb + plain: + emit 8, value + exit + local offset, symndx, type + dir32: + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_I386_DIR32 + jump add_relocation + dir32nb: + compute value, value + COFF.IMAGE_BASE + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_I386_DIR32NB + jump add_relocation + add_relocation: + compute offset, $% + emit 8, 0 scaleof value + check $% > offset + jno done + compute offset, offset - COFF.SECTION_OFFSET + local relocation + compute relocation, COFF.RELOCATION_INDEX * sizeof IMAGE_RELOCATION + asm store offset at COFF.relocations : relocation + IMAGE_RELOCATION.VirtualAddress + asm store symndx at COFF.relocations : relocation + IMAGE_RELOCATION.SymbolTableIndex + asm store type at COFF.relocations : relocation + IMAGE_RELOCATION.Type + compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1 + done: + end calminstruction + +else if COFF.MACHINE = IMAGE_FILE_MACHINE_AMD64 + + calminstruction dword? value + compute value, value + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable + jyes addr32 + check ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable + jyes addr32nb + check ~ value relativeto 0 & (value + COFF.SECTION_BASE) relativeto 1 elementof (value + COFF.SECTION_BASE) + jno plain + check 1 elementof (1 metadataof (value + COFF.SECTION_BASE)) relativeto COFF.relocatable + jyes rel32 + plain: + emit 4, value + exit + local offset, symndx, type + addr32: + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_AMD64_ADDR32 + jump add_relocation + addr32nb: + compute value, value + COFF.IMAGE_BASE + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_AMD64_ADDR32NB + jump add_relocation + rel32: + compute value, value + (COFF.SECTION_BASE + $% + 4 - COFF.SECTION_OFFSET) + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_AMD64_REL32 + jump add_relocation + add_relocation: + compute offset, $% + emit 4, 0 scaleof value + check $% > offset + jno done + compute offset, offset - COFF.SECTION_OFFSET + local relocation + compute relocation, COFF.RELOCATION_INDEX * sizeof IMAGE_RELOCATION + asm store offset at COFF.relocations : relocation + IMAGE_RELOCATION.VirtualAddress + asm store symndx at COFF.relocations : relocation + IMAGE_RELOCATION.SymbolTableIndex + asm store type at COFF.relocations : relocation + IMAGE_RELOCATION.Type + compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1 + done: + end calminstruction + + calminstruction qword? value + compute value, value + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable + jyes addr64 + check ~ value relativeto 0 & (value + COFF.IMAGE_BASE) relativeto 1 elementof (value + COFF.IMAGE_BASE) & 1 elementof (1 metadataof (value + COFF.IMAGE_BASE)) relativeto COFF.relocatable + jyes addr64nb + plain: + emit 8, value + exit + local offset, symndx, type + addr64: + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_AMD64_ADDR64 + jump add_relocation + addr64nb: + compute value, value + COFF.IMAGE_BASE + compute symndx, 0 scaleof (1 metadataof value) + compute type, IMAGE_REL_AMD64_ADDR64NB + jump add_relocation + add_relocation: + compute offset, $% + emit 8, 0 scaleof value + check $% > offset + jno done + compute offset, offset - COFF.SECTION_OFFSET + local relocation + compute relocation, COFF.RELOCATION_INDEX * sizeof IMAGE_RELOCATION + asm store offset at COFF.relocations : relocation + IMAGE_RELOCATION.VirtualAddress + asm store symndx at COFF.relocations : relocation + IMAGE_RELOCATION.SymbolTableIndex + asm store type at COFF.relocations : relocation + IMAGE_RELOCATION.Type + compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1 + done: + end calminstruction + +end if + +postpone + purge section? + section + namespace COFF + + NUMBER_OF_SECTIONS := SECTION_INDEX + STRING_TABLE_SIZE := STRING_POSITION + NUMBER_OF_SYMBOLS := SYMBOL_INDEX + NUMBER_OF_RELOCATIONS := RELOCATION_INDEX + + RELOCATIONS_OFFSET = $% + load byte_sequence : NUMBER_OF_RELOCATIONS * sizeof IMAGE_RELOCATION from relocations:0 + db byte_sequence + + SYMBOL_TABLE_OFFSET = $% + load byte_sequence : NUMBER_OF_SYMBOLS * sizeof IMAGE_SYMBOL from symbol_table:0 + db byte_sequence + + load byte_sequence : STRING_TABLE_SIZE from string_table:0 + db byte_sequence + + end namespace +end postpone diff --git a/toolchain/fasm2/include/format/elf32.inc b/toolchain/fasm2/include/format/elf32.inc new file mode 100644 index 0000000..fb8d540 --- /dev/null +++ b/toolchain/fasm2/include/format/elf32.inc @@ -0,0 +1,573 @@ + +macro struct? name + macro end?.struct?! + end namespace + esc end struc + virtual at 0 + name name + sizeof.name = $ + end virtual + purge end?.struct? + end macro + esc struc name + label . : sizeof.name + namespace . +end macro + +struct Elf32_Shdr + sh_name dd ? + sh_type dd ? + sh_flags dd ? + sh_addr dd ? + sh_offset dd ? + sh_size dd ? + sh_link dd ? + sh_info dd ? + sh_addralign dd ? + sh_entsize dd ? +end struct + +struct Elf32_Sym + st_name dd ? + st_value dd ? + st_size dd ? + st_info db ? + st_other db ? + st_shndx dw ? +end struct + +struct Elf32_Rel + r_offset dd ? + r_info dd ? +end struct + +struct Elf32_Rela + r_offset dd ? + r_info dd ? + r_addend dd ? +end struct + +struct Elf32_Phdr + p_type dd ? + p_offset dd ? + p_vaddr dd ? + p_paddr dd ? + p_filesz dd ? + p_memsz dd ? + p_flags dd ? + p_align dd ? +end struct + +purge struct? + +ELFCLASSNONE = 0 +ELFCLASS32 = 1 +ELFCLASS64 = 2 + +ELFDATANONE = 0 +ELFDATA2LSB = 1 +ELFDATA2MSB = 2 + +ELFOSABI_NONE = 0 +ELFOSABI_HPUX = 1 +ELFOSABI_NETBSD = 2 +ELFOSABI_GNU = 3 +ELFOSABI_LINUX = 3 +ELFOSABI_SOLARIS = 6 +ELFOSABI_AIX = 7 +ELFOSABI_IRIX = 8 +ELFOSABI_FREEBSD = 9 +ELFOSABI_TRU64 = 10 +ELFOSABI_MODESTO = 11 +ELFOSABI_OPENBSD = 12 +ELFOSABI_OPENVMS = 13 +ELFOSABI_NSK = 14 +ELFOSABI_AROS = 15 +ELFOSABI_FENIXOS = 16 +ELFOSABI_CLOUDABI = 17 +ELFOSABI_OPENVOS = 18 + +ET_NONE = 0 +ET_REL = 1 +ET_EXEC = 2 +ET_DYN = 3 +ET_CORE = 4 +ET_LOPROC = 0xff00 +ET_HIPROC = 0xffff + +EM_NONE = 0 +EM_M32 = 1 +EM_SPARC = 2 +EM_386 = 3 +EM_68K = 4 +EM_88K = 5 +EM_860 = 7 +EM_MIPS = 8 +EM_X86_64 = 62 + +EV_NONE = 0 +EV_CURRENT = 1 + +SHN_UNDEF = 0 +SHN_LORESERVE = 0xff00 +SHN_LOPROC = 0xff00 +SHN_HIPROC = 0xff1f +SHN_ABS = 0xfff1 +SHN_COMMON = 0xfff2 +SHN_HIRESERVE = 0xffff + +SHT_NULL = 0 +SHT_PROGBITS = 1 +SHT_SYMTAB = 2 +SHT_STRTAB = 3 +SHT_RELA = 4 +SHT_HASH = 5 +SHT_DYNAMIC = 6 +SHT_NOTE = 7 +SHT_NOBITS = 8 +SHT_REL = 9 +SHT_SHLIB = 10 +SHT_DYNSYM = 11 +SHT_LOPROC = 0x70000000 +SHT_HIPROC = 0x7fffffff +SHT_LOUSER = 0x80000000 +SHT_HIUSER = 0xffffffff + +SHF_WRITE = 0x1 +SHF_ALLOC = 0x2 +SHF_EXECINSTR = 0x4 +SHF_MASKPROC = 0xf0000000 + +STT_NOTYPE = 0 +STT_OBJECT = 1 +STT_FUNC = 2 +STT_SECTION = 3 +STT_FILE = 4 +STT_LOPROC = 13 +STT_HIPROC = 15 + +STB_LOCAL = 0 +STB_GLOBAL = 1 +STB_WEAK = 2 +STB_LOPROC = 13 +STB_HIPROC = 15 + +R_386_NONE = 0 +R_386_32 = 1 +R_386_PC32 = 2 +R_386_GOT32 = 3 +R_386_PLT32 = 4 +R_386_COPY = 5 +R_386_GLOB_DAT = 6 +R_386_JMP_SLOT = 7 +R_386_RELATIVE = 8 +R_386_GOTOFF = 9 +R_386_GOTPC = 10 + +R_X86_64_NONE = 0 +R_X86_64_64 = 1 +R_X86_64_PC32 = 2 +R_X86_64_GOT32 = 3 +R_X86_64_PLT32 = 4 +R_X86_64_COPY = 5 +R_X86_64_GLOB_DAT = 6 +R_X86_64_JUMP_SLOT = 7 +R_X86_64_RELATIVE = 8 +R_X86_64_GOTPCREL = 9 +R_X86_64_32 = 10 +R_X86_64_32S = 11 +R_X86_64_16 = 12 +R_X86_64_PC16 = 13 +R_X86_64_8 = 14 +R_X86_64_PC8 = 15 +R_X86_64_DPTMOD64 = 16 +R_X86_64_DTPOFF64 = 17 +R_X86_64_TPOFF64 = 18 +R_X86_64_TLSGD = 19 +R_X86_64_TLSLD = 20 +R_X86_64_DTPOFF32 = 21 +R_X86_64_GOTTPOFF = 22 +R_X86_64_TPOFF32 = 23 +R_X86_64_PC64 = 24 +R_X86_64_GOTOFF64 = 25 +R_X86_64_GOTPC32 = 26 + +ELF:: + +namespace ELF + + if defined Settings.Machine + MACHINE := Settings.Machine + else + MACHINE := EM_386 + end if + + if defined Settings.ABI + ABI := Settings.ABI + else + ABI := ELFOSABI_NONE + end if + + if MACHINE = EM_386 + R_32 = R_386_32 + R_PC32 = R_386_PC32 + R_GOTOFF = R_386_GOTOFF + R_PLT32 = R_386_PLT32 + else if MACHINE = EM_X86_64 + R_32 = R_X86_64_32 + R_PC32 = R_X86_64_PC32 + R_PLT32 = R_X86_64_PLT32 + end if + + Header: + + e_ident db 0x7F,'ELF',ELFCLASS32,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0 + e_type dw ET_REL + e_machine dw MACHINE + e_version dd EV_CURRENT + e_entry dd 0 + e_phoff dd 0 + e_shoff dd SECTION_TABLE_OFFSET + e_flags dd 0 + e_ehsize dw Content + e_phentsize dw 0 + e_phnum dw 0 + e_shentsize dw sizeof Elf32_Shdr + e_shnum dw NUMBER_OF_SECTIONS + e_shstrndx dw STRING_TABLE_SECTION_INDEX + + Content: + + virtual at 0 + section_table:: rb NUMBER_OF_SECTIONS * sizeof Elf32_Shdr + end virtual + + virtual at 0 + symbol_table:: rb NUMBER_OF_SYMBOLS * sizeof Elf32_Sym + end virtual + + virtual at 0 + string_table:: + _null db 0 + _symtab db '.symtab',0 + _strtab db '.strtab',0 + SECTION_NAME_POSITION = $ + rb SECTION_NAME_TABLE_SIZE - $ + STRING_POSITION = $ + rb STRING_TABLE_SIZE - $ + end virtual + + virtual at 0 + relocations:: rb NUMBER_OF_RELOCATIONS * sizeof Elf32_Rel + end virtual + + element relocatable? + + macro section_org + local sym + element sym : relocatable * SECTION_INDEX + SECTION_SYMBOL_INDEX + SECTION_BASE = sym + org sym + align.assume sym, SECTION_ALIGN + end macro + + RELOCATION_INDEX = 0 + SECTION_INDEX = 1 + SECTION_SYMBOL_INDEX = SECTION_INDEX + SECTION_RELOCATION_INDEX = RELOCATION_INDEX + SYMBOL_INDEX = NUMBER_OF_SECTION_SYMBOLS + + SECTION_OFFSET = $% + SECTION_ALIGN = 4 + SECTION_NAME = '.flat' + SECTION_FLAGS = SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR + DEFINED_SECTION = 0 + section_org + +end namespace + +macro section? + namespace ELF + + SECTION_SIZE = $% - SECTION_OFFSET + + if DEFINED_SECTION | SECTION_SIZE > 0 + + store SECTION_OFFSET at section_table : Elf32_Shdr.sh_offset + SECTION_INDEX * sizeof Elf32_Shdr + store SECTION_SIZE at section_table : Elf32_Shdr.sh_size + SECTION_INDEX * sizeof Elf32_Shdr + store SECTION_ALIGN at section_table : Elf32_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf32_Shdr + store SECTION_FLAGS at section_table : Elf32_Shdr.sh_flags + SECTION_INDEX * sizeof Elf32_Shdr + + if $%% = SECTION_OFFSET + store SHT_NOBITS at section_table : Elf32_Shdr.sh_type + SECTION_INDEX * sizeof Elf32_Shdr + section $ + else + store SHT_PROGBITS at section_table : Elf32_Shdr.sh_type + SECTION_INDEX * sizeof Elf32_Shdr + UNINITIALIZED_LENGTH = $% - $%% + section $ + db UNINITIALIZED_LENGTH dup 0 + end if + + store SECTION_INDEX at symbol_table : Elf32_Sym.st_shndx + SECTION_SYMBOL_INDEX * sizeof Elf32_Sym + store STT_SECTION + STB_LOCAL shl 4 at symbol_table : Elf32_Sym.st_info + SECTION_SYMBOL_INDEX * sizeof Elf32_Sym + + if RELOCATION_INDEX > SECTION_RELOCATION_INDEX + + store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * sizeof Elf32_Rel at section_table : Elf32_Shdr.sh_offset + (SECTION_INDEX+1) * sizeof Elf32_Shdr + store (RELOCATION_INDEX - SECTION_RELOCATION_INDEX) * sizeof Elf32_Rel at section_table : Elf32_Shdr.sh_size + (SECTION_INDEX+1) * sizeof Elf32_Shdr + store SHT_REL at section_table : Elf32_Shdr.sh_type + (SECTION_INDEX+1) * sizeof Elf32_Shdr + store SYMBOL_TABLE_SECTION_INDEX at section_table : Elf32_Shdr.sh_link + (SECTION_INDEX+1) * sizeof Elf32_Shdr + store SECTION_INDEX at section_table : Elf32_Shdr.sh_info + (SECTION_INDEX+1) * sizeof Elf32_Shdr + store sizeof Elf32_Rel at section_table : Elf32_Shdr.sh_entsize + (SECTION_INDEX+1) * sizeof Elf32_Shdr + store 4 at section_table : Elf32_Shdr.sh_addralign + (SECTION_INDEX+1) * sizeof Elf32_Shdr + + store SECTION_NAME_POSITION at section_table : Elf32_Shdr.sh_name + (SECTION_INDEX+1) * sizeof Elf32_Shdr + store SECTION_NAME_POSITION + 4 at section_table : Elf32_Shdr.sh_name + SECTION_INDEX * sizeof Elf32_Shdr + store SECTION_NAME_POSITION + 4 at symbol_table : Elf32_Sym.st_name + SECTION_SYMBOL_INDEX * sizeof Elf32_Sym + store '.rel' + SECTION_NAME shl (4*8) : 4 + lengthof (string SECTION_NAME) at string_table:SECTION_NAME_POSITION + SECTION_NAME_POSITION = SECTION_NAME_POSITION + 4 + lengthof (string SECTION_NAME) + 1 + + SECTION_INDEX = SECTION_INDEX + 2 + SECTION_SYMBOL_INDEX = SECTION_SYMBOL_INDEX + 1 + + else + store SECTION_NAME_POSITION at section_table : Elf32_Shdr.sh_name + SECTION_INDEX * sizeof Elf32_Shdr + store SECTION_NAME_POSITION at symbol_table : Elf32_Sym.st_name + SECTION_SYMBOL_INDEX * sizeof Elf32_Sym + store SECTION_NAME : lengthof (string SECTION_NAME) at string_table:SECTION_NAME_POSITION + SECTION_NAME_POSITION = SECTION_NAME_POSITION + lengthof (string SECTION_NAME) + 1 + + SECTION_INDEX = SECTION_INDEX + 1 + SECTION_SYMBOL_INDEX = SECTION_SYMBOL_INDEX + 1 + + end if + + end if + + end namespace +end macro + +macro section? declaration* + namespace ELF + + section + + DEFINED_SECTION = 1 + SECTION_FLAGS = SHF_ALLOC + SECTION_OFFSET = $% + SECTION_ALIGN = 4 + + match name attributes, declaration + + SECTION_NAME = name + + local seq,list + match flags =align? boundary, attributes + SECTION_ALIGN = boundary + define seq flags + else match =align? boundary, attributes + SECTION_ALIGN = boundary + define seq + else + define seq attributes + end match + while 1 + match car cdr, seq + define list car + define seq cdr + else + match any, seq + define list any + end match + break + end match + end while + irpv attribute, list + match =writeable?, attribute + SECTION_FLAGS = SECTION_FLAGS or SHF_WRITE + else match =executable?, attribute + SECTION_FLAGS = SECTION_FLAGS or SHF_EXECINSTR + else + err 'unknown attribute "',`attribute,'"' + end match + end irpv + + else + + SECTION_NAME = declaration + + end match + + section_org + + SECTION_RELOCATION_INDEX = RELOCATION_INDEX + + end namespace +end macro + +macro public? declaration* + namespace ELF + match value =as? str, declaration + SYMBOL_VALUE = value + SYMBOL_SIZE = sizeof value + SYMBOL_NAME = string str + else + SYMBOL_VALUE = declaration + SYMBOL_SIZE = sizeof declaration + SYMBOL_NAME = `declaration + end match + if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & 1 scaleof (1 metadataof SYMBOL_VALUE) > 0 + SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE) + SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE + else + SYMBOL_SECTION_INDEX = SHN_ABS + end if + store STRING_POSITION at symbol_table : Elf32_Sym.st_name + SYMBOL_INDEX * sizeof Elf32_Sym + store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION + STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1 + store SYMBOL_VALUE at symbol_table : Elf32_Sym.st_value + SYMBOL_INDEX * sizeof Elf32_Sym + store SYMBOL_SIZE at symbol_table : Elf32_Sym.st_size + SYMBOL_INDEX * sizeof Elf32_Sym + store SYMBOL_SECTION_INDEX at symbol_table : Elf32_Sym.st_shndx + SYMBOL_INDEX * sizeof Elf32_Sym + if SYMBOL_SIZE + store STT_OBJECT + STB_GLOBAL shl 4 at symbol_table : Elf32_Sym.st_info + SYMBOL_INDEX * sizeof Elf32_Sym + else + store STT_FUNC + STB_GLOBAL shl 4 at symbol_table : Elf32_Sym.st_info + SYMBOL_INDEX * sizeof Elf32_Sym + end if + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end namespace +end macro + +macro extrn? declaration* + namespace ELF + local sym,psym + element sym : relocatable * (-1) + SYMBOL_INDEX + element psym : PLT + SYMBOL_INDEX + match str =as? name:size, declaration + label name:size at sym + label PLT.name at psym + SYMBOL_NAME = string str + SYMBOL_SIZE = size + else match name:size, declaration + label name:size at sym + label PLT.name at psym + SYMBOL_NAME = `name + SYMBOL_SIZE = size + else match str =as? name, declaration + label name at sym + label PLT.name at psym + SYMBOL_NAME = string str + SYMBOL_SIZE = 0 + else + label declaration at sym + label PLT.declaration at psym + SYMBOL_NAME = `declaration + SYMBOL_SIZE = 0 + end match + store STRING_POSITION at symbol_table : Elf32_Sym.st_name + SYMBOL_INDEX * sizeof Elf32_Sym + store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION + STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1 + store SYMBOL_SIZE at symbol_table : Elf32_Sym.st_size + SYMBOL_INDEX * sizeof Elf32_Sym + store STT_NOTYPE + STB_GLOBAL shl 4 at symbol_table : Elf32_Sym.st_info + SYMBOL_INDEX * sizeof Elf32_Sym + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end namespace +end macro + +element _GLOBAL_OFFSET_TABLE_ +RVA? equ -_GLOBAL_OFFSET_TABLE_+ +element PLT? + +calminstruction dword? value + compute value, value + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto ELF.relocatable + jyes r_32 + check ~ value relativeto 0 & (value + _GLOBAL_OFFSET_TABLE_) relativeto 1 elementof (value + _GLOBAL_OFFSET_TABLE_) & 1 elementof (1 metadataof (value + _GLOBAL_OFFSET_TABLE_)) relativeto ELF.relocatable + jyes r_gotoff + check ~ value relativeto 0 & (value + ELF.SECTION_BASE) relativeto 1 elementof (value + ELF.SECTION_BASE) + jno plain + check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto ELF.relocatable + jyes r_pc32 + check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto PLT + jyes r_plt32 + plain: + emit 4, value + exit + local offset, info + r_32: + compute info, ELF.R_32 + (0 scaleof (1 metadataof value)) shl 8 + jump add_relocation + r_gotoff: + compute value, value + _GLOBAL_OFFSET_TABLE_ + compute info, ELF.R_GOTOFF + (0 scaleof (1 metadataof value)) shl 8 + jump add_relocation + r_pc32: + compute value, value + (ELF.SECTION_BASE + $% - ELF.SECTION_OFFSET) + compute info, ELF.R_PC32 + (0 scaleof (1 metadataof value)) shl 8 + jump add_relocation + r_plt32: + compute value, value + (ELF.SECTION_BASE + $% - ELF.SECTION_OFFSET) + compute info, ELF.R_PLT32 + (0 scaleof (1 metadataof value)) shl 8 + jump add_relocation + add_relocation: + compute offset, $% + emit 4, 0 scaleof value + check $% > offset + jno done + compute offset, offset - ELF.SECTION_OFFSET + local Rel + compute Rel, ELF.RELOCATION_INDEX * sizeof Elf32_Rel + asm store offset at ELF.relocations : Rel + Elf32_Rel.r_offset + asm store info at ELF.relocations : Rel + Elf32_Rel.r_info + compute ELF.RELOCATION_INDEX, ELF.RELOCATION_INDEX + 1 + done: +end calminstruction + +postpone + purge section? + section + namespace ELF + + SECTION_NAME_TABLE_SIZE := SECTION_NAME_POSITION + STRING_TABLE_SIZE := STRING_POSITION + + NUMBER_OF_SECTION_SYMBOLS := SECTION_SYMBOL_INDEX + NUMBER_OF_SYMBOLS := SYMBOL_INDEX + SYMBOL_TABLE_SIZE := NUMBER_OF_SYMBOLS * sizeof Elf32_Sym + + NUMBER_OF_RELOCATIONS := RELOCATION_INDEX + rb (-$%) and 11b + RELOCATIONS_OFFSET = $% + load byte_sequence : NUMBER_OF_RELOCATIONS * sizeof Elf32_Rel from relocations:0 + db byte_sequence + + store _symtab at section_table : Elf32_Shdr.sh_name + SECTION_INDEX * sizeof Elf32_Shdr + store $% at section_table : Elf32_Shdr.sh_offset + SECTION_INDEX * sizeof Elf32_Shdr + store SYMBOL_TABLE_SIZE at section_table : Elf32_Shdr.sh_size + SECTION_INDEX * sizeof Elf32_Shdr + store sizeof Elf32_Sym at section_table : Elf32_Shdr.sh_entsize + SECTION_INDEX * sizeof Elf32_Shdr + store 4 at section_table : Elf32_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf32_Shdr + store SHT_SYMTAB at section_table : Elf32_Shdr.sh_type + SECTION_INDEX * sizeof Elf32_Shdr + store STRING_TABLE_SECTION_INDEX at section_table : Elf32_Shdr.sh_link + SECTION_INDEX * sizeof Elf32_Shdr + store NUMBER_OF_SECTION_SYMBOLS at section_table : Elf32_Shdr.sh_info + SECTION_INDEX * sizeof Elf32_Shdr + SYMBOL_TABLE_SECTION_INDEX := SECTION_INDEX + load byte_sequence : SYMBOL_TABLE_SIZE from symbol_table:0 + db byte_sequence + SECTION_INDEX = SECTION_INDEX + 1 + + store _strtab at section_table : Elf32_Shdr.sh_name + SECTION_INDEX * sizeof Elf32_Shdr + store $% at section_table : Elf32_Shdr.sh_offset + SECTION_INDEX * sizeof Elf32_Shdr + store STRING_TABLE_SIZE at section_table : Elf32_Shdr.sh_size + SECTION_INDEX * sizeof Elf32_Shdr + store 1 at section_table : Elf32_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf32_Shdr + store SHT_STRTAB at section_table : Elf32_Shdr.sh_type + SECTION_INDEX * sizeof Elf32_Shdr + STRING_TABLE_SECTION_INDEX := SECTION_INDEX + load byte_sequence : STRING_TABLE_SIZE from string_table:0 + db byte_sequence + SECTION_INDEX = SECTION_INDEX + 1 + + assert SECTION_INDEX <= SHN_LORESERVE + + NUMBER_OF_SECTIONS := SECTION_INDEX + rb (-$%) and 11b + SECTION_TABLE_OFFSET := $% + load byte_sequence : NUMBER_OF_SECTIONS * sizeof Elf32_Shdr from section_table:0 + db byte_sequence + + end namespace +end postpone diff --git a/toolchain/fasm2/include/format/elf64.inc b/toolchain/fasm2/include/format/elf64.inc new file mode 100644 index 0000000..377302e --- /dev/null +++ b/toolchain/fasm2/include/format/elf64.inc @@ -0,0 +1,611 @@ + +macro struct? name + macro end?.struct?! + end namespace + esc end struc + virtual at 0 + name name + sizeof.name = $ + end virtual + purge end?.struct? + end macro + esc struc name + label . : sizeof.name + namespace . +end macro + +struct Elf64_Shdr + sh_name dd ? + sh_type dd ? + sh_flags dq ? + sh_addr dq ? + sh_offset dq ? + sh_size dq ? + sh_link dd ? + sh_info dd ? + sh_addralign dq ? + sh_entsize dq ? +end struct + +struct Elf64_Sym + st_name dd ? + st_info db ? + st_other db ? + st_shndx dw ? + st_value dq ? + st_size dq ? +end struct + +struct Elf64_Rel + r_offset dq ? + r_info dq ? +end struct + +struct Elf64_Rela + r_offset dq ? + r_info dq ? + r_addend dq ? +end struct + +struct Elf64_Phdr + p_type dd ? + p_flags dd ? + p_offset dq ? + p_vaddr dq ? + p_paddr dq ? + p_filesz dq ? + p_memsz dq ? + p_align dq ? +end struct + +purge struct? + +ELFCLASSNONE = 0 +ELFCLASS32 = 1 +ELFCLASS64 = 2 + +ELFDATANONE = 0 +ELFDATA2LSB = 1 +ELFDATA2MSB = 2 + +ELFOSABI_NONE = 0 +ELFOSABI_HPUX = 1 +ELFOSABI_NETBSD = 2 +ELFOSABI_GNU = 3 +ELFOSABI_LINUX = 3 +ELFOSABI_SOLARIS = 6 +ELFOSABI_AIX = 7 +ELFOSABI_IRIX = 8 +ELFOSABI_FREEBSD = 9 +ELFOSABI_TRU64 = 10 +ELFOSABI_MODESTO = 11 +ELFOSABI_OPENBSD = 12 +ELFOSABI_OPENVMS = 13 +ELFOSABI_NSK = 14 +ELFOSABI_AROS = 15 +ELFOSABI_FENIXOS = 16 +ELFOSABI_CLOUDABI = 17 +ELFOSABI_OPENVOS = 18 + +ET_NONE = 0 +ET_REL = 1 +ET_EXEC = 2 +ET_DYN = 3 +ET_CORE = 4 +ET_LOPROC = 0xff00 +ET_HIPROC = 0xffff + +EM_NONE = 0 +EM_IA_64 = 50 +EM_X86_64 = 62 + +EV_NONE = 0 +EV_CURRENT = 1 + +SHN_UNDEF = 0 +SHN_LORESERVE = 0xff00 +SHN_LOPROC = 0xff00 +SHN_HIPROC = 0xff1f +SHN_ABS = 0xfff1 +SHN_COMMON = 0xfff2 +SHN_HIRESERVE = 0xffff + +SHT_NULL = 0 +SHT_PROGBITS = 1 +SHT_SYMTAB = 2 +SHT_STRTAB = 3 +SHT_RELA = 4 +SHT_HASH = 5 +SHT_DYNAMIC = 6 +SHT_NOTE = 7 +SHT_NOBITS = 8 +SHT_REL = 9 +SHT_SHLIB = 10 +SHT_DYNSYM = 11 +SHT_LOPROC = 0x70000000 +SHT_HIPROC = 0x7fffffff +SHT_LOUSER = 0x80000000 +SHT_HIUSER = 0xffffffff + +SHF_WRITE = 0x1 +SHF_ALLOC = 0x2 +SHF_EXECINSTR = 0x4 +SHF_MASKPROC = 0xf0000000 + +STT_NOTYPE = 0 +STT_OBJECT = 1 +STT_FUNC = 2 +STT_SECTION = 3 +STT_FILE = 4 +STT_LOPROC = 13 +STT_HIPROC = 15 + +STB_LOCAL = 0 +STB_GLOBAL = 1 +STB_WEAK = 2 +STB_LOPROC = 13 +STB_HIPROC = 15 + +R_X86_64_NONE = 0 +R_X86_64_64 = 1 +R_X86_64_PC32 = 2 +R_X86_64_GOT32 = 3 +R_X86_64_PLT32 = 4 +R_X86_64_COPY = 5 +R_X86_64_GLOB_DAT = 6 +R_X86_64_JUMP_SLOT = 7 +R_X86_64_RELATIVE = 8 +R_X86_64_GOTPCREL = 9 +R_X86_64_32 = 10 +R_X86_64_32S = 11 +R_X86_64_16 = 12 +R_X86_64_PC16 = 13 +R_X86_64_8 = 14 +R_X86_64_PC8 = 15 +R_X86_64_DPTMOD64 = 16 +R_X86_64_DTPOFF64 = 17 +R_X86_64_TPOFF64 = 18 +R_X86_64_TLSGD = 19 +R_X86_64_TLSLD = 20 +R_X86_64_DTPOFF32 = 21 +R_X86_64_GOTTPOFF = 22 +R_X86_64_TPOFF32 = 23 +R_X86_64_PC64 = 24 +R_X86_64_GOTOFF64 = 25 +R_X86_64_GOTPC32 = 26 + +ELF:: + +namespace ELF + + if defined Settings.Machine + MACHINE := Settings.Machine + else + MACHINE := EM_X86_64 + end if + + if defined Settings.ABI + ABI := Settings.ABI + else + ABI := ELFOSABI_NONE + end if + + if MACHINE = EM_X86_64 + R_64 = R_X86_64_64 + R_32 = R_X86_64_32S + R_PC32 = R_X86_64_PC32 + R_PLT32 = R_X86_64_PLT32 + R_GOT32 = R_X86_64_GOT32 + R_GOTPCREL = R_X86_64_GOTPCREL + end if + + Header: + + e_ident db 0x7F,'ELF',ELFCLASS64,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0 + e_type dw ET_REL + e_machine dw MACHINE + e_version dd EV_CURRENT + e_entry dq 0 + e_phoff dq 0 + e_shoff dq SECTION_TABLE_OFFSET + e_flags dd 0 + e_ehsize dw Content + e_phentsize dw 0 + e_phnum dw 0 + e_shentsize dw sizeof Elf64_Shdr + e_shnum dw NUMBER_OF_SECTIONS + e_shstrndx dw STRING_TABLE_SECTION_INDEX + + Content: + + virtual at 0 + section_table:: rb NUMBER_OF_SECTIONS * sizeof Elf64_Shdr + end virtual + + virtual at 0 + symbol_table:: rb NUMBER_OF_SYMBOLS * sizeof Elf64_Sym + end virtual + + virtual at 0 + string_table:: + _null db 0 + _symtab db '.symtab',0 + _strtab db '.strtab',0 + SECTION_NAME_POSITION = $ + rb SECTION_NAME_TABLE_SIZE - $ + STRING_POSITION = $ + rb STRING_TABLE_SIZE - $ + end virtual + + virtual at 0 + relocations:: rb NUMBER_OF_RELOCATIONS * sizeof Elf64_Rela + end virtual + + element relocatable? + + macro section_org + local sym + element sym : relocatable * SECTION_INDEX + SECTION_SYMBOL_INDEX + SECTION_BASE = sym + org sym + align.assume sym, SECTION_ALIGN + end macro + + RELOCATION_INDEX = 0 + SECTION_INDEX = 1 + SECTION_SYMBOL_INDEX = SECTION_INDEX + SECTION_RELOCATION_INDEX = RELOCATION_INDEX + SYMBOL_INDEX = NUMBER_OF_SECTION_SYMBOLS + + SECTION_OFFSET = $% + SECTION_ALIGN = 8 + SECTION_NAME = '.flat' + SECTION_FLAGS = SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR + DEFINED_SECTION = 0 + section_org + +end namespace + +macro section? + namespace ELF + + SECTION_SIZE = $% - SECTION_OFFSET + + if DEFINED_SECTION | SECTION_SIZE > 0 + + store SECTION_OFFSET at section_table : Elf64_Shdr.sh_offset + SECTION_INDEX * sizeof Elf64_Shdr + store SECTION_SIZE at section_table : Elf64_Shdr.sh_size + SECTION_INDEX * sizeof Elf64_Shdr + store SECTION_ALIGN at section_table : Elf64_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf64_Shdr + store SECTION_FLAGS at section_table : Elf64_Shdr.sh_flags + SECTION_INDEX * sizeof Elf64_Shdr + + if $%% = SECTION_OFFSET + store SHT_NOBITS at section_table : Elf64_Shdr.sh_type + SECTION_INDEX * sizeof Elf64_Shdr + section $ + else + store SHT_PROGBITS at section_table : Elf64_Shdr.sh_type + SECTION_INDEX * sizeof Elf64_Shdr + UNINITIALIZED_LENGTH = $% - $%% + section $ + db UNINITIALIZED_LENGTH dup 0 + end if + + store SECTION_INDEX at symbol_table : Elf64_Sym.st_shndx + SECTION_SYMBOL_INDEX * sizeof Elf64_Sym + store STT_SECTION + STB_LOCAL shl 4 at symbol_table : Elf64_Sym.st_info + SECTION_SYMBOL_INDEX * sizeof Elf64_Sym + + if RELOCATION_INDEX > SECTION_RELOCATION_INDEX + + store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * sizeof Elf64_Rela at section_table : Elf64_Shdr.sh_offset + (SECTION_INDEX+1) * sizeof Elf64_Shdr + store (RELOCATION_INDEX - SECTION_RELOCATION_INDEX) * sizeof Elf64_Rela at section_table : Elf64_Shdr.sh_size + (SECTION_INDEX+1) * sizeof Elf64_Shdr + store SHT_RELA at section_table : Elf64_Shdr.sh_type + (SECTION_INDEX+1) * sizeof Elf64_Shdr + store SYMBOL_TABLE_SECTION_INDEX at section_table : Elf64_Shdr.sh_link + (SECTION_INDEX+1) * sizeof Elf64_Shdr + store SECTION_INDEX at section_table : Elf64_Shdr.sh_info + (SECTION_INDEX+1) * sizeof Elf64_Shdr + store sizeof Elf64_Rela at section_table : Elf64_Shdr.sh_entsize + (SECTION_INDEX+1) * sizeof Elf64_Shdr + store 8 at section_table : Elf64_Shdr.sh_addralign + (SECTION_INDEX+1) * sizeof Elf64_Shdr + + store SECTION_NAME_POSITION at section_table : Elf64_Shdr.sh_name + (SECTION_INDEX+1) * sizeof Elf64_Shdr + store SECTION_NAME_POSITION + 5 at section_table : Elf64_Shdr.sh_name + SECTION_INDEX * sizeof Elf64_Shdr + store SECTION_NAME_POSITION + 5 at symbol_table : Elf64_Sym.st_name + SECTION_SYMBOL_INDEX * sizeof Elf64_Sym + store '.rela' + SECTION_NAME shl (5*8) : 5 + lengthof (string SECTION_NAME) at string_table:SECTION_NAME_POSITION + SECTION_NAME_POSITION = SECTION_NAME_POSITION + 5 + lengthof (string SECTION_NAME) + 1 + + SECTION_INDEX = SECTION_INDEX + 2 + SECTION_SYMBOL_INDEX = SECTION_SYMBOL_INDEX + 1 + + else + store SECTION_NAME_POSITION at section_table : Elf64_Shdr.sh_name + SECTION_INDEX * sizeof Elf64_Shdr + store SECTION_NAME_POSITION at symbol_table : Elf64_Sym.st_name + SECTION_SYMBOL_INDEX * sizeof Elf64_Sym + store SECTION_NAME : lengthof (string SECTION_NAME) at string_table:SECTION_NAME_POSITION + SECTION_NAME_POSITION = SECTION_NAME_POSITION + lengthof (string SECTION_NAME) + 1 + + SECTION_INDEX = SECTION_INDEX + 1 + SECTION_SYMBOL_INDEX = SECTION_SYMBOL_INDEX + 1 + + end if + + end if + + end namespace +end macro + +macro section? declaration* + namespace ELF + + section + + DEFINED_SECTION = 1 + SECTION_FLAGS = SHF_ALLOC + SECTION_OFFSET = $% + SECTION_ALIGN = 8 + + match name attributes, declaration + + SECTION_NAME = name + + local seq,list + match flags =align? boundary, attributes + SECTION_ALIGN = boundary + define seq flags + else match =align? boundary, attributes + SECTION_ALIGN = boundary + define seq + else + define seq attributes + end match + while 1 + match car cdr, seq + define list car + define seq cdr + else + match any, seq + define list any + end match + break + end match + end while + irpv attribute, list + match =writeable?, attribute + SECTION_FLAGS = SECTION_FLAGS or SHF_WRITE + else match =executable?, attribute + SECTION_FLAGS = SECTION_FLAGS or SHF_EXECINSTR + else + err 'unknown attribute "',`attribute,'"' + end match + end irpv + + else + + SECTION_NAME = declaration + + end match + + section_org + + SECTION_RELOCATION_INDEX = RELOCATION_INDEX + + end namespace +end macro + +macro public? declaration* + namespace ELF + match value =as? str, declaration + SYMBOL_VALUE = value + SYMBOL_SIZE = sizeof value + SYMBOL_NAME = string str + else + SYMBOL_VALUE = declaration + SYMBOL_SIZE = sizeof declaration + SYMBOL_NAME = `declaration + end match + if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & 1 scaleof (1 metadataof SYMBOL_VALUE) > 0 + SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE) + SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE + else + SYMBOL_SECTION_INDEX = SHN_ABS + end if + store STRING_POSITION at symbol_table : Elf64_Sym.st_name + SYMBOL_INDEX * sizeof Elf64_Sym + store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION + STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1 + store SYMBOL_VALUE at symbol_table : Elf64_Sym.st_value + SYMBOL_INDEX * sizeof Elf64_Sym + store SYMBOL_SIZE at symbol_table : Elf64_Sym.st_size + SYMBOL_INDEX * sizeof Elf64_Sym + store SYMBOL_SECTION_INDEX at symbol_table : Elf64_Sym.st_shndx + SYMBOL_INDEX * sizeof Elf64_Sym + if SYMBOL_SIZE + store STT_OBJECT + STB_GLOBAL shl 4 at symbol_table : Elf64_Sym.st_info + SYMBOL_INDEX * sizeof Elf64_Sym + else + store STT_FUNC + STB_GLOBAL shl 4 at symbol_table : Elf64_Sym.st_info + SYMBOL_INDEX * sizeof Elf64_Sym + end if + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end namespace +end macro + +macro extrn? declaration* + namespace ELF + local sym,gsym,psym + element sym : relocatable * (-1) + SYMBOL_INDEX + element gsym : GOT + SYMBOL_INDEX + element psym : PLT + SYMBOL_INDEX + match str =as? name:size, declaration + label name:size at sym + label GOT.name at gsym + label PLT.name at psym + SYMBOL_NAME = string str + SYMBOL_SIZE = size + else match name:size, declaration + label name:size at sym + label GOT.name at gsym + label PLT.name at psym + SYMBOL_NAME = `name + SYMBOL_SIZE = size + else match str =as? name, declaration + label name at sym + label GOT.name at gsym + label PLT.name at psym + SYMBOL_NAME = string str + SYMBOL_SIZE = 0 + else + label declaration at sym + label GOT.declaration at gsym + label PLT.declaration at psym + SYMBOL_NAME = `declaration + SYMBOL_SIZE = 0 + end match + store STRING_POSITION at symbol_table : Elf64_Sym.st_name + SYMBOL_INDEX * sizeof Elf64_Sym + store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION + STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1 + store SYMBOL_SIZE at symbol_table : Elf64_Sym.st_size + SYMBOL_INDEX * sizeof Elf64_Sym + store STT_NOTYPE + STB_GLOBAL shl 4 at symbol_table : Elf64_Sym.st_info + SYMBOL_INDEX * sizeof Elf64_Sym + SYMBOL_INDEX = SYMBOL_INDEX + 1 + end namespace +end macro + +element GOT? +element PLT? + +calminstruction dword? value + compute value, value + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto ELF.relocatable + jyes r_32 + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto GOT + jyes r_got32 + check ~ value relativeto 0 & (value + ELF.SECTION_BASE) relativeto 1 elementof (value + ELF.SECTION_BASE) + jno plain + check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto ELF.relocatable + jyes r_pc32 + check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto PLT + jyes r_plt32 + check 1 elementof (1 metadataof (value + ELF.SECTION_BASE)) relativeto GOT + jyes r_gotpcrel + plain: + emit 4, value + exit + local offset, addend, info + r_32: + compute offset, $% + emit 4 + check $% > offset + jno done + compute offset, offset - ELF.SECTION_OFFSET + compute addend, 0 scaleof value + compute info, ELF.R_32 + (0 scaleof (1 metadataof value)) shl 32 + jump add_relocation + r_pc32: + compute offset, $% + emit 4 + check $% > offset + jno done + compute offset, offset - ELF.SECTION_OFFSET + compute addend,value + ELF.SECTION_BASE + offset - 1 elementof value + compute info, ELF.R_PC32 + (0 scaleof (1 metadataof value)) shl 32 + jump add_relocation + r_plt32: + compute offset, $% + emit 4 + check $% > offset + jno done + compute offset, offset - ELF.SECTION_OFFSET + compute addend, value + ELF.SECTION_BASE + offset - 1 elementof value + compute info, ELF.R_PLT32 + (0 scaleof (1 metadataof value)) shl 32 + jump add_relocation + r_gotpcrel: + compute offset, $% + emit 4 + check $% > offset + jno done + compute offset, offset - ELF.SECTION_OFFSET + compute addend, value + ELF.SECTION_BASE + offset - 1 elementof value + compute info, ELF.R_GOTPCREL + (0 scaleof (1 metadataof value)) shl 32 + jump add_relocation + r_got32: + compute offset, $% + emit 4 + check $% > offset + jno done + compute offset, offset - ELF.SECTION_OFFSET + compute addend, 0 scaleof value + compute info, ELF.R_GOT32 + (0 scaleof (1 metadataof value)) shl 32 + jump add_relocation + add_relocation: + local Rela + compute Rela, ELF.RELOCATION_INDEX * sizeof Elf64_Rela + asm store offset at ELF.relocations : Rela + Elf64_Rela.r_offset + asm store addend at ELF.relocations : Rela + Elf64_Rela.r_addend + asm store info at ELF.relocations : Rela + Elf64_Rela.r_info + compute ELF.RELOCATION_INDEX, ELF.RELOCATION_INDEX + 1 + done: +end calminstruction + +calminstruction qword? value + compute value, value + check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto ELF.relocatable + jyes r_64 + plain: + emit 8, value + exit + local offset, addend, info + r_64: + compute offset, $% + emit 8 + check $% > offset + jno done + compute offset, offset - ELF.SECTION_OFFSET + compute addend, 0 scaleof value + compute info, ELF.R_64 + (0 scaleof (1 metadataof value)) shl 32 + add_relocation: + local Rela + compute Rela, ELF.RELOCATION_INDEX * sizeof Elf64_Rela + asm store offset at ELF.relocations : Rela + Elf64_Rela.r_offset + asm store addend at ELF.relocations : Rela + Elf64_Rela.r_addend + asm store info at ELF.relocations : Rela + Elf64_Rela.r_info + compute ELF.RELOCATION_INDEX, ELF.RELOCATION_INDEX + 1 + done: +end calminstruction + +postpone + purge section? + section + namespace ELF + + SECTION_NAME_TABLE_SIZE := SECTION_NAME_POSITION + STRING_TABLE_SIZE := STRING_POSITION + + NUMBER_OF_SECTION_SYMBOLS := SECTION_SYMBOL_INDEX + NUMBER_OF_SYMBOLS := SYMBOL_INDEX + SYMBOL_TABLE_SIZE := NUMBER_OF_SYMBOLS * sizeof Elf64_Sym + + NUMBER_OF_RELOCATIONS := RELOCATION_INDEX + rb (-$%) and 111b + RELOCATIONS_OFFSET = $% + load byte_sequence : NUMBER_OF_RELOCATIONS * sizeof Elf64_Rela from relocations:0 + db byte_sequence + + store _symtab at section_table : Elf64_Shdr.sh_name + SECTION_INDEX * sizeof Elf64_Shdr + store $% at section_table : Elf64_Shdr.sh_offset + SECTION_INDEX * sizeof Elf64_Shdr + store SYMBOL_TABLE_SIZE at section_table : Elf64_Shdr.sh_size + SECTION_INDEX * sizeof Elf64_Shdr + store sizeof Elf64_Sym at section_table : Elf64_Shdr.sh_entsize + SECTION_INDEX * sizeof Elf64_Shdr + store 8 at section_table : Elf64_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf64_Shdr + store SHT_SYMTAB at section_table : Elf64_Shdr.sh_type + SECTION_INDEX * sizeof Elf64_Shdr + store STRING_TABLE_SECTION_INDEX at section_table : Elf64_Shdr.sh_link + SECTION_INDEX * sizeof Elf64_Shdr + store NUMBER_OF_SECTION_SYMBOLS at section_table : Elf64_Shdr.sh_info + SECTION_INDEX * sizeof Elf64_Shdr + SYMBOL_TABLE_SECTION_INDEX := SECTION_INDEX + load byte_sequence : SYMBOL_TABLE_SIZE from symbol_table:0 + db byte_sequence + SECTION_INDEX = SECTION_INDEX + 1 + + store _strtab at section_table : Elf64_Shdr.sh_name + SECTION_INDEX * sizeof Elf64_Shdr + store $% at section_table : Elf64_Shdr.sh_offset + SECTION_INDEX * sizeof Elf64_Shdr + store STRING_TABLE_SIZE at section_table : Elf64_Shdr.sh_size + SECTION_INDEX * sizeof Elf64_Shdr + store 1 at section_table : Elf64_Shdr.sh_addralign + SECTION_INDEX * sizeof Elf64_Shdr + store SHT_STRTAB at section_table : Elf64_Shdr.sh_type + SECTION_INDEX * sizeof Elf64_Shdr + STRING_TABLE_SECTION_INDEX := SECTION_INDEX + load byte_sequence : STRING_TABLE_SIZE from string_table:0 + db byte_sequence + SECTION_INDEX = SECTION_INDEX + 1 + + assert SECTION_INDEX <= SHN_LORESERVE + + NUMBER_OF_SECTIONS := SECTION_INDEX + rb (-$%) and 111b + SECTION_TABLE_OFFSET := $% + load byte_sequence : NUMBER_OF_SECTIONS * sizeof Elf64_Shdr from section_table:0 + db byte_sequence + + end namespace +end postpone diff --git a/toolchain/fasm2/include/format/elfexe.inc b/toolchain/fasm2/include/format/elfexe.inc new file mode 100644 index 0000000..0e60241 --- /dev/null +++ b/toolchain/fasm2/include/format/elfexe.inc @@ -0,0 +1,321 @@ + +ELFCLASSNONE = 0 +ELFCLASS32 = 1 +ELFCLASS64 = 2 + +ELFDATANONE = 0 +ELFDATA2LSB = 1 +ELFDATA2MSB = 2 + +ELFOSABI_NONE = 0 +ELFOSABI_HPUX = 1 +ELFOSABI_NETBSD = 2 +ELFOSABI_GNU = 3 +ELFOSABI_LINUX = 3 +ELFOSABI_SOLARIS = 6 +ELFOSABI_AIX = 7 +ELFOSABI_IRIX = 8 +ELFOSABI_FREEBSD = 9 +ELFOSABI_TRU64 = 10 +ELFOSABI_MODESTO = 11 +ELFOSABI_OPENBSD = 12 +ELFOSABI_OPENVMS = 13 +ELFOSABI_NSK = 14 +ELFOSABI_AROS = 15 +ELFOSABI_FENIXOS = 16 +ELFOSABI_CLOUDABI = 17 +ELFOSABI_OPENVOS = 18 + +ET_NONE = 0 +ET_REL = 1 +ET_EXEC = 2 +ET_DYN = 3 +ET_CORE = 4 +ET_LOPROC = 0xff00 +ET_HIPROC = 0xffff + +EM_NONE = 0 +EM_M32 = 1 +EM_SPARC = 2 +EM_386 = 3 +EM_68K = 4 +EM_88K = 5 +EM_860 = 7 +EM_MIPS = 8 +EM_X86_64 = 62 + +EV_NONE = 0 +EV_CURRENT = 1 + +PT_NULL = 0 +PT_LOAD = 1 +PT_DYNAMIC = 2 +PT_INTERP = 3 +PT_NOTE = 4 +PT_SHLIB = 5 +PT_PHDR = 6 +PT_GNU_EH_FRAME = 0x6474e550 +PT_GNU_STACK = 0x6474e551 +PT_GNU_RELRO = 0x6474e552 +PT_LOPROC = 0x70000000 +PT_HIPROC = 0x7fffffff + +PF_X = 1 +PF_W = 2 +PF_R = 4 +PF_MASKOS = 0x0ff00000 +PF_MASKPROC = 0xf0000000 + +ELF:: + +namespace ELF + + if defined Settings.Class + CLASS := Settings.Class + else + CLASS := ELFCLASS32 + end if + + if defined Settings.Type + TYPE := Settings.Type + else + TYPE := ET_EXEC + end if + + if defined Settings.Machine + MACHINE := Settings.Machine + else + MACHINE := EM_386 + end if + + if defined Settings.ABI + ABI := Settings.ABI + else + ABI := ELFOSABI_NONE + end if + + if TYPE = ET_DYN + element DYNAMIC + align.assume DYNAMIC, 1000h + else + DYNAMIC := 0 + end if + + if defined Settings.BaseAddress + BASE_ADDRESS := DYNAMIC + Settings.BaseAddress + else + BASE_ADDRESS := DYNAMIC + 8048000h + end if + + if defined Settings.LoadHeaders + LOAD_HEADERS := Settings.LoadHeaders + else + LOAD_HEADERS := 1 + end if + + Header: + + e_ident db 0x7F,'ELF',CLASS,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0 + e_type dw TYPE + e_machine dw MACHINE + e_version dd EV_CURRENT + if CLASS <> ELFCLASS64 + e_entry dd start - DYNAMIC + e_phoff dd ProgramHeader + e_shoff dd 0 + e_flags dd 0 + e_ehsize dw ProgramHeader + e_phentsize dw SEGMENT_HEADER_LENGTH + e_phnum dw NUMBER_OF_SEGMENTS + e_shentsize dw 28h + e_shnum dw 0 + e_shstrndx dw 0 + else + e_entry dq start - DYNAMIC + e_phoff dq ProgramHeader + e_shoff dq 0 + e_flags dd 0 + e_ehsize dw ProgramHeader + e_phentsize dw SEGMENT_HEADER_LENGTH + e_phnum dw NUMBER_OF_SEGMENTS + e_shentsize dw 40h + e_shnum dw 0 + e_shstrndx dw 0 + end if + + ProgramHeader: + if CLASS <> ELFCLASS64 + p_type dd PT_LOAD + p_offset dd 0 + p_vaddr dd BASE_ADDRESS - DYNAMIC + p_paddr dd BASE_ADDRESS - DYNAMIC + p_filesz dd 0 + p_memsz dd 0 + p_flags dd PF_R+PF_W+PF_X + p_align dd 1000h + else + p_type dd PT_LOAD + p_flags dd PF_R+PF_W+PF_X + p_offset dq 0 + p_vaddr dq BASE_ADDRESS - DYNAMIC + p_paddr dq BASE_ADDRESS - DYNAMIC + p_filesz dq 0 + p_memsz dq 0 + p_align dq 1000h + end if + + SEGMENT_HEADER_LENGTH = $ - ProgramHeader + + db (NUMBER_OF_SEGMENTS-1)*SEGMENT_HEADER_LENGTH dup 0 + + HEADERS_OFFSET = 0 + HEADERS_BASE = BASE_ADDRESS + OVERLAY_HEADERS = LOAD_HEADERS + + SEGMENT_INDEX = 0 + DEFINED_SEGMENT = 0 + SEGMENT_TYPE = PT_LOAD + FILE_OFFSET = $% + SEGMENT_BASE = BASE_ADDRESS + FILE_OFFSET and 0FFFh + org SEGMENT_BASE + start: + +end namespace + +RVA? equ -ELF.BASE_ADDRESS + + +macro entry? address* + namespace ELF + store address-DYNAMIC at ELF:e_entry + end namespace +end macro + +macro segment? + namespace ELF + + DEFINED_SEGMENT_SIZE = $ - SEGMENT_BASE + + if (DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0) & SEGMENT_TYPE = PT_LOAD & OVERLAY_HEADERS + FILE_OFFSET = HEADERS_OFFSET + SEGMENT_BASE = HEADERS_BASE + OVERLAY_HEADERS = 0 + end if + + store SEGMENT_BASE-DYNAMIC at ELF:p_vaddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + store SEGMENT_BASE-DYNAMIC at ELF:p_paddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + store FILE_OFFSET at ELF:p_offset+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + + if SEGMENT_TYPE = PT_LOAD + + RAW_DATA_SIZE = $%% - FILE_OFFSET + SEGMENT_SIZE = $ - SEGMENT_BASE + store RAW_DATA_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + + if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0 + FILE_OFFSET = $%% + align 1000h + SEGMENT_BASE = $ + FILE_OFFSET and 0FFFh + end if + + section SEGMENT_BASE + + else + + if OVERLAY_HEADERS = 0 & ( LOAD_HEADERS | SEGMENT_TYPE = PT_GNU_RELRO ) & ~ SEGMENT_TYPE = PT_GNU_STACK & ~ SEGMENT_TYPE = PT_NOTE + OVERLAY_HEADERS = 1 + HEADERS_OFFSET = FILE_OFFSET + HEADERS_BASE = SEGMENT_BASE + end if + + FILE_OFFSET = $% + SEGMENT_SIZE = $ - SEGMENT_BASE + store SEGMENT_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + + if OVERLAY_HEADERS = 0 + SEGMENT_BASE = DYNAMIC + (SEGMENT_BASE-DYNAMIC) and not 0FFFh + FILE_OFFSET and 0FFFh + else + SEGMENT_BASE = $ + end if + + if $% > $%% + store 0:byte at $-1 + end if + org SEGMENT_BASE + + end if + + if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0 + SEGMENT_INDEX = SEGMENT_INDEX + 1 + end if + + end namespace +end macro + +macro segment? attributes* + namespace ELF + + segment + + SEGMENT_TYPE = PT_LOAD + SEGMENT_FLAGS = 0 + + local seq,list + define seq attributes + while 1 + match car cdr, seq + define list car + define seq cdr + else + match any, seq + define list any + end match + break + end match + end while + irpv attribute, list + match =readable?, attribute + SEGMENT_FLAGS = SEGMENT_FLAGS or PF_R + else match =writeable?, attribute + SEGMENT_FLAGS = SEGMENT_FLAGS or PF_W + else match =executable?, attribute + SEGMENT_FLAGS = SEGMENT_FLAGS or PF_X + else match =interpreter?, attribute + SEGMENT_TYPE = PT_INTERP + else match =dynamic?, attribute + SEGMENT_TYPE = PT_DYNAMIC + else match =note?, attribute + SEGMENT_TYPE = PT_NOTE + else match =gnustack?, attribute + SEGMENT_TYPE = PT_GNU_STACK + else match =gnuehframe?, attribute + SEGMENT_TYPE = PT_GNU_EH_FRAME + else match =gnurelro?, attribute + SEGMENT_TYPE = PT_GNU_RELRO + else + err 'unknown attribute "',`attribute,'"' + end match + end irpv + + DEFINED_SEGMENT = 1 + + store SEGMENT_TYPE at ELF:p_type+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + store SEGMENT_FLAGS at ELF:p_flags+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + + if SEGMENT_TYPE = PT_LOAD + store 1000h at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + else + store 1 at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH + end if + + end namespace +end macro + +postpone + purge segment? + segment + namespace ELF + NUMBER_OF_SEGMENTS := SEGMENT_INDEX + end namespace +end postpone diff --git a/toolchain/fasm2/include/format/macho.inc b/toolchain/fasm2/include/format/macho.inc new file mode 100644 index 0000000..27732c1 --- /dev/null +++ b/toolchain/fasm2/include/format/macho.inc @@ -0,0 +1,1128 @@ + +CPU_TYPE_ANY = -1 +CPU_ARCH_ABI64 = 0x1000000 +CPU_TYPE_VAX = 1 +CPU_TYPE_ROMP = 2 +CPU_TYPE_NS32032 = 4 +CPU_TYPE_NS32332 = 5 +CPU_TYPE_MC680x0 = 6 +CPU_TYPE_I386 = 7 +CPU_TYPE_X86_64 = CPU_TYPE_I386 or CPU_ARCH_ABI64 +CPU_TYPE_MIPS = 8 +CPU_TYPE_NS32532 = 9 +CPU_TYPE_HPPA = 11 +CPU_TYPE_ARM = 12 +CPU_TYPE_MC88000 = 13 +CPU_TYPE_SPARC = 14 +CPU_TYPE_I860 = 15 +CPU_TYPE_I860_LITTLE = 16 +CPU_TYPE_RS6000 = 17 +CPU_TYPE_MC98000 = 18 +CPU_TYPE_POWERPC = 18 +CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC or CPU_ARCH_ABI64 +CPU_TYPE_VEO = 255 + +CPU_SUBTYPE_MASK = 0xff000000 +CPU_SUBTYPE_LIB64 = 0x80000000 + +CPU_SUBTYPE_I386_ALL = 3 +CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386_ALL +CPU_SUBTYPE_386 = 3 +CPU_SUBTYPE_486 = 4 +CPU_SUBTYPE_486SX = 4 + 128 +CPU_SUBTYPE_586 = 5 +CPU_SUBTYPE_PENT = 5 + 0 shl 4 +CPU_SUBTYPE_PENTPRO = 6 + 1 shl 4 +CPU_SUBTYPE_PENTII_M3 = 6 + 3 shl 4 +CPU_SUBTYPE_PENTII_M5 = 6 + 5 shl 4 +CPU_SUBTYPE_PENTIUM_4 = 10 + 0 shl 4 + +MH_OBJECT = 0x1 +MH_EXECUTE = 0x2 +MH_FVMLIB = 0x3 +MH_CORE = 0x4 +MH_PRELOAD = 0x5 +MH_DYLIB = 0x6 +MH_DYLINKER = 0x7 +MH_BUNDLE = 0x8 +MH_DYLIB_STUB = 0x9 +MH_DSYM = 0xA +MH_KEXT_BUNDLE = 0xB + +MH_NOUNDEFS = 0x1 +MH_INCRLINK = 0x2 +MH_DYLDLINK = 0x4 +MH_BINDATLOAD = 0x8 +MH_PREBOUND = 0x10 +MH_SPLIT_SEGS = 0x20 +MH_LAZY_INIT = 0x40 +MH_TWOLEVEL = 0x80 +MH_FORCE_FLAT = 0x100 +MH_NOMULTIDEFS = 0x200 +MH_NOFIXPREBINDING = 0x400 +MH_PREBINDABLE = 0x800 +MH_ALLMODSBOUND = 0x1000 +MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000 +MH_CANONICAL = 0x4000 +MH_WEAK_DEFINES = 0x8000 +MH_BINDS_TO_WEAK = 0x10000 +MH_ALLOW_STACK_EXECUTION = 0x20000 +MH_ROOT_SAFE = 0x40000 +MH_SETUID_SAFE = 0x80000 +MH_NO_REEXPORTED_DYLIBS = 0x100000 +MH_PIE = 0x200000 +MH_DEAD_STRIPPABLE_DYLIB = 0x400000 +MH_HAS_TLV_DESCRIPTORS = 0x800000 +MH_NO_HEAP_EXECUTION = 0x1000000 +MH_APP_EXTENSION_SAFE = 0x2000000 + +LC_REQ_DYLD = 0x80000000 +LC_SEGMENT = 0x1 +LC_SYMTAB = 0x2 +LC_SYMSEG = 0x3 +LC_THREAD = 0x4 +LC_UNIXTHREAD = 0x5 +LC_LOADFVMLIB = 0x6 +LC_IDFVMLIB = 0x7 +LC_IDENT = 0x8 +LC_FVMFILE = 0x9 +LC_PREPAGE = 0xa +LC_DYSYMTAB = 0xb +LC_LOAD_DYLIB = 0xc +LC_ID_DYLIB = 0xd +LC_LOAD_DYLINKER = 0xe +LC_ID_DYLINKER = 0xf +LC_PREBOUND_DYLIB = 0x10 +LC_ROUTINES = 0x11 +LC_SUB_FRAMEWORK = 0x12 +LC_SUB_UMBRELLA = 0x13 +LC_SUB_CLIENT = 0x14 +LC_SUB_LIBRARY = 0x15 +LC_TWOLEVEL_HINTS = 0x16 +LC_PREBIND_CKSUM = 0x17 +LC_LOAD_WEAK_DYLIB = 0x18 +LC_SEGMENT_64 = 0x19 +LC_ROUTINES_64 = 0x1a +LC_UUID = 0x1b +LC_RPATH = 0x1c + LC_REQ_DYLD +LC_CODE_SIGNATURE = 0x1d +LC_SEGMENT_SPLIT_INFO = 0x1e +LC_REEXPORT_DYLIB = 0x1f + LC_REQ_DYLD +LC_LAZY_LOAD_DYLIB = 0x20 +LC_ENCRYPTION_INFO = 0x21 +LC_DYLD_INFO = 0x22 +LC_DYLD_INFO_ONLY = 0x22 + LC_REQ_DYLD + +SG_HIGHVM = 0x1 +SG_FVMLIB = 0x2 +SG_NORELOC = 0x4 + +SECTION_TYPE = 0x000000ff +SECTION_ATTRIBUTES = 0xffffff00 + +S_REGULAR = 0x0 +S_ZEROFILL = 0x1 +S_CSTRING_LITERALS = 0x2 +S_4BYTE_LITERALS = 0x3 +S_8BYTE_LITERALS = 0x4 +S_LITERAL_POINTERS = 0x5 +S_NON_LAZY_SYMBOL_POINTERS = 0x6 +S_LAZY_SYMBOL_POINTERS = 0x7 +S_SYMBOL_STUBS = 0x8 +S_MOD_INIT_FUNC_POINTERS = 0x9 +S_MOD_TERM_FUNC_POINTERS = 0x0a +S_COALESCED = 0x0b +S_GB_ZEROFILL = 0x0c +S_INTERPOSING = 0x0d +S_16BYTE_LITERALS = 0x0e +S_DTRACE_DOF = 0x0f +S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10 +S_THREAD_LOCAL_REGULAR = 0x11 +S_THREAD_LOCAL_ZEROFILL = 0x12 +S_THREAD_LOCAL_VARIABLES = 0x13 +S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14 +S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15 + +SECTION_ATTRIBUTES_USR = 0xff000000 +S_ATTR_PURE_INSTRUCTIONS = 0x80000000 +S_ATTR_NO_TOC = 0x40000000 +S_ATTR_STRIP_STATIC_SYMS = 0x20000000 +S_ATTR_NO_DEAD_STRIP = 0x10000000 +S_ATTR_LIVE_SUPPORT = 0x08000000 +S_ATTR_SELF_MODIFYING_CODE = 0x04000000 +S_ATTR_DEBUG = 0x02000000 + +SECTION_ATTRIBUTES_SYS = 0x00ffff00 +S_ATTR_SOME_INSTRUCTIONS = 0x00000400 +S_ATTR_EXT_RELOC = 0x00000200 +S_ATTR_LOC_RELOC = 0x00000100 + +VM_PROT_NONE = 0x00 +VM_PROT_READ = 0x01 +VM_PROT_WRITE = 0x02 +VM_PROT_EXECUTE = 0x04 +VM_PROT_DEFAULT = VM_PROT_READ or VM_PROT_WRITE +VM_PROT_ALL = VM_PROT_READ or VM_PROT_WRITE or VM_PROT_EXECUTE +VM_PROT_NO_CHANGE = 0x08 +VM_PROT_COPY = 0x10 +VM_PROT_WANTS_COPY = 0x10 + +x86_THREAD_STATE32 = 1 +x86_FLOAT_STATE32 = 2 +x86_EXCEPTION_STATE32 = 3 +x86_THREAD_STATE64 = 4 +x86_FLOAT_STATE64 = 5 +x86_EXCEPTION_STATE64 = 6 +x86_THREAD_STATE = 7 +x86_FLOAT_STATE = 8 +x86_EXCEPTION_STATE = 9 +x86_DEBUG_STATE32 = 10 +x86_DEBUG_STATE64 = 11 +x86_DEBUG_STATE = 12 +THREAD_STATE_NONE = 13 + +N_STAB = 0xe0 +N_PEXT = 0x10 +N_TYPE = 0x0e +N_EXT = 0x01 +N_UNDF = 0x0 +N_ABS = 0x2 +N_SECT = 0xe +N_PBUD = 0xc +N_INDR = 0xa + +NO_SECT = 0 +MAX_SECT = 255 + +REFERENCE_TYPE = 0xf +REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0 +REFERENCE_FLAG_UNDEFINED_LAZY = 1 +REFERENCE_FLAG_DEFINED = 2 +REFERENCE_FLAG_PRIVATE_DEFINED = 3 +REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4 +REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5 +REFERENCED_DYNAMICALLY = 0x0010 + +GENERIC_RELOC_VANILLA = 0 +GENERIC_RELOC_PAIR = 1 +GENERIC_RELOC_SECTDIFF = 2 +GENERIC_RELOC_PB_LA_PTR = 3 +GENERIC_RELOC_LOCAL_SECTDIFF = 4 +GENERIC_RELOC_TLV = 5 + +X86_64_RELOC_UNSIGNED = 0 +X86_64_RELOC_SIGNED = 1 +X86_64_RELOC_BRANCH = 2 +X86_64_RELOC_GOT_LOAD = 3 +X86_64_RELOC_GOT = 4 +X86_64_RELOC_SUBTRACTOR = 5 +X86_64_RELOC_SIGNED_1 = 6 +X86_64_RELOC_SIGNED_2 = 7 +X86_64_RELOC_SIGNED_4 = 8 +X86_64_RELOC_TLV = 9 + +; Basic layer: command headers + +MachO:: + +namespace MachO + + if defined Settings.ProcessorType + CPUTYPE := Settings.ProcessorType + else + CPUTYPE := CPU_TYPE_I386 + end if + + if defined Settings.ProcessorSubtype + CPUSUBTYPE := Settings.ProcessorSubtype + else + if CPUTYPE and CPU_ARCH_ABI64 + CPUSUBTYPE := CPU_SUBTYPE_I386_ALL + CPU_SUBTYPE_LIB64 + else + CPUSUBTYPE := CPU_SUBTYPE_I386_ALL + end if + end if + + if defined Settings.FileType + FILETYPE := Settings.FileType + else + FILETYPE := MH_EXECUTE + end if + + if defined Settings.Flags + FLAGS := Settings.Flags + else if FILETYPE <> MH_OBJECT + FLAGS := MH_NOUNDEFS + MH_DYLDLINK + else + FLAGS := 0 + end if + + if defined Settings.SegmentAlignment + SEGMENT_ALIGNMENT := Settings.SegmentAlignment + else + SEGMENT_ALIGNMENT := 1000h + end if + + if defined Settings.FileAlignment + FILE_ALIGNMENT := Settings.FileAlignment + else + FILE_ALIGNMENT := 1000h + end if + + if defined Settings.HeaderPad + HEADER_PAD := Settings.HeaderPad + else + HEADER_PAD := 16 + end if + + if CPUTYPE and CPU_ARCH_ABI64 + magic dd 0xFEEDFACF + else + magic dd 0xFEEDFACE + end if + cputype dd CPUTYPE + cpusubtype dd CPUSUBTYPE + filetype dd FILETYPE + ncmds dd NUMBER_OF_COMMANDS + sizeofcmds dd SIZE_OF_COMMANDS + flags dd FLAGS + if CPUTYPE and CPU_ARCH_ABI64 + reserved dd ? + end if + + COMMAND_NUMBER = 0 + COMMAND_POSITION = $ + + commands db SIZE_OF_COMMANDS dup 0, HEADER_PAD dup ? + + org $ + + macro command type + if MachO.COMMAND_POSITION > 0 + virtual at MachO.COMMAND_POSITION + MachO.COMMAND_POSITION = 0 + end if + match t, type + if MachO.COMMAND_NUMBER > 0 + repeat 1, p:MachO.COMMAND_NUMBER + MachO.load#p.SIZE := $ - MachO.load#p.cmd + end repeat + end if + MachO.COMMAND_NUMBER = MachO.COMMAND_NUMBER + 1 + MachO.COMMAND = $ + repeat 1, n:MachO.COMMAND_NUMBER + namespace MachO.load#n + cmd dd t + cmdsize dd SIZE + end namespace + end repeat + end match + end macro + + macro text + if MachO.COMMAND_POSITION = 0 + MachO.COMMAND_POSITION = $ + load MachO.COMMAND_DATA:$-$$ from $$ + store MachO.COMMAND_DATA:$-$$ at MachO:$$ + end virtual + end if + end macro + +end namespace + +postpone + MachO.text + namespace MachO + if COMMAND_NUMBER > 0 + repeat 1, p:COMMAND_NUMBER + load#p.SIZE := COMMAND_POSITION - MachO.load#p.cmd + end repeat + end if + NUMBER_OF_COMMANDS := COMMAND_NUMBER + SIZE_OF_COMMANDS := COMMAND_POSITION - commands + end namespace +end postpone + +; Intermediate layer: segments and sections + +namespace MachO + + if defined Settings.BaseAddress + + VM_ADDRESS = Settings.BaseAddress + + if CPUTYPE and CPU_ARCH_ABI64 + MachO.command LC_SEGMENT_64 + else + MachO.command LC_SEGMENT + end if + namespace MachO.segment1 + segname emit 16: '__PAGEZERO' + if CPUTYPE and CPU_ARCH_ABI64 + vmaddr dq 0 + vmsize dq VM_ADDRESS + fileoff dq 0 + filesize dq 0 + else + vmaddr dd 0 + vmsize dd VM_ADDRESS + fileoff dd 0 + filesize dd 0 + end if + maxprot dd 0 + initprot dd 0 + nsects dd 0 + flags dd 0 + end namespace + + SEGMENT_NUMBER = 1 + else + VM_ADDRESS = 0 + SEGMENT_NUMBER = 0 + end if + + GLOBAL_SECTION_NUMBER = 0 + TEXT_OFFSET = $% + +end namespace + +macro MachO.segment declaration + MachO.close_segment + + local NAME,VMADDR,VMSIZE,FILEOFF,FILESIZE,MAXPROT,INITPROT,NSECTS + + INITPROT = VM_PROT_NONE + MAXPROT = VM_PROT_ALL + match name attributes, declaration + NAME = name + local sequence + define sequence attributes: + while 1 + match attribute tail, sequence + match =readable?, attribute + INITPROT = INITPROT or VM_PROT_READ + MAXPROT = MAXPROT or VM_PROT_READ + else match =notreadable?, attribute + INITPROT = INITPROT and not VM_PROT_READ + MAXPROT = MAXPROT and not VM_PROT_READ + else match =writeable?, attribute + INITPROT = INITPROT or VM_PROT_WRITE + MAXPROT = MAXPROT or VM_PROT_WRITE + else match =writable?, attribute + INITPROT = INITPROT or VM_PROT_WRITE + MAXPROT = MAXPROT or VM_PROT_WRITE + else match =notwriteable?, attribute + INITPROT = INITPROT and not VM_PROT_WRITE + MAXPROT = MAXPROT and not VM_PROT_WRITE + else match =notwritable?, attribute + INITPROT = INITPROT and not VM_PROT_WRITE + MAXPROT = MAXPROT and not VM_PROT_WRITE + else match =executable?, attribute + INITPROT = INITPROT or VM_PROT_EXECUTE + MAXPROT = MAXPROT or VM_PROT_EXECUTE + else match =notexecutable?, attribute + INITPROT = INITPROT and not VM_PROT_EXECUTE + MAXPROT = MAXPROT and not VM_PROT_EXECUTE + else + err 'unknown attribute "',`attribute,'"' + end match + redefine sequence tail + else + break + end match + end while + else + NAME = definition + end match + if NAME eqtype '' & lengthof NAME > 16 + err 'name too long' + end if + + VMADDR := MachO.VM_ADDRESS + + if $% = MachO.TEXT_OFFSET & FILESIZE > 0 & MachO.FILETYPE <> MH_OBJECT + MachO.FILE_OFFSET = 0 + else + MachO.FILE_OFFSET = $% + end if + + if FILESIZE + FILEOFF := MachO.FILE_OFFSET + else + FILEOFF := 0 + end if + + MachO.SEGMENT_NUMBER = MachO.SEGMENT_NUMBER + 1 + if MachO.CPUTYPE and CPU_ARCH_ABI64 + MachO.command LC_SEGMENT_64 + else + MachO.command LC_SEGMENT + end if + repeat 1, s:MachO.SEGMENT_NUMBER + namespace MachO.segment#s + segname emit 16: NAME + if MachO.CPUTYPE and CPU_ARCH_ABI64 + vmaddr dq VMADDR + vmsize dq VMSIZE + fileoff dq FILEOFF + filesize dq FILESIZE + else + vmaddr dd VMADDR + vmsize dd VMSIZE + fileoff dd FILEOFF + filesize dd FILESIZE + end if + maxprot dd MAXPROT + initprot dd INITPROT + nsects dd NSECTS + flags dd 0 + end namespace + repeat NSECTS + namespace MachO.segment#s#_section#% + sectname emit 16: ? + segname emit 16: ? + if MachO.CPUTYPE and CPU_ARCH_ABI64 + addr dq ? + size dq ? + else + addr dd ? + size dd ? + end if + offset dd ? + ?align dd ? + reloff dd ? + nreloc dd ? + flags dd ? + reserved1 dd ? + reserved2 dd ? + if MachO.CPUTYPE and CPU_ARCH_ABI64 + dd ? + end if + end namespace + end repeat + end repeat + + macro MachO.close_segment + MachO.close_section + local OFFSET,NEXT,TOP,FILL + TOP = $% + NSECTS := MachO.SECTION_NUMBER + if MachO.FILE_OFFSET >= $%% + FILL = MachO.FILE_OFFSET + else + FILL = $%% + end if + repeat 1, s:MachO.SEGMENT_NUMBER + repeat NSECTS, n:2 + if % = 1 + load OFFSET from MachO:MachO.segment#s#_section#%.offset + else + OFFSET = NEXT + end if + if % < %% + load NEXT from MachO:MachO.segment#s#_section#n.offset + else + NEXT = TOP + end if + if OFFSET >= $%% + store S_ZEROFILL at MachO:MachO.segment#s#_section#%.flags + store 0 at MachO:MachO.segment#s#_section#%.size + else if OFFSET + FILL = NEXT + end if + end repeat + end repeat + FILESIZE := FILL - MachO.FILE_OFFSET + FILL = FILL - $%% + MachO.SECTION_BYPASS = 1 + section MachO.VM_ADDRESS + FILESIZE - FILL + restore MachO.SECTION_BYPASS + db FILL dup 0 + if FILESIZE + rb (MachO.FILE_ALIGNMENT-$%) and (MachO.FILE_ALIGNMENT-1) + end if + MachO.VM_ADDRESS = MachO.VM_ADDRESS + TOP - MachO.FILE_OFFSET + MachO.VM_ADDRESS = MachO.VM_ADDRESS + (MachO.SEGMENT_ALIGNMENT-MachO.VM_ADDRESS) and (MachO.SEGMENT_ALIGNMENT-1) + VMSIZE := MachO.VM_ADDRESS - VMADDR + purge MachO.close_segment + end macro + + MachO.text + org VMADDR + $% - MachO.FILE_OFFSET + MachO.SECTION_NUMBER = 0 + +end macro + +macro MachO.section declaration + if MachO.SEGMENT_NUMBER = 0 + MachO.segment '__TEXT' readable writable executable + end if + MachO.close_section + + local SECTNAME,SEGNAME,FLAGS,ALIGN,RESERVED1,RESERVED2 + + FLAGS = S_REGULAR + ALIGN = 0 + RESERVED1 = 0 + RESERVED2 = 0 + + local sequence + match segname:sectname tail, declaration: + SECTNAME = sectname + SEGNAME = segname + define sequence tail + else match name tail, declaration: + SECTNAME = name + repeat 1, s:MachO.SEGMENT_NUMBER + load SEGNAME from MachO:MachO.segment#s.segname + end repeat + define sequence tail + end match + + while 1 + match :, sequence + break + else match =align? boundary tail, sequence + ALIGN = bsf boundary + if bsf boundary <> bsr boundary + err 'invalid alignment value' + end if + redefine sequence tail + else match =flags?(value) tail, sequence + FLAGS = value + redefine sequence tail + else match =reserved1?(value) tail, sequence + RESERVED1 = value + redefine sequence tail + else match =reserved2?(value) tail, sequence + RESERVED2 = value + redefine sequence tail + else + err 'invalid arguments' + end match + end while + + MachO.text + if ALIGN + align 1 shl ALIGN + end if + + MachO.SECTION_ALIGN = 1 shl ALIGN + + MachO.SECTION_NUMBER = MachO.SECTION_NUMBER + 1 + MachO.GLOBAL_SECTION_NUMBER = MachO.GLOBAL_SECTION_NUMBER + 1 + + repeat 1, s:MachO.SEGMENT_NUMBER, t:MachO.SECTION_NUMBER + if ~ defined MachO.segment#s#_section#t.sectname + MachO.command + namespace MachO.segment#s#_section#t + sectname emit 16: ? + segname emit 16: ? + if MachO.CPUTYPE and CPU_ARCH_ABI64 + addr dq ? + size dq ? + else + addr dd ? + size dd ? + end if + offset dd ? + ?align dd ? + reloff dd ? + nreloc dd ? + flags dd ? + reserved1 dd ? + reserved2 dd ? + if MachO.CPUTYPE and CPU_ARCH_ABI64 + dd ? + end if + end namespace + MachO.text + end if + store SECTNAME at MachO:MachO.segment#s#_section#t.sectname + store SEGNAME at MachO:MachO.segment#s#_section#t.segname + store $ at MachO:MachO.segment#s#_section#t.addr + store $% at MachO:MachO.segment#s#_section#t.offset + store FLAGS at MachO:MachO.segment#s#_section#t.flags + store ALIGN at MachO:MachO.segment#s#_section#t.align + store RESERVED1 at MachO:MachO.segment#s#_section#t.reserved1 + store RESERVED2 at MachO:MachO.segment#s#_section#t.reserved2 + end repeat + +end macro + +macro MachO.close_section + MachO.text + if MachO.SECTION_NUMBER + local SIZE + repeat 1, s:MachO.SEGMENT_NUMBER, t:MachO.SECTION_NUMBER + load OFFSET from MachO:MachO.segment#s#_section#t.offset + store $%-OFFSET at MachO:MachO.segment#s#_section#t.size + end repeat + end if +end macro + +macro MachO.close_segment +end macro + +postpone + MachO.close_segment + if MachO.FILETYPE <> MH_OBJECT & $%% < 1000h + store 0:byte at $-1 ; enforce minimum file size for OS X 10.10.5 and higher + end if +end postpone + +macro segment? args& + MachO.segment args +end macro + +macro section? args& + if defined MachO.SECTION_BYPASS + section args + else + MachO.section args + end if +end macro + +macro entry? regs& + iterate reg, regs + match name:value, reg + MachO.thread.name? := value + else if MachO.CPUTYPE = CPU_TYPE_I386 + MachO.thread.eip? := reg + else if MachO.CPUTYPE = CPU_TYPE_X86_64 + MachO.thread.rip? := reg + end if + end iterate + MachO.command LC_UNIXTHREAD + if MachO.CPUTYPE = CPU_TYPE_I386 + MachO.thread.flavor dd x86_THREAD_STATE32 + iterate name, eax,ebx,ecx,edx,edi,esi,ebp,esp,ss,eflags,eip,cs,ds,es,fs,gs + if % = 1 + MachO.thread.count dd %% + end if + if defined MachO.thread.name? + dd MachO.thread.name? + else + dd ? + end if + end iterate + else if MachO.CPUTYPE = CPU_TYPE_X86_64 + MachO.thread.flavor dd x86_THREAD_STATE64 + iterate name, rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp,r8,r9,r10,r11,r12,r13,r14,r15,rip,rflags,cs,fs,gs + if % = 1 + MachO.thread.count dd %%*2 + end if + if defined MachO.thread.name? + dq MachO.thread.name? + else + dq ? + end if + end iterate + else + err 'CPU not supported' + end if + MachO.text +end macro + +; Upper layer: symbol tables + +define macroBuilder? + +macro macroBuilder? declaration& + macro macroBuilder?.definition + esc macro declaration + end macro +end macro + +macro macroBuilder?.line? content& + macro macroBuilder?.definition + macroBuilder?.definition + content + end macro +end macro + +macro macroBuilder?.end? + macroBuilder?.definition + esc end macro +end macro + +if MachO.FILETYPE <> MH_OBJECT + + namespace MachO + NSYMS = 0 + LIB_NUMBER = 0 + end namespace + + macro interpreter? path + MachO.command LC_LOAD_DYLINKER + namespace MachO.dylinker_command + lc_str dd dylinker-MachO.COMMAND + dylinker db path,0 + if MachO.CPUTYPE and CPU_ARCH_ABI64 + align 8 + else + align 4 + end if + end namespace + end macro + + macro uses? lib& + MachO.LIB_NUMBER = MachO.LIB_NUMBER + 1 + MachO.command LC_LOAD_DYLIB + repeat 1, l:MachO.LIB_NUMBER + namespace MachO.dylib#l#_command + lc_str dd dylib-MachO.COMMAND + timestamp dd 2 + match path (a.b.c=,x.y.z), lib + current_version dd (x and 0FFFFh) shl 16 + y shl 8 + z + compatibility_version dd (a and 0FFFFh) shl 16 + b shl 8 + c + dylib db path,0 + else + current_version dd 10000h + compatibility_version dd 10000h + dylib db lib,0 + end match + if MachO.CPUTYPE and CPU_ARCH_ABI64 + align 8 + else + align 4 + end if + end namespace + end repeat + end macro + + macro import? definitions& + iterate , definitions + MachO.NSYMS = MachO.NSYMS + 1 + define MachO.nlist name + name.imported := 1 + name.type := N_EXT + name.desc := REFERENCE_FLAG_UNDEFINED_NON_LAZY + define name.str string + end iterate + end macro + + MachO.__TEXT = 0 + MachO.__DATA = 0 + + macro segment? args& + MachO.segment args + if MachO.NSYMS + repeat 1, s:MachO.SEGMENT_NUMBER + load MachO.SEGNAME from MachO:MachO.segment#s.segname + end repeat + if ~MachO.__TEXT & MachO.SEGNAME = '__TEXT' + MachO.__TEXT = 1 + MachO.__stubs + else if ~MachO.__DATA & MachO.SEGNAME = '__DATA' + MachO.__DATA = 1 + MachO.__nl_symbol_ptr + end if + end if + end macro + + postpone + if MachO.NSYMS + + macroBuilder MachO.__stubs + + macroBuilder.line section '__stubs' flags(S_SYMBOL_STUBS+S_ATTR_SOME_INSTRUCTIONS+S_ATTR_PURE_INSTRUCTIONS) reserved1(0) reserved2(MachO.JUMP_SIZE) align 16 + + irpv sym, MachO.nlist + if sym.imported + macroBuilder.line sym: jmp [sym.ptr] + if % = 1 + macroBuilder.line MachO.JUMP_SIZE := $ - sym + end if + end if + end irpv + + macroBuilder.end + + macroBuilder MachO.__nl_symbol_ptr + + if MachO.CPUTYPE and CPU_ARCH_ABI64 + macroBuilder.line section '__nl_symbol_ptr' flags(S_NON_LAZY_SYMBOL_POINTERS) reserved1(0) align 8 + else + macroBuilder.line section '__nl_symbol_ptr' flags(S_NON_LAZY_SYMBOL_POINTERS) reserved1(0) align 4 + end if + + irpv sym, MachO.nlist + if sym.imported + if MachO.CPUTYPE and CPU_ARCH_ABI64 + macroBuilder.line sym.ptr dq 0 + else + macroBuilder.line sym.ptr dd 0 + end if + end if + end irpv + + macroBuilder.end + + if ~MachO.__TEXT + segment '__TEXT' readable executable + end if + + if ~MachO.__DATA + segment '__DATA' readable writable + end if + + segment '__LINKEDIT' readable + + MachO.SYMOFF := $% + irpv sym, MachO.nlist + namespace MachO.nlist#% + n_strx dd sym.strx + n_type db sym.type + n_sect db 0 + n_desc dw sym.desc + if MachO.CPUTYPE and CPU_ARCH_ABI64 + n_value dq sym + else + n_value dd sym + end if + end namespace + end irpv + + MachO.INDIRECTSYMOFF := $% + irpv sym, MachO.nlist + if sym.imported + dd %-1 + end if + end irpv + + MachO.STROFF := $% + db 20h,0 + irpv sym, MachO.nlist + sym.strx := $% - MachO.STROFF + db string sym.str, 0 + end irpv + MachO.STRSIZE := $% - MachO.STROFF + + MachO.command LC_SYMTAB + namespace MachO.symtab_command + symoff dd SYMOFF + nsyms dd NSYMS + stroff dd STROFF + strsize dd STRSIZE + end namespace + + MachO.command LC_DYSYMTAB + namespace MachO.dysymtab_command + ilocalsym dd 0 + nlocalsym dd 0 + iextdefsym dd 0 + nextdefsym dd 0 + iundefsym dd 0 + nundefsym dd NSYMS + tocoff dd 0 + ntoc dd 0 + modtaboff dd 0 + nmodtab dd 0 + extrefsymoff dd 0 + nextrefsyms dd 0 + indirectsymoff dd INDIRECTSYMOFF + nindirectsyms dd NSYMS + extreloff dd 0 + nextrel dd 0 + locreloff dd 0 + nlocrel dd 0 + end namespace + + end if + end postpone + +else + + namespace MachO + + element MachO.section? + element MachO.symbol? + + VM_ADDRESS = 0 + + define nlist null + null.value := 0 + null.type := 0 + null.sect := 0 + null.desc := 0 + null.str := '' + + NSYMS = 1 + NRELOC = 0 + + end namespace + + segment 0 readable writable executable + + macro MachO.section declaration + if MachO.SECTION_NUMBER + org 0 scaleof (1 metadataof $) + 0 scaleof $ + end if + MachO.section declaration + local sym + element sym : MachO.GLOBAL_SECTION_NUMBER * MachO.section + $ + org sym + align.assume sym, MachO.SECTION_ALIGN + MachO.SECTION_OFFSET = $% + MachO.SECTION_REL_INDEX = MachO.NRELOC + repeat 1, s:MachO.SEGMENT_NUMBER, t:MachO.SECTION_NUMBER + store MachO.RELOFF+MachO.SECTION_REL_INDEX*8 at MachO:MachO.segment#s#_section#t.reloff + end repeat + end macro + + macro MachO.close_section + MachO.close_section + if MachO.SECTION_NUMBER + repeat 1, s:MachO.SEGMENT_NUMBER, t:MachO.SECTION_NUMBER + store MachO.NRELOC-MachO.SECTION_REL_INDEX at MachO:MachO.segment#s#_section#t.nreloc + end repeat + end if + end macro + + macro public? declaration* + local name + define MachO.nlist name + match value =as? namestr, declaration + name = value + define name.str string namestr + else + name = declaration + define name.str `declaration + end match + if name relativeto 1 elementof name & 1 elementof (1 metadataof name) eq MachO.section + name.value := 0 scaleof (1 metadataof name) + 0 scaleof name + name.type := N_SECT + N_EXT + name.sect := 1 scaleof (1 metadataof name) + else + name.value := name + name.type := N_ABS + name.sect := 0 + end if + name.desc := REFERENCE_FLAG_DEFINED + MachO.NSYMS = MachO.NSYMS + 1 + end macro + + macro extrn? declaration* + match namestr =as? sym, declaration + define MachO.nlist sym + define sym.str string namestr + else + define MachO.nlist declaration + define declaration.str `declaration + end match + match sym, MachO.nlist + element sym : MachO.NSYMS * MachO.symbol + sym.type := N_EXT + sym.sect := 0 + sym.desc := 0 + sym.value := 0 + end match + MachO.NSYMS = MachO.NSYMS + 1 + end macro + + MachO.reloc.stack equ MachO.reloc + + calminstruction dword? v* + compute v, v + check ~ v relativeto 0 & v relativeto 1 elementof v & (1 elementof (1 metadataof v) eq MachO.section | 1 elementof (1 metadataof v) eq MachO.symbol) + jyes dir + check ~ v relativeto 0 & (v + $) relativeto 1 elementof (v + $) & (1 elementof (1 metadataof (v + $)) eq MachO.section | 1 elementof (1 metadataof (v + $)) eq MachO.symbol) + jyes rel + emit 4, v + exit + + local r, o + dir: + compute r, $% - MachO.SECTION_OFFSET + (1 scaleof (1 metadataof v)) shl 32 + 2 shl 57 + GENERIC_RELOC_VANILLA shl 60 + check 1 elementof (1 metadataof v) eq MachO.symbol + jno dir_ready + compute r, r + 1 shl 59 + dir_ready: + compute o, $% + emit 4, 0 scaleof (1 metadataof v) + 0 scaleof v + check $% > o + jyes record + exit + + rel: + check MachO.CPUTYPE = CPU_TYPE_X86_64 + jyes rel_x64 + compute v, v + 0 scaleof (1 metadataof v) - 0 scaleof (1 metadataof $) + compute r, $% - MachO.SECTION_OFFSET + (1 scaleof (1 metadataof (v + $))) shl 32 + 1 shl 56 + 2 shl 57 + GENERIC_RELOC_VANILLA shl 60 + jump rel_prepared + rel_x64: + check 1 elementof (1 metadataof (v + $)) eq MachO.symbol + jyes rel_x64_symbol + compute v, v + 0 scaleof (1 metadataof v) - 0 scaleof (1 metadataof $) + jump rel_x64_prepare + rel_x64_symbol: + compute v, v + $ + 4 + rel_x64_prepare: + compute r, $% - MachO.SECTION_OFFSET + (1 scaleof (1 metadataof (v + $))) shl 32 + 1 shl 56 + 2 shl 57 + X86_64_RELOC_SIGNED_4 shl 60 + rel_prepared: + check 1 elementof (1 metadataof (v + $)) eq MachO.symbol + jno rel_ready + compute r, r + 1 shl 59 + rel_ready: + compute o, $% + emit 4, 0 scaleof v + check $% > o + jyes record + exit + + record: + publish :MachO.reloc.stack, r + compute MachO.NRELOC, MachO.NRELOC + 1 + + end calminstruction + + postpone + if MachO.NSYMS + + MachO.close_section + macro MachO.close_section + MachO.text + end macro + + rb (-$%) and 11b + + MachO.RELOFF := $% + irpv rel, MachO.reloc + dq rel + end irpv + + MachO.SYMOFF := $% + irpv sym, MachO.nlist + namespace MachO.nlist#% + n_strx dd sym.strx + n_type db sym.type + n_sect db sym.sect + n_desc dw sym.desc + if MachO.CPUTYPE and CPU_ARCH_ABI64 + n_value dq sym.value + else + n_value dd sym.value + end if + end namespace + end irpv + + MachO.STROFF := $% + irpv sym, MachO.nlist + sym.strx := $% - MachO.STROFF + db string sym.str, 0 + end irpv + MachO.STRSIZE := $% - MachO.STROFF + + MachO.command LC_SYMTAB + namespace MachO.symtab_command + symoff dd SYMOFF + nsyms dd NSYMS + stroff dd STROFF + strsize dd STRSIZE + end namespace + + end if + end postpone + +end if diff --git a/toolchain/fasm2/include/format/mz.inc b/toolchain/fasm2/include/format/mz.inc new file mode 100644 index 0000000..e05e08d --- /dev/null +++ b/toolchain/fasm2/include/format/mz.inc @@ -0,0 +1,146 @@ + +MZ:: +.signature dw "MZ" +.bytes_in_last_page dw .LENGTH and 1FFh +.number_of_pages dw (.LENGTH-1) shr 9 + 1 +.number_of_relocations dw .NUMBER_OF_RELOCATIONS +.number_of_header_paragraphs dw .HEADER_LENGTH shr 4 +.minimum_heap dw (.LENGTH+.RESERVED_LENGTH-1) shr 4 - (.LENGTH-1) shr 4 +.maximum_heap dw 0FFFFh +.initial_ss dw 0 +.initial_sp dw 0 +.checksum dw 0 +.initial_ip dw 0 +.initial_cs dw 0 +.relocations_offset dw .relocations +.overlay_number dw 0 +.relocations dw .NUMBER_OF_RELOCATIONS dup (?,?) + rb 0Fh - ($%+0Fh) and 0Fh +.HEADER_LENGTH = $ +.RELOCATION_INDEX = 0 + +.ENTRY_DEFINED = 0 +.HEAP_DEFINED = 0 +.STACK_DEFINED = 0 +.STACK_LENGTH = 1000h + +org 0 + +macro entry? definition + local v + if MZ.ENTRY_DEFINED + err 'setting already specified' + else match seg:offs, definition + v = seg + if v relativeto MZ.segment + store v - MZ.segment : word at MZ : MZ.initial_cs + else + err 'incorrect segment' + end if + v = offs + if v >= 0 & v < 10000h + store v : word at MZ : MZ.initial_ip + else + err 'value out of range' + end if + MZ.ENTRY_DEFINED = 1 + else + err 'invalid argument' + end match +end macro + +macro heap? definition + local v,min + if MZ.HEAP_DEFINED + err 'setting already specified' + else + v = definition + if v >= 0 & v < 10000h + load min : word from MZ : MZ.minimum_heap + v = v + min + if v > 0FFFFh + v = 0FFFFh + end if + store v : word at MZ : MZ.maximum_heap + else + err 'value out of range' + end if + MZ.HEAP_DEFINED = 1 + end if +end macro + +macro stack? definition + local v + if MZ.STACK_DEFINED + err 'setting already specified' + else match seg:offs, definition + v = seg + if v relativeto MZ.segment + store v - MZ.segment : word at MZ : MZ.initial_ss + else + err 'incorrect segment' + end if + v = offs + if v >= 0 & v < 10000h + store v : word at MZ : MZ.initial_sp + else + err 'value out of range' + end if + MZ.STACK_DEFINED = 1 + MZ.STACK_LENGTH = 0 + else + MZ.STACK_DEFINED = 1 + MZ.STACK_LENGTH = definition + end match +end macro + +element MZ.segment + +macro segment? definition + rb 0Fh - ($%+0Fh) and 0Fh + match name =use16?, definition + name := MZ.segment + ($%-MZ.HEADER_LENGTH) shr 4 + use16 + else match name =use32?, definition + name := MZ.segment + ($%-MZ.HEADER_LENGTH) shr 4 + use32 + else match name, definition + name := MZ.segment + ($%-MZ.HEADER_LENGTH) shr 4 + end match + org 0 +end macro + +iterate word, word,dword + + calminstruction word? value + compute value, value + check value relativeto MZ.segment + jno plain + local offset + compute offset, $% + emit word, value - MZ.segment + check $% > offset + jno done + compute offset, offset - MZ.HEADER_LENGTH + compute offset, offset and 0FFFFh + (offset and not 0FFFFh) shl 12 + asm store offset:4 at MZ : MZ.relocations + MZ.RELOCATION_INDEX shl 2 + compute MZ.RELOCATION_INDEX, MZ.RELOCATION_INDEX + 1 + done: + exit + plain: + emit word, value + end calminstruction + +end iterate + +postpone + if MZ.STACK_LENGTH + rb 0Fh - ($%+0Fh) and 0Fh + store ($%-MZ.HEADER_LENGTH) shr 4 : word at MZ : MZ.initial_ss + rb MZ.STACK_LENGTH + store MZ.STACK_LENGTH : word at MZ : MZ.initial_sp + end if + MZ.LENGTH = $%% + MZ.RESERVED_LENGTH = $%-$%% + MZ.NUMBER_OF_RELOCATIONS = MZ.RELOCATION_INDEX +end postpone diff --git a/toolchain/fasm2/include/format/pe.inc b/toolchain/fasm2/include/format/pe.inc new file mode 100644 index 0000000..de57a2b --- /dev/null +++ b/toolchain/fasm2/include/format/pe.inc @@ -0,0 +1,999 @@ + +IMAGE_FILE_MACHINE_UNKNOWN = 0x0 +IMAGE_FILE_MACHINE_AM33 = 0x1D3 +IMAGE_FILE_MACHINE_AMD64 = 0x8664 +IMAGE_FILE_MACHINE_ARM = 0x1C0 +IMAGE_FILE_MACHINE_ARMNT = 0x1C4 +IMAGE_FILE_MACHINE_ARM64 = 0xAA64 +IMAGE_FILE_MACHINE_EBC = 0xEBC +IMAGE_FILE_MACHINE_I386 = 0x14C +IMAGE_FILE_MACHINE_IA64 = 0x200 +IMAGE_FILE_MACHINE_M32R = 0x9041 +IMAGE_FILE_MACHINE_MIPS16 = 0x266 +IMAGE_FILE_MACHINE_MIPSFPU = 0x366 +IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466 +IMAGE_FILE_MACHINE_POWERPC = 0x1F0 +IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1 +IMAGE_FILE_MACHINE_R4000 = 0x166 +IMAGE_FILE_MACHINE_SH3 = 0x1A2 +IMAGE_FILE_MACHINE_SH3DSP = 0x1A3 +IMAGE_FILE_MACHINE_SH4 = 0x1A6 +IMAGE_FILE_MACHINE_SH5 = 0x1A8 +IMAGE_FILE_MACHINE_THUMB = 0x1C2 +IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169 + +IMAGE_FILE_RELOCS_STRIPPED = 0x0001 +IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 +IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 +IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 +IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010 +IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 +IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 +IMAGE_FILE_32BIT_MACHINE = 0x0100 +IMAGE_FILE_DEBUG_STRIPPED = 0x0200 +IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 +IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 +IMAGE_FILE_SYSTEM = 0x1000 +IMAGE_FILE_DLL = 0x2000 +IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 +IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 + +IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020 +IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040 +IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080 +IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100 +IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200 +IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400 +IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800 +IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000 +IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000 +IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000 +IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 + +IMAGE_SUBSYSTEM_UNKNOWN = 0 +IMAGE_SUBSYSTEM_NATIVE = 1 +IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 +IMAGE_SUBSYSTEM_WINDOWS_CUI = 3 +IMAGE_SUBSYSTEM_POSIX_CUI = 7 +IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9 +IMAGE_SUBSYSTEM_EFI_APPLICATION = 10 +IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11 +IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12 +IMAGE_SUBSYSTEM_EFI_ROM = 13 +IMAGE_SUBSYSTEM_XBOX = 14 + +IMAGE_SCN_TYPE_NO_PAD = 0x00000008 +IMAGE_SCN_CNT_CODE = 0x00000020 +IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 +IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 +IMAGE_SCN_LNK_OTHER = 0x00000100 +IMAGE_SCN_LNK_INFO = 0x00000200 +IMAGE_SCN_LNK_REMOVE = 0x00000800 +IMAGE_SCN_LNK_COMDAT = 0x00001000 +IMAGE_SCN_GPREL = 0x00008000 +IMAGE_SCN_MEM_PURGEABLE = 0x00020000 +IMAGE_SCN_MEM_16BIT = 0x00020000 +IMAGE_SCN_MEM_LOCKED = 0x00040000 +IMAGE_SCN_MEM_PRELOAD = 0x00080000 +IMAGE_SCN_ALIGN_1BYTES = 0x00100000 +IMAGE_SCN_ALIGN_2BYTES = 0x00200000 +IMAGE_SCN_ALIGN_4BYTES = 0x00300000 +IMAGE_SCN_ALIGN_8BYTES = 0x00400000 +IMAGE_SCN_ALIGN_16BYTES = 0x00500000 +IMAGE_SCN_ALIGN_32BYTES = 0x00600000 +IMAGE_SCN_ALIGN_64BYTES = 0x00700000 +IMAGE_SCN_ALIGN_128BYTES = 0x00800000 +IMAGE_SCN_ALIGN_256BYTES = 0x00900000 +IMAGE_SCN_ALIGN_512BYTES = 0x00A00000 +IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000 +IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000 +IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000 +IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000 +IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000 +IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 +IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 +IMAGE_SCN_MEM_NOT_PAGED = 0x08000000 +IMAGE_SCN_MEM_SHARED = 0x10000000 +IMAGE_SCN_MEM_EXECUTE = 0x20000000 +IMAGE_SCN_MEM_READ = 0x40000000 +IMAGE_SCN_MEM_WRITE = 0x80000000 + +IMAGE_REL_BASED_ABSOLUTE = 0 +IMAGE_REL_BASED_HIGH = 1 +IMAGE_REL_BASED_LOW = 2 +IMAGE_REL_BASED_HIGHLOW = 3 +IMAGE_REL_BASED_HIGHADJ = 4 +IMAGE_REL_BASED_DIR64 = 10 + +PE:: + +namespace PE + + if defined Settings.Magic + MAGIC = Settings.Magic + else + MAGIC = 0x10B + end if + + if defined Settings.Machine + MACHINE = Settings.Machine + else + MACHINE = IMAGE_FILE_MACHINE_I386 + end if + + if defined Settings.Characteristics + CHARACTERISTICS = Settings.Characteristics + else + CHARACTERISTICS = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE + end if + + if defined Settings.DllCharacteristics + DLL_CHARACTERISTICS = Settings.DllCharacteristics + else + DLL_CHARACTERISTICS = 0 + end if + + if defined Settings.Subsystem + SUBSYSTEM = Settings.Subsystem + else + SUBSYSTEM = IMAGE_SUBSYSTEM_WINDOWS_CUI + end if + + if defined Settings.MajorSubsystemVersion + MAJOR_SUBSYSTEM_VERSION = Settings.MajorSubsystemVersion + else + MAJOR_SUBSYSTEM_VERSION = 3 + end if + + if defined Settings.MinorSubsystemVersion + MINOR_SUBSYSTEM_VERSION = Settings.MinorSubsystemVersion + else + MINOR_SUBSYSTEM_VERSION = 10 + end if + + if defined Settings.SectionAlignment + SECTION_ALIGNMENT := Settings.SectionAlignment + else + SECTION_ALIGNMENT := 1000h + end if + + if defined Settings.FileAlignment + FILE_ALIGNMENT := Settings.FileAlignment + else + FILE_ALIGNMENT := 512 + end if + + if defined Fixups + element RELOCATION + DLL_CHARACTERISTICS = DLL_CHARACTERISTICS or IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE + align.assume RELOCATION, PE.SECTION_ALIGNMENT + else + RELOCATION := 0 + CHARACTERISTICS = CHARACTERISTICS or IMAGE_FILE_RELOCS_STRIPPED + end if + + if defined Settings.ImageBase + IMAGE_BASE := RELOCATION + Settings.ImageBase + else + IMAGE_BASE := RELOCATION + 400000h + end if + + if defined Settings.LegacyHeaders + LEGACY_HEADERS := Settings.LegacyHeaders + else + LEGACY_HEADERS := 1 + end if + + NUMBER_OF_DIRECTORIES := 16 + + if defined Settings.Stub + + virtual at 0 + file Settings.Stub + if $ >= 1Ch + load SIGNATURE : word from 0 + if SIGNATURE = "MZ" | SIGNATURE = "ZM" + StubTemplate:: + end if + end if + end virtual + + if defined StubTemplate + + load .BYTES_IN_LAST_PAGE : word from StubTemplate:2 + load .NUMBER_OF_PAGES : word from StubTemplate:4 + .TEMPLATE_LENGTH = .NUMBER_OF_PAGES shl 9 - (-.BYTES_IN_LAST_PAGE) and 1FFh + + load .RELOCATIONS_OFFSET : word from StubTemplate:18h + if .RELOCATIONS_OFFSET >= 40h + file Settings.Stub,.TEMPLATE_LENGTH + else + load .NUMBER_OF_RELOCATIONS : word from StubTemplate:6 + .RELOCATIONS_LENGTH = .NUMBER_OF_RELOCATIONS shl 2 + load .NUMBER_OF_HEADER_PARAGRAPHS : word from StubTemplate:8 + .TEMPLATE_HEADER_LENGTH = .NUMBER_OF_HEADER_PARAGRAPHS shl 4 + + file Settings.Stub,1Ch + rb 40h - $ + file Settings.Stub:.RELOCATIONS_OFFSET,.RELOCATIONS_LENGTH + align 16 + .HEADER_LENGTH = $ + file Settings.Stub:.TEMPLATE_HEADER_LENGTH,.TEMPLATE_LENGTH-.TEMPLATE_HEADER_LENGTH + .LENGTH = $ + + store 40h : word at 18h + store .HEADER_LENGTH shr 4 : word at 8 + store .LENGTH and 1FFh : word at 2 + store (.LENGTH-1) shr 9 + 1 : word at 4 + end if + + store Header : dword at 3Ch + + else + + Stub: + .signature dw "MZ" + .bytes_in_last_page dw .LENGTH and 1FFh + .number_of_pages dw (.LENGTH-1) shr 9 + 1 + .number_of_relocations dw 0 + .number_of_header_paragraphs dw .HEADER_LENGTH shr 4 + .minimum_heap dw (10000h - (.LENGTH-.HEADER_LENGTH)) shr 4 + .maximum_heap dw 0FFFFh + .initial_ss dw (-100h) shr 4 + .initial_sp dw 0FFFEh + .checksum dw 0 + .initial_ip dw 100h + .initial_cs dw (-100h) shr 4 + .relocations_offset dw 40h + .overlay_number dw 0 + rb 3Ch - $ + .new_header_offset dd Header + + .HEADER_LENGTH = $ + + file Settings.Stub + + .LENGTH = $ + + end if + + else + + Stub: + .signature dw "MZ" + .bytes_in_last_page dw .LENGTH and 1FFh + .number_of_pages dw (.LENGTH-1) shr 9 + 1 + .number_of_relocations dw 0 + .number_of_header_paragraphs dw .HEADER_LENGTH shr 4 + .minimum_heap dw .STACK_LENGTH shr 4 + .maximum_heap dw 0FFFFh + .initial_ss dw 0 + .initial_sp dw .LENGTH - .HEADER_LENGTH + .STACK_LENGTH + .checksum dw 0 + .initial_ip dw 0 + .initial_cs dw 0 + .relocations_offset dw 40h + .overlay_number dw 0 + rb 3Ch - $ + .new_header_offset dd Header + + .HEADER_LENGTH = $ + .STACK_LENGTH = 100h + + namespace Stub + + use16 + + start: + + push cs + pop ds + mov dx,message - start + mov ah,9 + int 21h + mov ax,4C01h + int 21h + + message db 'This program cannot be run in DOS mode.',0Dh,0Ah,24h + + end namespace + + align 16 + + .LENGTH = $ + + end if + + if defined Settings.Stamp + TIMESTAMP := Settings.Stamp + else + TIMESTAMP := __TIME__ + end if + + align 8 + + Header: + .Signature dw "PE",0 + .Machine dw MACHINE + .NumberOfSections dw NUMBER_OF_SECTIONS + .TimeDateStamp dd TIMESTAMP + .PointerToSymbolTable dd 0 + .NumberOfSymbols dd 0 + .SizeOfOptionalHeader dw SectionTable - OptionalHeader + .Characteristics dw CHARACTERISTICS + + OptionalHeader: + .Magic dw MAGIC + .MajorLinkerVersion db 2 + .MinorLinkerVersion db 0 + .SizeOfCode dd 0 + .SizeOfInitializedData dd 0 + .SizeOfUninitializedData dd 0 + .AddressOfEntryPoint dd 0 + .BaseOfCode dd 0 + if MAGIC <> 0x20B + .BaseOfData dd 0 + .ImageBase dd IMAGE_BASE - RELOCATION + else + .ImageBase dq IMAGE_BASE - RELOCATION + end if + .SectionAlignment dd SECTION_ALIGNMENT + .FileAlignment dd FILE_ALIGNMENT + .MajorOperatingSystemVersion dw 1 + .MinorOperatingSystemVersion dw 0 + .MajorImageVersion dw 0 + .MinorImageVersion dw 0 + .MajorSubsystemVersion dw MAJOR_SUBSYSTEM_VERSION + .MinorSubsystemVersion dw MINOR_SUBSYSTEM_VERSION + .Win32VersionValue dd 0 + .SizeOfImage dd SIZE_OF_IMAGE + .SizeOfHeaders dd SIZE_OF_HEADERS + .CheckSum dd 0 + .Subsystem dw SUBSYSTEM + .DllCharacteristics dw DLL_CHARACTERISTICS + if MAGIC <> 0x20B + .SizeOfStackReserve dd 1000h + .SizeOfStackCommit dd 1000h + .SizeOfHeapReserve dd 10000h + .SizeOfHeapCommit dd 0 + else + .SizeOfStackReserve dq 1000h + .SizeOfStackCommit dq 1000h + .SizeOfHeapReserve dq 10000h + .SizeOfHeapCommit dq 0 + end if + .LoaderFlags dd 0 + .NumberOfRvaAndSizes dd NUMBER_OF_DIRECTORIES + RvaAndSizes: + .Rva dd 0 + .Size dd 0 + .ENTRY_LENGTH = $ - RvaAndSizes + db (NUMBER_OF_DIRECTORIES-1)*RvaAndSizes.ENTRY_LENGTH dup 0 + SectionTable: + .Name dq '.flat' + .VirtualSize dd 0 + .VirtualAddress dd 0 + .SizeOfRawData dd 0 + .PointerToRawData dd 0 + .PointerToRelocations dd 0 + .PointerToLineNumbers dd 0 + .NumberOfRelocations dw 0 + .NumberOfLineNumbers dw 0 + .Characteristics dd IMAGE_SCN_MEM_EXECUTE + IMAGE_SCN_MEM_READ + IMAGE_SCN_MEM_WRITE + .ENTRY_LENGTH = $ - SectionTable + db (NUMBER_OF_SECTIONS-1)*SectionTable.ENTRY_LENGTH dup 0 + + HeadersEnd: + define CheckSumBlocks PE,HeadersEnd + + SECTION_INDEX = 0 + RELOCATION_INDEX = 0 + DEFINED_SECTION = 0 + SECTION_DIRECTORIES = 0 + align SECTION_ALIGNMENT + FIRST_SECTION_RVA: + section $%% + align FILE_ALIGNMENT,0 + SIZE_OF_HEADERS = $% + FILE_OFFSET = $% + SECTION_BASE = IMAGE_BASE + FIRST_SECTION_RVA + org SECTION_BASE + + store SECTION_BASE-IMAGE_BASE at PE:OptionalHeader.AddressOfEntryPoint + store SECTION_BASE-IMAGE_BASE at PE:SectionTable.VirtualAddress + store FILE_OFFSET at PE:SectionTable.PointerToRawData + + virtual at 0 + relocated_addresses:: rd NUMBER_OF_RELOCATIONS + end virtual + + virtual at 0 + relocation_types:: rw NUMBER_OF_RELOCATIONS + end virtual + +end namespace + +RVA? equ -PE.IMAGE_BASE + + +macro entry? address* + namespace PE + store address-IMAGE_BASE at PE:OptionalHeader.AddressOfEntryPoint + end namespace +end macro + +macro stack? reserve*,commit:1000h + namespace PE + store reserve at PE:OptionalHeader.SizeOfStackReserve + store commit at PE:OptionalHeader.SizeOfStackCommit + end namespace +end macro + +macro heap? reserve*,commit:0 + namespace PE + store reserve at PE:OptionalHeader.SizeOfHeapReserve + store commit at PE:OptionalHeader.SizeOfHeapCommit + end namespace +end macro + +macro section? + namespace PE + + repeat SECTION_DIRECTORIES + end data + end repeat + + local AREA,DATA_LENGTH + AREA:: + DATA_LENGTH = $-$$-($%-$%%) + CheckSumBlocks reequ CheckSumBlocks,AREA,DATA_LENGTH + + SECTION_SIZE = $ - SECTION_BASE + store SECTION_SIZE at PE:SectionTable.VirtualSize+SECTION_INDEX*SectionTable.ENTRY_LENGTH + align SECTION_ALIGNMENT + SECTION_BASE = $ + section $%% + align FILE_ALIGNMENT,0 + RAW_DATA_SIZE = $% - FILE_OFFSET + store RAW_DATA_SIZE at PE:SectionTable.SizeOfRawData+SECTION_INDEX*SectionTable.ENTRY_LENGTH + FILE_OFFSET = $% + org SECTION_BASE + + load SECTION_CHARACTERISTICS from PE:SectionTable.Characteristics+SECTION_INDEX*SectionTable.ENTRY_LENGTH + if SECTION_SIZE > 0 & RAW_DATA_SIZE = 0 + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_CNT_UNINITIALIZED_DATA + store SECTION_CHARACTERISTICS at PE:SectionTable.Characteristics+SECTION_INDEX*SectionTable.ENTRY_LENGTH + end if + + if LEGACY_HEADERS + if SECTION_CHARACTERISTICS and IMAGE_SCN_CNT_CODE & RAW_DATA_SIZE > 0 + load CODE_SIZE from PE:OptionalHeader.SizeOfCode + if CODE_SIZE = 0 + load CODE_BASE from PE:SectionTable.VirtualAddress+SECTION_INDEX*SectionTable.ENTRY_LENGTH + store CODE_BASE at PE:OptionalHeader.BaseOfCode + end if + CODE_SIZE = CODE_SIZE + RAW_DATA_SIZE + store CODE_SIZE at PE:OptionalHeader.SizeOfCode + end if + if SECTION_CHARACTERISTICS and IMAGE_SCN_CNT_INITIALIZED_DATA & RAW_DATA_SIZE > 0 + load DATA_SIZE from PE:OptionalHeader.SizeOfInitializedData + if DATA_SIZE = 0 & MAGIC <> 0x20B + load DATA_BASE from PE:SectionTable.VirtualAddress+SECTION_INDEX*SectionTable.ENTRY_LENGTH + store DATA_BASE at PE:OptionalHeader.BaseOfData + end if + DATA_SIZE = DATA_SIZE + RAW_DATA_SIZE + store DATA_SIZE at PE:OptionalHeader.SizeOfInitializedData + end if + if SECTION_CHARACTERISTICS and IMAGE_SCN_CNT_UNINITIALIZED_DATA + load BSS_SIZE from PE:OptionalHeader.SizeOfUninitializedData + BSS_SIZE = BSS_SIZE + SECTION_SIZE + store BSS_SIZE at PE:OptionalHeader.SizeOfUninitializedData + end if + end if + + if DEFINED_SECTION | SECTION_SIZE > 0 + SECTION_INDEX = SECTION_INDEX + 1 + end if + + end namespace +end macro + +macro section? declaration* + namespace PE + + section + + DEFINED_SECTION = 1 + + store SECTION_BASE-IMAGE_BASE at PE:SectionTable.VirtualAddress+SECTION_INDEX*SectionTable.ENTRY_LENGTH + store FILE_OFFSET at PE:SectionTable.PointerToRawData+SECTION_INDEX*SectionTable.ENTRY_LENGTH + + SECTION_DIRECTORIES = 0 + + match name attributes, declaration + + store name:qword at PE:SectionTable.Name+SECTION_INDEX*SectionTable.ENTRY_LENGTH + + SECTION_CHARACTERISTICS = 0 + + local seq + define seq attributes: + while 1 + match :, seq + break + else match =readable? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_READ + else match =writeable? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_WRITE + else match =writable? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_WRITE + else match =executable? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_EXECUTE + else match =discardable? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_DISCARDABLE + else match =shareable? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_SHARED + else match =import? tail, seq + redefine seq tail + SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1 + data import + else match =export? tail, seq + redefine seq tail + SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1 + data export + else match =resource? =from? path tail, seq + redefine seq tail + SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1 + data resource from path + else match =resource? tail, seq + redefine seq tail + SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1 + data resource + else match =fixups? tail, seq + redefine seq tail + SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1 + data fixups + else match =code? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_CNT_CODE + else match =data? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_CNT_INITIALIZED_DATA + else match =udata? tail, seq + redefine seq tail + SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_CNT_UNINITIALIZED_DATA + else match attribute tail, seq + err 'unknown attribute "',`attribute,'"' + redefine seq : + end match + end while + + store SECTION_CHARACTERISTICS at PE:SectionTable.Characteristics+SECTION_INDEX*SectionTable.ENTRY_LENGTH + else + + store declaration:qword at PE:SectionTable.Name+SECTION_INDEX*SectionTable.ENTRY_LENGTH + + end match + + end namespace +end macro + +macro data? type* + namespace PE + local number,content + define content + match =export?, type + number = 0 + else match =import?, type + number = 1 + else match =resource? =from? path, type + number = 2 + define content resource_from path + else match =resource?, type + number = 2 + else match =fixups?, type + number = 5 + define content fixups + else + number = type + end match + define DATA_DIRECTORY number + load DATA_BASE:dword from PE:RvaAndSizes.Rva+DATA_DIRECTORY*RvaAndSizes.ENTRY_LENGTH + if DATA_BASE = 0 + store $-IMAGE_BASE:dword at PE:RvaAndSizes.Rva+DATA_DIRECTORY*RvaAndSizes.ENTRY_LENGTH + match instruction, content + instruction + end match + else + err 'data already defined' + end if + end namespace +end macro + +macro end?.data? + namespace PE + load DATA_BASE:dword from PE:RvaAndSizes.Rva+DATA_DIRECTORY*RvaAndSizes.ENTRY_LENGTH + store $-IMAGE_BASE-DATA_BASE:dword at PE:RvaAndSizes.Size+DATA_DIRECTORY*RvaAndSizes.ENTRY_LENGTH + restore DATA_DIRECTORY + end namespace +end macro + +macro PE.resource_directory? + namespace PE + Resource: rb RESOURCE_HEADERS_LENGTH + Resource.counter = 0 + define RESOURCE_DIRECTORIES_LIST Resource_root + Resource_root.counter = 0 + end namespace +end macro + +macro PE.resource_data? type*,id*,lang*,codepage:0 + namespace PE + local _type,_id,_lang + _type = type + _id = id + _lang = lang + if ~ type eqtype 0 + _type = _type shl 32 + end if + if ~ id eqtype 0 + _id = id shl 32 + end if + if ~ lang eqtype 0 + _lang = lang shl 32 + end if + repeat 1, %type:_type, %id:_id, %lang:_lang + if ~ defined Resource_#%type#_#%id.counter + if ~ defined Resource_#%type.counter + repeat 1, i:Resource_root.counter + Resource_root.entry#i = type + Resource_root.offset#i = (Resource_#%type - Resource) or 80000000h + end repeat + Resource_root.counter = Resource_root.counter + 1 + match list, RESOURCE_DIRECTORIES_LIST + define RESOURCE_DIRECTORIES_LIST list,Resource_#%type + end match + Resource_#%type.counter = 0 + end if + repeat 1, i:Resource_#%type.counter + Resource_#%type.entry#i = id + Resource_#%type.offset#i = (Resource_#%type#_#%id - Resource) or 80000000h + end repeat + Resource_#%type.counter = Resource_#%type.counter + 1 + + match list, RESOURCE_DIRECTORIES_LIST + define RESOURCE_DIRECTORIES_LIST list,Resource_#%type#_#%id + end match + Resource_#%type#_#%id.counter = 0 + end if + repeat 1, i:Resource_#%type#_#%id.counter + Resource_#%type#_#%id.entry#i = lang + Resource_#%type#_#%id.offset#i = Resource_#%type#_#%id#_#%lang - Resource + end repeat + Resource_#%type#_#%id.counter = Resource_#%type#_#%id.counter + 1 + repeat 1, i:Resource.counter + Resource_#%type#_#%id#_#%lang := Resource.entry#i + Resource.cp#i := codepage + Resource.data#i: + end repeat + end repeat + end namespace +end macro + +macro PE.end_resource_data? + namespace PE + repeat 1, i:Resource.counter + Resource.size#i := $ - Resource.data#i + end repeat + Resource.counter = Resource.counter + 1 + align 4 + end namespace +end macro + +macro PE.end_resource_directory? + namespace PE + RESOURCE_HEADERS_POINTER = 0 + + match list, RESOURCE_DIRECTORIES_LIST + iterate dir, list + dir := Resource + RESOURCE_HEADERS_POINTER + RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 16 + dir.counter * 8 + local x,y,z,a,b + x = dir.counter shr 1 + while x > 0 + y = x + while y < dir.counter + z = y + while z-x >= 0 + repeat 1, i:z, j:z-x + if dir.entry#i eqtype 0 + if ~ dir.entry#j eqtype 0 | dir.entry#i >= dir.entry#j + z = 0 + end if + else if ~ dir.entry#j eqtype 0 + a = dir.entry#i bswap lengthof dir.entry#i + b = dir.entry#j bswap lengthof dir.entry#j + if ( lengthof a >= lengthof b & a shr ((lengthof a - lengthof b)*8) >= b ) | ( lengthof a < lengthof b & a > b shr ((lengthof b - lengthof a)*8) ) + z = 0 + end if + end if + if z > 0 + a = dir.entry#i + b = dir.offset#i + dir.entry#i = dir.entry#j + dir.offset#i = dir.offset#j + dir.entry#j = a + dir.offset#j = b + z = z - x + end if + end repeat + end while + y = y + 1 + end while + x = x shr 1 + end while + end iterate + iterate dir, list + store __TIME__ : 4 at dir + 4 + dir.names_counter = 0 + repeat dir.counter, i:0 + if dir.entry#i eqtype 0 + store dir.entry#i : 4 at dir + 16 + i * 8 + else + dir.names_counter = dir.names_counter + 1 + repeat 1, %id:dir.entry#i + if ~ defined Resource_string#%id + restore Resource_string#%id + Resource_string#%id = Resource + RESOURCE_HEADERS_POINTER + if lengthof dir.entry#i and 1 + err 'a word-aligned string is expected as a name' + end if + RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + lengthof dir.entry#i + 2 + store (lengthof dir.entry#i)/2 : 2 at Resource_string#%id + store dir.entry#i : lengthof dir.entry#i at Resource_string#%id + 2 + end if + store (Resource_string#%id - Resource) or 80000000h : 4 at dir + 16 + i * 8 + end repeat + end if + store dir.offset#i : 4 at dir + 16 + i * 8 + 4 + end repeat + store dir.names_counter : 2 at dir + 12 + store dir.counter - dir.names_counter : 2 at dir + 14 + end iterate + end match + + if RESOURCE_HEADERS_POINTER and 11b + RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 4 - RESOURCE_HEADERS_POINTER and 11b + end if + + repeat Resource.counter, i:0 + Resource.entry#i := Resource + RESOURCE_HEADERS_POINTER + RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 16 + store RVA(Resource.data#i) : 4 at Resource.entry#i + store Resource.size#i : 4 at Resource.entry#i + 4 + store Resource.cp#i : 4 at Resource.entry#i + 8 + end repeat + + RESOURCE_HEADERS_LENGTH = RESOURCE_HEADERS_POINTER + end namespace +end macro + +macro PE.resource_from path* + + local res_file,res_size,res_header_size,res_data_size,res_data + local offset,char,type,id,lang + + virtual at 0 + res_file:: file path + res_size := $ + end virtual + + PE.resource_directory + + offset = 0 + while offset < res_size + load res_header_size : 4 from res_file : offset + 4 + load res_data_size : 4 from res_file : offset + 0 + + if res_data_size > 0 + + offset =: offset + 8 + load char : 2 from res_file : offset + if char = 0FFFFh + load char : 2 from res_file : offset + 2 + type = +char + offset = offset + 4 + else + while 1 + if char = 0 + load type : (%-1)*2 from res_file : offset + offset = offset + (% + % and 1)*2 + break + end if + load char : 2 from res_file : offset + %*2 + end while + end if + load char : 2 from res_file : offset + if char = 0FFFFh + load char : 2 from res_file : offset + 2 + id = +char + offset = offset + 4 + else + while 1 + if char = 0 + load id : (%-1)*2 from res_file : offset + offset = offset + (% + % and 1)*2 + break + end if + load char : 2 from res_file : offset + %*2 + end while + end if + load char : 2 from res_file : offset + 6 + lang = +char + + restore offset + + PE.resource_data type,id,lang + load res_data : res_data_size from res_file : offset + res_header_size + db res_data + PE.end_resource_data + + end if + + offset = offset + res_header_size + res_data_size + if offset and 11b + offset = offset + 4 - offset and 11b + end if + end while + + PE.end_resource_directory + +end macro + +macro PE.fixups + namespace PE + Fixups: + calminstruction BuildFixups + local PAGE_RVA, BLOCK_HEADER, BLOCK_SIZE + local INDEX, ADDRESS, TYPE, FIXUP + check NUMBER_OF_RELOCATIONS = 0 + jyes dummy + compute PAGE_RVA, -1 + compute BLOCK_HEADER, 0 + compute BLOCK_SIZE, 0 + compute INDEX,0 + process: + check INDEX = NUMBER_OF_RELOCATIONS + jyes close_block + load ADDRESS, relocated_addresses:INDEX shl 2, 4 + check PAGE_RVA >= 0 & ADDRESS and not 0FFFh = PAGE_RVA + jyes append_to_block + close_block: + check BLOCK_HEADER + jno start_new_block + check BLOCK_SIZE and 11b + jno finish_block + emit 2, 0 + compute BLOCK_SIZE, BLOCK_SIZE + 2 + finish_block: + store BLOCK_HEADER+4, 4, BLOCK_SIZE + start_new_block: + check INDEX = NUMBER_OF_RELOCATIONS + jyes done + compute PAGE_RVA, ADDRESS and not 0FFFh + compute BLOCK_HEADER, $% + emit 4, PAGE_RVA + emit 4, 0 + compute BLOCK_SIZE, 8 + append_to_block: + load TYPE, relocation_types:INDEX shl 1, 2 + compute FIXUP, (ADDRESS and 0FFFh) or (TYPE shl 12) + emit 2, FIXUP + compute BLOCK_SIZE, BLOCK_SIZE + 2 + compute INDEX, INDEX + 1 + jump process + dummy: + emit 4, 0 + emit 4, 8 + done: + end calminstruction + BuildFixups + end namespace +end macro + +if defined PE.Fixups + + calminstruction dword? value* + compute value, value + check value relativeto 0 | ~ value relativeto PE.RELOCATION + jyes plain + local offset + compute offset, $% + emit 4, value - PE.RELOCATION + check $% > offset + jno done + store PE.relocated_addresses:PE.RELOCATION_INDEX shl 2, 4, $-4-PE.IMAGE_BASE + store PE.relocation_types:PE.RELOCATION_INDEX shl 1, 2, IMAGE_REL_BASED_HIGHLOW + compute PE.RELOCATION_INDEX, PE.RELOCATION_INDEX + 1 + done: + exit + plain: + emit 4, value + end calminstruction + + calminstruction qword? value* + compute value, value + check value relativeto 0 | ~ value relativeto PE.RELOCATION + jyes plain + local offset + compute offset, $% + emit 8, value - PE.RELOCATION + check $% > offset + jno done + store PE.relocated_addresses:PE.RELOCATION_INDEX shl 2, 4, $-8-PE.IMAGE_BASE + store PE.relocation_types:PE.RELOCATION_INDEX shl 1, 2, IMAGE_REL_BASED_DIR64 + compute PE.RELOCATION_INDEX, PE.RELOCATION_INDEX + 1 + done: + exit + plain: + emit 8, value + end calminstruction + +end if + +postpone + purge section? + section + namespace PE + SIZE_OF_IMAGE := SECTION_BASE - IMAGE_BASE + NUMBER_OF_SECTIONS := SECTION_INDEX + NUMBER_OF_RELOCATIONS := RELOCATION_INDEX + end namespace +end postpone + +postpone ? + namespace PE + CHECKSUM = 0 + + calminstruction CheckSum + local AREA, DATA_LENGTH, POS, H + get_block: + match AREA=,DATA_LENGTH=,CheckSumBlocks, CheckSumBlocks + jyes block_ready + match AREA=,DATA_LENGTH, CheckSumBlocks + jyes last_block + exit + last_block: + arrange CheckSumBlocks, + block_ready: + compute POS, 0 + process_block: + check POS + 2 <= DATA_LENGTH + jno finish_block + load H, AREA:POS, 2 + compute CHECKSUM, CHECKSUM + H + compute POS, POS + 2 + jump process_block + finish_block: + check POS + 1 = DATA_LENGTH + jno reduce_checksum + load H, AREA:POS, 1 + compute CHECKSUM, CHECKSUM + H + reduce_checksum: + check CHECKSUM shr 16 + jno get_block + compute CHECKSUM, CHECKSUM shr 16 + CHECKSUM and 0FFFFh + jump reduce_checksum + done: + end calminstruction + + CheckSum + CHECKSUM = CHECKSUM + $% + store CHECKSUM at PE:OptionalHeader.CheckSum + end namespace +end postpone diff --git a/toolchain/fasm2/include/iset/3dnow.inc b/toolchain/fasm2/include/iset/3dnow.inc new file mode 100644 index 0000000..3374dfc --- /dev/null +++ b/toolchain/fasm2/include/iset/3dnow.inc @@ -0,0 +1,46 @@ + +iterate , pf2id,1Dh, pfacc,0AEh, pfadd,9Eh, pfmax,0A4h, pfmin,94h, \ + pfmul,0B4h, pfrcp,96h, pfsub,9Ah, pi2fd,0Dh, pi2fw,0Ch, \ + pfsubr,0AAh, pavgusb,0BFh, pfcmpeq,0B0h, pfcmpge,90h, pfcmpgt,0A0h, \ + pfrsqrt,97h, pmulhrw,0B7h, pfrcpit2,0B6h, pfrsqit1,0A7h + + calminstruction instr? dest*,src* + call x86.require.3DNow + call MMX.parse_operand@dest, dest + call MMX.parse_operand@src, src + check @src.size and not @dest.size + jno size_ok + err 'operand sizes do not match' + size_ok: + check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + jno invalid_combination_of_operands + xcall x86.store_instruction@src, <0Fh,0Fh>,@dest.rm,(1),(opcode) + exit + invalid_combination_of_operands: + err 'invalid combination of operands' + end calminstruction + +end iterate + +calminstruction femms? + call x86.require.3DNow + emit 1, 0Fh + emit 1, 0Eh +end calminstruction + +iterate , prefetch,0, prefetchw,1 + calminstruction instr? src* + call x86.require.3DNow + call MMX.parse_operand@src, src + check @src.type = 'mem' + jno invalid_operand + check @src.size and not 1 + jno size_ok + err 'invalid operand size' + size_ok: + xcall x86.store_instruction@src, <0Fh,0Dh>,(postbyte) + exit + invalid_operand: + err 'invalid operand' + end calminstruction +end iterate diff --git a/toolchain/fasm2/include/iset/aes.inc b/toolchain/fasm2/include/iset/aes.inc new file mode 100644 index 0000000..ecf2a7c --- /dev/null +++ b/toolchain/fasm2/include/iset/aes.inc @@ -0,0 +1,58 @@ + +iterate , aesdec,0DEh, aesenc,0DCh, aesdeclast,0DFh, aesenclast,0DDh + + macro instr? dest*,src* + require AESNI + SSE.basic_instruction 66h,<38h,supp>,16,dest,src + end macro + + macro v#instr? dest*,src*,src2* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @dest.size <> @src.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + @src2.memsize = 0 + if x86.ext and x86.VAES.ext + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,0,@dest.rm,@src.rm + else + require AESNI + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,EVEX_FORBIDDEN,opcode,0,@dest.rm,@src.rm + end if + + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , aesimc,0DBh + + macro instr? dest*,src* + require AESNI + SSE.basic_instruction 66h,<38h,supp>,16,dest,src + end macro + + macro v#instr? dest*,src* + require AESNI + AVX_512.single_source_instruction VEX_66_0F38_W0,EVEX_FORBIDDEN,opcode,16,dest,src + end macro + +end iterate + +iterate , aeskeygenassist,0DFh + + macro instr? dest*,src*,imm* + require AESNI + SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm + end macro + + macro v#instr? dest*,src*,imm* + require AESNI + AVX_512.single_source_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,opcode,16,dest,src,imm + end macro + +end iterate diff --git a/toolchain/fasm2/include/iset/avx.inc b/toolchain/fasm2/include/iset/avx.inc new file mode 100644 index 0000000..a327bf6 --- /dev/null +++ b/toolchain/fasm2/include/iset/avx.inc @@ -0,0 +1,4319 @@ + +element AVX.reg + +repeat 16, i:0 + element ymm#i? : AVX.reg + i +end repeat + +element AVX_512.reg + +element AVX_512.r128 : AVX_512.reg + 16 +element AVX_512.r256 : AVX_512.reg + 32 +element AVX_512.r512 : AVX_512.reg + 64 + +repeat 32, i:0 + element zmm#i? : AVX_512.r512 + i +end repeat + +repeat 16, i:16 + element xmm#i? : AVX_512.r128 + i + element ymm#i? : AVX_512.r256 + i +end repeat + +element AVX_512.maskreg + +repeat 8, i:0 + element k#i? : AVX_512.maskreg + i +end repeat + +VEX_0F_W0 = 1 +VEX_66_0F_W0 = 1 + 1 shl 8 +VEX_F3_0F_W0 = 1 + 10b shl 8 +VEX_F2_0F_W0 = 1 + 11b shl 8 + +VEX_0F38_W0 = 10b +VEX_66_0F38_W0 = 10b + 1 shl 8 +VEX_F3_0F38_W0 = 10b + 10b shl 8 +VEX_F2_0F38_W0 = 10b + 11b shl 8 + +VEX_0F3A_W0 = 11b +VEX_66_0F3A_W0 = 11b + 1 shl 8 +VEX_F3_0F3A_W0 = 11b + 10b shl 8 +VEX_F2_0F3A_W0 = 11b + 11b shl 8 + +VEX_0F_W1 = VEX_0F_W0 or 8000h +VEX_66_0F_W1 = VEX_66_0F_W0 or 8000h +VEX_F3_0F_W1 = VEX_F3_0F_W0 or 8000h +VEX_F2_0F_W1 = VEX_F2_0F_W0 or 8000h + +VEX_0F38_W1 = VEX_0F38_W0 or 8000h +VEX_66_0F38_W1 = VEX_66_0F38_W0 or 8000h +VEX_F3_0F38_W1 = VEX_F3_0F38_W0 or 8000h +VEX_F2_0F38_W1 = VEX_F2_0F38_W0 or 8000h + +VEX_0F3A_W1 = VEX_0F3A_W0 or 8000h +VEX_66_0F3A_W1 = VEX_66_0F3A_W0 or 8000h +VEX_F3_0F3A_W1 = VEX_F3_0F3A_W0 or 8000h +VEX_F2_0F3A_W1 = VEX_F2_0F3A_W0 or 8000h + +EVEX_AS_VEX = 0 +EVEX_W1 = 1 shl 15 +EVEX_REQUIRED = 1 shl 10 +EVEX_FORBIDDEN = 1 shl 2 +EVEX_VL = 1 shl 22 +EVEX_VL_AVX2 = 1 shl 32 +EVEX_BW = 1 shl 23 +EVEX_DQ = 1 shl 24 + +iterate context, @dest,@src,@src2,@aux + + namespace context + + define vex + define evex + define evex_flags + define mask + define evex_b + define memsize + define broadcast + define rounding + define visize + + calminstruction AVX_512.parse_operand#context operand + + call x86.parse_operand#context, operand + + check type = 'reg' & size = 1 & rm >= 4 & (~ defined x86.REX_FORBIDDEN | rm and x86.REX_FORBIDDEN) + jyes invalid_operand + check type = 'imm' & size = 0 + jno export_common + + check imm eq 1 elementof imm & 1 metadataof imm relativeto SSE.reg + jyes xmm_register + check imm eq 1 elementof imm & 1 metadataof imm relativeto AVX.reg + jyes ymm_register + check 1 metadataof (1 metadataof imm) relativeto AVX_512.reg & imm eq 1 elementof imm + jyes xyzmm_register + check imm eq 1 elementof imm & 1 metadataof imm relativeto AVX_512.maskreg + jyes mask_register + exit + + invalid_operand: + err 'invalid operand' + + xmm_register: + + compute rm, 1 metadataof imm - SSE.reg + compute size, 16 + + jump export_mmreg + + ymm_register: + + compute rm, 1 metadataof imm - AVX.reg + compute size, 32 + + jump export_mmreg + + mask_register: + + compute rm, 1 metadataof imm - AVX_512.maskreg + compute size, 8 + compute type, 'maskreg' + + jump export_reg + + xyzmm_register: + + compute rm, 1 metadataof imm - 1 elementof (1 metadataof imm) + compute size, 1 metadataof (1 metadataof imm) - AVX_512.reg + + export_mmreg: + + compute type, 'mmreg' + + export_reg: + + compute mod, 11b + + export_common: + + compute mask, 0 + compute evex_b, 0 + compute memsize, 0 + + end calminstruction + + calminstruction AVX_512.parse_k1z_operand#context operand + + local k1, z + transform operand + match operand {k1} { =z? }, operand + jyes k1z + match operand {k1}, operand + jyes k1 + call AVX_512.parse_operand#context, operand + exit + k1z: + compute z, 80h + jump masked + k1: + compute z, 0 + masked: + call AVX_512.parse_operand#context, operand + check z & type = 'mem' + jyes invalid_mask + check k1 eq 1 elementof k1 & 1 metadataof k1 relativeto AVX_512.maskreg & 1 metadataof k1 - AVX_512.maskreg > 0 + jno invalid_mask + compute mask, (1 metadataof k1 - AVX_512.maskreg) or z + exit + invalid_mask: + err 'invalid mask' + + end calminstruction + + calminstruction AVX_512.parse_k1_operand#context operand + + local k1 + transform operand + match operand {k1}, operand + jyes k1 + call AVX_512.parse_operand#context, operand + exit + k1: + call AVX_512.parse_operand#context, operand + check k1 eq 1 elementof k1 & 1 metadataof k1 relativeto AVX_512.maskreg & 1 metadataof k1 - AVX_512.maskreg > 0 + jno invalid_mask + compute mask, 1 metadataof k1 - AVX_512.maskreg + exit + invalid_mask: + err 'invalid mask' + + end calminstruction + + calminstruction AVX_512.parse_bcst_operand#context operand,unit + + transform operand + match operand {broadcast}, operand + jyes mem_bcst + call AVX_512.parse_operand#context, operand + exit + + invalid_operand: + err 'invalid operand' + + mem_bcst: + call AVX_512.parse_operand#context, operand + + check type = 'mem' + jno invalid_operand + + compute memsize, unit + check memsize + jyes implied_unit + check size + jno operand_size_not_specified + compute memsize, size + jump unit_ok + operand_size_not_specified: + err 'operand size not specified' + exit + implied_unit: + check size and not memsize + jno unit_ok + err 'invalid operand size' + exit + unit_ok: + + match =1to2?, broadcast + jyes bcst_2 + match =1to4?, broadcast + jyes bcst_4 + match =1to8?, broadcast + jyes bcst_8 + match =1to16?, broadcast + jyes bcst_16 + err 'invalid broadcast' + exit + bcst_2: + compute broadcast, 2 + jump bcst_ok + bcst_4: + compute broadcast, 4 + jump bcst_ok + bcst_8: + compute broadcast, 8 + jump bcst_ok + bcst_16: + compute broadcast, 16 + bcst_ok: + compute size, memsize * broadcast + compute evex_b, 1 + + end calminstruction + + calminstruction AVX_512.parse_er#context operand,vsize:64 + + check type = 'mem' | size <> vsize + jyes invalid_operand + + match { =rn?-=sae? }, operand + jyes rounding_0 + match { =rd?-=sae? }, operand + jyes rounding_1 + match { =ru?-=sae? }, operand + jyes rounding_2 + match { =rz?-=sae? }, operand + jyes rounding_3 + invalid_operand: + err 'invalid operand' + exit + rounding_0: + compute rounding, 0 + jump rounding_ok + rounding_1: + compute rounding, 1 + jump rounding_ok + rounding_2: + compute rounding, 2 + jump rounding_ok + rounding_3: + compute rounding, 3 + jump rounding_ok + + rounding_ok: + compute evex_b, 1 + + end calminstruction + + calminstruction AVX_512.parse_sae#context operand + + check type = 'mem' + jyes invalid_operand + + match { =sae? }, operand + jno invalid_operand + + compute evex_b, 1 + compute rounding, -1 + + exit + + invalid_operand: + err 'invalid operand' + + end calminstruction + + calminstruction AVX_512.parse_vsib_operand#context operand + + local i, pre, suf + + compute segment_prefix, 0 + + compute size, 0 + compute displacement_size, 0 + + transform operand + + match pre suf, operand + jno no_size_prefix + transform pre, x86 + jno no_size_prefix + match :size, pre + jno no_size_prefix + arrange operand, suf + no_size_prefix: + + match [address], operand + jyes memory_operand + match =ptr? address, operand + jyes memory_operand + + jump invalid_operand + + memory_operand: + compute type, 'mem' + + match segment:address, address + jno segment_prefix_ok + check segment eq 1 elementof segment & 1 metadataof segment relativeto x86.sreg + jno invalid_operand + compute segment, 1 metadataof segment - x86.sreg + check segment >= 4 + jyes segment_prefix_386 + compute segment_prefix, 26h + segment shl 3 + jump segment_prefix_ok + segment_prefix_386: + compute segment_prefix, 64h + segment-4 + segment_prefix_ok: + + match pre suf, address + jno no_address_size_prefix + transform pre, x86 + jno no_address_size_prefix + match :pre, pre + jno no_address_size_prefix + arrange address, suf + check pre = 4 | pre = 8 + jno invalid_address_size + compute mode, pre shl 3 + no_address_size_prefix: + + compute mode, 0 + compute scale, 0 + compute index, 0 + compute base, 0 + compute auto_relative, 0 + + check size + jyes size_override + compute size, sizeof address + size_override: + + compute address, address + compute base_registers, 0 + compute index_registers, 0 + compute i, 1 + extract_registers: + check i > elementsof address + jyes registers_extracted + check i metadataof address relativeto SSE.reg | i metadataof address relativeto AVX.reg | 1 metadataof (i metadataof address) relativeto AVX_512.reg + jyes index_term + check i metadataof address relativeto x86.r32 | i metadataof address relativeto x86.r64 + jno next_term + compute base_registers, base_registers + i elementof address * i scaleof address + jump next_term + index_term: + compute index_registers, index_registers + i elementof address * i scaleof address + next_term: + compute i, i+1 + jump extract_registers + registers_extracted: + compute displacement, address - base_registers - index_registers + compute auto_relative, 0 + + check elementsof index_registers = 1 + jno invalid_address + compute scale, 1 scaleof index_registers + compute index, 0 scaleof (1 metadataof index_registers) + check scale and (scale-1) | scale > 8 + jyes invalid_address + check 1 metadataof index_registers relativeto SSE.reg + jyes xmm_index + check 1 metadataof index_registers relativeto AVX.reg + jyes ymm_index + compute visize, 1 metadataof (1 metadataof index_registers) - AVX_512.reg + jump index_ok + ymm_index: + compute visize, 32 + jump index_ok + xmm_index: + compute visize, 16 + index_ok: + + compute rm, 4 + check elementsof base_registers = 1 & 1 scaleof base_registers = 1 + jyes base_and_index + check elementsof base_registers = 0 + jno invalid_address + compute base, 5 + compute displacement_size, 4 + compute mod, 0 + compute mode, x86.mode + check mode > 16 + jyes ready + compute mode, 32 + jump ready + base_and_index: + compute base, 0 scaleof (1 metadataof base_registers) + check mode & mode <> 0 scaleof (1 metadataof (1 metadataof base_registers)) shl 3 + jyes invalid_address + compute mode, 0 scaleof (1 metadataof (1 metadataof base_registers)) shl 3 + + setup_displacement: + check displacement relativeto 0 + jno displacement_32bit + check displacement = 0 & rm and 111b <> 5 & (rm <> 4 | base and 111b <> 5) + jyes displacement_empty + check displacement < 80h & displacement >= -80h + jyes displacement_8bit + check displacement - 1 shl mode >= -80h & displacement < 1 shl mode + jyes displacement_8bit_wrap + displacement_32bit: + compute displacement_size, 4 + compute mod, 2 + jump ready + displacement_8bit_wrap: + compute displacement, displacement - 1 shl mode + displacement_8bit: + compute displacement_size, 1 + compute mod, 1 + jump ready + index_only: + compute displacement_size, 4 + compute mod, 0 + jump ready + displacement_empty: + compute displacement_size, 0 + compute mod, 0 + + ready: + + compute mask, 0 + compute evex_b, 0 + compute memsize, 0 + + exit + + invalid_operand: + err 'invalid operand' + exit + invalid_address: + err 'invalid address' + exit + invalid_address_size: + err 'invalid address size' + exit + + end calminstruction + + calminstruction AVX_512.parse_k1_vsib_operand#context operand + + local k1 + transform operand + match operand {k1}, operand + jyes k1 + call AVX_512.parse_vsib_operand#context, operand + exit + k1: + call AVX_512.parse_vsib_operand#context, operand + check k1 eq 1 elementof k1 & 1 metadataof k1 relativeto AVX_512.maskreg & 1 metadataof k1 - AVX_512.maskreg > 0 + jno invalid_mask + compute mask, 1 metadataof k1 - AVX_512.maskreg + exit + invalid_mask: + err 'invalid mask' + + end calminstruction + + calminstruction AVX.store_instruction#context vsize*,vex_mpw*,opcode*,reg*,vreg:0,imm_size:0,immediate + compute evex_b, 0 + compute memsize, 0 + xcall AVX_512.store_instruction#context, vsize,vex_mpw,(EVEX_FORBIDDEN),opcode,(0),reg,vreg,imm_size,immediate + end calminstruction + + calminstruction AVX_512.store_instruction#context vsize*,vex_mpw*,evex_f*,opcode*,mask*,reg*,vreg:0,imm_size:0,immediate + + check segment_prefix + jno segment_prefix_ok + + check mode = 64 + jyes segment_in_long_mode + check mode = 16 & ( rm = 2 | rm = 3 | ( mod > 0 & rm = 6 ) ) + jyes ss_segment_default + check mode = 32 & ( ( mod > 0 & rm = 5 ) | ( rm = 4 & base = 4 ) | ( mod > 0 & rm = 4 & base = 5 ) ) + jyes ss_segment_default + + ds_segment_default: + check segment_prefix = 3Eh + jyes segment_prefix_ok + jump store_segment_prefix + ss_segment_default: + check segment_prefix = 36h + jyes segment_prefix_ok + jump store_segment_prefix + segment_in_long_mode: + check segment_prefix < 64h + jyes segment_prefix_ok + store_segment_prefix: + emit 1, segment_prefix + segment_prefix_ok: + + check mod <> 11b & mode <> x86.mode + jno addressing_prefix_ok + check mode = 64 | (mode = 16 & x86.mode = 64) + jno store_addressing_prefix + err 'illegal addressing mode' + store_addressing_prefix: + emit 1, 67h + addressing_prefix_ok: + + compute evex, vex_mpw + compute evex_flags, evex_f + + check x86.simd >= x86.AVX512F.simd + jyes avx_level_ok + compute evex_flags, evex_flags or EVEX_FORBIDDEN + avx_level_ok: + + check evex_b + jno evex_L'L + compute evex, evex or evex_b shl 20 + evex_L'L: + check mod = 11b & evex_b & rounding >= 0 + jyes evex_rounding + check vsize = 64 + jyes evex_L' + check evex_flags and EVEX_VL & x86.ext and x86.AVX512VL.ext = 0 + jno evex_L + compute evex_flags, evex_flags or EVEX_FORBIDDEN + evex_L: + check vsize = 32 + jno evex_mask + compute evex, evex or 1 shl 21 + check evex_flags and EVEX_VL_AVX2 + jno evex_mask + call x86.require.AVX2 + jump evex_mask + evex_L': + compute evex, evex or 1 shl 22 + jump evex_mask + evex_rounding: + compute evex, evex or rounding shl 21 + + evex_mask: + check mask + jno evex_X + compute evex, evex or mask shl 16 + + evex_X: + check rm and 10000b | (mod <> 11b & mode > 16 & rm = 4 & index and 1000b) + jno evex_B + compute evex, evex or 1 shl 6 + evex_B: + check rm and 1000b | (mod <> 11b & mode > 16 & rm = 4 & base and 1000b) + jno evex_R' + compute evex, evex or 1 shl 5 + evex_R': + check reg and 10000b + jno evex_R + compute evex, evex or 1 shl 4 + evex_R: + check reg and 1000b + jno evex_V' + compute evex, evex or 1 shl 7 + evex_V': + check vreg and 10000b + jno evex_vvvv + compute evex, evex or 1 shl 19 + evex_vvvv: + compute evex, evex or (vreg and 1111b) shl 11 + + check x86.mode < 64 & evex and 00001000_01000000_11110000b + jno allowed + err 'instruction requires long mode' + allowed: + + local evex_displacement_size, compressed_displacement + + check displacement_size + jno no_displacement_compression + compute displacement, displacement + check (mode > 16 & rm = 5) | (mode = 16 & rm = 6) + jyes no_displacement_compression + check memsize + jyes displacement_compression + compute memsize, vsize + displacement_compression: + check displacement relativeto 0 & displacement mod? memsize = 0 + jno displacement_incompressible + compute compressed_displacement, displacement / memsize + check compressed_displacement < 80h & compressed_displacement >= -80h + jyes displacement_compressed + check compressed_displacement - 1 shl mode >= -80h & compressed_displacement < 1 shl mode + jno displacement_incompressible + compute compressed_displacement, compressed_displacement - 1 shl mode + displacement_compressed: + compute evex_displacement_size, 1 + jump choose_prefix + displacement_incompressible: + compute evex_displacement_size, 4 + check mode > 16 + jyes choose_prefix + compute evex_displacement_size, 2 + jump choose_prefix + no_displacement_compression: + compute evex_displacement_size, displacement_size + + choose_prefix: + check evex_flags and EVEX_REQUIRED | evex and 11011111_00000000_00010000b | rm and 10000b + jyes evex_required + check ~ evex_flags and EVEX_FORBIDDEN & evex_displacement_size + 1 < displacement_size + jyes evex + jump vex + evex_required: + check evex_flags and EVEX_FORBIDDEN + jno evex + err 'invalid operand' + + vex: + call x86.require.AVX + compute vex, evex and 11111011_11111111b or (evex and 1 shl 21) shr (21-10) + check vex and 10000000_01111111b <> 1 + jyes vex_3byte + vex_2byte: + emit 1, 0C5h + emit 1, ((vex and 10000000b) or ((vex shr 8) and 1111111b)) xor 11111000b + jump evex_done + vex_3byte: + emit 1, 0C4h + emit 1, (vex and 11111111b) xor 11100000b + emit 1, (vex shr 8) xor 01111000b + jump evex_done + + evex: + call x86.require.AVX512F + check evex_flags and EVEX_BW + jno bw_ok + call x86.require.AVX512BW + bw_ok: + check evex_flags and EVEX_DQ + jno dq_ok + call x86.require.AVX512DQ + dq_ok: + compute evex, evex or 1 shl 10 + check evex_flags and EVEX_W1 + jno evex_4byte + compute evex, evex or 1 shl 15 + evex_4byte: + emit 4, 62h + (evex xor 00001000_01111000_11110000b) shl 8 + check mod <> 11b & mod <> 0 & evex_displacement_size > 0 + jno evex_done + compute displacement_size, evex_displacement_size + check evex_displacement_size = 1 + jyes evex_compressed_displacement + compute mod, 2 + jump evex_done + evex_compressed_displacement: + compute displacement, compressed_displacement + compute mod, 1 + evex_done: + + asm db opcode + emit 1, mod shl 6 + (reg and 111b) shl 3 + rm and 111b + + check mod <> 11b & rm = 4 & mode <> 16 + jno sib_ok + emit 1, (bsf scale) shl 6 + (index and 111b) shl 3 + base and 111b + sib_ok: + + check displacement_size = 1 + jyes displacement_8bit + check displacement_size = 2 + jyes displacement_16bit + check displacement_size = 4 | displacement_size = 8 + jno displacement_ok + + check auto_relative + jno auto_relative_ok + check imm_size < 8 + jyes adjust_auto_relative_displacement + compute displacement, displacement - ($ + 4 + 4) + jump auto_relative_ok + adjust_auto_relative_displacement: + compute displacement, displacement - ($ + 4 + imm_size) + auto_relative_ok: + + check mode = 64 & displacement relativeto 0 + jno displacement_ready + check displacement - 1 shl 64 >= -80000000h & displacement < 1 shl 64 + jyes adjust_displacement_wrap + check displacement >= -80000000h & displacement < 80000000h + jyes displacement_ready + err 'address value out of signed range' + adjust_displacement_wrap: + compute displacement, displacement - 1 shl 64 + displacement_ready: + + call dword, displacement + + jump displacement_ok + displacement_16bit: + call word, displacement + jump displacement_ok + displacement_8bit: + emit 1, displacement + displacement_ok: + + check imm_size = 1 + jyes immediate_8bit + check imm_size = 2 + jyes immediate_16bit + check imm_size = 4 + jyes immediate_32bit + check imm_size = 8 + jno immediate_ok + call x86.simm32, immediate + jump immediate_ok + immediate_32bit: + compute imm, +immediate + call dword, imm + jump immediate_ok + immediate_16bit: + compute imm, +immediate + call word, imm + jump immediate_ok + immediate_8bit: + compute imm, +immediate + emit 1, imm + immediate_ok: + + end calminstruction + + end namespace + +end iterate + +macro AVX_512.basic_instruction_bcst_er vex_mpw,evex_f,opcode,unit,dest,src,src_er& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + match src2=,er, src_er + AVX_512.parse_operand@src2 src2 + AVX_512.parse_er@src2 er + else + AVX_512.parse_bcst_operand@src2 src_er,unit + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction_bcst_sae vex_mpw,evex_f,opcode,unit,dest,src,src_sae& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + match src2=,sae, src_sae + AVX_512.parse_operand@src2 src2 + AVX_512.parse_sae@src2 sae + else + AVX_512.parse_bcst_operand@src2 src_sae,unit + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction_bcst_sae_imm8 vex_mpw,evex_f,opcode,unit,dest,src,src2,aux& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,unit + match sae=,imm, aux + AVX_512.parse_sae@src2 sae + x86.parse_operand@aux imm + else + x86.parse_operand@aux aux + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @src.size <> @dest.size | @src2.size and not @dest.size | @aux.size and not 1 + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction_bcst vex_mpw,evex_f,opcode,unit,dest,src,src2 + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,unit + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction_bcst_imm8 vex_mpw,evex_f,opcode,unit,dest,src,src2,aux + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,unit + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + else if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction_er vex_mpw,evex_f,opcode,unit,dest,src,src_er& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + match src2=,er, src_er + AVX_512.parse_operand@src2 src2 + AVX_512.parse_er@src2 er,(unit-1) and not 15 + 16 + else + AVX_512.parse_operand@src2 src_er + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) ) + err 'invalid operand size' + else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg')) + err 'operand sizes do not match' + end if + @src2.memsize = unit + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction_sae vex_mpw,evex_f,opcode,unit,dest,src,src_sae& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + match src2=,sae, src_sae + AVX_512.parse_operand@src2 src2 + AVX_512.parse_sae@src2 sae + else + AVX_512.parse_operand@src2 src_sae + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) ) + err 'invalid operand size' + else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg')) + err 'operand sizes do not match' + end if + @src2.memsize = unit + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction_sae_imm8 vex_mpw,evex_f,opcode,unit,dest,src,src2,aux& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + match sae=,imm, aux + AVX_512.parse_sae@src2 sae + x86.parse_operand@aux imm + else + x86.parse_operand@aux aux + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if ( unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) ) ) | @aux.size and not 1 + err 'invalid operand size' + else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg')) + err 'operand sizes do not match' + end if + @src2.memsize = unit + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction vex_mpw,evex_f,opcode,unit,dest,src,src2 + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) ) + err 'invalid operand size' + else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg')) + err 'operand sizes do not match' + end if + @src2.memsize = unit + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.basic_instruction_imm8 vex_mpw,evex_f,opcode,unit,dest,src,src2,aux& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if ( unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src2.type = 'mem' & @src2.size and not unit) ) ) | @aux.size and not 1 + err 'invalid operand size' + else if @dest.size <> @src.size | (@src2.size and not @dest.size & (unit = 0 | @src2.type = 'mmreg')) + err 'operand sizes do not match' + end if + @src2.memsize = unit + AVX_512.store_instruction@src2 @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.single_source_instruction_bcst_er vex_mpw,evex_f,opcode,unit,dest,src_er& + AVX_512.parse_k1z_operand@dest dest + match src=,er, src_er + AVX_512.parse_operand@src src + AVX_512.parse_er@src er + else + AVX_512.parse_bcst_operand@src src_er,unit + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.single_source_instruction_bcst_sae vex_mpw,evex_f,opcode,unit,dest,src_sae& + AVX_512.parse_k1z_operand@dest dest + match src=,sae, src_sae + AVX_512.parse_operand@src src + AVX_512.parse_sae@src sae + else + AVX_512.parse_bcst_operand@src src_sae,unit + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.single_source_instruction_bcst_sae_imm8 vex_mpw,evex_f,opcode,unit,dest,src,aux& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_bcst_operand@src src,unit + match sae=,imm, aux + AVX_512.parse_sae@src sae + x86.parse_operand@aux imm + else + x86.parse_operand@aux aux + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.single_source_instruction_bcst vex_mpw,evex_f,opcode,unit,dest,src& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_bcst_operand@src src,unit + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.single_source_instruction vex_mpw,evex_f,opcode,unit,dest,src + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src.type = 'mem' & @src.size and not unit) ) + err 'invalid operand size' + else if @src.size and not @dest.size & (unit = 0 | @src.type = 'mmreg') + err 'operand sizes do not match' + end if + @src.memsize = unit + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro AVX_512.single_source_instruction_imm8 vex_mpw,evex_f,opcode,unit,dest,src,aux + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @aux.size and not 1 + err 'invalid operand size' + else if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src.type = 'mem' & @src.size and not unit) ) + err 'invalid operand size' + else if @src.size and not @dest.size & (unit = 0 | @src.type = 'mmreg') + err 'operand sizes do not match' + end if + @src.memsize = unit + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +iterate , add,58h, mul,59h, sub,5Ch, div,5Eh + + macro v#instr#pd? dest*,src*,src2*& + AVX_512.basic_instruction_bcst_er VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2 + end macro + + macro v#instr#ps? dest*,src*,src2*& + AVX_512.basic_instruction_bcst_er VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2 + end macro + + macro v#instr#sd? dest*,src*,src2*& + AVX_512.basic_instruction_er VEX_F2_0F_W0,EVEX_W1,opcode,8,dest,src,src2 + end macro + + macro v#instr#ss? dest*,src*,src2*& + AVX_512.basic_instruction_er VEX_F3_0F_W0,EVEX_AS_VEX,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , min,5Dh, max,5Fh + + macro v#instr#pd? dest*,src*,src2*& + AVX_512.basic_instruction_bcst_sae VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2 + end macro + + macro v#instr#ps? dest*,src*,src2*& + AVX_512.basic_instruction_bcst_sae VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2 + end macro + + macro v#instr#sd? dest*,src*,src2*& + AVX_512.basic_instruction_sae VEX_F2_0F_W0,EVEX_W1,opcode,8,dest,src,src2 + end macro + + macro v#instr#ss? dest*,src*,src2*& + AVX_512.basic_instruction_sae VEX_F3_0F_W0,EVEX_AS_VEX,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , unpckh,15h, unpckl,14h + + macro v#instr#pd? dest*,src*,src2*& + AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2 + end macro + + macro v#instr#ps? dest*,src*,src2*& + AVX_512.basic_instruction_bcst VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , addsub,0D0h, hadd,7Ch, hsub,7Dh + + macro v#instr#pd? dest*,src*,src2* + AVX_512.basic_instruction VEX_66_0F_W0,EVEX_FORBIDDEN,opcode,0,dest,src,src2 + end macro + + macro v#instr#ps? dest*,src*,src2* + AVX_512.basic_instruction VEX_F2_0F_W0,EVEX_FORBIDDEN,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , rsqrt,52h, rcp,53h + + macro v#instr#ps? dest*,src* + AVX_512.single_source_instruction VEX_0F_W0,EVEX_FORBIDDEN,opcode,0,dest,src + end macro + + macro v#instr#ss? dest*,src*,src2* + AVX_512.basic_instruction VEX_F3_0F_W0,EVEX_FORBIDDEN,opcode,4,dest,src,src2 + end macro + +end iterate + +macro vsqrtpd? dest*,src*& + AVX_512.single_source_instruction_bcst_er VEX_66_0F_W0,EVEX_W1+EVEX_VL,51h,8,dest,src +end macro + +macro vsqrtps? dest*,src*& + AVX_512.single_source_instruction_bcst_er VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,51h,4,dest,src +end macro + +macro vsqrtsd? dest*,src*,src2*& + AVX_512.basic_instruction_er VEX_F2_0F_W0,EVEX_W1,51h,8,dest,src,src2 +end macro + +macro vsqrtss? dest*,src*,src2*& + AVX_512.basic_instruction_er VEX_F3_0F_W0,EVEX_AS_VEX,51h,4,dest,src,src2 +end macro + +macro vroundpd? dest*,src*,aux* + AVX_512.single_source_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,9,0,dest,src,aux +end macro + +macro vroundps? dest*,src*,aux* + AVX_512.single_source_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,8,0,dest,src,aux +end macro + +macro vroundsd? dest*,src*,src2*,aux* + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,0Bh,8,dest,src,src2,aux +end macro + +macro vroundss? dest*,src*,src2*,aux* + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,0Ah,4,dest,src,src2,aux +end macro + +macro vshufpd? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_bcst_imm8 VEX_66_0F_W0,EVEX_W1+EVEX_VL,0C6h,8,dest,src,src2,aux +end macro + +macro vshufps? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_bcst_imm8 VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,0C6h,4,dest,src,src2,aux +end macro + +iterate , blendps,0Ch, blendpd,0Dh + + macro v#instr? dest*,src*,src2*,imm* + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,opcode,0,dest,src,src2,imm + end macro + +end iterate + +iterate , blendvps,4Ah, blendvpd,4Bh + + macro v#instr? dest*,src*,src2*,mask* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + AVX_512.parse_operand@aux mask + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'mmreg' + if @src.size <> @dest.size | @src2.size and not @dest.size | @aux.size <> @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F3A_W0,EVEX_FORBIDDEN,opcode,0,@dest.rm,@src.rm,1,(@aux.rm and 1111b) shl 4 + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vbroadcastss? dest*,src* + require AVX2+ + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not 4) + err 'invalid operand size' + end if + @src2.memsize = 4 + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,18h,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro vbroadcastsd? dest*,src* + require AVX2+ + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if @dest.size = 16 | (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not 8) + err 'invalid operand size' + end if + @src.memsize = 8 + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_W1+EVEX_VL,19h,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vpbroadcastd,58h,7Ch,4, vpbroadcastq,59h,7Ch,8 + + macro instr? dest*,src* + require AVX2+ + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if (@src.type='mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not msize) + err 'invalid operand size' + end if + @src.memsize = msize + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX,opcode,@dest.mask,@dest.rm + else if @dest.type = 'mmreg' & @src.type = 'reg' + if @src.size <> msize & (@src.size <> 4 | msize = 8) + err 'invalid operand size' + end if + @src.memsize = msize + if msize = 8 + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode_g,@dest.mask,@dest.rm + else + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode_g,@dest.mask,@dest.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vbroadcastf128? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if @dest.size <> 32 | @src.size and not 16 + err 'invalid operand size' + end if + AVX_512.store_instruction@src 32,VEX_66_0F38_W0,EVEX_FORBIDDEN,1Ah,0,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vbroadcastf32x4,VEX_66_0F38_W0,1Ah,16, vbroadcastf64x4,VEX_66_0F38_W1,1Bh,32, \ + vbroadcasti32x4,VEX_66_0F38_W0,5Ah,16, vbroadcasti64x4,VEX_66_0F38_W1,5Bh,32 + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if @dest.size <= msize | @src.size and not msize + err 'invalid operand size' + end if + @src.memsize = msize + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vshuff32x4,VEX_66_0F3A_W0,23h,4, vshuff64x2,VEX_66_0F3A_W1,23h,4, \ + vshufi32x4,VEX_66_0F3A_W0,43h,4, vshufi64x2,VEX_66_0F3A_W1,43h,4 + + macro instr? dest*,src*,src2*,aux* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,unit + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @dest.size < 32 | @aux.size and not 1 + err 'invalid operand size' + else if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vextractps? dest*,src*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size and not 4 | @src.size <> 16 | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.memsize = 4 + AVX_512.store_instruction@dest 16,VEX_66_0F3A_W0,EVEX_AS_VEX,17h,0,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vinsertps? dest*,src*,src2*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mmreg' | @src2.type = 'mem') & @aux.type = 'imm' + if @dest.size <> 16 | @src.size <> 16 | (@src2.type = 'mmreg' & @src2.size <> 16) | (@src2.type = 'mem' & @src2.size and not 4) | @aux.size and not 1 + err 'invalid operand size' + end if + @src2.memsize = 4 + AVX_512.store_instruction@src2 16,VEX_66_0F3A_W0,EVEX_AS_VEX,21h,0,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vextractf128? dest*,src*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size and not 16 | @src.size <> 32 | @aux.size and not 1 + err 'invalid operand size' + end if + AVX_512.store_instruction@dest 32,VEX_66_0F3A_W0,EVEX_FORBIDDEN,19h,0,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vinsertf128? dest*,src*,src2*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mmreg' | @src2.type = 'mem') & @aux.type = 'imm' + if @dest.size <> 32 | @src.size <> 32 | @src2.size and not 16 | @aux.size and not 1 + err 'invalid operand size' + end if + AVX_512.store_instruction@src2 32,VEX_66_0F3A_W0,EVEX_FORBIDDEN,18h,0,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + + +iterate , vextractf32x4,VEX_66_0F3A_W0,19h,16, vextractf64x4,VEX_66_0F3A_W1,1Bh,32, \ + vextracti32x4,VEX_66_0F3A_W0,39h,16, vextracti64x4,VEX_66_0F3A_W1,3Bh,32 + + macro instr? dest*,src*,aux* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size and not msize | @src.size <= msize | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.memsize = msize + AVX_512.store_instruction@dest @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vinsertf32x4,VEX_66_0F3A_W0,18h,16, vinsertf64x4,VEX_66_0F3A_W1,1Ah,32, \ + vinserti32x4,VEX_66_0F3A_W0,38h,16, vinserti64x4,VEX_66_0F3A_W1,3Ah,32 + + macro instr? dest*,src*,src2*,aux* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mmreg' | @src2.type = 'mem') & @aux.type = 'imm' + if @dest.size <= msize | @src.size <= msize | @src2.size and not msize | @aux.size and not 1 + err 'invalid operand size' + end if + @src2.memsize = msize + AVX_512.store_instruction@src2 @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcmpps,VEX_0F_W0,VEX_0F_W0,4, vcmppd,VEX_66_0F_W0,VEX_66_0F_W1,8 + + macro instr? dest*,src*,src2*,aux*& + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,unit + match sae=,imm, aux + AVX_512.parse_sae@src2 sae + x86.parse_operand@aux imm + else + x86.parse_operand@aux aux + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + else if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_FORBIDDEN,0C2h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + else if @src2.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,evex_mpw,EVEX_REQUIRED+EVEX_VL,0C2h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcmpss,VEX_F3_0F_W0,VEX_F3_0F_W0,4, vcmpsd,VEX_F2_0F_W0,VEX_F2_0F_W1,8 + + macro instr? dest*,src*,src2*,aux*& + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + match sae=,imm, aux + AVX_512.parse_sae@src2 sae + x86.parse_operand@aux imm + else + x86.parse_operand@aux aux + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @dest.size <> 16 | (@src2.type = 'mem' & @src2.size and not unit) + err 'invalid operand size' + else if @dest.size <> @src.size | (@src2.type = 'mmreg' & @src2.size <> @dest.size) + err 'operand sizes do not match' + end if + @src2.memsize = unit + AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_FORBIDDEN,0C2h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @src.size <> 16 | (@src2.type = 'mem' & @src2.size and not unit) | @aux.size and not 1 + err 'invalid operand size' + else if @src2.type = 'mmreg' & @src2.size <> @src.size + err 'operand sizes do not match' + end if + @src2.memsize = unit + AVX_512.store_instruction@src2 @src.size,evex_mpw,EVEX_REQUIRED,0C2h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , eq,0, lt,1, le,2, unord,3, neq,4, nlt,5, nle,6, ord,7, \ + eq_uq,8, nge,9, ngt,0Ah, false,0Bh, neq_qq,0Ch, ge,0Dh, gt,0Eh, true,0Fh, \ + eq_os,10h, lt_oq,11h, le_oq,12h, unord_s,13h, neq_us,14h, nlt_uq,15h, nle_uq,16h, ord_s,17h, \ + eq_us,18h, nge_uq,19h, ngt_uq,1Ah, false_os,1Bh, neq_os,1Ch, ge_oq,1Dh, gt_oq,1Eh, true_us,1Fh + + macro vcmp#cond#pd? dest*,src*,src2*& + vcmppd dest,src,src2,code + end macro + + macro vcmp#cond#ps? dest*,src*,src2*& + vcmpps dest,src,src2,code + end macro + + macro vcmp#cond#sd? dest*,src*,src2*& + vcmpsd dest,src,src2,code + end macro + + macro vcmp#cond#ss? dest*,src*,src2*& + vcmpss dest,src,src2,code + end macro + +end iterate + +iterate , vcomiss,VEX_0F_W0,EVEX_AS_VEX,2Fh,4, vcomisd,VEX_66_0F_W0,EVEX_W1,2Fh,8, vucomiss,VEX_0F_W0,EVEX_AS_VEX,2Eh,4, vucomisd,VEX_66_0F_W0,EVEX_W1,2Eh,8 + + macro instr? dest*,src_sae*& + AVX_512.parse_k1z_operand@dest dest + match src=,sae, src_sae + AVX_512.parse_operand@src src + AVX_512.parse_sae@src sae + else + AVX_512.parse_operand@src src_sae + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if unit & ( @dest.size <> (unit-1) and not 15 + 16 | (@src.type = 'mem' & @src.size and not unit) ) + err 'invalid operand size' + else if @src.size and not @dest.size & (unit = 0 | @src.type = 'mmreg') + err 'operand sizes do not match' + end if + @src.memsize = unit + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , kandw,41h, kandnw,42h, knotw,44h, korw,45h, kxnorw,46h, kxorw,47h + + macro instr? dest*,src*,src2* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg' + AVX.store_instruction@src2 32,VEX_0F_W0,opcode,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , knotw,44h, kortestw,98h + + macro instr? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & @src.type = 'maskreg' + AVX.store_instruction@src 16,VEX_0F_W0,opcode,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro kmovw? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & (@src.type = 'maskreg' | @src.type = 'mem') + if @src.type = 'mem' & @src.size and not 2 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,VEX_0F_W0,90h,@dest.rm + else if @dest.type = 'mem' & @src.type = 'maskreg' + if @dest.size and not 2 + err 'invalid operand size' + end if + AVX.store_instruction@dest 16,VEX_0F_W0,91h,@src.rm + else if @dest.type = 'maskreg' & @src.type = 'reg' + if @src.size <> 4 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,VEX_0F_W0,92h,@dest.rm + else if @dest.type = 'reg' & @src.type = 'maskreg' + if @dest.size <> 4 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,VEX_0F_W0,93h,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , kshiftrw,VEX_66_0F3A_W1,30h, kshiftlw,VEX_66_0F3A_W1,32h + + macro instr? dest*,src*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,vex_mpw,opcode,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro kunpckbw? dest*,src*,src2* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg' + AVX.store_instruction@src2 32,VEX_66_0F_W0,4Bh,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vcvtdq2pd,EVEX_AS_VEX+EVEX_VL,0E6h, vcvtudq2pd,EVEX_REQUIRED+EVEX_VL,7Ah + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_bcst_operand@src src,4 + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size) + err 'invalid operand size' + end if + if @src.memsize = 0 + @src.memsize = @dest.size shr 1 + end if + AVX_512.store_instruction@src @dest.size,VEX_F3_0F_W0,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvtpd2dq,VEX_F2_0F_W0,EVEX_W1+EVEX_VL,0E6h, vcvtpd2ps,VEX_66_0F_W0,EVEX_W1+EVEX_VL,5Ah, vcvtpd2udq,VEX_0F_W1,EVEX_REQUIRED+EVEX_VL,79h + + macro instr? dest*,src_er*& + AVX_512.parse_k1z_operand@dest dest + match src=,er, src_er + AVX_512.parse_operand@src src + AVX_512.parse_er@src er + else + AVX_512.parse_bcst_operand@src src_er,8 + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @src.size = 0 + if @dest.size = 16 + err 'operand size not specified' + else + @src.size = 64 + end if + end if + if (@src.size shr 1 - 1) and not 15 + 16 <> @dest.size | @src.size > 64 + err 'invalid operand size' + end if + AVX_512.store_instruction@src @src.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvtps2pd,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,5Ah + + macro instr? dest*,src_sae*& + AVX_512.parse_k1z_operand@dest dest + match src=,sae, src_sae + AVX_512.parse_operand@src src + AVX_512.parse_sae@src sae + else + AVX_512.parse_bcst_operand@src src_sae,4 + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size) + err 'invalid operand size' + end if + if @src.memsize = 0 + @src.memsize = @dest.size shr 1 + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvttpd2dq,VEX_66_0F_W0,EVEX_W1+EVEX_VL,0E6h, vcvttpd2udq,VEX_0F_W1,EVEX_REQUIRED+EVEX_VL,78h + + macro instr? dest*,src_sae*& + AVX_512.parse_k1z_operand@dest dest + match src=,sae, src_sae + AVX_512.parse_operand@src src + AVX_512.parse_sae@src sae + else + AVX_512.parse_bcst_operand@src src_sae,8 + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @src.size = 0 + if @dest.size = 16 + err 'operand size not specified' + else + @src.size = 64 + end if + end if + if (@src.size shr 1 - 1) and not 15 + 16 <> @dest.size | @src.size > 64 + err 'invalid operand size' + end if + AVX_512.store_instruction@src @src.size,vex_mpw,evex_f,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvtdq2ps,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,5Bh, vcvtudq2ps,VEX_F2_0F_W0,EVEX_REQUIRED+EVEX_VL,7Ah, \ + vcvtps2dq,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,5Bh, vcvtps2udq,VEX_0F_W0,EVEX_REQUIRED+EVEX_VL,79h + + macro instr? dest*,src*& + AVX_512.single_source_instruction_bcst_er vex_mpw,evex_f,opcode,4,dest,src + end macro + +end iterate + + +iterate , vcvttps2dq,VEX_F3_0F_W0,EVEX_AS_VEX+EVEX_VL,5Bh, vcvttps2udq,VEX_0F_W0,EVEX_REQUIRED+EVEX_VL,78h + + macro instr? dest*,src*& + AVX_512.single_source_instruction_bcst_sae vex_mpw,evex_f,opcode,4,dest,src + end macro + +end iterate + +macro vcvtph2ps? dest*,src_sae*& + AVX_512.parse_k1z_operand@dest dest + match src=,sae, src_sae + AVX_512.parse_operand@src src + AVX_512.parse_sae@src sae + else + AVX_512.parse_operand@src src_sae + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size) + err 'invalid operand size' + end if + if @src.memsize = 0 + @src.memsize = @dest.size shr 1 + end if + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,13h,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro vcvtps2ph? dest*,src*,aux*& + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + match sae=,imm, aux + AVX_512.parse_sae@dest sae + x86.parse_operand@aux imm + else + x86.parse_operand@aux aux + end match + if (@dest.type = 'mem' | @dest.type = 'mmreg') & @src.type = 'mmreg' + if (@dest.type = 'mem' & @dest.size and not (@src.size shr 1)) | (@dest.type = 'mmreg' & (@src.size shr 1 - 1) and not 15 + 16 <> @dest.size) + err 'invalid operand size' + end if + if @dest.memsize = 0 + @dest.memsize = @src.size shr 1 + end if + AVX_512.store_instruction@dest @src.size,VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_VL,1Dh,@dest.mask,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vcvtsd2si,VEX_F2_0F,EVEX_AS_VEX,2Dh,8, vcvtss2si,VEX_F3_0F,EVEX_AS_VEX,2Dh,4, \ + vcvtsd2usi,VEX_F2_0F,EVEX_REQUIRED,79h,8, vcvtss2usi,VEX_F3_0F,EVEX_REQUIRED,79h,4 + + macro instr? dest*,src_er*& + x86.parse_operand@dest dest + match src=,er, src_er + AVX_512.parse_operand@src src + AVX_512.parse_er@src er,16 + else + AVX_512.parse_operand@src src_er + end match + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@dest.size <> 4 & @dest.size <> 8) | (@src.type = 'mem' & @src.size and not msize) | (@src.type = 'mmreg' & @src.size <> 16) + err 'invalid operand size' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX_512.store_instruction@src 16,vex_mp#_W1,evex_f,opcode,0,@dest.rm + else + AVX_512.store_instruction@src 16,vex_mp#_W0,evex_f,opcode,0,@dest.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvttsd2si,VEX_F2_0F,EVEX_AS_VEX,2Ch,8, vcvttss2si,VEX_F3_0F,EVEX_AS_VEX,2Ch,4, \ + vcvttsd2usi,VEX_F2_0F,EVEX_REQUIRED,78h,8, vcvttss2usi,VEX_F3_0F,EVEX_REQUIRED,78h,4 + + macro instr? dest*,src_sae*& + x86.parse_operand@dest dest + match src=,sae, src_sae + AVX_512.parse_operand@src src + AVX_512.parse_sae@src sae + else + AVX_512.parse_operand@src src_sae + end match + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@dest.size <> 4 & @dest.size <> 8) | (@src.type = 'mem' & @src.size and not msize) | (@src.type = 'mmreg' & @src.size <> 16) + err 'invalid operand size' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX_512.store_instruction@src 16,vex_mp#_W1,evex_f,opcode,0,@dest.rm + else + AVX_512.store_instruction@src 16,vex_mp#_W0,evex_f,opcode,0,@dest.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vcvtsd2ss? dest*,src*,src2*& + AVX_512.basic_instruction_er VEX_F2_0F_W0,EVEX_W1,5Ah,8,dest,src,src2 +end macro + +macro vcvtss2sd? dest*,src*,src2*& + AVX_512.basic_instruction_sae VEX_F3_0F_W0,EVEX_AS_VEX,5Ah,4,dest,src,src2 +end macro + +iterate , vcvtsi2sd,EVEX_AS_VEX,2Ah, vcvtusi2sd,EVEX_REQUIRED,7Bh + + macro instr? dest*,src*,src_er*& + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + match src2=,er, src_er + AVX_512.parse_operand@src2 src2 + AVX_512.parse_er@src2 er,8 + else + AVX_512.parse_operand@src2 src_er + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'reg' | @src2.type = 'mem') + if @src.size = 0 + err ' operand size not specified' + else if @dest.size <> 16 | @src.size <> 16 | (@src2.size <> 4 & @src2.size <> 8) + err 'invalid operand size' + end if + if @src2.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX_512.store_instruction@src2 16,VEX_F2_0F_W1,evex_f,opcode,0,@dest.rm,@src.rm + else + AVX_512.store_instruction@src2 16,VEX_F2_0F_W0,evex_f,opcode,0,@dest.rm,@src.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvtsi2ss,EVEX_AS_VEX,2Ah, vcvtusi2ss,EVEX_REQUIRED,7Bh + + macro instr? dest*,src*,src_er*& + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + match src2=,er, src_er + AVX_512.parse_operand@src2 src2 + AVX_512.parse_er@src2 er,@src2.size + else + AVX_512.parse_operand@src2 src_er + end match + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'reg' | @src2.type = 'mem') + if @src.size = 0 + err ' operand size not specified' + else if @dest.size <> 16 | @src.size <> 16 | (@src2.size <> 4 & @src2.size <> 8) + err 'invalid operand size' + end if + if @src2.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX_512.store_instruction@src2 16,VEX_F3_0F_W1,evex_f,opcode,0,@dest.rm,@src.rm + else + AVX_512.store_instruction@src2 16,VEX_F3_0F_W0,evex_f,opcode,0,@dest.rm,@src.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vmovapd,VEX_66_0F_W0,EVEX_W1+EVEX_VL,28h,29h, vmovaps,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,28h,29h, \ + vmovupd,VEX_66_0F_W0,EVEX_W1+EVEX_VL,10h,11h, vmovups,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,10h,11h, \ + vmovdqa32,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh, vmovdqa64,VEX_66_0F_W1,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh, \ + vmovdqu32,VEX_F3_0F_W0,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh, vmovdqu64,VEX_F3_0F_W1,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode_rm,@dest.mask,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@dest @src.size,vex_mpw,evex_f,opcode_mr,@dest.mask,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vmovd? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'reg' | @src.type = 'mem') + if @dest.size <> 16 | @src.size and not 4 + err 'invalid operand size' + end if + @src.memsize = 4 + AVX_512.store_instruction@src 16,VEX_66_0F_W0,EVEX_AS_VEX,6Eh,0,@dest.rm + else if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' + if @dest.size and not 4 | @src.size <> 16 + err 'operand sizes do not match' + end if + @dest.memsize = 4 + AVX_512.store_instruction@dest 16,VEX_66_0F_W0,EVEX_AS_VEX,7Eh,0,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro vmovq? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if @dest.size <> 16 | (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' and @src.size and not 8) + err 'invalid operand size' + end if + @src.memsize = 8 + AVX_512.store_instruction@src 16,VEX_F3_0F_W0,EVEX_W1,7Eh,0,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not 8 | @src.size <> 16 + err 'invalid operand size' + end if + @dest.memsize = 8 + AVX_512.store_instruction@dest 16,VEX_66_0F_W0,EVEX_W1,0D6h,0,@src.rm + else if @dest.type = 'mmreg' & @src.type = 'reg' + if @dest.size <> 16 | @src.size <> 8 + err 'invalid operand size' + end if + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX_512.store_instruction@src 16,VEX_66_0F_W1,EVEX_W1,6Eh,0,@dest.rm + else if @dest.type = 'reg' & @src.type = 'mmreg' + if @dest.size <> 8 | @src.size <> 16 + err 'invalid operand size' + end if + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX_512.store_instruction@dest 16,VEX_66_0F_W1,EVEX_W1,7Eh,0,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro vmovddup? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if @src.type = 'mem' & @dest.size = 16 + if @src.size and not 8 + err 'invalid operand size' + end if + @src.memsize = 8 + else + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + @src.memsize = @dest.size + end if + AVX_512.store_instruction@src @dest.size,VEX_F2_0F_W0,EVEX_W1+EVEX_VL,12h,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vmovhlps,12h, vmovlhps,16h + + macro instr? dest*,src*,src2* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mmreg' + if @dest.size <> 16 + err 'invalid operand size' + else if @src.size <> @dest.size | @src2.size <> @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 16,VEX_0F_W0,EVEX_AS_VEX,opcode,0,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vmovhpd,VEX_66_0F_W0,EVEX_W1,16h, vmovhps,VEX_0F_W0,EVEX_AS_VEX,16h, vmovlpd,VEX_66_0F_W0,EVEX_W1,12h, vmovlps,VEX_0F_W0,EVEX_AS_VEX,12h + + macro instr? dest*,src*,src2 + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + match , src2 + if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not 8 | @src.size <> 16 + err 'invalid operand size' + end if + @dest.memsize = 8 + AVX_512.store_instruction@dest 16,vex_mpw,evex_f,opcode+1,0,@src.rm + else + err 'invalid combination of operands' + end if + else + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mem' + if @dest.size <> 16 | @src.size <> 16 | @src2.size and not 8 + err 'invalid operand size' + end if + @src2.memsize = 8 + AVX_512.store_instruction@src2 16,vex_mpw,evex_f,opcode,0,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end match + end macro + +end iterate + +iterate , vmovntdq,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL,0E7h, vmovntpd,VEX_66_0F_W0,EVEX_W1+EVEX_VL,2Bh, vmovntps,VEX_0F_W0,EVEX_AS_VEX+EVEX_VL,2Bh + + macro instr? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@dest @src.size,vex_mpw,evex_f,opcode,0,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vmovntdqa? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2,2Ah,0,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vmovmskpd,VEX_66_0F_W0, vmovmskps,VEX_0F_W0 + + macro instr? dest*,src* + x86.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'reg' & @src.type = 'mmreg' + if @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8) + err 'invalid operand size' + end if + AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_FORBIDDEN,50h,0,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vmovsd,VEX_F2_0F_W0,EVEX_W1,8, vmovss,VEX_F3_0F_W0,EVEX_AS_VEX,4 + + macro instr? dest*,src*,src2 + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + match , src2 + if @dest.type = 'mmreg' & @src.type = 'mem' + if @dest.size <> 16 | @src.size and not msize + err 'invalid operand size' + end if + @src.memsize = msize + AVX_512.store_instruction@src 16,vex_mpw,evex_f,10h,@dest.mask,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not msize | @src.size <> 16 + err 'invalid operand size' + end if + @dest.memsize = msize + AVX_512.store_instruction@dest 16,vex_mpw,evex_f,11h,@dest.mask,@src.rm + else + err 'invalid combination of operands' + end if + else + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mmreg' + if @dest.size <> 16 | @src.size <> 16 | @src2.size <> 16 + err 'invalid operand size' + end if + AVX_512.store_instruction@src2 16,vex_mpw,evex_f,10h,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end match + end macro + +end iterate + +macro vmovshdup? dest*,src* + AVX_512.single_source_instruction VEX_F3_0F_W0,EVEX_AS_VEX+EVEX_VL,16h,0,dest,src +end macro + +macro vmovsldup? dest*,src* + AVX_512.single_source_instruction VEX_F3_0F_W0,EVEX_AS_VEX+EVEX_VL,12h,0,dest,src +end macro + +iterate , vpermilps,4,EVEX_AS_VEX+EVEX_VL,0Ch,4, vpermilpd,8,EVEX_W1+EVEX_VL,0Dh,5 + + macro instr? dest*,src*,src2* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_bcst_operand@src src,unit + AVX_512.parse_bcst_operand@src2 src2,unit + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,evex_f,opcode_rrm,@dest.mask,@dest.rm,@src.rm + else if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @src2.type = 'imm' + if @src2.size and not 1 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,VEX_66_0F3A_W0,evex_f,opcode_rri,@dest.mask,@dest.rm,,1,@src2.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpaddd,0FEh, vpsubd,0FAh, vpunpckhdq,6Ah, vpunpckldq,62h + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vpaddq,0D4h, vpmuludq,0F4h, vpsubq,0FBh, vpunpckhqdq,6Dh, vpunpcklqdq,6Ch + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_W1+EVEX_VL+EVEX_VL_AVX2,opcode,8,dest,src,src2 + end macro + +end iterate + +iterate , vpandd,0DBh, vpandnd,0DFh, vpord,0EBh, vpxord,0EFh + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vpandq,0DBh, vpandnq,0DFh, vporq,0EBh, vpxorq,0EFh + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2 + end macro + +end iterate + +iterate , vpmaxsd,3Dh, vpmaxud,3Fh, vpminsd,39h, vpminud,3Bh, vpmulld,40h + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vpmuldq,28h + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_W1+EVEX_VL+EVEX_VL_AVX2,opcode,8,dest,src,src2 + end macro + +end iterate + +iterate , vpmuldq,28h, vpmaxsq,3Dh, vpmaxuq,3Fh, vpminsq,39h, vpminuq,3Bh, vpmullq,40h + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2 + end macro + +end iterate + +iterate , vpabsd,1Eh + + macro instr? dest*,src* + AVX_512.single_source_instruction_bcst VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2,opcode,4,dest,src + end macro + +end iterate + +iterate , vpabsq,1Fh + + macro instr? dest*,src* + AVX_512.single_source_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src + end macro + +end iterate + +iterate , vpshufd,VEX_66_0F_W0 + + macro instr? dest*,src*,aux* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2,70h,@dest.mask,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpsllvd,47h, vpsrlvd,45h, vpsravd,46h + + macro instr? dest*,src*,src2* + require AVX2+ + AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vpsllvq,EVEX_AS_VEX+EVEX_VL,47h, vpsrlvq,EVEX_AS_VEX+EVEX_VL,45h, vpsravq,EVEX_REQUIRED+EVEX_VL,46h + + macro instr? dest*,src*,src2* + require AVX2+ + AVX_512.basic_instruction_bcst VEX_66_0F38_W1,evex_f,opcode,8,dest,src,src2 + end macro + +end iterate + +iterate , vpermi2d,4,VEX_66_0F38_W0,76h, vpermi2q,8,VEX_66_0F38_W1,76h, \ + vpermt2d,4,VEX_66_0F38_W0,7Eh, vpermt2q,8,VEX_66_0F38_W1,7Eh, \ + vprorvd,4,VEX_66_0F38_W0,14h, vprorvq,8,VEX_66_0F38_W1,14h, \ + vprolvd,4,VEX_66_0F38_W0,15h, vprolvq,8,VEX_66_0F38_W1,15h + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src,src2 + end macro + +end iterate + +iterate , vprord,4,VEX_66_0F_W0,0, vprorq,8,VEX_66_0F_W1,0, vprold,4,VEX_66_0F_W0,1, vprolq,8,VEX_66_0F_W1,1 + + macro instr? dest*,src*,aux* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_bcst_operand@src src,unit + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @src.size and not @dest.size | @aux.size and not 1 + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,72h,@dest.mask,postbyte,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpslld,0F2h,72h,6, vpsrad,0E2h,72h,4, vpsrld,0D2h,72h,2 + + macro instr? dest*,src*,src2* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src2 src2 + if @src2.type = 'imm' + AVX_512.parse_bcst_operand@src src,4 + else + AVX_512.parse_operand@src src + end if + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + @src2.memsize = 16 + if @src2.size and not @src2.memsize + err 'invalid operand size' + else if @src.size <> @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2,opcode_rrm,@dest.mask,@dest.rm,@src.rm + else if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') & @src2.type = 'imm' + if @src2.size and not 1 + err 'invalid operand size' + else if @src.size <> @dest.size + err 'operand sizes do not match' + end if + if @src.type = 'mem' + AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL+EVEX_VL_AVX2,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm + else + AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpsllq,0F3h,73h,6, vpsraq,0E2h,72h,4, vpsrlq,0D3h,73h,2 + + macro instr? dest*,src*,src2* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src2 src2 + if @src2.type = 'imm' + AVX_512.parse_bcst_operand@src src,8 + else + AVX_512.parse_operand@src src + end if + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + @src2.memsize = 16 + if @src2.size and not @src2.memsize + err 'invalid operand size' + else if @src.size <> @dest.size + err 'operand sizes do not match' + end if + if `instr = 'vpsraq' + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F_W1,EVEX_REQUIRED+EVEX_VL,opcode_rrm,@dest.mask,@dest.rm,@src.rm + else + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F_W0,EVEX_W1+EVEX_VL+EVEX_VL_AVX2,opcode_rrm,@dest.mask,@dest.rm,@src.rm + end if + else if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') & @src2.type = 'imm' + if @src2.size and not 1 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + if @src.type = 'mem' | `instr = 'vpsraq' + AVX_512.store_instruction@src @dest.size,VEX_66_0F_W1,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm + else + AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_W1+EVEX_VL+EVEX_VL_AVX2,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpcmpeqd,76h, vpcmpgtd,66h + + macro instr? dest*,src*,src2* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,4 + if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src2.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm + else if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,VEX_66_0F_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpcmpeqq,29h, vpcmpgtq,37h + + macro instr? dest*,src*,src2* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,8 + if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src2.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm + else if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,VEX_66_0F38_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vptestnmd,4,VEX_F3_0F38_W0,27h, vptestnmq,8,VEX_F3_0F38_W1,27h, vptestmd,4,VEX_66_0F38_W0,27h, vptestmq,8,VEX_66_0F38_W1,27h + + macro instr? dest*,src*,src2* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,unit + if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src2.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpcmpd,4,VEX_66_0F3A_W0,1Fh, vpcmpud,4,VEX_66_0F3A_W0,1Eh, vpcmpq,8,VEX_66_0F3A_W1,1Fh, vpcmpuq,8,VEX_66_0F3A_W1,1Eh + + macro instr? dest*,src*,src2*,aux* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,unit + x86.parse_operand@aux aux + if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @src2.size and not @src.size | @aux.size and not 1 + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpmovsxbd,21h,4, vpmovsxbq,22h,2, vpmovsxwd,23h,8, vpmovsxwq,24h,4, vpmovsxdq,25h,8, \ + vpmovzxbd,31h,4, vpmovzxbq,32h,2, vpmovzxwd,33h,8, vpmovzxwq,34h,4, vpmovzxdq,35h,8 + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + @src.memsize = msize * (@dest.size shr 4) + if (@src.type = 'mmreg' & @src.size <> (@src.memsize-1) and not 15 + 16) | (@src.type = 'mem' & @src.size and not @src.memsize) + err 'invalid operand size' + end if + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpermq,0, vpermpd,1 + + macro instr? dest*,src*,aux* + require AVX2+ + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_bcst_operand@src src,8 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @dest.size < 32 | @aux.size and not 1 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,VEX_66_0F3A_W1,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpermd,36h, vpermps,16h + + macro instr? dest*,src*,src2* + require AVX2+ + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_bcst_operand@src2 src2,4 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @dest.size < 32 + err 'invalid operand size' + else if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + + macro vperm2f128? dest*,src*,src2*,imm* + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,6,32,dest,src,src2,imm + end macro + + +iterate , vfmaddsub,6, vfmsubadd,7, vfmaddsub,8, vfmsub,0Ah, vfnmadd,0Ch, vfnmsub,0Eh + + iterate , 132,90h, 213,0A0h, 231,0B0h + + macro instr#order#pd? dest*,src*,src2*& + AVX_512.basic_instruction_bcst_er VEX_66_0F38_W1,EVEX_AS_VEX+EVEX_VL,hcode+lcode,8,dest,src,src2 + end macro + + macro instr#order#ps? dest*,src*,src2*& + AVX_512.basic_instruction_bcst_er VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,hcode+lcode,4,dest,src,src2 + end macro + + if lcode > 7 + + macro instr#order#sd? dest*,src*,src2*& + AVX_512.basic_instruction_er VEX_66_0F38_W1,EVEX_AS_VEX,hcode+lcode+1,8,dest,src,src2 + end macro + + macro instr#order#ss? dest*,src*,src2*& + AVX_512.basic_instruction_er VEX_66_0F38_W0,EVEX_AS_VEX,hcode+lcode+1,4,dest,src,src2 + end macro + + end if + + end iterate + +end iterate + +iterate , valignd,4,VEX_66_0F3A_W0,3, vpternlogd,4,VEX_66_0F3A_W0,25h, vpternlogq,8,VEX_66_0F3A_W1,25h + + macro instr? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_bcst_imm8 vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src,src2,aux + end macro + +end iterate + +iterate , valignq,3 + + macro instr? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_bcst_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2,aux + end macro + +end iterate + +iterate , vblendmps,65h, vpblendmd,64h + + macro instr? dest*,src*,src2*& + AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vblendmpd,65h, vpblendmq,64h + + macro instr? dest*,src*,src2*& + AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2 + end macro + +end iterate + +iterate , vrcp14ps,4,VEX_66_0F38_W0,4Ch, vrcp14pd,8,VEX_66_0F38_W1,4Ch, vrsqrt14ps,4,VEX_66_0F38_W0,4Eh, vrsqrt14pd,8,VEX_66_0F38_W1,4Eh + + macro instr? dest*,src*& + AVX_512.single_source_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src + end macro + +end iterate + +iterate , vrcp14ss,4,VEX_66_0F38_W0,4Dh, vrcp14sd,8,VEX_66_0F38_W1,4Dh, vrsqrt14ss,4,VEX_66_0F38_W0,4Fh, vrsqrt14sd,8,VEX_66_0F38_W1,4Fh + + macro instr? dest*,src*& + AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED,opcode,unit,dest,src + end macro + +end iterate + +iterate , vcompressps,VEX_66_0F_W0,8Ah, vcompresspd,VEX_66_0F_W1,8Ah, vpcompressd,VEX_66_0F38_W0,8Bh, vpcompressq,VEX_66_0F38_W1,8Bh + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' + if @dest.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@dest @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vexpandps,VEX_66_0F38_W0,88h, vexpandpd,VEX_66_0F38_W1,88h, vpexpandd,VEX_66_0F38_W0,89h, vpexpandq,VEX_66_0F38_W1,89h + + macro instr? dest*,src* + AVX_512.single_source_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src + end macro + +end iterate + +iterate , fixupimm,54h + + macro v#instr#pd? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_bcst_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2,aux + end macro + + macro v#instr#ps? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_bcst_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2,aux + end macro + + macro v#instr#sd? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED,opcode+1,8,dest,src,src2,aux + end macro + + macro v#instr#ss? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED,opcode+1,4,dest,src,src2,aux + end macro + +end iterate + +iterate , getexp,42h + + macro v#instr#pd? dest*,src*& + AVX_512.single_source_instruction_bcst_sae VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src + end macro + + macro v#instr#ps? dest*,src*& + AVX_512.single_source_instruction_bcst_sae VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src + end macro + + macro v#instr#sd? dest*,src*,src2*& + AVX_512.basic_instruction_sae VEX_66_0F38_W1,EVEX_REQUIRED,opcode+1,8,dest,src,src2 + end macro + + macro v#instr#ss? dest*,src*,src2*& + AVX_512.basic_instruction_sae VEX_66_0F38_W0,EVEX_REQUIRED,opcode+1,4,dest,src,src2 + end macro + +end iterate + +iterate , getmant,26h,26h,27h,27h, rndscale,8,9,0Ah,0Bh + + macro v#instr#pd? dest*,src*,aux*& + AVX_512.single_source_instruction_bcst_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL,opcode_pd,8,dest,src,aux + end macro + + macro v#instr#ps? dest*,src*,aux*& + AVX_512.single_source_instruction_bcst_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_VL,opcode_ps,4,dest,src,aux + end macro + + macro v#instr#sd? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED,opcode_sd,8,dest,src,src2,aux + end macro + + macro v#instr#ss? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED,opcode_ss,4,dest,src,src2,aux + end macro + +end iterate + +iterate , vscalefpd,8,VEX_66_0F38_W1, vscalefps,4,VEX_66_0F38_W0 + + macro instr? dest*,src*,src2*& + AVX_512.basic_instruction_bcst_er vex_mpw,EVEX_REQUIRED+EVEX_VL,2Ch,unit,dest,src,src2 + end macro + +end iterate + +iterate , vscalefsd,8,VEX_66_0F38_W1, vscalefss,4,VEX_66_0F38_W0 + + macro instr? dest*,src*,src2*& + AVX_512.basic_instruction_er vex_mpw,EVEX_REQUIRED,2Dh,unit,dest,src,src2 + end macro + +end iterate + +iterate , vpmovusdb,4,11h, vpmovsdb,4,21h, vpmovdb,4,31h, \ + vpmovusqb,8,12h, vpmovsqb,8,22h, vpmovqb,8,32h, \ + vpmovusdw,2,13h, vpmovsdw,2,23h, vpmovdw,2,33h, \ + vpmovusqw,4,14h, vpmovsqw,4,24h, vpmovqw,4,34h, \ + vpmovusqd,2,15h, vpmovsqd,2,25h, vpmovqd,2,35h + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' + @dest.memsize = @src.size / ratio + if (@dest.type = 'mmreg' & @dest.size <> (@dest.memsize-1) and not 15 + 16) | (@dest.type = 'mem' & @dest.size and not @dest.memsize) + err 'invalid operand size' + end if + AVX_512.store_instruction@dest @src.size,VEX_F3_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpgatherdd,90h,4, vpgatherqd,91h,8, vgatherdps,92h,4, vgatherqps,93h,8 + + macro instr? dest*,src*,aux + match , aux + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_vsib_operand@src src + if @dest.type = 'mmreg' & @dest.mask & @src.type = 'mem' + if @src.size and not 4 | (@dest.size > 16 & @dest.size * (asize shr 2) > @src.visize) | (@src.visize > 16 & @dest.size * (asize shr 2) < @src.visize) + err 'invalid operand size' + else if @dest.rm = @src.index + err 'disallowed combination of registers' + end if + @src.memsize = 4 + AVX_512.store_instruction@src @src.visize,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.index and 10000b + else + err 'invalid combination of operands' + end if + else + require AVX2+ + AVX_512.parse_operand@dest dest + AVX_512.parse_vsib_operand@src src + AVX_512.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mem' & @aux.type = 'mmreg' + if @src.size and not 4 | (@dest.size > 16 & @dest.size * (asize shr 2) > @src.visize) | (@src.visize > 16 & @dest.size * (asize shr 2) < @src.visize) + err 'invalid operand size' + else if @aux.size <> @dest.size + err 'operand sizes do not match' + else if @dest.rm = @aux.rm | @dest.rm = @src.index | @aux.rm = @src.index + err 'disallowed combination of registers' + end if + AVX.store_instruction@src @src.visize,VEX_66_0F38_W0,opcode,@dest.rm,@aux.rm + else + err 'invalid combination of operands' + end if + end match + end macro + +end iterate + +iterate , vpgatherdq,90h,4, vpgatherqq,91h,8, vgatherdpd,92h,4, vgatherqpd,93h,8 + + macro instr? dest*,src*,aux + match , aux + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_vsib_operand@src src + if @dest.type = 'mmreg' & @dest.mask & @src.type = 'mem' + if @src.size and not 8 | (@dest.size > 16 & @dest.size * (asize shr 2) > @src.visize * 2) | (@src.visize > 16 & @dest.size * (asize shr 2) < @src.visize * 2) + err 'invalid operand size' + else if @dest.rm = @src.index + err 'disallowed combination of registers' + end if + @src.memsize = 8 + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@dest.rm,@src.index and 10000b + else + err 'invalid combination of operands' + end if + else + require AVX2+ + AVX_512.parse_operand@dest dest + AVX_512.parse_vsib_operand@src src + AVX_512.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mem' & @aux.type = 'mmreg' + if @src.size and not 8 | (@dest.size > 16 & @dest.size * (asize shr 2) > @src.visize * 2) | (@src.visize > 16 & @dest.size * (asize shr 2) < @src.visize * 2) + err 'invalid operand size' + else if @aux.size <> @dest.size + err 'operand sizes do not match' + else if @dest.rm = @aux.rm | @dest.rm = @src.index | @aux.rm = @src.index + err 'disallowed combination of registers' + end if + AVX.store_instruction@src @dest.size,VEX_66_0F38_W1,opcode,@dest.rm,@aux.rm + else + err 'invalid combination of operands' + end if + end match + end macro + +end iterate + +iterate , vpscatterdd,0A0h,4, vpscatterqd,0A1h,8, vscatterdps,0A2h,4, vscatterqps,0A3h,8 + + macro instr? dest*,src* + AVX_512.parse_k1_vsib_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mem' & @dest.mask & @src.type = 'mmreg' + if @dest.size and not 4 | (@src.size > 16 & @src.size * (asize shr 2) > @dest.visize) | (@dest.visize > 16 & @src.size * (asize shr 2) < @dest.visize) + err 'invalid operand size' + else if @src.rm = @dest.index + err 'disallowed combination of registers' + end if + @dest.memsize = 4 + AVX_512.store_instruction@dest @dest.visize,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm,@dest.index and 10000b + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpscatterdq,0A0h,4, vpscatterqq,0A1h,8, vscatterdpd,0A2h,4, vscatterqpd,0A3h,8 + + macro instr? dest*,src* + AVX_512.parse_k1_vsib_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mem' & @dest.mask & @src.type = 'mmreg' + if @dest.size and not 8 | (@src.size > 16 & @src.size * (asize shr 2) > @dest.visize * 2) | (@dest.visize > 16 & @src.size * (asize shr 2) < @dest.visize * 2) + err 'invalid operand size' + else if @src.rm = @dest.index + err 'disallowed combination of registers' + end if + @dest.memsize = 8 + AVX_512.store_instruction@dest @src.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm,@dest.index and 10000b + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , d,VEX_66_0F_W1,4, q,VEX_0F_W1,8 + + iterate , kand,41h, kandn,42h, knot,44h, kor,45h, kxnor,46h, kxor,47h, kadd,4Ah + + macro instr#t? dest*,src*,src2* + require AVX512BW + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg' + AVX.store_instruction@src2 32,vex_mpw,opcode,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + + end iterate + + iterate , knot,44h, kortest,98h, ktest,99h + + macro instr#t? dest*,src* + require AVX512BW + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & @src.type = 'maskreg' + AVX.store_instruction@src 16,vex_mpw,opcode,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + + end iterate + + macro kmov#t? dest*,src* + require AVX512BW + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & (@src.type = 'maskreg' | @src.type = 'mem') + if @src.type = 'mem' & @src.size and not msize + err 'invalid operand size' + end if + AVX.store_instruction@src 16,vex_mpw,90h,@dest.rm + else if @dest.type = 'mem' & @src.type = 'maskreg' + if @dest.size and not msize + err 'invalid operand size' + end if + AVX.store_instruction@dest 16,vex_mpw,91h,@src.rm + else if @dest.type = 'maskreg' & @src.type = 'reg' + if (msize < 8 & @src.size <> 4) | (msize = 8 & @src.size <> 8) + err 'invalid operand size' + else if msize = 8 & x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src 16,vex_mpw,92h,@dest.rm + else if @dest.type = 'reg' & @src.type = 'maskreg' + if (msize < 8 & @dest.size <> 4) | (msize = 8 & @dest.size <> 8) + err 'invalid operand size' + else if msize = 8 & x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src 16,vex_mpw,93h,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , kshiftrd,VEX_66_0F3A_W0,31h, kshiftrq,VEX_66_0F3A_W1,31h, \ + kshiftld,VEX_66_0F3A_W0,33h, kshiftlq,VEX_66_0F3A_W1,33h + + macro instr? dest*,src*,aux* + require AVX512BW + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,vex_mpw,opcode,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , kunpckwd,VEX_0F_W0, kunpckdq,VEX_0F_W1 + + macro instr? dest*,src*,src2* + require AVX512BW + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg' + AVX.store_instruction@src2 32,vex_mpw,4Bh,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vmovdqu8,VEX_F2_0F_W0,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh, vmovdqu16,VEX_F2_0F_W1,EVEX_REQUIRED+EVEX_VL,6Fh,7Fh + + macro instr? dest*,src* + require AVX512BW + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,evex_f,opcode_rm,@dest.mask,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@dest @src.size,vex_mpw,evex_f,opcode_mr,@dest.mask,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpabsb,1Ch, vpabsw,1Dh + + macro instr? dest*,src* + AVX_512.single_source_instruction VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,0,dest,src + end macro + +end iterate + +iterate , vpacksswb,63h, vpackuswb,67h, vpaddb,0FCh, vpaddw,0FDh, vpaddsb,0ECh, vpaddsw,0EDh, vpaddusb,0DCh, vpaddusw,0DDh, vpavgb,0E0h, vpavgw,0E3h, \ + vpmaddwd,0F5h, vpmaxsw,0EEh, vpmaxub,0DEh, vpminsw,0EAh, vpminub,0DAh, vpmulhuw,0E4h, vpmulhw,0E5h, vpmullw,0D5h, \ + vpsadbw,0F6h, vpsubb,0F8h, vpsubw,0F9h, vpsubsb,0E8h, vpsubsw,0E9h, vpsubusb,0D8h, vpsubusw,0D9h, \ + vpunpckhbw,68h, vpunpckhwd,69h, vpunpcklbw,60h, vpunpcklwd,61h + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , vpackssdw,6Bh + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vpackusdw,2Bh + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vpalignr,0Fh + + macro instr? dest*,src*,src2*,imm* + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,0,dest,src,src2,imm + end macro + +end iterate + +iterate , vpmaddubsw,4, vpmaxsb,3Ch, vpmaxuw,3Eh, vpminsb,38h, vpminuw,3Ah, vpmulhrsw,0Bh, vpshufb,0 + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , vpcmpeqb,74h, vpcmpeqw,75h, vpcmpgtb,64h, vpcmpgtw,65h + + macro instr? dest*,src*,src2* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src2.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,@dest.mask,@dest.rm,@src.rm + else if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,VEX_66_0F_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vpextrb? dest*,src*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if (@dest.type = 'reg' & @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | (@dest.type = 'mem' & @dest.size and not 1) | @src.size <> 16 | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.memsize = 1 + AVX_512.store_instruction@dest 16,VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_BW,14h,0,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vpextrw? dest*,src*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8) | @src.size <> 16 | @aux.size and not 1 + err 'invalid operand size' + end if + AVX_512.store_instruction@src 16,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_BW,0C5h,0,@dest.rm,,1,@aux.imm + else if @dest.type = 'mem' & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size and not 2 | @src.size <> 16 | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.memsize = 2 + AVX_512.store_instruction@dest 16,VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_BW,15h,0,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vpinsrb,VEX_66_0F3A_W0,20h,1, vpinsrw,VEX_66_0F_W0,0C4h,2 + + macro instr? dest*,src*,src2*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'reg' | @src2.type = 'mem') & @aux.type = 'imm' + if @dest.size <> 16 | @src.size <> 16 | (@src2.type = 'reg' & @src2.size <> 4) | (@src2.type = 'mem' & @src2.size and not msize) | @aux.size and not 1 + err 'invalid operand size' + end if + @src2.memsize = msize + AVX_512.store_instruction@src2 16,vex_mpw,EVEX_AS_VEX+EVEX_BW,opcode,0,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpmovsxbw,20h,8, vpmovzxbw,30h,8 + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + @src.memsize = msize * (@dest.size shr 4) + if (@src.type = 'mmreg' & @src.size <> (@src.memsize-1) and not 15 + 16) | (@src.type = 'mem' & @src.size and not @src.memsize) + err 'invalid operand size' + end if + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpshufhw,VEX_F3_0F_W0, vpshuflw,VEX_F2_0F_W0 + + macro instr? dest*,src*,aux* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,70h,@dest.mask,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpslldq,7, vpsrldq,3 + + macro instr? dest*,src*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + else if @src.size <> @dest.size + err 'operand sizes do not match' + end if + if @src.type = 'mem' + AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,73h,0,postbyte,@dest.rm,1,@aux.imm + else + AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,73h,0,postbyte,@dest.rm,1,@aux.imm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpsllw,0F1h,71h,6, vpsraw,0E1h,71h,4, vpsrlw,0D1h,71h,2 + + macro instr? dest*,src*,src2* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + @src2.memsize = 16 + if @src2.size and not @src2.memsize + err 'invalid operand size' + else if @src.size <> @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode_rrm,@dest.mask,@dest.rm,@src.rm + else if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') & @src2.type = 'imm' + if @src2.size and not 1 + err 'invalid operand size' + else if @src.size <> @dest.size + err 'operand sizes do not match' + end if + if @src.type = 'mem' + AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_REQUIRED+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm + else + AVX_512.store_instruction@src @dest.size,VEX_66_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_VL_AVX2+EVEX_BW,opcode,@dest.mask,postbyte,@dest.rm,1,@src2.imm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vdbpsadbw,VEX_66_0F3A_W0,42h + + macro instr? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_imm8 vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,0,dest,src,src2,aux + end macro + +end iterate + +iterate , vpblendmb,VEX_66_0F38_W0,66h, vpblendmw,VEX_66_0F38_W1,66h + + macro instr? dest*,src*,src2*& + AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , vpbroadcastb,78h,7Ah,1, vpbroadcastw,79h,7Bh,2 + + macro instr? dest*,src* + require AVX2+ + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if (@src.type='mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not msize) + err 'invalid operand size' + end if + @src.memsize = msize + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL+EVEX_BW,opcode,@dest.mask,@dest.rm + else if @dest.type = 'mmreg' & @src.type = 'reg' + if @src.size <> msize & (@src.size <> 4 | msize = 8) + err 'invalid operand size' + end if + @src.memsize = msize + if msize = 8 + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode_g,@dest.mask,@dest.rm + else + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode_g,@dest.mask,@dest.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpcmpb,VEX_66_0F3A_W0,3Fh, vpcmpub,VEX_66_0F3A_W0,3Eh, vpcmpw,VEX_66_0F3A_W1,3Fh, vpcmpuw,VEX_66_0F3A_W1,3Eh + + macro instr? dest*,src*,src2*,aux* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @src2.size and not @src.size | @aux.size and not 1 + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpermw,VEX_66_0F38_W1,8Dh, vpermi2w,VEX_66_0F38_W1,75h, vpermt2w,VEX_66_0F38_W1,7Dh + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , vpmovb2m,VEX_F3_0F38_W0,29h, vpmovw2m,VEX_F3_0F38_W1,29h + + macro instr? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & @src.type = 'mmreg' + AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,0,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpmovm2b,VEX_F3_0F38_W0,28h, vpmovm2w,VEX_F3_0F38_W1,28h + + macro instr? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'maskreg' + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,0,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpmovuswb,2,10h, vpmovswb,2,20h, vpmovwb,2,30h + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' + @dest.memsize = @src.size / ratio + if (@dest.type = 'mmreg' & @dest.size <> (@dest.memsize-1) and not 15 + 16) | (@dest.type = 'mem' & @dest.size and not @dest.memsize) + err 'invalid operand size' + end if + AVX_512.store_instruction@dest @src.size,VEX_F3_0F38_W0,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,@dest.mask,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpsllvw,12h, vpsrlvw,10h, vpsravw,11h + + macro instr? dest*,src*,src2* + AVX_512.basic_instruction VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , vptestnmb,VEX_F3_0F38_W0,26h, vptestnmw,VEX_F3_0F38_W1,26h, vptestmb,VEX_66_0F38_W0,26h, vptestmw,VEX_66_0F38_W1,26h + + macro instr? dest*,src*,src2* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src2.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_BW,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vtestps,0Eh, vtestpd,0Fh, vptest,17h + + macro instr? dest*,src* + AVX_512.single_source_instruction VEX_66_0F38_W0,EVEX_FORBIDDEN,opcode,0,dest,src + end macro + +end iterate + +iterate , kandb,41h, kandnb,42h, knotb,44h, korb,45h, kxnorb,46h, kxorb,47h, kaddb,4Ah + + macro instr? dest*,src*,src2* + require AVX512DQ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg' + AVX.store_instruction@src2 32,VEX_66_0F_W0,opcode,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , knotb,44h, kortestb,98h, ktestb,99h + + macro instr? dest*,src* + require AVX512DQ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & @src.type = 'maskreg' + AVX.store_instruction@src 16,VEX_66_0F_W0,opcode,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro kmovb? dest*,src* + require AVX512DQ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & (@src.type = 'maskreg' | @src.type = 'mem') + if @src.type = 'mem' & @src.size and not 1 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,VEX_66_0F_W0,90h,@dest.rm + else if @dest.type = 'mem' & @src.type = 'maskreg' + if @dest.size and not 1 + err 'invalid operand size' + end if + AVX.store_instruction@dest 16,VEX_66_0F_W0,91h,@src.rm + else if @dest.type = 'maskreg' & @src.type = 'reg' + if @src.size <> 4 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,VEX_66_0F_W0,92h,@dest.rm + else if @dest.type = 'reg' & @src.type = 'maskreg' + if @dest.size <> 4 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,VEX_66_0F_W0,93h,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro kaddw? dest*,src*,src2* + require AVX512DQ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @src2.type = 'maskreg' + AVX.store_instruction@src2 32,VEX_0F_W0,opcode,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro ktestw? dest*,src* + require AVX512DQ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & @src.type = 'maskreg' + AVX.store_instruction@src 16,VEX_0F_W0,opcode,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , kshiftrb,VEX_66_0F3A_W0,30h, kshiftlb,VEX_66_0F3A_W0,32h + + macro instr? dest*,src*,aux* + require AVX512DQ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'maskreg' & @src.type = 'maskreg' & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + end if + AVX.store_instruction@src 16,vex_mpw,opcode,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , and,54h, andn,55h, or,56h, xor,57h + + macro v#instr#pd? dest*,src*,src2*& + AVX_512.basic_instruction_bcst VEX_66_0F_W0,EVEX_W1+EVEX_VL+EVEX_DQ,opcode,8,dest,src,src2 + end macro + + macro v#instr#ps? dest*,src*,src2*& + AVX_512.basic_instruction_bcst VEX_0F_W0,EVEX_AS_VEX+EVEX_VL+EVEX_DQ,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vbroadcastf32x2,19h, vbroadcasti32x2,59h + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if @dest.size = 16 | (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size and not 8) + err 'invalid operand size' + end if + @src.memsize = 8 + AVX_512.store_instruction@src @dest.size,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vbroadcastf32x8,VEX_66_0F38_W0,1Bh,32, vbroadcastf64x2,VEX_66_0F38_W1,1Ah,16, \ + vbroadcasti32x8,VEX_66_0F38_W0,5Bh,32, vbroadcasti64x2,VEX_66_0F38_W1,5Ah,16 + + macro instr? dest*,src* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if @dest.size <= msize | @src.size and not msize + err 'invalid operand size' + end if + @src.memsize = msize + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvtpd2qq,VEX_66_0F_W1,7Bh, vcvtpd2uqq,VEX_66_0F_W1,79h, \ + vcvtqq2pd,VEX_F3_0F_W1,0E6h, vcvtuqq2pd,VEX_F3_0F_W1,7Ah + + macro instr? dest*,src*& + AVX_512.single_source_instruction_bcst_er vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,8,dest,src + end macro + +end iterate + +iterate , vcvttpd2qq,VEX_66_0F_W1,7Ah, vcvttpd2uqq,VEX_66_0F_W1,78h + + macro instr? dest*,src*& + AVX_512.single_source_instruction_bcst_sae vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,8,dest,src + end macro + +end iterate + +iterate , vcvtps2qq,VEX_66_0F_W0,7Bh, vcvtps2uqq,VEX_66_0F_W0,79h + + macro instr? dest*,src_er*& + AVX_512.parse_k1z_operand@dest dest + match src=,er, src_er + AVX_512.parse_operand@src src + AVX_512.parse_er@src er,32 + else + AVX_512.parse_bcst_operand@src src_er,4 + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size) + err 'invalid operand size' + end if + if @src.memsize = 0 + @src.memsize = @dest.size shr 1 + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvtqq2ps,VEX_0F_W1,5Bh, vcvtuqq2ps,VEX_F2_0F_W1,7Ah + + macro instr? dest*,src_er*& + AVX_512.parse_k1z_operand@dest dest + match src=,er, src_er + AVX_512.parse_operand@src src + AVX_512.parse_er@src er + else + AVX_512.parse_bcst_operand@src src_er,8 + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @src.size = 0 + if @dest.size = 16 + err 'operand size not specified' + else + @src.size = 64 + end if + end if + if (@src.size shr 1 - 1) and not 15 + 16 <> @dest.size | @src.size > 64 + err 'invalid operand size' + end if + AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vcvttps2qq,VEX_66_0F_W0,7Ah, vcvttps2uqq,VEX_66_0F_W0,78h + + macro instr? dest*,src_sae*& + AVX_512.parse_k1z_operand@dest dest + match src=,sae, src_sae + AVX_512.parse_operand@src src + AVX_512.parse_sae @src,sae + else + AVX_512.parse_bcst_operand@src src_sae,4 + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@src.type = 'mem' & @src.size and not (@dest.size shr 1)) | (@src.type = 'mmreg' & (@dest.size shr 1 - 1) and not 15 + 16 <> @src.size) + err 'invalid operand size' + end if + if @src.memsize = 0 + @src.memsize = @dest.size shr 1 + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vcvtph2ps? dest*,src* + require F16C + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mmreg' | @src.type = 'mem') + if (@src.type = 'mmreg' & @src.size <> 16) | (@src.type = 'mem' & @src.size*2 <> @dest.size) + err 'invalid operand size' + end if + AVX.store_instruction@src @dest.size,VEX_66_0F38_W0,13h,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro vcvtps2ph? dest*,src*,round* + require F16C + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux round + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if (@dest.type = 'mmreg' & @dest.size <> 16) | (@dest.type = 'mem' & @dest.size*2 <> @src.size) | @aux.size and not 1 + err 'invalid operand size' + end if + AVX.store_instruction@dest @src.size,VEX_66_0F3A_W0,1Dh,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vextractf32x8,VEX_66_0F3A_W0,1Bh,32, vextractf64x2,VEX_66_0F3A_W1,19h,16, \ + vextracti32x8,VEX_66_0F3A_W0,3Bh,32, vextracti64x2,VEX_66_0F3A_W1,39h,16 + + macro instr? dest*,src*,aux* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size and not msize | @src.size <= msize | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.memsize = msize + AVX_512.store_instruction@dest @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,@dest.mask,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vinsertf32x8,VEX_66_0F3A_W0,1Ah,32, vinsertf64x2,VEX_66_0F3A_W1,18h,16, \ + vinserti32x8,VEX_66_0F3A_W0,3Ah,32, vinserti64x2,VEX_66_0F3A_W1,38h,16 + + macro instr? dest*,src*,src2*,aux* + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mmreg' | @src2.type = 'mem') & @aux.type = 'imm' + if @dest.size <= msize | @src.size <= msize | @src2.size and not msize | @aux.size and not 1 + err 'invalid operand size' + end if + @src2.memsize = msize + AVX_512.store_instruction@src2 @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vfpclasspd,8,VEX_66_0F3A_W1, vfpclassps,4,VEX_66_0F3A_W0 + + macro instr? dest*,src*,aux* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_bcst_operand@src src,unit + x86.parse_operand@aux aux + if @dest.type = 'maskreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @src.size = 0 + err 'operand size not specified' + else if (@src.size <> 16 & @src.size <> 32 & @src.size <> 64) | @aux.size and not 1 + err 'invalid operand size' + end if + AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,66h,@dest.mask,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vfpclasssd,8,VEX_66_0F3A_W1, vfpclassss,4,VEX_66_0F3A_W0 + + macro instr? dest*,src*,aux* + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'maskreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if (@src.type = 'mem' & @src.size and not unit) | (@src.type = 'mmreg' & @src.size <> 16) | @aux.size and not 1 + err 'invalid operand size' + end if + @src.memsize = 16 + AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_DQ,67h,@dest.mask,@dest.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vpextrd? dest*,src*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if (@dest.type = 'reg' & @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | (@dest.type = 'mem' & @dest.size and not 4) | @src.size <> 16 | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.memsize = 4 + AVX_512.store_instruction@dest 16,VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_DQ,16h,0,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vpinsrd? dest*,src*,src2*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'reg' | @src2.type = 'mem') & @aux.type = 'imm' + if @dest.size <> 16 | @src.size <> 16 | (@src2.type = 'reg' & @src2.size <> 4) | (@src2.type = 'mem' & @src2.size and not 4) | @aux.size and not 1 + err 'invalid operand size' + end if + @src2.memsize = 4 + AVX_512.store_instruction@src2 16,VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_DQ,22h,0,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vpextrq? dest*,src*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if (@dest.type = 'reg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size and not 8 | @src.size <> 16 | @aux.size and not 1 + err 'invalid operand size' + end if + if x86.mode < 64 + err 'instruction requires long mode' + end if + @dest.memsize = 8 + AVX_512.store_instruction@dest 16,VEX_66_0F3A_W1,EVEX_AS_VEX+EVEX_DQ,16h,0,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vpinsrq? dest*,src*,src2*,aux* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'reg' | @src2.type = 'mem') & @aux.type = 'imm' + if @dest.size <> 16 | @src.size <> 16 | @src2.size and not 8 | @aux.size and not 1 + err 'invalid operand size' + end if + if x86.mode < 64 + err 'instruction requires long mode' + end if + @src2.memsize = 8 + AVX_512.store_instruction@src2 16,VEX_66_0F3A_W1,EVEX_AS_VEX+EVEX_DQ,22h,0,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vpmullq? dest*,src*,src2* + AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,40h,8,dest,src,src2 +end macro + +iterate , vpmovm2d,VEX_F3_0F38_W0,38h, vpmovm2q,VEX_F3_0F38_W1,38h + + macro instr? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'maskreg' + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,0,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpmovd2m,VEX_F3_0F38_W0,39h, vpmovq2m,VEX_F3_0F38_W1,39h + + macro instr? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'maskreg' & @src.type = 'mmreg' + AVX_512.store_instruction@src @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,0,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , range,50h + + macro v#instr#pd? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_bcst_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,8,dest,src,src2,aux + end macro + + macro v#instr#ps? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_bcst_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,opcode,4,dest,src,src2,aux + end macro + + macro v#instr#sd? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_DQ,opcode+1,8,dest,src,src2,aux + end macro + + macro v#instr#ss? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_DQ,opcode+1,4,dest,src,src2,aux + end macro + +end iterate + +macro vreducepd? dest*,src*,aux*& + AVX_512.single_source_instruction_bcst_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,56h,8,dest,src,aux +end macro + +macro vreduceps? dest*,src*,aux*& + AVX_512.single_source_instruction_bcst_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_VL+EVEX_DQ,56h,4,dest,src,aux +end macro + +macro vreducesd? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W1,EVEX_REQUIRED+EVEX_DQ,57h,8,dest,src,src2,aux +end macro + +macro vreducess? dest*,src*,src2*,aux*& + AVX_512.basic_instruction_sae_imm8 VEX_66_0F3A_W0,EVEX_REQUIRED+EVEX_DQ,57h,4,dest,src,src2,aux +end macro + + +iterate , pand,0DBh, pandn,0DFh, por,0EBh, pxor,0EFh + + macro v#instr? dest*,src*,src2* + AVX_512.basic_instruction VEX_66_0F_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , phaddw,1, phaddd,2, phaddsw,3, phsubw,5, phsubd,6, phsubsw,7, \ + psignb,8, psignw,9, psignd,0Ah + + macro v#instr? dest*,src*,src2* + AVX_512.basic_instruction VEX_66_0F38_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , mpsadbw,42h, pblendd,02h + + macro v#instr? dest*,src*,src2*,imm* + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,opcode,0,dest,src,src2,imm + end macro + +end iterate + +iterate , pblendw,0Eh + + macro v#instr? dest*,src* + AVX_512.single_source_instruction VEX_66_0F38_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,opcode,0,dest,src + end macro + +end iterate + +macro vpblendvb? dest*,src*,src2*,mask* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + AVX_512.parse_operand@aux mask + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'mmreg' + if @src.size <> @dest.size | @src2.size and not @dest.size | @aux.size <> @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F3A_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,4Ch,0,@dest.rm,@src.rm,1,(@aux.rm and 1111b) shl 4 + else + err 'invalid combination of operands' + end if +end macro + +macro vpmovmskb? dest*,src* + x86.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'reg' & @src.type = 'mmreg' + if (@dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) + err 'invalid operand size' + end if + AVX_512.store_instruction@src @src.size,VEX_66_0F_W0,EVEX_FORBIDDEN+EVEX_VL_AVX2,0D7h,0,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro vdppd? dest*,src*,src2*,imm* + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,41h,16,dest,src,src2,imm +end macro + +macro vdpps? dest*,src*,src2*,imm* + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,40h,16,dest,src,src2,imm +end macro + +macro vlddqu? dest*,src* + AVX_512.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,VEX_F2_0F_W0,EVEX_FORBIDDEN,0F0h,0,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vldmxcsr,2, vstmxcsr,3 + + macro instr? src* + x86.parse_operand@src src + if @src.type = 'mem' + if @src.size and not 4 + err 'invalid operand size' + end if + AVX_512.store_instruction@src 16,VEX_0F_W0,EVEX_FORBIDDEN,0AEh,0,postbyte + else + err 'invalid operand' + end if + end macro + +end iterate + +macro vmaskmovdqu? dest*,src* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mmreg' + if @dest.size <> 16 | @src.size <> 16 + err 'invalid operand size' + end if + AVX_512.store_instruction@src 16,VEX_66_0F_W0,EVEX_FORBIDDEN,0F7h,0,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vmaskmovps,2Ch, vmaskmovpd,2Dh + + macro instr? dest*,src*,src2* + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mem' + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F38_W0,EVEX_FORBIDDEN,opcode,0,@dest.rm,@src.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' & @src2.type = 'mmreg' + if @src.size <> @src2.size | @dest.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@dest @dest.size,VEX_66_0F38_W0,EVEX_FORBIDDEN,opcode+2,0,@src2.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpmaskmovd,0, vpmaskmovq,1 + + macro instr? dest*,src*,src2* + require AVX2+ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mem' + if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + AVX.store_instruction@src2 @dest.size,VEX_66_0F38_W#w,8Ch,@dest.rm,@src.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' & @src2.type = 'mmreg' + if @src.size <> @src2.size | @dest.size and not @src.size + err 'operand sizes do not match' + end if + AVX.store_instruction@dest @src.size,VEX_66_0F38_W#w,8Eh,@src2.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro vbroadcasti128? dest*,src* + require AVX2+ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if @dest.size <> 32 | @src.size and not 16 + err 'invalid operand size' + end if + AVX.store_instruction@src 32,VEX_66_0F38_W0,5Ah,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro vextracti128? dest*,src*,aux* + require AVX2+ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + x86.parse_operand@aux aux + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size and not 16 | @src.size <> 32 | @aux.size and not 1 + err 'invalid operand size' + end if + AVX.store_instruction@dest 32,VEX_66_0F3A_W0,39h,@src.rm,,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vinserti128? dest*,src*,src2*,aux* + require AVX2+ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mmreg' | @src2.type = 'mem') & @aux.type = 'imm' + if @dest.size <> 32 | @src.size <> 32 | @src2.size and not 16 | @aux.size and not 1 + err 'invalid operand size' + end if + AVX.store_instruction@src2 32,VEX_66_0F3A_W0,38h,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro vperm2i128? dest*,src*,src2*,imm* + require AVX2+ + AVX_512.basic_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,46h,32,dest,src,src2,imm +end macro + +macro vzeroall? + require AVX+ + db 0C5h,11111100b,77h +end macro + +macro vzeroupper? + require AVX+ + db 0C5h,11111000b,77h +end macro + +macro xsaveopt? src* + require AVX+ + x86.parse_operand@src src + if @src.type = 'mem' + x86.store_instruction@src <0Fh,0AEh>,6 + else + err 'invalid operand' + end if +end macro + +iterate , vpbroadcastmb2q,VEX_F3_0F38_W1,2Ah, vpbroadcastmw2d,VEX_F3_0F38_W0,3Ah + + macro instr? dest*,src* + require AVX512CD + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'maskreg' + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpconflictd,4,VEX_66_0F38_W0,0C4h, vpconflictq,8,VEX_66_0F38_W1,0C4h, vplzcntd,4,VEX_66_0F38_W0,44h, vplzcntq,8,VEX_66_0F38_W1,44h + + macro instr? dest*,src*& + require AVX512CD + AVX_512.single_source_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src + end macro + +end iterate + +iterate , vfmaddsub,6, vfmsubadd,7, vfmadd,8, vfmsub,0Ah, vfnmadd,0Ch, vfnmsub,0Eh + + iterate , 132,90h, 213,0A0h, 231,0B0h + + macro instr#order#pd? dest*,src*,src2* + require FMA + AVX_512.basic_instruction VEX_66_0F38_W1,EVEX_FORBIDDEN,hcode+lcode,0,dest,src,src2 + end macro + + macro instr#order#ps? dest*,src*,src2* + require FMA + AVX_512.basic_instruction VEX_66_0F38_W0,EVEX_FORBIDDEN,hcode+lcode,0,dest,src,src2 + end macro + + if lcode > 7 + + macro instr#order#sd? dest*,src*,src2* + require FMA + AVX_512.basic_instruction VEX_66_0F38_W1,EVEX_FORBIDDEN,hcode+lcode+1,8,dest,src,src2 + end macro + + macro instr#order#ss? dest*,src*,src2* + require FMA + AVX_512.basic_instruction VEX_66_0F38_W0,EVEX_FORBIDDEN,hcode+lcode+1,4,dest,src,src2 + end macro + + end if + + end iterate + +end iterate + +iterate , vpmadd52luq,0B4h, vpmadd52huq,0B5h + + macro instr? dest*,src*,src2* + require AVX512_IFMA + AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2 + end macro + +end iterate + +iterate , vexp2ps,4,VEX_66_0F38_W0,0C8h, vexp2pd,4,VEX_66_0F38_W1,0C8h, \ + vrcp28ps,4,VEX_66_0F38_W0,0CAh, vrcp28pd,8,VEX_66_0F38_W1,0CAh, vrsqrt28ps,4,VEX_66_0F38_W0,0CCh, vrsqrt28pd,8,VEX_66_0F38_W1,0CCh + + macro instr? dest*,src_sae*& + require AVX512ER + AVX_512.parse_k1z_operand@dest dest + match src=,sae, src_sae + AVX_512.parse_operand@src src + AVX_512.parse_sae@src sae + else + AVX_512.parse_bcst_operand@src src_sae,unit + end match + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 64 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src @dest.size,vex_mpw,EVEX_REQUIRED,opcode,@dest.mask,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vrcp28ss,4,VEX_66_0F38_W0,0CBh, vrcp28sd,8,VEX_66_0F38_W1,0CBh, vrsqrt28ss,4,VEX_66_0F38_W0,0CDh, vrsqrt28sd,8,VEX_66_0F38_W1,0CDh + + macro instr? dest*,src*,src2*& + require AVX512ER + AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED,opcode,unit,dest,src,src2 + end macro + +end iterate + +iterate , gatherpf0,1 ,gatherpf1,2 ,scatterpf0,5, scatterpf1,6 + + macro v#instr#dps? src* + require AVX512PF + AVX_512.parse_k1_vsib_operand@src src + if @src.type = 'mem' & @src.mask + if @src.size and not 4 | @src.visize <> 64 + err 'invalid operand size' + end if + @src.memsize = 4 + AVX_512.store_instruction@src 64,VEX_66_0F38_W0,EVEX_REQUIRED,0C6h,@src.mask,postbyte,@src.index and 10000b + else + err 'invalid combination of operands' + end if + end macro + + macro v#instr#qps? src* + require AVX512PF + AVX_512.parse_k1_vsib_operand@src src + if @src.type = 'mem' & @src.mask + if @src.size and not 8 | @src.visize <> 64 + err 'invalid operand size' + end if + @src.memsize = 4 + AVX_512.store_instruction@src 64,VEX_66_0F38_W0,EVEX_REQUIRED,0C7h,@src.mask,postbyte,@src.index and 10000b + else + err 'invalid combination of operands' + end if + end macro + + macro v#instr#dpd? src* + require AVX512PF + AVX_512.parse_k1_vsib_operand@src src + if @src.type = 'mem' & @src.mask + if @src.size and not 4 | @src.visize <> 32 + err 'invalid operand size' + end if + @src.memsize = 8 + AVX_512.store_instruction@src 64,VEX_66_0F38_W1,EVEX_REQUIRED,0C6h,@src.mask,postbyte,@src.index and 10000b + else + err 'invalid combination of operands' + end if + end macro + + macro v#instr#qpd? src* + require AVX512PF + AVX_512.parse_k1_vsib_operand@src src + if @src.type = 'mem' & @src.mask + if @src.size and not 8 | @src.visize <> 64 + err 'invalid operand size' + end if + @src.memsize = 8 + AVX_512.store_instruction@src 64,VEX_66_0F38_W1,EVEX_REQUIRED,0C7h,@src.mask,postbyte,@src.index and 10000b + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpopcntb,VEX_66_0F38_W0,54h, vpopcntw,VEX_66_0F38_W1,54h + + macro instr? dest*,src* + require AVX512_BITALG + AVX_512.single_source_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src + end macro + +end iterate + +macro vpshufbitqmb? dest*,src*,src2* + require AVX512_BITALG + AVX_512.parse_k1_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + if @dest.type = 'maskreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') + if @src2.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@src2 @src.size,VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,8Fh,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , vpopcntd,4,VEX_66_0F38_W0,55h, vpopcntq,8,VEX_66_0F38_W1,55h + + + macro instr? dest*,src* + require AVX512_VPOPCNTDQ + AVX_512.single_source_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src + end macro + +end iterate + +iterate , vpdpbusd,50h, vpdpbusds,51h, vpdpwssd,52h, vpdpwssds,53h + + macro instr? dest*,src*,src2* + require AVX512_VNNI + AVX_512.basic_instruction_bcst VEX_66_0F38_W0,EVEX_REQUIRED+EVEX_VL,opcode,4,dest,src,src2 + end macro + +end iterate + +iterate , vp4dpwssd,52h, vp4dpwssds,53h + + macro instr? dest*,src*,src2* + require AVX512_4VNNIW + AVX_512.parse_k1z_operand@dest dest + match rsrc+=3, src + AVX_512.parse_operand@src rsrc + else + AVX_512.parse_operand@src src + end match + AVX_512.parse_operand@src2 src2 + if @dest.type = 'mmreg' & @src.type = 'mmreg' & @src2.type = 'mem' + if @dest.size <> 64 | @src2.size and not 16 + err 'invalid operand size' + else if @dest.size <> @src.size + err 'operand sizes do not match' + end if + @src2.memsize = 0 + AVX_512.store_instruction@src2 @dest.size,VEX_F2_0F38_W0,EVEX_REQUIRED,opcode,@dest.mask,@dest.rm,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate diff --git a/toolchain/fasm2/include/iset/bmi.inc b/toolchain/fasm2/include/iset/bmi.inc new file mode 100644 index 0000000..bbb2106 --- /dev/null +++ b/toolchain/fasm2/include/iset/bmi.inc @@ -0,0 +1,290 @@ + +macro andn? dest*,src*,src2* + require BMI1 + x86.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@src2 src2 + if @dest.type = 'reg' & @src.type = 'reg' & (@src2.type = 'mem' | @src2.type = 'reg') + if @dest.size < 4 + err 'invalid operand size' + else if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src2 16,VEX_0F38_W1,0F2h,@dest.rm,@src.rm + else + AVX.store_instruction@src2 16,VEX_0F38_W0,0F2h,@dest.rm,@src.rm + end if + else + err 'invalid combination of operands' + end if +end macro + +macro bextr? dest*,src*,src2* + require BMI1 + x86.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@src2 src2 + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & @src2.type = 'reg' + if @dest.size < 4 + err 'invalid operand size' + else if @src.size and not @dest.size | @src2.size <> @dest.size + err 'operand sizes do not match' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src 16,VEX_0F38_W1,0F7h,@dest.rm,@src2.rm + else + AVX.store_instruction@src 16,VEX_0F38_W0,0F7h,@dest.rm,@src2.rm + end if + else + err 'invalid combination of operands' + end if +end macro + +iterate , blsi,0F3h,3, blsmsk,0F3h,2, blsr,0F3h,1 + + macro instr? dest*,src* + require BMI1 + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') + if @dest.size < 4 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src 16,VEX_0F38_W1,opcode,postbyte,@dest.rm + else + AVX.store_instruction@src 16,VEX_0F38_W0,opcode,postbyte,@dest.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , lzcnt,0BDh, tzcnt,0BCh + + macro instr? dest*,src* + require BMI1 + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'reg' & ( @src.type = 'reg' | @src.type = 'mem' ) + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + @src.opcode_prefix = 0F3h + if @dest.size > 1 + x86.select_operand_prefix@src @dest.size + x86.store_instruction@src <0Fh,opcode>,@dest.rm + else + err 'invalid operand size' + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , bzhi,0F5h + + macro instr? dest*,src*,src2* + require BMI2 + x86.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@src2 src2 + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & @src2.type = 'reg' + if @dest.size < 4 + err 'invalid operand size' + else if @src.size and not @dest.size | @src2.size <> @dest.size + err 'operand sizes do not match' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src 16,VEX_0F38_W1,opcode,@dest.rm,@src2.rm + else + AVX.store_instruction@src 16,VEX_0F38_W0,opcode,@dest.rm,@src2.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , mulx,VEX_F2_0F38,0F6h, pdep,VEX_F2_0F38,0F5h, pext,VEX_F3_0F38,0F5h + + macro instr? dest*,src*,src2* + require BMI2 + x86.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@src2 src2 + if @dest.type = 'reg' & @src.type = 'reg' & (@src2.type = 'mem' | @src2.type = 'reg') + if @dest.size < 4 + err 'invalid operand size' + else if @src.size <> @dest.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src2 16,vex_mp#_W1,opcode,@dest.rm,@src.rm + else + AVX.store_instruction@src2 16,vex_mp#_W0,opcode,@dest.rm,@src.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro rorx? dest*,src*,src2* + require BMI2 + x86.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@src2 src2 + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & @src2.type = 'imm' + if @dest.size < 4 | @src2.size and not 1 + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src 16,VEX_F2_0F3A_W1,0F0h,@dest.rm,,1,@src2.imm + else + AVX.store_instruction@src 16,VEX_F2_0F3A_W0,0F0h,@dest.rm,,1,@src2.imm + end if + else + err 'invalid combination of operands' + end if +end macro + +iterate , sarx,VEX_F3_0F38,0F7h, shlx,VEX_66_0F38,0F7h, shrx,VEX_F2_0F38,0F7h + + macro instr? dest*,src*,src2* + require BMI2 + x86.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@src2 src2 + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & @src2.type = 'reg' + if @dest.size < 4 + err 'invalid operand size' + else if @src.size and not @dest.size | @src2.size <> @dest.size + err 'operand sizes do not match' + end if + if @dest.size = 8 + if x86.mode < 64 + err 'instruction requires long mode' + end if + AVX.store_instruction@src 16,vex_mp#_W1,opcode,@dest.rm,@src2.rm + else + AVX.store_instruction@src 16,vex_mp#_W0,opcode,@dest.rm,@src2.rm + end if + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpermb,VEX_66_0F38_W0,8Dh, vpermi2b,VEX_66_0F38_W0,75h, vpermt2b,VEX_66_0F38_W0,7Dh + + macro instr? dest*,src*,src2* + require AVX512_VBMI + AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , vpmultishiftqb,83h + + macro instr? dest*,src*,src2* + require AVX512_VBMI + AVX_512.basic_instruction_bcst VEX_66_0F38_W1,EVEX_REQUIRED+EVEX_VL,opcode,8,dest,src,src2 + end macro + +end iterate + +iterate , vpshldw,VEX_66_0F3A_W1,70h, vpshrdw,VEX_66_0F3A_W1,72h + + macro instr? dest*,src*,src2*,aux*& + require AVX512_VBMI2 + AVX_512.basic_instruction_imm8 vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2,aux + end macro + +end iterate + +iterate , vpshldd,4,VEX_66_0F3A_W0,71h, vpshldq,8,VEX_66_0F3A_W1,71h, \ + vpshrdd,4,VEX_66_0F3A_W0,73h, vpshrdq,8,VEX_66_0F3A_W1,73h + + macro instr? dest*,src*,src2*,aux*& + require AVX512_VBMI2 + AVX_512.basic_instruction_bcst_imm8 vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src,src2,aux + end macro + +end iterate + +iterate , vpshldvw,VEX_66_0F38_W1,70h, vpshrdvw,VEX_66_0F38_W1,72h + + macro instr? dest*,src*,src2* + require AVX512_VBMI2 + AVX_512.basic_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , vpshldvd,4,VEX_66_0F38_W0,71h, vpshldvq,8,VEX_66_0F38_W1,71h, \ + vpshrdvd,4,VEX_66_0F38_W0,73h, vpshrdvq,8,VEX_66_0F38_W1,73h + + macro instr? dest*,src*,src2* + require AVX512_VBMI2 + AVX_512.basic_instruction_bcst vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,unit,dest,src,src2 + end macro + +end iterate + +iterate , vpcompressb,VEX_66_0F38_W0,63h, vpcompressw,VEX_66_0F38_W1,63h + + macro instr? dest*,src* + require AVX512_VBMI2 + AVX_512.parse_k1z_operand@dest dest + AVX_512.parse_operand@src src + if (@dest.type = 'mmreg' | @dest.type = 'mem') & @src.type = 'mmreg' + if @dest.size and not @src.size + err 'operand sizes do not match' + end if + AVX_512.store_instruction@dest @src.size,vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,@dest.mask,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , vpexpandb,VEX_66_0F38_W0,62h, vpexpandw,VEX_66_0F38_W1,62h + + macro instr? dest*,src* + require AVX512_VBMI2 + AVX_512.single_source_instruction vex_mpw,EVEX_REQUIRED+EVEX_VL,opcode,0,dest,src + end macro + +end iterate diff --git a/toolchain/fasm2/include/iset/cet.inc b/toolchain/fasm2/include/iset/cet.inc new file mode 100644 index 0000000..d1ddce3 --- /dev/null +++ b/toolchain/fasm2/include/iset/cet.inc @@ -0,0 +1,122 @@ + + +iterate , endbr32,0FBh, endbr64,0FAh + + macro instr? + require CET_IBT + db 0F3h,0Fh,1Eh,modrm + end macro + +end iterate + +iterate , clrssbsy,0AEh,6, rstorssp,01h,5 + + macro instr? src* + require CET_SS + x86.parse_operand@src src + if @src.type = 'mem' + if @src.size and not 8 + err 'invalid operand size' + else + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,ext>,postbyte + end if + else + err 'invalid operand' + end if + end macro + +end iterate + +iterate , incsspd,0AEh,5, rdsspd,1Eh,1 + + macro instr? src* + require CET_SS + x86.parse_operand@src src + if @src.type = 'reg' + if @src.size <> 4 + err 'invalid operand size' + else + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,ext>,postbyte + end if + else + err 'invalid operand' + end if + end macro + +end iterate + +iterate , incsspq,0AEh,5, rdsspq,1Eh,1 + + macro instr? src* + require CET_SS + x86.parse_operand@src src + if @src.type = 'reg' + if @src.size <> 8 + err 'invalid operand size' + else + x86.select_operand_prefix@src 8 + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,ext>,postbyte + end if + else + err 'invalid operand' + end if + end macro + +end iterate + +iterate , saveprevssp,0EAh, setssbsy,0E8h + + macro instr? + require CET_SS + db 0F3h,0Fh,01h,modrm + end macro + +end iterate + +iterate , wrssd,0,0F6h, wrussd,66h,0F5h + + macro instr? dest*,src* + require CET_SS + x86.parse_operand@dest dest + x86.parse_operand@src src + local size + if @src.size <> 4 + err 'invalid operand size' + else if @dest.size and not @src.size + err 'operand sizes do not match' + end if + if @src.type = 'reg' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + @dest.opcode_prefix = prefix + x86.store_instruction@dest <0Fh,38h,ext>,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +iterate , wrssq,0,0F6h, wrussq,66h,0F5h + + macro instr? dest*,src* + require CET_SS + x86.parse_operand@dest dest + x86.parse_operand@src src + local size + if @src.size <> 8 + err 'invalid operand size' + else if @dest.size and not @src.size + err 'operand sizes do not match' + end if + if @src.type = 'reg' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + x86.select_operand_prefix@dest 8 + @dest.opcode_prefix = prefix + x86.store_instruction@dest <0Fh,38h,ext>,@src.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate diff --git a/toolchain/fasm2/include/iset/fpu.inc b/toolchain/fasm2/include/iset/fpu.inc new file mode 100644 index 0000000..414eb87 --- /dev/null +++ b/toolchain/fasm2/include/iset/fpu.inc @@ -0,0 +1,742 @@ + +element st? + +repeat 8, i:0 + element st#i? : st? + i +end repeat + +iterate context, @dest,@src,@src2,@aux + + namespace context + + calminstruction x87.parse_operand#context operand + + local i + + match =st?(i), operand + jyes indexed_streg_operand + + call x86.parse_operand#context, operand + + check type = 'imm' & size = 0 + jno done + check imm eq 1 elementof imm & 1 metadataof imm relativeto st? + jyes streg_operand + check imm relativeto st? & imm = st? + jno done + + compute type, 'streg' + compute mod, 11b + compute rm, 0 + + exit + + streg_operand: + + compute type, 'streg' + compute mod, 11b + compute rm, 1 metadataof imm - st? + + exit + + indexed_streg_operand: + + compute size, 0 + compute type, 'streg' + compute mod, 11b + compute rm, +i + + done: + + end calminstruction + + end namespace + +end iterate + +iterate , fwait,9Bh, wait,9Bh + + calminstruction instr? + call x86.require.8087 + emit 1, opcode + end calminstruction + +end iterate + +iterate , fnop,0D9h,0D0h, fchs,0D9h,0E0h, fabs,0D9h,0E1h, ftst,0D9h,0E4h, fxam,0D9h,0E5h, fld1,0D9h,0E8h, \ + fldl2t,0D9h,0E9h, fldl2e,0D9h,0EAh, fldpi,0D9h,0EBh, fldlg2,0D9h,0ECh, fldln2,0D9h,0EDh, fldz,0D9h,0EEh, \ + f2xm1,0D9h,0F0h, fyl2x,0D9h,0F1h, fptan,0D9h,0F2h, fpatan,0D9h,0F3h, fxtract,0D9h,0F4h, \ + fdecstp,0D9h,0F6h, fincstp,0D9h,0F7h, fprem,0D9h,0F8h, \ + fyl2xp1,0D9h,0F9h, fsqrt,0D9h,0FAh, frndint,0D9h,0FCh, fscale,0D9h,0FDh, \ + fneni,0DBh,0E0h, fndisi,0DBh,0E1h, fnclex,0DBh,0E2h, fninit,0DBh,0E3h, \ + fcompp,0DEh,0D9h + + calminstruction instr? + call x86.require.8087 + emit 1, byte1 + emit 1, byte2 + end calminstruction + +end iterate + +iterate , fneni,0E0h, fndisi,0E1h + + calminstruction instr? + call x86.requireexact.8087 + emit 1, 0DBh + emit 1, opcode + end calminstruction + +end iterate + +iterate op, eni, disi, clex, init + calminstruction f#op? + asm fwait? + asm fn#op? + end calminstruction +end iterate + +calminstruction fsetpm? + call x86.requireexact.80287 + emit 1, 0DBh + emit 1, 0E4h +end calminstruction + +iterate , fadd,0, fmul,1, fsub,4, fsubr,5, fdiv,6, fdivr,7 + + calminstruction instr? operand& + call x86.require.8087 + local dest, src + match dest=,src, operand + jyes st + call x87.parse_operand@dest, operand + check @dest.type = 'mem' + jno invalid_combination_of_operands + check @dest.size = 4 + jyes mem_dword + check @dest.size = 8 + jyes mem_qword + check @dest.size + jno unknown_size + err 'invalid operand size' + jump mem_dword + unknown_size: + err 'operand size not specified' + mem_dword: + xcall x86.store_instruction@dest, (0D8h),(postbyte) + exit + mem_qword: + xcall x86.store_instruction@dest, (0DCh),(postbyte) + exit + st: + call x87.parse_operand@dest, dest + call x87.parse_operand@src, src + check @dest.type = 'streg' & @src.type = 'streg' + jno invalid_combination_of_operands + check @dest.rm = 0 + jyes st0_sti + check @src.rm = 0 + jyes sti_st0 + jump invalid_combination_of_operands + st0_sti: + emit 1, 0D8h + emit 1, 11b shl 6 + postbyte shl 3 + @src.rm + exit + sti_st0: + check postbyte >= 4 + jyes switched + emit 1, 0DCh + emit 1, 11b shl 6 + postbyte shl 3 + @dest.rm + exit + switched: + emit 1, 0DCh + emit 1, 11b shl 6 + (postbyte xor 1) shl 3 + @dest.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' + end calminstruction + +end iterate + +iterate , faddp,0, fmulp,1, fsubrp,4, fsubp,5, fdivrp,6, fdivp,7 + + calminstruction instr? operand& + call x86.require.8087 + local dest, src + match , operand + jyes default + match dest=,src, operand + jno invalid_combination_of_operands + call x87.parse_operand@dest, dest + call x87.parse_operand@src, src + check @dest.type = 'streg' & @src.type = 'streg' & @src.rm = 0 + jyes ok + invalid_combination_of_operands: + err 'invalid combination of operands' + exit + default: + compute @dest.rm, 1 + ok: + emit 1, 0DEh + emit 1, 11b shl 6 + postbyte shl 3 + @dest.rm + end calminstruction + +end iterate + +iterate , fcom,2, fcomp,3 + + calminstruction instr? src:st1 + call x86.require.8087 + call x87.parse_operand@src, src + check @src.type = 'streg' + jyes st + check @src.type = 'mem' + jno invalid_operand + check @src.size = 4 + jyes mem_dword + check @src.size = 8 + jyes mem_qword + check @src.size + jno unknown_size + err 'invalid operand size' + jump mem_dword + unknown_size: + err 'operand size not specified' + mem_dword: st: + xcall x86.store_instruction@src, (0D8h),(postbyte) + exit + mem_qword: + xcall x86.store_instruction@src, (0DCh),(postbyte) + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , fiadd,0, fimul,1, ficom,2, ficomp,3, fisub,4, fisubr,5, fidiv,6, fidivr,7 + + calminstruction instr? src* + call x86.require.8087 + call x87.parse_operand@src, src + check @src.type = 'mem' + jno invalid_operand + check @src.size = 2 + jyes mem_word + check @src.size = 4 + jyes mem_dword + check @src.size + jno unknown_size + err 'invalid operand size' + jump mem_word + unknown_size: + err 'operand size not specified' + mem_word: + xcall x86.store_instruction@src, (0DEh),(postbyte) + exit + mem_dword: + xcall x86.store_instruction@src, (0DAh),(postbyte) + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +calminstruction fld? src* + call x86.require.8087 + call x87.parse_operand@src, src + check @src.type = 'streg' + jyes st + check @src.type = 'mem' + jno invalid_operand + check @src.size = 4 + jyes mem_dword + check @src.size = 8 + jyes mem_qword + check @src.size = 10 + jyes mem_tword + check @src.size + jno unknown_size + err 'invalid operand size' + jump mem_dword + unknown_size: + err 'operand size not specified' + mem_dword: st: + xcall x86.store_instruction@src, (0D9h),(0) + exit + mem_qword: + xcall x86.store_instruction@src, (0DDh),(0) + exit + mem_tword: + xcall x86.store_instruction@src, (0DBh),(5) + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +calminstruction fst? dest* + call x86.require.8087 + call x87.parse_operand@dest, dest + check @dest.type = 'streg' + jyes st + check @dest.type = 'mem' + jno invalid_operand + check @dest.size = 4 + jyes mem_dword + check @dest.size = 8 + jyes mem_qword + check @dest.size + jno unknown_size + err 'invalid operand size' + jump mem_dword + unknown_size: + err 'operand size not specified' + mem_dword: + xcall x86.store_instruction@dest, (0D9h),(2) + exit + mem_qword: st: + xcall x86.store_instruction@dest, (0DDh),(2) + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +calminstruction fstp? dest* + call x86.require.8087 + call x87.parse_operand@dest, dest + check @dest.type = 'streg' + jyes st + check @dest.type = 'mem' + jno invalid_operand + check @dest.size = 4 + jyes mem_dword + check @dest.size = 8 + jyes mem_qword + check @dest.size = 10 + jyes mem_tword + check @dest.size + jno unknown_size + err 'invalid operand size' + jump mem_dword + unknown_size: + err 'operand size not specified' + mem_dword: + xcall x86.store_instruction@dest, (0D9h),(3) + exit + mem_qword: st: + xcall x86.store_instruction@dest, (0DDh),(3) + exit + mem_tword: + xcall x86.store_instruction@dest, (0DBh),(7) + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +calminstruction fild? src* + call x86.require.8087 + call x87.parse_operand@src, src + check @src.type = 'mem' + jno invalid_operand + check @src.size = 2 + jyes mem_word + check @src.size = 4 + jyes mem_dword + check @src.size = 8 + jyes mem_qword + check @src.size + jno unknown_size + err 'invalid operand size' + jump mem_word + unknown_size: + err 'operand size not specified' + mem_word: + xcall x86.store_instruction@src, (0DFh),(0) + exit + mem_dword: + xcall x86.store_instruction@src, (0DBh),(0) + exit + mem_qword: + xcall x86.store_instruction@src, (0DFh),(5) + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +calminstruction fist? dest* + call x86.require.8087 + call x87.parse_operand@dest, dest + check @dest.type = 'mem' + jno invalid_operand + check @dest.size = 2 + jyes mem_word + check @dest.size = 4 + jyes mem_dword + check @dest.size + jno unknown_size + err 'invalid operand size' + jump mem_word + unknown_size: + err 'operand size not specified' + mem_word: + xcall x86.store_instruction@dest, (0DFh),(2) + exit + mem_dword: + xcall x86.store_instruction@dest, (0DBh),(2) + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +calminstruction fistp? dest* + call x86.require.8087 + call x87.parse_operand@dest, dest + check @dest.type = 'mem' + jno invalid_operand + check @dest.size = 2 + jyes mem_word + check @dest.size = 4 + jyes mem_dword + check @dest.size = 8 + jyes mem_qword + check @dest.size + jno unknown_size + err 'invalid operand size' + jump mem_word + unknown_size: + err 'operand size not specified' + mem_word: + xcall x86.store_instruction@dest, (0DFh),(3) + exit + mem_dword: + xcall x86.store_instruction@dest, (0DBh),(3) + exit + mem_qword: + xcall x86.store_instruction@dest, (0DFh),(7) + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +calminstruction fisttp? dest* + call x86.require.8087 + call x87.parse_operand@dest, dest + check @dest.type = 'mem' + jno invalid_operand + check @dest.size = 2 + jyes mem_word + check @dest.size = 4 + jyes mem_dword + check @dest.size = 8 + jyes mem_qword + check @dest.size + jno unknown_size + err 'invalid operand size' + jump mem_word + unknown_size: + err 'operand size not specified' + mem_word: + xcall x86.store_instruction@dest, (0DFh),(1) + exit + mem_dword: + xcall x86.store_instruction@dest, (0DBh),(1) + exit + mem_qword: + xcall x86.store_instruction@dest, (0DDh),(1) + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +iterate , fbld,4, fbstp,6 + + calminstruction instr? src* + call x86.require.8087 + call x87.parse_operand@src, src + check @src.type = 'mem' + jno invalid_operand + check @src.size and not 10 + jyes invalid_operand_size + xcall x86.store_instruction@src, (0DFh),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +calminstruction fxch? src:st1 + call x86.require.8087 + call x87.parse_operand@src, src + check @src.type = 'streg' + jno invalid_operand + emit 1, 0D9h + emit 1, 11b shl 6 + 1 shl 3 + @src.rm + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +iterate , ffree,0DDh, ffreep,0DFh + + calminstruction instr? src* + call x86.require.8087 + call x87.parse_operand@src, src + check @src.type = 'streg' + jno invalid_operand + emit 1, basecode + emit 1, 11b shl 6 + @src.rm + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +calminstruction fnstsw? dest* + call x86.require.8087 + call x86.parse_operand@dest, dest + check @dest.size and not 2 + jyes invalid_operand_size + check @dest.type = 'mem' + jyes mem + check @dest.type = 'reg' & @dest.rm = 0 + jno invalid_operand + emit 1, 0DFh + emit 1, 0E0h + exit + mem: + xcall x86.store_instruction@dest, (0DDh),(7) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' +end calminstruction + +iterate , fldcw,5, fnstcw,7 + + calminstruction instr? dest* + call x86.parse_operand@dest, dest + check @dest.size and not 2 + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_instruction@dest, (0D9h),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , fldenv,4, fnstenv,6 + + calminstruction instr? dest* + call x86.require.8087 + call x86.parse_operand@dest, dest + check @dest.size and not 14 + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_instruction@dest, (0D9h),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , frstor,4, fnsave,6 + + calminstruction instr? dest* + call x86.require.8087 + call x86.parse_operand@dest, dest + check @dest.size and not 94 + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_instruction@dest, (0DDh),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate op, stsw, stcw, stenv, save + calminstruction f#op? dest* + asm fwait? + asm fn#op? dest + end calminstruction +end iterate + +iterate , fprem1,0D9h,0F5h, fsincos,0D9h,0FBh, fsin,0D9h,0FEh, fcos,0D9h,0FFh, fucompp,0DAh,0E9h + + calminstruction instr? + call x86.require.80387 + emit 1, byte1 + emit 1, byte2 + end calminstruction + +end iterate + +iterate , fucom,4, fucomp,5 + + calminstruction instr? src:st1 + call x86.require.80387 + call x87.parse_operand@src, src + check @src.type = 'streg' + jno invalid_operand + xcall x86.store_instruction@src, (0DDh),(postbyte) + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + + +iterate , fldenv,4, fnstenv,6 + + calminstruction instr? dest* + call x86.require.80387 + call x86.parse_operand@dest, dest + check @dest.size & ( ( x86.mode = 16 & @dest.size <> 14 ) | ( x86.mode = 32 & @dest.size <> 28 ) ) + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_instruction@dest, (0D9h),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , fldenvw,4, fnstenvw,6 + + calminstruction instr? dest* + call x86.require.80387 + call x86.parse_operand@dest, dest + check @dest.size and not 14 + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_operand_prefix, (2) + xcall x86.store_instruction@dest, (0D9h),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , fldenvd,4, fnstenvd,6 + + calminstruction instr? dest* + call x86.require.80387 + call x86.parse_operand@dest, dest + check @dest.size and not 28 + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_operand_prefix, (4) + xcall x86.store_instruction@dest, (0D9h),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , frstor,4, fnsave,6 + + calminstruction instr? dest* + call x86.require.80387 + call x86.parse_operand@dest, dest + check @dest.size & ( ( x86.mode = 16 & @dest.size <> 94 ) | ( x86.mode = 32 & @dest.size <> 108 ) ) + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_instruction@dest, (0DDh),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , frstorw,4, fnsavew,6 + + calminstruction instr? dest* + call x86.require.80387 + call x86.parse_operand@dest, dest + check @dest.size and not 94 + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_operand_prefix, (2) + xcall x86.store_instruction@dest, (0DDh),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , frstord,4, fnsaved,6 + calminstruction instr? dest* + call x86.require.80387 + call x86.parse_operand@dest, dest + check @dest.size and not 108 + jyes invalid_operand_size + check @dest.type = 'mem' + jno invalid_operand + xcall x86.store_operand_prefix, (4) + xcall x86.store_instruction@dest, (0DDh),(postbyte) + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate op, stenvw, stenvd, savew, saved + calminstruction f#op? dest* + asm fwait? + asm fn#op? dest + end calminstruction +end iterate diff --git a/toolchain/fasm2/include/iset/gfni.inc b/toolchain/fasm2/include/iset/gfni.inc new file mode 100644 index 0000000..e8e7e2e --- /dev/null +++ b/toolchain/fasm2/include/iset/gfni.inc @@ -0,0 +1,33 @@ + +iterate , gf2p8mulb,0CFh + macro instr? dest*,src* + require GFNI + SSE.basic_instruction 66h,<38h,supp>,16,dest,src + end macro +end iterate + +iterate , gf2p8affineinvqb,0CFh, gf2p8affineqb,0CEh + macro instr? dest*,src*,imm* + require GFNI + SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm + end macro +end iterate + +iterate , gf2p8mulb,0CFh + + macro v#instr? dest*,src*,src2*& + require GFNI + AVX_512.basic_instruction VEX_66_0F38_W0,EVEX_AS_VEX+EVEX_VL,opcode,0,dest,src,src2 + end macro + +end iterate + +iterate , gf2p8affineinvqb,0CFh, gf2p8affineqb,0CEh + + macro v#instr? dest*,src*,src2*,imm*& + require GFNI + AVX_512.basic_instruction_bcst_imm8 VEX_66_0F3A_W1,EVEX_W1+EVEX_VL,opcode,8,dest,src,src2,imm + end macro + +end iterate + diff --git a/toolchain/fasm2/include/iset/mmx.inc b/toolchain/fasm2/include/iset/mmx.inc new file mode 100644 index 0000000..8bbb2d4 --- /dev/null +++ b/toolchain/fasm2/include/iset/mmx.inc @@ -0,0 +1,164 @@ + +element MMX.reg + +repeat 8, i:0 + element mm#i? : MMX.reg + i +end repeat + +iterate context, @dest,@src,@src2,@aux + + namespace context + + calminstruction MMX.parse_operand#context operand + + call x86.parse_operand#context, operand + + check type = 'imm' & size = 0 + jno done + check imm eq 1 elementof imm & 1 metadataof imm relativeto MMX.reg + jno done + + compute type, 'mmreg' + compute mod, 11b + compute rm, 1 metadataof imm - MMX.reg + compute size, 8 + + done: + + end calminstruction + + calminstruction MMX.select_operand_prefix#context size* + check size = 16 + jno no_prefix + call x86.require.SSE2 + compute prefix, 66h + exit + no_prefix: + check size <> 8 + jno done + err 'invalid operand size' + done: + end calminstruction + + end namespace + +end iterate + +calminstruction MMX.basic_instruction ext,dest,src + call x86.require.MMX + call SSE.parse_operand@dest, dest + call SSE.parse_operand@src, src + check @src.size and not @dest.size + jno size_ok + err 'operand sizes do not match' + size_ok: + check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + jno invalid_combination_of_operands + call MMX.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' +end calminstruction + +calminstruction MMX.bit_shift_instruction ext,dest,src + call x86.require.MMX + call SSE.parse_operand@dest, dest + call SSE.parse_operand@src, src + check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + jyes mmreg_rm + check @dest.type = 'mmreg' & @src.type = 'imm' + jyes mmreg_imm + err 'invalid combination of operands' + exit + mmreg_rm: + check @src.size and not @dest.size + jno mmreg_rm_ok + err 'operand sizes do not match' + mmreg_rm_ok: + call MMX.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm + exit + mmreg_imm: + check @src.size and not 1 + jno rm_mmreg_ok + err 'invalid operand size' + rm_mmreg_ok: + local iext, irm + compute iext, 70h+(ext and 0Fh) + compute irm, ((ext shr 4)-0Ch) shl 1 + call MMX.select_operand_prefix@dest, @dest.size + xcall x86.store_instruction@dest, <0Fh,iext>,irm,byte,@src.imm +end calminstruction + +iterate , punpcklbw,60h, punpcklwd,61h, punpckldq,62h, packsswb,63h, pcmpgtb,64h, pcmpgtw,65h, pcmpgtd,66h, packuswb,67h, punpckhbw,68h, \ + punpckhwd,69h, punpckhdq,6Ah, packssdw,6Bh, pcmpeqb,74h, pcmpeqw,75h, pcmpeqd,76h, pmullw,0D5h, psubusb,0D8h, psubusw,0D9h, \ + pand,0DBh, paddusb,0DCh, paddusw,0DDh, pandn,0DFh, pmulhw,0E5h, psubsb,0E8h, psubsw,0E9h, por,0EBh, paddsb,0ECh, paddsw,0EDh, \ + pxor,0EFh, pmaddwd,0F5h, psubb,0F8h, psubw,0F9h, psubd,0FAh, paddb,0FCh, paddw,0FDh, paddd,0FEh + + macro instr? dest*,src* + MMX.basic_instruction opcode,dest,src + end macro + +end iterate + +calminstruction movq? dest*,src* + call x86.require.MMX + call MMX.parse_operand@dest, dest + call MMX.parse_operand@src, src + check (@src.size or @dest.size) and not 8 + jno size_ok + err 'invalid operand size' + size_ok: + check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + jyes mmreg_mem + check @dest.type = 'mem' & @src.type = 'mmreg' + jyes mem_mmreg + err 'invalid combination of operands' + exit + mmreg_mem: + xcall x86.store_instruction@src, <0Fh,6Fh>,@dest.rm + exit + mem_mmreg: + xcall x86.store_instruction@dest, <0Fh,7Fh>,@src.rm + exit +end calminstruction + +calminstruction movd? dest*,src* + call x86.require.MMX + call MMX.parse_operand@dest, dest + call MMX.parse_operand@src, src + check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg') + jyes mmreg_rm + check (@dest.type = 'mem' | @dest.type = 'reg') & @src.type = 'mmreg' + jyes rm_mmreg + err 'invalid combination of operands' + exit + mmreg_rm: + check @src.size and not 4 + jno mmreg_rm_ok + err 'invalid operand size' + mmreg_rm_ok: + xcall x86.store_instruction@src, <0Fh,6Eh>,@dest.rm + exit + rm_mmreg: + check @dest.size and not 4 + jno rm_mmreg_ok + err 'invalid operand size' + rm_mmreg_ok: + xcall x86.store_instruction@dest, <0Fh,7Eh>,@src.rm +end calminstruction + +iterate , psrlw,0D1h, psrld,0D2h, psrlq,0D3h, psrad,0E2h, psraw,0E1h, psllw,0F1h, pslld,0F2h, psllq,0F3h + + macro instr? dest*,src* + MMX.bit_shift_instruction opcode,dest,src + end macro + +end iterate + +calminstruction emms? + call x86.require.MMX + emit 1, 0Fh + emit 1, 77h +end calminstruction diff --git a/toolchain/fasm2/include/iset/mpx.inc b/toolchain/fasm2/include/iset/mpx.inc new file mode 100644 index 0000000..7288f00 --- /dev/null +++ b/toolchain/fasm2/include/iset/mpx.inc @@ -0,0 +1,194 @@ + +element MPX.bnd + +repeat 4, i:0 + element bnd#i? : MPX.bnd + i +end repeat + +macro MPX.parse_operand ns,op + x86.parse_operand#ns op + if ns.type = 'imm' & ns.size = 0 & ns.imm eq 1 elementof ns.imm & 1 metadataof ns.imm relativeto MPX.bnd + ns.type = 'bnd' + ns.mod = 11b + ns.rm = 1 metadataof ns.imm - MPX.bnd + ns.size = 0 + end if +end macro + +macro MPX.parse_sib_operand ns,op& + match [b=,si], op + ns.split = 1 + ns.segment_prefix = 0 + ns.prefix = 0 + ns.opcode_prefix = 0 + ns.rex_prefix = 0 + ns.size = 0 + ns.type = 'mem' + ns.base_part = +b + ns.index_part = +si + if x86.mode = 64 + ns.mode = 64 + ns.address_registers_type = x86.r64 + else + ns.mode = 32 + ns.address_registers_type = x86.r32 + end if + ns.base_registers = 0 + ns.index_registers = 0 + repeat elementsof ns.base_part + if % metadataof ns.base_part relativeto x86.r16 | % metadataof ns.base_part relativeto x86.r32 | % metadataof ns.base_part relativeto x86.r64 | % metadataof ns.address relativeto x86.ip + ns.base_registers = ns.base_registers + % elementof ns.base_part * % scaleof ns.base_part + end if + end repeat + repeat elementsof ns.index_part + if % metadataof ns.index_part relativeto x86.r16 | % metadataof ns.index_part relativeto x86.r32 | % metadataof ns.index_part relativeto x86.r64 | % metadataof ns.address relativeto x86.ip + ns.index_registers = ns.index_registers + % elementof ns.index_part * % scaleof ns.index_part + end if + end repeat + ns.displacement = ns.base_part - ns.base_registers + ns.index_part - ns.index_registers + if ns.index_registers eq 0 + ns.index = 4 + ns.scale = 1 + else if elementsof ns.index_registers = 1 & 1 metadataof ns.index_registers relativeto ns.address_registers_type & 1 metadataof ns.index_registers - ns.address_registers_type <> 4 + ns.index = 1 metadataof ns.index_registers - ns.address_registers_type + ns.scale = 1 scaleof ns.index_registers + else + err 'invalid address' + end if + if ns.base_registers eq 0 + ns.rm = 4 + ns.base = 5 + ns.index_only = 1 + else if ns.base_registers eq 1 elementof ns.base_registers & 1 metadataof ns.base_registers relativeto ns.address_registers_type + ns.base = 1 metadataof ns.base_registers - ns.address_registers_type + if ns.index = 4 & ns.base <> 4 + ns.rm = ns.base + else + ns.rm = 4 + end if + ns.index_only = 0 + else + err 'invalid address' + end if + ns.auto_relative = 0 + ns.displacement_size = 4 + ns.mod = 2 + if ns.index_only + ns.mod = 0 + else if ns.displacement relativeto 0 + if ns.displacement = 0 & ns.rm and 111b <> 5 & (ns.rm <> 4 | ns.base and 111b <> 5) + ns.displacement_size = 0 + ns.mod = 0 + else if ns.displacement < 80h & ns.displacement >= -80h + ns.displacement_size = 1 + ns.mod = 1 + else if ns.displacement - 1 shl ns.mode >= -80h & ns.displacement < 1 shl ns.mode + ns.displacement = ns.displacement - 1 shl ns.mode + ns.displacement_size = 1 + ns.mod = 1 + end if + end if + else + ns.split = 0 + x86.parse_operand#ns op + end match +end macro + +macro bndmk? dest*,src*& + require MPX + MPX.parse_operand @dest,dest + MPX.parse_sib_operand @src,src + if @dest.type = 'bnd' & @src.type = 'mem' + if @src.split & ~ 0 scaleof @src.base_part eq 0 + err 'invalid base address' + end if + if (x86.mode = 64 & @src.size and not 8) | (x86.mode < 64 & @src.size and not 4) + err 'invalid operand size' + end if + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,1Bh>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro bndmov? dest*,src* + require MPX + MPX.parse_operand @dest,dest + MPX.parse_operand @src,src + if @dest.type = 'bnd' & (@src.type = 'bnd' | @src.type = 'mem') + if (x86.mode = 64 & @src.size and not 16) | (x86.mode < 64 & @src.size and not 8) + err 'invalid operand size' + end if + if @src.type = 'mem' & @src.mode <> x86.mode + err 'invalid address' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,1Ah>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'bnd' + if (x86.mode = 64 & @dest.size and not 16) | (x86.mode < 64 & @dest.size and not 8) + err 'invalid operand size' + end if + if @dest.type = 'mem' & @dest.mode <> x86.mode + err 'invalid address' + end if + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,1Bh>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , bndcl,0F3h,1Ah, bndcu,0F2h,1Ah, bndcn,0F2h,1Bh + + macro instr? dest*,src* + require MPX + MPX.parse_operand @dest,dest + x86.parse_operand @src,src + if @dest.type = 'bnd' & (@src.type = 'reg' | @src.type = 'mem') + if (x86.mode = 64 & @src.size and not 8) | (x86.mode < 64 & @src.size and not 4) + err 'invalid operand size' + end if + if @src.type = 'mem' & @src.mode <> x86.mode + err 'invalid address' + end if + @src.opcode_prefix = prefix + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid operand' + end if + end macro + +end iterate + +macro bndldx? dest*,src*& + require MPX + MPX.parse_operand @dest,dest + MPX.parse_sib_operand @src,src + if @dest.type = 'bnd' & @src.type = 'mem' + if @src.scale > 1 | ( @src.split & ~ 0 scaleof @src.index_part eq 0 ) + err 'invalid index' + end if + x86.store_instruction@src <0Fh,1Ah>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro bndstx? operands*& + require MPX + match [dest] =, src, operands + MPX.parse_sib_operand @dest,[dest] + MPX.parse_operand @src,src + if @dest.type = 'mem' & @src.type = 'bnd' + if @dest.scale > 1 | ( @dest.split & ~ 0 scaleof @dest.index_part eq 0 ) + err 'invalid index' + end if + x86.store_instruction@dest <0Fh,1Bh>,@src.rm + else + err 'invalid combination of operands' + end if + else + err 'invalid combination of operands' + end match +end macro diff --git a/toolchain/fasm2/include/iset/pclmulqdq.inc b/toolchain/fasm2/include/iset/pclmulqdq.inc new file mode 100644 index 0000000..0e7cfc2 --- /dev/null +++ b/toolchain/fasm2/include/iset/pclmulqdq.inc @@ -0,0 +1,24 @@ + +macro pclmulqdq? dest*,src*,imm* + require PCLMULQDQ + SSE.basic_instruction_imm8 66h,<3Ah,44h>,16,dest,src,imm +end macro + +macro vpclmulqdq? dest*,src*,src2*,aux* + require VPCLMULQDQ + AVX_512.parse_operand@dest dest + AVX_512.parse_operand@src src + AVX_512.parse_operand@src2 src2 + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & @src.type = 'mmreg' & (@src2.type = 'mem' | @src2.type = 'mmreg') & @aux.type = 'imm' + if @aux.size and not 1 + err 'invalid operand size' + else if @dest.size <> @src.size | @src2.size and not @dest.size + err 'operand sizes do not match' + end if + @src2.memsize = 0 + AVX_512.store_instruction@src2 @dest.size,VEX_66_0F3A_W0,EVEX_AS_VEX+EVEX_VL,44h,@dest.mask,@dest.rm,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro diff --git a/toolchain/fasm2/include/iset/sse.inc b/toolchain/fasm2/include/iset/sse.inc new file mode 100644 index 0000000..e9e1a49 --- /dev/null +++ b/toolchain/fasm2/include/iset/sse.inc @@ -0,0 +1,444 @@ + +element SSE.reg + +repeat 16, i:0 + element xmm#i? : SSE.reg + i +end repeat + +iterate context, @dest,@src,@src2,@aux + + namespace context + + calminstruction SSE.parse_operand#context operand + + call x86.parse_operand#context, operand + + check type = 'imm' & size = 0 + jno done + check imm eq 1 elementof imm & 1 metadataof imm relativeto MMX.reg + jyes mm_register + check imm eq 1 elementof imm & 1 metadataof imm relativeto SSE.reg + jyes xmm_register + exit + + mm_register: + + compute rm, 1 metadataof imm - MMX.reg + compute size, 8 + + jump export_mmreg + + xmm_register: + + compute rm, 1 metadataof imm - SSE.reg + compute size, 16 + + export_mmreg: + + compute type, 'mmreg' + compute mod, 11b + + done: + + end calminstruction + + end namespace + +end iterate + +calminstruction SSE.basic_instruction pre,ext,msize,dest,src + call x86.require.SSE + call SSE.parse_operand@dest, dest + call SSE.parse_operand@src, src + check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + jno invalid_combination_of_operands + check @dest.size <> 16 | (@src.type = 'mem' & @src.size and not msize) | (@src.type = 'mmreg' & @src.size <> 16) + jno size_ok + err 'invalid operand size' + size_ok: + compute @src.opcode_prefix, pre + xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' +end calminstruction + +calminstruction SSE.basic_instruction_imm8 pre,ext,msize,dest,src,aux + call x86.require.SSE + call SSE.parse_operand@dest, dest + call SSE.parse_operand@src, src + call x86.parse_operand@aux, aux + check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + jno invalid_combination_of_operands + check @dest.size <> 16 | (@src.type = 'mem' & @src.size and not msize) | (@src.type = 'mmreg' & @src.size <> 16) | @aux.size and not 1 + jno size_ok + err 'invalid operand size' + size_ok: + compute @src.opcode_prefix, pre + xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm,byte,@aux.imm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' +end calminstruction + +iterate , sqrt,51h, rsqrt,52h, rcp,53h, add,58h, mul,59h, sub,5Ch, min,5Dh, div,5Eh, max,5Fh + macro instr#ps? dest*,src* + SSE.basic_instruction 0,ext,16,dest,src + end macro + macro instr#ss? dest*,src* + SSE.basic_instruction 0F3h,ext,4,dest,src + end macro +end iterate + +iterate , and,54h, andn,55h, or,56h, xor,57h, unpckl,14h, unpckh,15h + macro instr#ps? dest*,src* + SSE.basic_instruction 0,ext,16,dest,src + end macro +end iterate + +macro cmpps? dest*,src*,code* + SSE.basic_instruction_imm8 0,0C2h,16,dest,src,code +end macro + +macro cmpss? dest*,src*,code* + SSE.basic_instruction_imm8 0F3h,0C2h,4,dest,src,code +end macro + +iterate , eq,0, lt,1, le,2, unord,3, neq,4, nlt,5, nle,6, ord,7 + macro cmp#cond#ps? dest*,src* + cmpps dest,src,code + end macro + macro cmp#cond#ss? dest*,src* + cmpss dest,src,code + end macro +end iterate + +macro shufps? dest*,src*,imm* + SSE.basic_instruction_imm8 0,0C6h,16,dest,src,imm +end macro + +iterate , movaps,28h, movups,10h + macro instr? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + x86.store_instruction@src <0Fh,ext>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + x86.store_instruction@dest <0Fh,ext+1>,@src.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , movlps,12h, movhps,16h + macro instr? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if @dest.size <> 16 | @src.size and not 8 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,ext>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not 8 | @src.size <> 16 + err 'invalid operand size' + end if + x86.store_instruction@dest <0Fh,ext+1>,@src.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , movhlps,12h, movlhps,16h + macro instr? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + if @dest.type = 'mmreg' & @src.type = 'mmreg' + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +macro movss? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 4) | (@src.type = 'mmreg' & @src.size <> 16) + err 'invalid operand size' + end if + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,10h>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not 4 | @src.size <> 16 + err 'invalid operand size' + end if + @dest.opcode_prefix = 0F3h + x86.store_instruction@dest <0Fh,11h>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro movntps? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mem' & @src.type = 'mmreg' + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + x86.store_instruction@dest <0Fh,2Bh>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro movmskps? dest*,src* + require SSE+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'reg' & @src.type = 'mmreg' + if (@dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | @src.size <> 16 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,50h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , ucomiss,2Eh, comiss,2Fh + macro instr? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 4) | (@src.type = 'mmreg' & @src.size <> 16) + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +macro cvtpi2ps? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 16 | @src.size and not 8 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,2Ah>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro cvtsi2ss? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg') + if @src.size = 0 + err 'operand size not specified' + else if @dest.size <> 16 | @src.size < 4 + err 'invalid operand size' + end if + x86.select_operand_prefix@src @src.size + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,2Ah>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , cvttps2pi,2Ch, cvtps2pi,2Dh + macro instr? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 8 | (@src.size = 'mem' & @src.size and not 8) | (@src.size = 'mmreg' & @src.size <> 16) + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , cvttss2si,2Ch, cvtss2si,2Dh + macro instr? dest*,src* + require SSE+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size < 4 | (@src.size = 'mem' & @src.size and not 4) | (@src.size = 'mmreg' & @src.size <> 16) + err 'invalid operand size' + end if + x86.select_operand_prefix@src @dest.size + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , pminub,0DAh, pmaxub,0DEh, pavgb,0E0h, pavgw,0E3h, pmulhuw,0E4h, pminsw,0EAh, pmaxsw,0EEh, psadbw,0F6h + macro instr? dest*,src* + require SSE+ + MMX.basic_instruction ext,dest,src + end macro +end iterate + +macro pinsrw? dest*,src*,sel* + require SSE+ + MMX.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@aux sel + if @dest.type = 'mmreg' & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm' + if (@src.type = 'reg' & @src.size <> 4) | (@src.type = 'mem' & @src.size and not 2) | @aux.size and not 1 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,0C4h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pextrw? dest*,src*,sel* + require SSE+ + x86.parse_operand@dest dest + MMX.parse_operand@src src + x86.parse_operand@aux sel + if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm' + if @dest.size <> 4 | @aux.size and not 1 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,0C5h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pshufw? dest*,src*,sel* + require SSE+ + MMX.parse_operand@dest dest + MMX.parse_operand@src src + x86.parse_operand@aux sel + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @src.size and not 8 | @aux.size and not 1 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,70h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pmovmskb? dest*,src* + require SSE+ + x86.parse_operand@dest dest + MMX.parse_operand@src src + if @dest.type = 'reg' & @src.type = 'mmreg' + if @dest.size <> 4 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,0D7h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro movntq? dest*,src* + require SSE+ + MMX.parse_operand@dest dest + MMX.parse_operand@src src + if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not 8 + err 'invalid operand size' + end if + x86.store_instruction@dest <0Fh,0E7h>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro maskmovq? src*,sel* + require SSE+ + MMX.parse_operand@src src + MMX.parse_operand@aux sel + if @src.type = 'mmreg' & @aux.type = 'mmreg' + x86.store_instruction@aux <0Fh,0F7h>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , prefetchnta,0, prefetcht0,1, prefetcht1,2, prefetcht2,3 + macro instr? src* + require SSE+ + x86.parse_operand@src src + if @src.type = 'mem' + if @src.size and not 1 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,18h>,postbyte + else + err 'invalid operand' + end if + end macro +end iterate + +macro sfence? + db 0Fh,0AEh,0F8h +end macro + +iterate , fxsave,0, fxrstor,1 + macro instr? src* + require SSE+ + x86.parse_operand@src src + if @src.type = 'mem' + if @src.size and not 512 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,0AEh>,postbyte + else + err 'invalid operand' + end if + end macro +end iterate + +iterate , ldmxcsr,2, stmxcsr,3 + macro instr? src* + require SSE+ + x86.parse_operand@src src + if @src.type = 'mem' + if @src.size and not 4 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,0AEh>,postbyte + else + err 'invalid operand' + end if + end macro +end iterate diff --git a/toolchain/fasm2/include/iset/sse2.inc b/toolchain/fasm2/include/iset/sse2.inc new file mode 100644 index 0000000..ac820b4 --- /dev/null +++ b/toolchain/fasm2/include/iset/sse2.inc @@ -0,0 +1,579 @@ + +iterate , sqrt,51h, rsqrt,52h, rcp,53h, add,58h, mul,59h, sub,5Ch, min,5Dh, div,5Eh, max,5Fh + macro instr#pd? dest*,src* + require SSE2+ + SSE.basic_instruction 66h,ext,16,dest,src + end macro + macro instr#sd? dest*,src* + require SSE2+ + SSE.basic_instruction 0F2h,ext,8,dest,src + end macro +end iterate + +iterate , and,54h, andn,55h, or,56h, xor,57h, unpckl,14h, unpckh,15h + macro instr#pd? dest*,src* + require SSE2+ + SSE.basic_instruction 66h,ext,16,dest,src + end macro +end iterate + +macro cmppd? dest*,src*,code* + require SSE2+ + SSE.basic_instruction_imm8 66h,0C2h,16,dest,src,code +end macro + +macro SSE.cmpsd? dest*,src*,code* + require SSE2+ + SSE.basic_instruction_imm8 0F2h,0C2h,8,dest,src,code +end macro + +calminstruction cmpsd? args& + match , args + jno sse + xcall x86.store_operand_prefix, (4) + emit 1, 0A7h + exit + sse: + arrange args, =SSE.=cmpsd args + assemble args +end calminstruction + +iterate , eq,0, lt,1, le,2, unord,3, neq,4, nlt,5, nle,6, ord,7 + macro cmp#cond#pd? dest*,src* + require SSE2+ + cmppd dest,src,code + end macro + macro cmp#cond#sd? dest*,src* + require SSE2+ + cmpsd dest,src,code + end macro +end iterate + +macro shufpd? dest*,src*,imm* + require SSE2+ + SSE.basic_instruction_imm8 66h,0C6h,16,dest,src,imm +end macro + +iterate , movapd,28h, movupd,10h + macro instr? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,ext>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,ext+1>,@src.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , movlpd,12h, movhpd,16h + macro instr? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if @dest.size <> 16 | @src.size and not 8 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,ext>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not 8 | @src.size <> 16 + err 'invalid operand size' + end if + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,ext+1>,@src.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +macro SSE.movsd? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> 16) + err 'invalid operand size' + end if + @src.opcode_prefix = 0F2h + x86.store_instruction@src <0Fh,10h>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not 8 | @src.size <> 16 + err 'invalid operand size' + end if + @dest.opcode_prefix = 0F2h + x86.store_instruction@dest <0Fh,11h>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +calminstruction movsd? args& + match , args + jno sse + xcall x86.store_operand_prefix, (4) + emit 1, 0A5h + exit + sse: + arrange args, =SSE.=movsd args + assemble args +end calminstruction + +iterate , movdqa,66h, movdqu,0F3h + macro instr? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + @src.opcode_prefix = pre + x86.store_instruction@src <0Fh,6Fh>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'mmreg' + @dest.opcode_prefix = pre + x86.store_instruction@dest <0Fh,7Fh>,@src.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , movntpd,2Bh, movntdq,0E7h + macro instr? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mem' & @src.type = 'mmreg' + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,ext>,@src.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +macro movmskpd? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'reg' & @src.type = 'mmreg' + if (@dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | @src.size <> 16 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,50h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro maskmovdqu? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mmreg' + if (@dest.size or @src.size) <> 16 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,0F7h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , ucomisd,2Eh, comisd,2Fh + macro instr? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> 16) + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +macro cvtps2pd? dest*,src* + require SSE2+ + SSE.basic_instruction 0,5Ah,8,dest,src +end macro + +macro cvtpd2ps? dest*,src* + require SSE2+ + SSE.basic_instruction 66h,5Ah,16,dest,src +end macro + +macro cvtsd2ss? dest*,src* + require SSE2+ + SSE.basic_instruction 0F2h,5Ah,8,dest,src +end macro + +macro cvtss2sd? dest*,src* + require SSE2+ + SSE.basic_instruction 0F3h,5Ah,4,dest,src +end macro + +macro cvtdq2ps? dest*,src* + require SSE2+ + SSE.basic_instruction 0,5Bh,16,dest,src +end macro + +macro cvtps2dq? dest*,src* + require SSE2+ + SSE.basic_instruction 66h,5Bh,16,dest,src +end macro + +macro cvttps2dq? dest*,src* + require SSE2+ + SSE.basic_instruction 0F3h,5Bh,16,dest,src +end macro + +macro cvttpd2dq? dest*,src* + require SSE2+ + SSE.basic_instruction 66h,0E6h,16,dest,src +end macro + +macro cvtpd2dq? dest*,src* + require SSE2+ + SSE.basic_instruction 0F2h,0E6h,16,dest,src +end macro + +macro cvtdq2pd? dest*,src* + require SSE2+ + SSE.basic_instruction 0F3h,0E6h,8,dest,src +end macro + +macro movdq2q? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mmreg' + if @dest.size <> 8 | @src.size <> 16 + err 'invalid operand size' + end if + @src.opcode_prefix = 0F2h + x86.store_instruction@src <0Fh,0D6h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro movq2dq? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mmreg' + if @dest.size <> 16 | @src.size <> 8 + err 'invalid operand size' + end if + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,0D6h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro cvtpi2pd? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 16 | @src.size and not 8 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,2Ah>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro cvtsi2sd? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg') + if @src.size = 0 + err 'operand size not specified' + else if @dest.size <> 16 | @src.size < 4 + err 'invalid operand size' + end if + x86.select_operand_prefix@src @src.size + @src.opcode_prefix = 0F2h + x86.store_instruction@src <0Fh,2Ah>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , cvttpd2pi,2Ch, cvtpd2pi,2Dh + macro instr? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size <> 8 | @src.size and not 16 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , cvttsd2si,2Ch, cvtsd2si,2Dh + macro instr? dest*,src* + require SSE2+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg') + if @dest.size < 4 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <>16) + err 'invalid operand size' + end if + x86.select_operand_prefix@src @dest.size + @src.opcode_prefix = 0F2h + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , paddq,0D4h, pmuludq,0F4h, psubq,0FBh + macro instr? dest*,src* + require SSE2+ + MMX.basic_instruction ext,dest,src + end macro +end iterate + +macro movq? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> @dest.size) + err 'invalid operand size' + end if + if @dest.size = 8 + x86.store_instruction@src <0Fh,6Fh>,@dest.rm + else + @src.opcode_prefix = 0F3h + x86.store_instruction@src <0Fh,7Eh>,@dest.rm + end if + else if @dest.type = 'mem' & @src.type = 'mmreg' + if @dest.size and not 8 + err 'invalid operand size' + end if + if @src.size = 8 + x86.store_instruction@dest <0Fh,7Fh>,@src.rm + else + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,0D6h>,@src.rm + end if + else if @dest.type = 'reg' & @src.type = 'mmreg' + if @dest.size <> 8 + err 'invalid operand size' + end if + if @src.size = 16 + @dest.opcode_prefix = 66h + end if + @dest.prefix = 48h + x86.store_instruction@dest <0Fh,7Eh>,@src.rm + else if @dest.type = 'mmreg' & @src.type = 'reg' + if @src.size <> 8 + err 'invalid operand size' + end if + if @dest.size = 16 + @src.opcode_prefix = 66h + end if + @src.prefix = 48h + x86.store_instruction@src <0Fh,6Eh>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +macro movd? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg') + if @src.size and not 4 + err 'invalid operand size' + end if + MMX.select_operand_prefix@src @dest.size + x86.store_instruction@src <0Fh,6Eh>,@dest.rm + else if (@dest.type = 'mem' | @dest.type = 'reg') & @src.type = 'mmreg' + if @dest.size and not 4 + err 'invalid operand size' + end if + MMX.select_operand_prefix@dest @src.size + x86.store_instruction@dest <0Fh,7Eh>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro pinsrw? dest*,src*,sel* + require SSE2+ + SSE.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@aux sel + if @dest.type = 'mmreg' & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm' + if (@src.type = 'reg' & @src.size <> 4) | (@src.type = 'mem' & @src.size and not 2) | @aux.size and not 1 + err 'invalid operand size' + end if + MMX.select_operand_prefix@src @dest.size + x86.store_instruction@src <0Fh,0C4h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pextrw? dest*,src*,sel* + require SSE2+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + x86.parse_operand@aux sel + if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm' + if x86.mode = 64 & @dest.size = 8 + @dest.size = 4 + end if + if @dest.size <> 4 | @aux.size and not 1 + err 'invalid operand size' + end if + MMX.select_operand_prefix@src @src.size + x86.store_instruction@src <0Fh,0C5h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +iterate , pshufd,66h, pshuflw,0F2h, pshufhw,0F3h + macro instr? dest*,src*,sel* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + x86.parse_operand@aux sel + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @dest.size <> 16 | @src.size and not 16 | @aux.size and not 1 + err 'invalid operand size' + end if + @src.opcode_prefix = pre + x86.store_instruction@src <0Fh,70h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +macro pmovmskb? dest*,src* + require SSE2+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'reg' & @src.type = 'mmreg' + if @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8) + err 'invalid operand size' + end if + MMX.select_operand_prefix@src @src.size + x86.store_instruction@src <0Fh,0D7h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , psrldq,3, pslldq,7 + macro instr? dest*,cnt* + require SSE2+ + SSE.parse_operand@dest dest + x86.parse_operand@aux cnt + if @dest.type = 'mmreg' & @aux.type = 'imm' + if @dest.size <> 16 | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,73h>,postbyte,1,@aux.imm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , punpcklqdq,6Ch, punpckhqdq,6Dh + macro instr? dest*,src* + require SSE2+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,ext>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +macro movnti? dest*,src* + require SSE2+ + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'mem' & @src.type = 'reg' + if @dest.size and not @src.size + err 'operand sizes do not match' + else if @src.size <> 4 & @src.size <> 8 + err 'invalid operand size' + end if + x86.select_operand_prefix@dest @src.size + x86.store_instruction@dest <0Fh,0C3h>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro clflush? src* + require SSE2+ + x86.parse_operand@src src + if @src.type = 'mem' + if @src.size and not 1 + err 'invalid operand size' + end if + x86.store_instruction@src <0Fh,0AEh>,7 + else + err 'invalid operand' + end if +end macro + +macro lfence? + require SSE2+ + db 0Fh,0AEh,0E8h +end macro + +macro mfence? + require SSE2+ + db 0Fh,0AEh,0F0h +end macro diff --git a/toolchain/fasm2/include/iset/sse3.inc b/toolchain/fasm2/include/iset/sse3.inc new file mode 100644 index 0000000..5462af1 --- /dev/null +++ b/toolchain/fasm2/include/iset/sse3.inc @@ -0,0 +1,84 @@ + +macro fisttp? src* + require SSE3+ + x86.parse_operand@src src + if @src.type = 'mem' + if @src.size = 2 + x86.store_instruction@src 0DFh,1 + else if @src.size = 4 + x86.store_instruction@src 0DBh,1 + else if @src.size = 8 + x86.store_instruction@src 0DDh,1 + else if @src.size + err 'invalid operand size' + else + err 'operand size not specified' + end if + else + err 'invalid operand' + end if +end macro + +iterate , addsub,0D0h, hadd,7Ch, hsub,7Dh + macro instr#pd? dest*,src* + require SSE3+ + SSE.basic_instruction 66h,ext,16,dest,src + end macro + macro instr#ps? dest*,src* + require SSE3+ + SSE.basic_instruction 0F2h,ext,16,dest,src + end macro +end iterate + +iterate , movsldup,12h, movshdup,16h + macro instr? dest*,src* + require SSE3+ + SSE.basic_instruction 0F3h,ext,16,dest,src + end macro +end iterate + +macro movddup? dest*,src* + require SSE3+ + SSE.basic_instruction 0F2h,12h,8,dest,src +end macro + +macro lddqu? dest*,src* + require SSE3+ + SSE.parse_operand@src dest + SSE.parse_operand@src src + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + if @dest.type = 'mmreg' & @src.type = 'mem' + @src.opcode_prefix = 0F2h + x86.store_instruction@src <0Fh,0F0h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +iterate , pshufb,0, phaddw,1, phaddd,2, phaddsw,3, pmaddubsw,4, phsubw,5, phsubd,6, phsubsw,7, psignb,8, psignw,9, psignd,0Ah, pmulhrsw,0Bh, pabsb,1Ch, pabsw,1Dh, pabsd,1Eh + macro instr? dest*,src* + require SSSE3+ + MMX.basic_instruction <38h,supp>,dest,src + end macro +end iterate + +macro palignr? dest*,src*,aux* + require SSSE3+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + x86.parse_operand@aux aux + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm' + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + if @aux.size and not 1 + err 'invalid operand size' + end if + MMX.select_operand_prefix@src @dest.size + x86.store_instruction@src <0Fh,3Ah,0Fh>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro diff --git a/toolchain/fasm2/include/iset/sse4.inc b/toolchain/fasm2/include/iset/sse4.inc new file mode 100644 index 0000000..4d04b4e --- /dev/null +++ b/toolchain/fasm2/include/iset/sse4.inc @@ -0,0 +1,278 @@ + +iterate , ptest,17h, pmuldq,28h, pcmpeqq,29h, packusdw,2Bh, pminsb,38h, pminsd,39h, pminuw,3Ah, pminud,3Bh, pmaxsb,3Ch, pmaxsd,3Dh, pmaxuw,3Eh, pmaxud,3Fh, pmulld,40h, phminposuw,41h + macro instr? dest*,src* + require SSE4.1+ + SSE.basic_instruction 66h,<38h,supp>,16,dest,src + end macro +end iterate + +iterate , roundps,08h, roundpd,09h, roundss,0Ah, roundsd,0Bh, blendps,0Ch, blendpd,0Dh, pblendw,0Eh, dpps,40h, dppd,41h, mpsadbw,42h + macro instr? dest*,src*,imm* + require SSE4.1+ + SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm + end macro +end iterate + +iterate , pblendvb,10h, blendvps,14h, blendvpd,15h + macro instr? dest*,src*,sel* + require SSE4.1+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + SSE.parse_operand@aux sel + if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'mmreg' & @aux.size = 16 & @aux.rm = 0 + if @dest.size or @src.size and not 16 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,38h,supp>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro +end iterate + +iterate , bw,0,8, bd,1,4, bq,2,2, wd,3,8, wq,4,4, dq,5,8 + macro pmovsx#conv? dest*,src* + require SSE4.1+ + SSE.basic_instruction 66h,<38h,20h+code>,msize,dest,src + end macro + macro pmovzx#conv? dest*,src* + require SSE4.1+ + SSE.basic_instruction 66h,<38h,30h+code>,msize,dest,src + end macro +end iterate + +macro insertps? dest*,src*,sel* + require SSE4.1+ + SSE.basic_instruction_imm8 66h,<3Ah,21h>,4,dest,src,sel +end macro + +macro extractps? dest*,src*,sel* + require SSE4.1+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + x86.parse_operand@aux sel + if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm' + if x86.mode = 64 & @dest.size = 8 + @dest.size = 4 + end if + if @dest.size <> 4 | @src.size and not 16 | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,3Ah,17h>,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pinsrb? dest*,src*,sel* + require SSE4.1+ + SSE.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@aux sel + if (@dest.type = 'mmreg' & @dest.size = 16) & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm' + if (@src.type = 'reg' & @src.size <> 4) | (@src.type = 'mem' & @src.size and not 1) | @aux.size and not 1 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,3Ah,20h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pinsrd? dest*,src*,sel* + require SSE4.1+ + SSE.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@aux sel + if (@dest.type = 'mmreg' & @dest.size = 16) & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm' + if @src.size and not 4 | @aux.size and not 1 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,3Ah,22h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pinsrq? dest*,src*,sel* + require SSE4.1+ + SSE.parse_operand@dest dest + x86.parse_operand@src src + x86.parse_operand@aux sel + if (@dest.type = 'mmreg' & @dest.size = 16) & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm' + if @src.size and not 8 | @aux.size and not 1 + err 'invalid operand size' + end if + if x86.mode < 64 + err 'instruction requires long mode' + end if + @src.opcode_prefix = 66h + @src.rex_prefix = 48h + x86.store_instruction@src <0Fh,3Ah,22h>,@dest.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pextrb? dest*,src*,sel* + require SSE4.1+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + x86.parse_operand@aux sel + if (@dest.type = 'reg' | @dest.type = 'mem') & (@src.type = 'mmreg' & @src.size = 16) & @aux.type = 'imm' + if x86.mode = 64 & @dest.type = 'reg' & @dest.size = 8 + @dest.size = 4 + end if + if (@dest.type = 'reg' & @dest.size <> 4) | (@dest.size = 'mem' & @dest.size and not 1) | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,3Ah,14h>,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pextrw? dest*,src*,sel* + require SSE4.1+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + x86.parse_operand@aux sel + if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm' + if x86.mode = 64 & @dest.size = 8 + @dest.size = 4 + end if + if @dest.size <> 4 | @aux.size and not 1 + err 'invalid operand size' + end if + MMX.select_operand_prefix@src @src.size + x86.store_instruction@src <0Fh,0C5h>,@dest.rm,1,@aux.imm + else if @dest.type = 'mem' & (@src.type = 'mmreg' & @src.size = 16) & @aux.type = 'imm' + if @dest.size and not 2 | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,3Ah,15h>,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pextrd? dest*,src*,sel* + require SSE4.1+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + x86.parse_operand@aux sel + if (@dest.type = 'reg' | @dest.type = 'mem') & (@src.type = 'mmreg' & @src.size = 16) & @aux.type = 'imm' + if x86.mode = 64 & @dest.type = 'reg' & @dest.size = 8 + @dest.size = 4 + end if + if @dest.size and not 4 | @aux.size and not 1 + err 'invalid operand size' + end if + @dest.opcode_prefix = 66h + x86.store_instruction@dest <0Fh,3Ah,16h>,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro pextrq? dest*,src*,sel* + require SSE4.1+ + x86.parse_operand@dest dest + SSE.parse_operand@src src + x86.parse_operand@aux sel + if (@dest.type = 'reg' | @dest.type = 'mem') & (@src.type = 'mmreg' & @src.size = 16) & @aux.type = 'imm' + if @dest.size and not 8 | @aux.size and not 1 + err 'invalid operand size' + end if + if x86.mode < 64 + err 'instruction requires long mode' + end if + @dest.opcode_prefix = 66h + @dest.rex_prefix = 48h + x86.store_instruction@dest <0Fh,3Ah,16h>,@src.rm,1,@aux.imm + else + err 'invalid combination of operands' + end if +end macro + +macro movntdqa? dest*,src* + require SSE4.1+ + SSE.parse_operand@dest dest + SSE.parse_operand@src src + if @dest.type = 'mmreg' & @src.type = 'mem' + if (@dest.size or @src.size) and not 16 + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,38h,2Ah>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + + +iterate , pcmpgtq,37h + macro instr? dest*,src* + require SSE4.2+ + SSE.basic_instruction 66h,<38h,supp>,16,dest,src + end macro +end iterate + +iterate , pcmpestrm,60h, pcmpestri,61h, pcmpistrm,62h, pcmpistri,63h + macro instr? dest*,src*,imm* + require SSE4.2+ + SSE.basic_instruction_imm8 66h,<3Ah,supp>,16,dest,src,imm + end macro + macro v#instr? dest*,src*,imm* + require AVX+ + AVX_512.single_source_instruction_imm8 VEX_66_0F3A_W0,EVEX_FORBIDDEN,supp,16,dest,src,imm + end macro +end iterate + +macro crc32? dest*,src* + require SSE4.2+ + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'reg' & ( @src.type = 'reg' | @src.type = 'mem' ) + if @dest.size <> 4 & ( @dest.size <> 8 | x86.mode <> 64 ) + err 'invalid operand size' + end if + @src.opcode_prefix = 0F2h + if @src.size > 1 + x86.select_operand_prefix@src @src.size + x86.store_instruction@src <0Fh,38h,0F1h>,@dest.rm + else if @src.size > 0 + x86.store_instruction@src <0Fh,38h,0F0h>,@dest.rm + else + err 'operand size not specified' + end if + else + err 'invalid combination of operands' + end if +end macro + +macro popcnt? dest*,src* + require POPCNT + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'reg' & ( @src.type = 'reg' | @src.type = 'mem' ) + if @src.size and not @dest.size + err 'operand sizes do not match' + end if + @src.opcode_prefix = 0F3h + if @dest.size > 1 + x86.select_operand_prefix@src @dest.size + x86.store_instruction@src <0Fh,0B8h>,@dest.rm + else + err 'invalid operand size' + end if + else + err 'invalid combination of operands' + end if +end macro diff --git a/toolchain/fasm2/include/iset/vmx.inc b/toolchain/fasm2/include/iset/vmx.inc new file mode 100644 index 0000000..3997223 --- /dev/null +++ b/toolchain/fasm2/include/iset/vmx.inc @@ -0,0 +1,72 @@ + +iterate , vmxon,0F3h,0C7h,6, vmclear,66h,0C7h,6, \ + vmptrld,0,0C7h,6, vmptrst,0,0C7h,7 + + macro instr? src* + require VMX + x86.parse_operand@src src + if @src.type = 'mem' + if @src.size and not 8 + err 'invalid operand size' + else + @src.opcode_prefix = prefix + x86.store_instruction@src <0Fh,ext>,postbyte + end if + else + err 'invalid operand' + end if + end macro + +end iterate + +macro vmxoff? + require VMX + db 0Fh,1,0C4h +end macro + +macro vmcall? + require VMX + db 0Fh,1,0C1h +end macro + +macro vmlaunch? + require VMX + db 0Fh,1,0C2h +end macro + +macro vmresume? + require VMX + db 0Fh,1,0C3h +end macro + +macro vmread? dest*,src* + require VMX + x86.parse_operand@dest dest + x86.parse_operand@src src + if @src.type = 'reg' & (@dest.type = 'mem' | @dest.type = 'reg') + if (x86.mode < 64 & @src.size <> 4) | (x86.mode = 64 & @src.size <> 8) + err 'invalid operand size' + else if @dest.size and not @src.size + err 'operand sizes do not match' + end if + x86.store_instruction@dest <0Fh,78h>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro vmwrite? dest*,src* + require VMX + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') + if (x86.mode < 64 & @dest.size <> 4) | (x86.mode = 64 & @dest.size <> 8) + err 'invalid operand size' + else if @src.size and not @dest.size + err 'operand sizes do not match' + end if + x86.store_instruction@src <0Fh,79h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro diff --git a/toolchain/fasm2/include/listing.inc b/toolchain/fasm2/include/listing.inc new file mode 100644 index 0000000..9db14b0 --- /dev/null +++ b/toolchain/fasm2/include/listing.inc @@ -0,0 +1,155 @@ + +; Listing generator, which shows generated bytes next to offset in the output file +; and assumed address in memory (limited to the constant term if an address is a linear polynomial). +; The listing is stored in a file with .LST extension. + +define Listing? Listing + +namespace Listing + + virtual at 0 + HexDigits:: db '0123456789ABCDEF' + end virtual + + spc0 := '' + repeat 34, i:0 + spc#% := spc#i bappend ' ' + end repeat + + collected_source = '' + collected_$ = $ + collected_$% = $% + collected_$%% = $%% + + calminstruction generate + local source, $, $%, $%% + + reverse: + take source, collected_source + take $, collected_$ + take $%, collected_$% + take $%%, collected_$%% + jyes reverse + + local offset + compute offset, $% + + main: + take , $% + take , $%% + take $%, $% + jno done + + check source + jno next + + local undefined_bytes, defined_bytes + compute undefined_bytes, $% - $%% + compute defined_bytes, $%% - offset + compute offset, $% + + local counter, digit + + compute counter, 16 + emit 1, '[' + print_address: + compute counter, counter - 1 + compute digit, ($ shr (counter shl 2)) and 0Fh + load digit, HexDigits:digit, 1 + emit 1, digit + check counter + jyes print_address + emit 2, '] ' + + check defined_bytes > 0 + jyes bytes_present + emit 34, spc34 + jump print_source + + bytes_present: + compute counter, 8 + print_offset: + compute counter, counter - 1 + compute digit, (($%-undefined_bytes-defined_bytes) shr (counter shl 2)) and 0Fh + load digit, HexDigits:digit, 1 + emit 1, digit + check counter + jyes print_offset + + local column, byte + + emit 2, ': ' + compute column, 0 + print_bytes: + check defined_bytes > 0 + jno fill_up + load byte, $% - undefined_bytes - defined_bytes, 1 + check column = 8 + jno print_byte + compute column, 0 + emit 1, ' ' + emit lengthof source, source + emit 2, 0A0Dh + emit 29, spc29 + compute source, '' + print_byte: + compute digit, byte shr 4 + load digit, HexDigits:digit, 1 + emit 1, digit + compute digit, byte and 0Fh + load digit, HexDigits:digit, 1 + emit 1, digit + emit 1, ' ' + compute defined_bytes, defined_bytes - 1 + compute column, column + 1 + jump print_bytes + fill_up: + check column >= 8 + jyes print_source + emit 3, spc3 + compute column, column + 1 + jump fill_up + print_source: + emit 1, ' ' + emit lengthof source, source + emit 2, 0A0Dh + next: + take , source + take , $ + jump main + done: + end calminstruction + +end namespace + +postpone ? + purge ? + virtual as 'lst' + Listing.generate + end virtual +end postpone + +calminstruction ? &line& + local tmp + arrange tmp, line + stringify tmp + take Listing.collected_source, tmp + compute tmp, $ scale 0 + take Listing.collected_$, tmp + compute tmp, $% + take Listing.collected_$%, tmp + compute tmp, $%% + take Listing.collected_$%%, tmp + assemble line +end calminstruction + +calminstruction restartout? origin + arrange origin, =restartout origin + assemble origin + reset: + take , Listing.collected_source + take , Listing.collected_$ + take , Listing.collected_$% + take , Listing.collected_$%% + jyes reset +end calminstruction diff --git a/toolchain/fasm2/include/macro/com32.inc b/toolchain/fasm2/include/macro/com32.inc new file mode 100644 index 0000000..7d26a7c --- /dev/null +++ b/toolchain/fasm2/include/macro/com32.inc @@ -0,0 +1,54 @@ + +macro cominvk Object,proc,args& + iterate arg, args + indx 1+%%-% + pushd arg + end iterate + if ~ defined Object#.com.object + err `Object,' is not a COM object' + end if + mov eax,[Object] + push eax + mov eax,[eax] + call [eax+Object.proc] +end macro + +macro comcall handle,Interface,proc,args& + iterate arg, args + indx 1+%%-% + pushd arg + end iterate + if ~ defined Interface#.com.interface + err `Interface,' is not a COM interface' + end if + match prefix [addr], :handle + mov eax,handle + push eax + mov eax,[eax] + else + push handle + local _handle + _handle := handle + mov eax,[_handle] + end match + call [eax+Interface.proc] +end macro + +macro interface name,methods& + struc name + . dd ? + virtual at 0 + iterate method, methods + .method dd ? + end iterate + end virtual + .com.object = name.com.interface + end struc + virtual at 0 + iterate method, methods + name.method dd ? + end iterate + define name + name.com.interface = $ shr 2 + end virtual +end macro diff --git a/toolchain/fasm2/include/macro/com64.inc b/toolchain/fasm2/include/macro/com64.inc new file mode 100644 index 0000000..731f5b2 --- /dev/null +++ b/toolchain/fasm2/include/macro/com64.inc @@ -0,0 +1,51 @@ + +macro cominvk Object,proc,args& + if ~ defined Object#.com.object + err `Object,' is not a COM object' + end if + macro call dummy + mov rax,[rcx] + Call [rax+Object.proc] + end macro + match any, args + fastcall -,[Object],args + else + fastcall -,[Object] + end match + purge call +end macro + +macro comcall handle,Interface,proc,args& + if ~ defined Interface#.com.interface + err `Interface,' is not a COM interface' + end if + macro call dummy + mov rax,[rcx] + Call [rax+Interface.proc] + end macro + match any, args + fastcall -,handle,args + else + fastcall -,handle + end match + purge call +end macro + +macro interface name,methods& + struc name + . dq ? + virtual at 0 + iterate method, methods + .method dq ? + end iterate + end virtual + .com.object = name.com.interface + end struc + virtual at 0 + iterate method, methods + name.method dq ? + end iterate + define name + name.com.interface = $ shr 3 + end virtual +end macro diff --git a/toolchain/fasm2/include/macro/export.inc b/toolchain/fasm2/include/macro/export.inc new file mode 100644 index 0000000..ef207c4 --- /dev/null +++ b/toolchain/fasm2/include/macro/export.inc @@ -0,0 +1,67 @@ + +macro export dllname,exports& + iterate , exports + + local module,addresses,names,ordinal,count + count = %% + dd 0,0,0,RVA module,1 + dd count,count,RVA addresses,RVA names,RVA ordinal + addresses: + repeat count + indx % + dd RVA label + end repeat + names: + repeat count + dd RVA names.name#% + end repeat + ordinal: + repeat count + dw %-1 + end repeat + module db dllname,0 + repeat count + indx % + names.name#% db string,0 + end repeat + + local x,y,z,str1,str2,v1,v2 + x = count shr 1 + while x > 0 + y = x + while y < count + z = y + while z-x >= 0 + load v1:dword from names+z*4 + str1 = ($-(RVA $))+v1 + load v2:dword from names+(z-x)*4 + str2 = ($-(RVA $))+v2 + while v1 > 0 + load v1:byte from str1+%-1 + load v2:byte from str2+%-1 + if v1 <> v2 + break + end if + end while + if v1 < v2 + load v1:dword from names+z*4 + load v2:dword from names+(z-x)*4 + store v1:dword at names+(z-x)*4 + store v2:dword at names+z*4 + load v1:word from ordinal+z*2 + load v2:word from ordinal+(z-x)*2 + store v1:word at ordinal+(z-x)*2 + store v2:word at ordinal+z*2 + else + break + end if + z = z-x + end while + y = y+1 + end while + x = x shr 1 + end while + + break + end iterate +end macro diff --git a/toolchain/fasm2/include/macro/if.inc b/toolchain/fasm2/include/macro/if.inc new file mode 100644 index 0000000..83b8450 --- /dev/null +++ b/toolchain/fasm2/include/macro/if.inc @@ -0,0 +1,337 @@ + +define _if _if + +define _if..if? _if +define _if..else? _else +define _if..elseif? _elseif +define _if..endif? _endif +define _if..while? _while +define _if..endw? _endw +define _if..repeat? _repeat +define _if..until? _until + +calminstruction (cmd) ? &a& + transform cmd,_if + arrange cmd, cmd a + assemble cmd +end calminstruction + +macro _if cond + __IF equ : + local endif + __ENDIF equ endif + local else + __ELSE equ else + jcondexpr __ELSE,1,cond +end macro + +macro _else + jmp __ENDIF + match _else, __ELSE + _else: + end match + restore __IF + __IF equ +end macro + +macro _elseif cond + jmp __ENDIF + match _else, __ELSE + _else: + end match + restore __ELSE + local else + __ELSE equ else + jcondexpr __ELSE,1,cond +end macro + +macro _endif + match :_else, __IF __ELSE + _else: + end match + match endif, __ENDIF + endif: + end match + restore __ELSE + restore __ENDIF + restore __IF +end macro + +macro _while cond + local while + while: + __WHILE equ while + local endw + __ENDW equ endw + jcondexpr __ENDW,1,cond +end macro + +macro _endw + jmp __WHILE + match endw, __ENDW + endw: + end match + restore __ENDW + restore __WHILE +end macro + +macro _repeat + local repeat + repeat: + __REPEAT equ repeat +end macro + +macro _until cond + jcondexpr __REPEAT,1,cond + restore __REPEAT +end macro + +macro newlocal? var + local new + redefine var new +end macro + +macro JCONDEXPR?: target,mode,cond + local buffer,current,counter + local neg,conj + local f,t + buffer equ cond + newlocal f + newlocal t + while 1 + match ~x, buffer + buffer equ x + neg = (mode) xor 1 + else + neg = mode + end match + + match (x, buffer + counter = 1 + current equ ( + buffer equ x + while counter > 0 + match p)s, buffer + match (ps, p + counter = counter + 1 + current equ current ( + buffer equ ps)s + else match pp(ps, p + counter = counter + 1 + current equ current pp( + buffer equ ps)s + else + counter = counter - 1 + current equ current p + buffer equ )s + end match + else + current equ current buffer + buffer equ + break + end match + end while + else + current equ + end match + + match a|b, buffer + match c&d, a + current equ current c + buffer equ &d|b + else + current equ current a + buffer equ |b + end match + else match c&d, buffer + match a|b, c + current equ current a + buffer equ |b&d + else + current equ current c + buffer equ &d + end match + else + current equ current buffer + buffer equ + end match + + match , buffer + match (c), current + jcondexpr t,neg,c + else match c, current + jcond t,neg,c + end match + break + else + match |b, buffer + buffer equ b + conj = 0 + else match &d, buffer + buffer equ d + conj = 1 + else + err 'invalid expression' + end match + if (mode) xor conj + match (c), current + jcondexpr f,neg xor 1,c + else match c, current + jcond f,neg xor 1,c + end match + match t,t + t: + end match + newlocal t + + else + match (c), current + jcondexpr t,neg,c + else match c, current + jcond t,neg,c + end match + match f,f + f: + end match + newlocal f + end if + end match + end while + match t,t + label t at target + end match + match f,f + f: + end match +end macro + +macro JCOND? target,neg,cond + match =signed? v1>==v2, cond + cmp v1,v2 + if neg + jl target + else + jge target + end if + else match =signed? v1<==v2, cond + cmp v1,v2 + if neg + jg target + else + jle target + end if + else match v1>==v2, cond + cmp v1,v2 + if neg + jb target + else + jae target + end if + else match v1<==v2, cond + cmp v1,v2 + if neg + ja target + else + jbe target + end if + else match v1==v2, cond + cmp v1,v2 + if neg + jne target + else + je target + end if + else match v1<>v2, cond + cmp v1,v2 + if neg + je target + else + jne target + end if + else match =signed? v1>v2, cond + cmp v1,v2 + if neg + jle target + else + jg target + end if + else match =signed? v1v2, cond + cmp v1,v2 + if neg + jbe target + else + ja target + end if + else match v1, definitions + if ~ name.redundant + dd RVA name.lookup,0,0,RVA name.str,RVA name.address + end if + name.referred = 1 + end iterate + dd 0,0,0,0,0 + iterate , definitions + if ~ name.redundant + name.str db string,0 + align 2 + end if + end iterate +end macro + +macro import? name,definitions& + align 4 + if defined name.referred + name.lookup: + iterate , definitions + if used label + if string eqtype '' + dd RVA name.label + else + dd 80000000h + string + end if + end if + end iterate + if $ > name.lookup + name.redundant = 0 + dd 0 + else + name.redundant = 1 + end if + name.address: + iterate , definitions + if used label + if string eqtype '' + label dd RVA name.label + else + label dd 80000000h + string + end if + end if + end iterate + if ~ name.redundant + dd 0 + end if + iterate , definitions + if used label & string eqtype '' + name.label dw 0 + db string,0 + align 2 + end if + end iterate + end if +end macro diff --git a/toolchain/fasm2/include/macro/import64.inc b/toolchain/fasm2/include/macro/import64.inc new file mode 100644 index 0000000..516187f --- /dev/null +++ b/toolchain/fasm2/include/macro/import64.inc @@ -0,0 +1,59 @@ + +macro library? definitions& + PE.Imports: + iterate , definitions + if ~ name.redundant + dd RVA name.lookup,0,0,RVA name.str,RVA name.address + end if + name.referred = 1 + end iterate + dd 0,0,0,0,0 + iterate , definitions + if ~ name.redundant + name.str db string,0 + align 2 + end if + end iterate +end macro + +macro import? name,definitions& + align 8 + if defined name.referred + name.lookup: + iterate , definitions + if used label + if string eqtype '' + dq RVA name.label + else + dq 8000000000000000h + string + end if + end if + end iterate + if $ > name.lookup + name.redundant = 0 + dq 0 + else + name.redundant = 1 + end if + name.address: + iterate , definitions + if used label + if string eqtype '' + label dq RVA name.label + else + label dq 8000000000000000h + string + end if + end if + end iterate + if ~ name.redundant + dq 0 + end if + iterate , definitions + if used label & string eqtype '' + name.label dw 0 + db string,0 + align 2 + end if + end iterate + end if +end macro diff --git a/toolchain/fasm2/include/macro/inline.inc b/toolchain/fasm2/include/macro/inline.inc new file mode 100644 index 0000000..fc2bfd8 --- /dev/null +++ b/toolchain/fasm2/include/macro/inline.inc @@ -0,0 +1,88 @@ + +; Simple preprocessor for inline macros. + +; Example of use: +; +; inlinemacro oddflip(number) +; return = (number) xor 1 +; end inlinemacro +; +; db oddflip(3), oddflip(oddflip(0) shl 1) + +; Any kind of definition of an expression-class symbol may be used for the return value. + +include 'xcalm.inc' + +define inlinemacro? inlinemacro? + +inlinemacro... = 0 + +calminstruction inlinemacro?! &declaration& + local name + match name(arguments?), declaration + jyes define + match name= arguments?, declaration + jyes define + match name arguments?, declaration + define: + arrange tmp, =__inline__.name + arrange name, =inlinemacro.name + publish name, tmp + arrange tmp, =struc (=return?) name arguments + assemble tmp +end calminstruction + +calminstruction end?.inlinemacro?! + asm end struc + check inlinemacro... + jyes done + compute inlinemacro..., 1 + asm inlinemacro?.enable? + done: +end calminstruction + +macro inlinemacro?.enable? chain + chain + macro include?! file*, head + include file, inlinemacro.enable head + purge ?, include? + end macro + calminstruction ?! &text& + local head, tail, name, arguments, more, i + init i, 0 + match =inlinemacro? more, text + jyes ready + transform text, inlinemacro + jno ready + match =else? more, text + jno preprocess + compute i, i+1 + arrange text, =__inline__.?(=else =if 1) =__inline__.?(=__return__.i==1) text =__inline__.?(=end =if) =__inline__.?(=if ~=definite =__return__.i) + preprocess: + match head? =__inline__.name tail?, text + jno ready + match (arguments?) tail?, tail, () + jyes inline + arrange text, head name tail + jump preprocess + inline: + match ?, name + jyes special + local tmp, return + compute i, i+1 + arrange return, =__return__.i + arrange tmp, return =inlinemacro.name arguments + arrange text, head return tail + take text, tmp + jump preprocess + special: + arrange text, head tail + take text, arguments + jump preprocess + ready: + assemble text + take , text + take text, text + jyes preprocess + end calminstruction +end macro diff --git a/toolchain/fasm2/include/macro/proc32.inc b/toolchain/fasm2/include/macro/proc32.inc new file mode 100644 index 0000000..9710d01 --- /dev/null +++ b/toolchain/fasm2/include/macro/proc32.inc @@ -0,0 +1,395 @@ + +define stdcall? stdcall + +macro stdcall?.push_string value& + local continue + if sizeof.TCHAR > 1 + local alignment + virtual at $+5 + align sizeof.TCHAR + alignment = $-$$ + end virtual + db alignment dup 90h + end if + call continue + TCHAR value,0 + continue: +end macro + +macro stdcall?: proc*,args& + local count + count = 0 + iterate arg, args + indx 1+%%-% + match =addr? val, arg + if val relativeto 0 | val relativeto $ + push dword val + else + lea edx,[val] + push edx + end if + else match =double? [var], arg + push dword [var+4] + push dword [var] + count = count + 1 + else match =double? val, arg + local low,high + virtual at 0 + dq val + load low:dword from 0 + load high:dword from 4 + end virtual + push dword high + push dword low + count = count + 1 + else match =invoke? func, arg + invoke func + push eax + else match =cinvoke? func, arg + cinvoke func + push eax + else match =stdcall? func, arg + stdcall func + push eax + else match =ccall? func, arg + ccall func + push eax + else match first=,rest, arg + stdcall?.push_string arg + else match size [var], arg + if size = 4 + push arg + else + if size = 1 + mov al, arg + else if size = 2 + mov ax, arg + else + mov eax, arg + end if + push eax + end if + else match [var], arg + push dword arg + else + if arg eqtype '' + stdcall?.push_string arg + else + push dword arg + end if + end match + count = count + 1 + end iterate + pcountcheck proc,count + call proc +end macro + +macro ccall?: proc*,args& + local count + count = 0 + iterate arg, args + indx 1+%%-% + match =addr? val, arg + if val relativeto 0 | val relativeto $ + push dword val + else + lea edx,[val] + push edx + end if + else match =double? [var], arg + push dword [var+4] + push dword [var] + count = count + 1 + else match =double? val, arg + local low,high + virtual at 0 + dq val + load low:dword from 0 + load high:dword from 4 + end virtual + push dword high + push dword low + count = count + 1 + else match =invoke? func, arg + invoke func + push eax + else match =cinvoke? func, arg + cinvoke func + push eax + else match =stdcall? func, arg + stdcall func + push eax + else match =ccall? func, arg + ccall func + push eax + else match first=,rest, arg + stdcall?.push_string arg + else match size [var], arg + if size = 4 + push arg + else + if size = 1 + mov al, arg + else if size = 2 + mov ax, arg + else + mov eax, arg + end if + push eax + end if + else match [var], arg + push dword arg + else + if arg eqtype '' + stdcall?.push_string arg + else + push dword arg + end if + end match + count = count + 1 + end iterate + pcountcheck proc,count + call proc + if count + add esp,count*4 + end if +end macro + +macro invoke?: proc*,args& + stdcall [proc],args +end macro + +macro cinvoke?: proc*,args& + ccall [proc],args +end macro + +macro pcountcheck? proc*,args* +end macro + +define pcountsuffix % + +prologue@proc equ prologuedef + +macro prologuedef procname,flag,parmbytes,localbytes,reglist + local loc + loc = (localbytes+3) and (not 3) + parmbase@proc equ ebp+8 + localbase@proc equ ebp-loc + if parmbytes | localbytes + push ebp + mov ebp,esp + if localbytes + sub esp,loc + end if + end if + iterate reg, reglist + push reg + end iterate +end macro + +epilogue@proc equ epiloguedef + +macro epiloguedef procname,flag,parmbytes,localbytes,reglist + iterate reg, reglist + indx %%-%+1 + pop reg + end iterate + if parmbytes | localbytes + leave + end if + if flag and 10000b + retn + else + retn parmbytes + end if +end macro + +close@proc equ + +macro proc? statement& + + local _local,params,flag,regs,parmbytes,localbytes,current,tmp,initlocal + + macro endp?! + + localbytes = current + + purge ret?,locals?,endl?,proclocal? + + match close:reglist, close@proc, + close name,flag,parmbytes,localbytes,reglist + end match + + end match + end namespace + end if + end match + + purge endp? + + end macro + + match name declaration, statement : + if used name + name: + namespace name + outscope match local?, proclocal + + match =stdcall? args :, declaration + define params args + flag = 11b + else match =stdcall? :, declaration + define params + flag = 11b + else match =c? args :, declaration + define params args + flag = 10001b + else match =c? :, declaration + define params + flag = 10001b + else match args :, declaration + define params args + flag = 0 + else + define params + flag = 0 + end match + define regs + match =uses? list, params + define params list + while 1 + match =, tail, params + define params tail + break + else match reg tail, params& + match more&, tail + define params more + else + define params + end match + if % = 1 + regs equ reg + else + regs equ regs,reg + end if + else + break + end match + end while + else match =, tail, params + define params tail + end match + + match prologue:reglist, prologue@proc: + prologue name,flags,parmbytes,localbytes,reglist + end match + + virtual at parmbase@proc + namespace name + match args, params + iterate arg, args + match argname:type, arg + label argname:type + rb type + else + ?arg dd ? + end match + end iterate + end match + parmbytes := $-(parmbase@proc) + match p, pcountsuffix + name#p = parmbytes/4 + end match + end namespace + end virtual + + macro ret? operand + match any, operand + retn operand + else + match epilogue:reglist, epilogue@proc: + epilogue name,flag,parmbytes,localbytes,reglist + end match + end match + end macro + + current = 0 + + macro initlocal + local area,pointer,length,value + area:: + pointer = localbase@proc+current + length = $@ - (localbase@proc) - current + current = $ - (localbase@proc) + end virtual + while length > 0 + if length < 2 + load value:byte from area:pointer + mov byte [pointer],value + pointer = pointer + 1 + length = length - 1 + else if length < 4 + load value:word from area:pointer + mov word [pointer],value + pointer = pointer + 2 + length = length - 2 + else + load value:dword from area:pointer + mov dword [pointer],value + pointer = pointer + 4 + length = length - 4 + end if + end while + virtual at localbase@proc+current + end macro + + macro locals? + virtual at localbase@proc+current + iterate dword, dword,qword + macro dword? value + if value relativeto 0 + emit dword: value + else + initlocal + local pointer + pointer := $ + end virtual + mov dword [pointer],value + virtual at pointer+4 + current = $ - (localbase@proc) + end if + end macro + end iterate + macro ? line& + line + if $ > $@ + initlocal + end if + end macro + end macro + + macro endl? + purge ?, dword?,qword? + initlocal + end virtual + end macro + + macro proclocal? args& + locals + iterate arg, args + match varname[count]:type, arg + ?varname dbx type:count dup ? + else match varname:type, arg + ?varname dbx type, ? + else match varname[count], arg + ?varname rd count + else match varname type, arg + ?varname type + else + ?arg dd ? + end match + end iterate + endl + end macro + +end macro diff --git a/toolchain/fasm2/include/macro/proc64.inc b/toolchain/fasm2/include/macro/proc64.inc new file mode 100644 index 0000000..ab9450c --- /dev/null +++ b/toolchain/fasm2/include/macro/proc64.inc @@ -0,0 +1,491 @@ +define fastcall? fastcall + +fastcall.r1 equ rcx +fastcall.rd1 equ ecx +fastcall.rw1 equ cx +fastcall.rb1 equ cl +fastcall.rf1 equ xmm0 + +fastcall.r2 equ rdx +fastcall.rd2 equ edx +fastcall.rw2 equ dx +fastcall.rb2 equ dl +fastcall.rf2 equ xmm1 + +fastcall.r3 equ r8 +fastcall.rd3 equ r8d +fastcall.rw3 equ r8w +fastcall.rb3 equ r8b +fastcall.rf3 equ xmm2 + +fastcall.r4 equ r9 +fastcall.rd4 equ r9d +fastcall.rw4 equ r9w +fastcall.rb4 equ r9b +fastcall.rf4 equ xmm3 + +fastcall?.frame = -1 + +macro frame? + local size + define fastcall?.frame_size size + fastcall?.frame =: 0 + sub rsp,size +end macro + +macro end?.frame? + match size, fastcall?.frame_size + size := fastcall?.frame + add rsp,size + end match + restore fastcall?.frame,fastcall?.frame_size +end macro + +macro endf? + end frame +end macro + +macro fastcall?.inline_string var + local data,continue + jmp continue + if sizeof.TCHAR > 1 + align sizeof.TCHAR,90h + end if + match value, var + data TCHAR value,0 + end match + redefine var data + continue: +end macro + +macro fastcall?: proc*,args& + local offset,framesize,type,value + if framesize & fastcall?.frame < 0 + sub rsp,framesize + end if + offset = 0 + local nest,called + called = 0 + iterate arg, args + nest = 0 + match =invoke? func, arg + nest = % + else match =fastcall? func, arg + nest = % + end match + if nest + if called + mov [rsp+8*(called-1)],rax + end if + frame + arg + end frame + called = nest + end if + end iterate + iterate arg, args + match =float? val, arg + type = 'f' + value reequ val + SSE.parse_operand@src val + else match =addr? val, arg + type = 'a' + value reequ val + x86.parse_operand@src [val] + else match =invoke? func, arg + if called = % + type = 0 + value reequ rax + x86.parse_operand@src rax + else + type = 'r' + end if + else match =fastcall? func, arg + if called = % + type = 0 + value reequ rax + x86.parse_operand@src rax + else + type = 'r' + end if + else match first=,rest, arg + type = 's' + value reequ arg + else + type = 0 + value reequ arg + SSE.parse_operand@src arg + if @src.type = 'imm' & @src.size = 0 + if value eqtype '' + type = 's' + end if + end if + end match + if type = 's' + fastcall.inline_string value + type = 'a' + end if + if % < 5 + if type = 'f' + if @src.size = 8 | ~ @src.size | @src.type = 'mmreg' + if @src.type = 'imm' + mov rax,value + movq fastcall.rf#%,rax + else + movq fastcall.rf#%,value + end if + else if @src.size = 4 + if @src.type = 'imm' + mov eax,value + movd fastcall.rf#%,eax + else + movd fastcall.rf#%,value + end if + else + err 'invalid argument ',`arg + end if + else + if type = 'a' + lea fastcall.r#%,[value] + else + if type = 'r' + @src.size = 8 + @src.type = 'mem' + value equ [rsp+8*(%-1)] + end if + if @src.size = 8 | ~ @src.size + if @src.type <> 'reg' | ~ @src.imm eq fastcall.r#% + mov fastcall.r#%,value + end if + else if @src.size = 4 + if @src.type <> 'reg' | ~ @src.imm eq fastcall.rd#% + mov fastcall.rd#%,value + end if + else if @src.size = 2 + if @src.type <> 'reg' | ~ @src.imm eq fastcall.rw#% + mov fastcall.rw#%,value + end if + else if @src.size = 1 + if @src.type <> 'reg' | ~ @src.imm eq fastcall.rb#% + mov fastcall.rb#%,value + end if + else + err 'invalid argument ',`arg + end if + end if + end if + else + if type = 'r' + ; already on stack + else if @src.type = 'reg' + mov [rsp+offset],value + else if @src.type = 'mem' + if type = 'a' + lea rax,[value] + mov [rsp+offset],rax + else + if @src.size = 8 | ~ @src.size + mov rax,value + mov [rsp+offset],rax + else if @src.size = 4 + mov eax,value + mov [rsp+offset],eax + else if @src.size = 2 + mov ax,value + mov [rsp+offset],ax + else if @src.size = 1 + mov al,value + mov [rsp+offset],al + else + err 'invalid argument ',`arg + end if + end if + else if @src.type = 'imm' + if @src.size = 8 | ~ @src.size + if (value) relativeto 0 & (value) - 1 shl 64 >= -80000000h & (value) < 1 shl 64 + mov rax,(value) - 1 shl 64 + mov [rsp+offset],rax + else if (value) relativeto 0 & ( (value) >= 80000000h | (value) < -80000000h ) + mov rax,value + mov [rsp+offset],rax + else + mov qword [rsp+offset],value + end if + else if @src.size = 4 + mov dword [rsp+offset],value + else if @src.size = 2 + mov word [rsp+offset],value + else if @src.size = 1 + mov byte [rsp+offset],value + else + err 'invalid argument ',`arg + end if + else if type = 'f' & @src.type = 'mmreg' & @src.size = 16 + movq [rsp+offset],value + else + err 'invalid argument ',`arg + end if + end if + offset = offset + 8 + end iterate + pcountcheck proc,offset/8 + if offset < 20h + offset = 20h + end if + framesize = offset + offset and 8 + call proc + if framesize & fastcall?.frame < 0 + add rsp,framesize + else if fastcall?.frame >= 0 & framesize > fastcall?.frame + fastcall?.frame = framesize + end if +end macro + +macro invoke?: proc*,args& + fastcall [proc],args +end macro + +macro cinvoke?: proc*,args& + fastcall [proc],args +end macro + +macro pcountcheck? proc*,args* +end macro + +define pcountsuffix % + +prologue@proc equ prologuedef + +macro prologuedef procname,flag,parmbytes,localbytes,reglist + local loc,fill + loc = (localbytes+15) and (not 15) + parmbase@proc equ rbp+16 + localbase@proc equ rbp-loc + push rbp + mov rbp,rsp + if loc+fill + sub rsp,loc+fill + end if + match any, reglist + iterate reg, reglist + push reg + if % = %% + fill := 8*(% and 1) + end if + end iterate + else + fill := 0 + end match +end macro + +epilogue@proc equ epiloguedef + +macro epiloguedef procname,flag,parmbytes,localbytes,reglist + iterate reg, reglist + indx %%-%+1 + pop reg + end iterate + leave + retn +end macro + +close@proc equ + +macro proc? statement& + + local _local,params,flag,regs,parmbytes,localbytes,current,tmp,initlocal + + macro endp?! + + localbytes = current + + purge ret?,locals?,endl?,proclocal? + + match close:reglist, close@proc, + close name,flag,parmbytes,localbytes,reglist + end match + + end match + end namespace + end if + end match + + purge endp? + + end macro + + match name declaration, statement : + if used name + name: + namespace name + outscope match local?, proclocal + + match =stdcall? args :, declaration + define params args + flag = 11b + else match =stdcall? :, declaration + define params + flag = 11b + else match =c? args :, declaration + define params args + flag = 10001b + else match =c? :, declaration + define params + flag = 10001b + else match args :, declaration + define params args + flag = 0 + else + define params + flag = 0 + end match + define regs + match =uses? list, params + define params list + while 1 + match =, tail, params + define params tail + break + else match reg tail, params& + match more&, tail + define params more + else + define params + end match + if % = 1 + regs equ reg + else + regs equ regs,reg + end if + else + break + end match + end while + else match =, tail, params + define params tail + end match + + match prologue:reglist, prologue@proc: + prologue name,flags,parmbytes,localbytes,reglist + end match + + virtual at parmbase@proc + namespace name + match args, params + iterate arg, args + match argname:type, arg + label argname:type + rb type + else + ?arg dq ? + end match + end iterate + end match + parmbytes := $-(parmbase@proc) + match p, pcountsuffix + name#p = parmbytes/8 + end match + end namespace + end virtual + + macro ret? operand + match any, operand + retn operand + else + match epilogue:reglist, epilogue@proc: + epilogue name,flag,parmbytes,localbytes,reglist + end match + end match + end macro + + current = 0 + + macro initlocal + local area,pointer,length,value + area:: + pointer = localbase@proc+current + length = $@ - (localbase@proc) - current + current = $ - (localbase@proc) + end virtual + while length > 0 + if length < 2 + load value:byte from area:pointer + mov byte [pointer],value + pointer = pointer + 1 + length = length - 1 + else if length < 4 + load value:word from area:pointer + mov word [pointer],value + pointer = pointer + 2 + length = length - 2 + else if length < 8 + load value:dword from area:pointer + mov dword [pointer],value + pointer = pointer + 4 + length = length - 4 + else + load value:qword from area:pointer + if value < 80000000h | value >= 1 shl 64 - 80000000h + mov qword [pointer],value + pointer = pointer + 8 + length = length - 8 + else + mov dword [pointer],value and 0FFFFFFFFh + pointer = pointer + 4 + length = length - 4 + end if + end if + end while + virtual at localbase@proc+current + end macro + + macro locals? + virtual at localbase@proc+current + iterate dword, dword,qword + macro dword? value + if value relativeto 0 + emit dword: value + else + initlocal + local pointer + pointer := $ + end virtual + mov dword [pointer],value + virtual at pointer+4 + current = $ - (localbase@proc) + end if + end macro + end iterate + macro ? line& + line + if $ > $@ + initlocal + end if + end macro + end macro + + macro endl? + purge ?, dword?,qword? + initlocal + end virtual + end macro + + macro proclocal? args& + locals + iterate arg, args + match varname[count]:type, arg + ?varname dbx type:count dup ? + else match varname:type, arg + ?varname dbx type, ? + else match varname[count], arg + ?varname rq count + else match varname type, arg + ?varname type + else + ?arg dq ? + end match + end iterate + endl + end macro + +end macro diff --git a/toolchain/fasm2/include/macro/resource.inc b/toolchain/fasm2/include/macro/resource.inc new file mode 100644 index 0000000..9d060fe --- /dev/null +++ b/toolchain/fasm2/include/macro/resource.inc @@ -0,0 +1,314 @@ + +macro directory definitions& + iterate , definitions + root@resource dd 0,%t,0,%% shl 16 + local total,current,next + total = %% + current = -1 + next = 0 + while current < next + current = next + repeat total + indx % + if type = current + dd type,80000000h+label-root@resource + else if type > current & ( next = current | next > type ) + next = type + end if + end repeat + end while + break + end iterate +end macro + +macro resource dir,definitions& + iterate , definitions + dir dd 0,%t,0,%% shl 16 + local total,current,next,counter + total = %% + current = -1 + next = 0 + while current < next + current = next + counter = 0 + repeat total + indx % + if id = current + if counter = 0 + dd id,80000000h+label.directory-root@resource + end if + counter = counter + 1 + label.count = counter + else if id > current & ( next = current | next > id ) + next = id + end if + end repeat + end while + current = -1 + next = 0 + while current < next + current = next + counter = 0 + repeat total + indx % + if id = current + if counter = 0 + label.directory dd 0,%t,0,label.count shl 16 + dd lang,label-root@resource + label.resid = id + else + dd lang,label-root@resource + end if + counter = counter + 1 + else if id > current & ( next = current | next > id ) + next = id + end if + end repeat + end while + break + end iterate +end macro + +macro bitmap label,bitmap_file + local data,size + label dd RVA data,size,0,0 + data file bitmap_file:0Eh + size = $ - data + align 4 +end macro + +macro icon group,definitions& + local data,size,position,header + iterate , definitions + virtual at 0 + file icon_file:6,16 + load size:dword from 8 + load position:dword from 12 + end virtual + label dd RVA data#%,size,0,0 + data#% file icon_file:position,size + if % = %% + align 4 + group dd RVA header,6+%%*14,0,0 + header dw 0,1,%% + repeat %% + indx % + file icon_file:6,12 + dw label.resid + end repeat + align 4 + end if + end iterate +end macro + +macro cursor group,definitions& + local data,header + iterate , definitions + virtual at 0 + file cursor_file:6,16 + load label.width:byte from 0 + load label.height:byte from 1 + load label.size:dword from 8 + load label.position:dword from 12 + end virtual + label dd RVA data#%,label.size+4,0,0 + data#% file cursor_file:10,4 + file cursor_file:label.position,label.size + if % = %% + align 4 + group dd RVA header,6+%%*14,0,0 + header dw 0,2,%% + repeat %% + indx % + dw label.width,label.height,1,0 + dd label.size+4 + dw label.resid + end repeat + align 4 + end if + end iterate +end macro + +macro menu label + local data,size + label dd RVA data,size,0,0 + data dw 1,4,0,0 + local menu_level + menu_level = 1 + macro menuitem string,id,resinfo:0,status:0,type:0 + dd MFT_STRING or type,status,id + dw resinfo + du string,0 + align 4 + if resinfo and MFR_END + menu_level = menu_level - 1 + end if + if resinfo and MFR_POPUP + menu_level = menu_level + 1 + dd 0 + end if + if menu_level = 0 + size = $ - data + purge menuitem,menuseparator + end if + end macro + macro menuseparator resinfo:0 + dd MFT_SEPARATOR,0,0 + dw resinfo,0 + if resinfo and MFR_END + menu_level = menu_level - 1 + end if + if menu_level = 0 + size = $ - data + purge menuitem,menuseparator + end if + end macro +end macro + +macro dialog label,title,x,y,cx,cy,style,exstyle:0,menu:0,fontname:'MS Sans Serif',fontsize:8 + local data,size,items + label dd RVA data,size,0,0 + data dd style or DS_SETFONT,exstyle + dw items,x,y,cx,cy + if menu <> 0 + dw 0FFFFh + end if + du menu,0,title,0 + du fontsize,fontname,0 + align 4 + local dialog_items_counter + dialog_items_counter = 0 + macro dialogitem class,it_title,it_id,it_x,it_y,it_cx,it_cy,it_style,it_exstyle:0 + dd it_style or WS_CHILD,it_exstyle + dw it_x,it_y,it_cx,it_cy,it_id + if class eq 'BUTTON' + dw 0FFFFh,80h + else if class eq 'EDIT' + dw 0FFFFh,81h + else if class eq 'STATIC' + dw 0FFFFh,82h + else if class eq 'LISTBOX' + dw 0FFFFh,83h + else if class eq 'SCROLLBAR' + dw 0FFFFh,84h + else if class eq 'COMBOBOX' + dw 0FFFFh,85h + else + du class,0 + end if + match any=,any, it_title + du it_title,0 + else if it_title eqtype '' + du it_title,0 + else + dw 0FFFFh,it_title + end if + dw 0 + align 4 + dialog_items_counter = dialog_items_counter + 1 + end macro + macro enddialog + size = $ - data + items = dialog_items_counter + purge dialogitem,enddialog + end macro +end macro + +macro accelerator label,definitions& + local data,size + label dd RVA data,size,0,0 + data: + iterate , definitions + if % = %% + dw fvirt or 80h,key + size = %% * 8 + else + dw fvirt,key + end if + dd cmd + end iterate +end macro + +macro versioninfo label,fileos,filetype:0,filesubtype:0,lang,cp:0,values& + local data,size,vivalue,visize + label dd RVA data,size,0,0 + data dw size,visize,0 + du 'VS_VERSION_INFO',0,0 + vivalue dd 0FEEF04BDh,00010000h + local version,count,shift,char,filever,productver + filever = 0 + productver = 0 + iterate , values + if name eq 'FileVersion' | name eq 'ProductVersion' + virtual at 0 + db value + count = $ + version = 0 + shift = 16 + repeat count + load char:byte from %-1 + if char='.' + if shift mod 32 + shift = shift-16 + else + shift = shift+32+16 + end if + else + version = (version and not (0FFFFh shl shift)) or ((version shr shift and 0FFFFh)*10+char-'0') shl shift + end if + end repeat + end virtual + if name eq 'FileVersion' + filever = version + else if name eq 'ProductVersion' + productver = version + end if + end if + end iterate + dq filever,productver + dd 0,0,fileos,filetype,filesubtype,0,0 + visize = $ - vivalue + local sfi_data,sfi_size + sfi_data dd sfi_size + du 1,'StringFileInfo',0 + local str_data,str_size + str_data dd str_size + du 1,'040904E4',0 + macro vdata name,value& + local vs_data,vs_size,value_data,value_size + align 4 + vs_data dw vs_size,value_size/2 + du 1,name,0 + align 4 + value_data du value,0 + value_size = $ - value_data + vs_size = $ - vs_data + end macro + iterate , values + vdata name,value + end iterate + purge vdata + align 4 + str_size = $ - str_data + sfi_size = $ - sfi_data + local vfi_data,vfi_size,var_data,var_size + vfi_data dd vfi_size + du 1,'VarFileInfo',0,0 + var_data dw var_size,4 + du 0,'Translation',0,0 + dw lang,cp + var_size = $ - var_data + vfi_size = $ - vfi_data + size = $ - data +end macro + +macro resdata label + local data,size + label dd RVA data,size,0,0 + data = $ + macro endres + size = $ - data + align 4 + purge endres + end macro +end macro diff --git a/toolchain/fasm2/include/macro/struct.inc b/toolchain/fasm2/include/macro/struct.inc new file mode 100644 index 0000000..7be6a66 --- /dev/null +++ b/toolchain/fasm2/include/macro/struct.inc @@ -0,0 +1,456 @@ + +define struct? struct? + +namespace struct? + + calminstruction instantiate: instance*, sname*, &values& + + local tmp + arrange tmp, =label instance : sname.=__size__ + assemble tmp + arrange tmp, =namespace instance + assemble tmp + + match , values + jyes values_ready + call struct?.initialize, sname, values + values_ready: + + local i + compute i, 1 + local field, val, stack + process_statement: + arrange field, sname.=__label#i + transform field + jyes labeled_statement + arrange field, + arrange tmp, sname.=__statement#i + transform tmp + jyes statement_ready + jump finish + + labeled_statement: + arrange tmp, sname.=__label#i sname.=__definition#i + transform tmp + arrange val, =__init__.#field + transform val + jyes got_value + arrange val, sname.=__default__.#field + arrange field, + transform val + jno statement_ready + got_value: + arrange tmp, tmp val + + statement_ready: + + take stack, field + take stack, i + take stack, sname + assemble tmp + take , sname + take sname, stack + take , i + take i, stack + take , field + take field, stack + match , field + jyes next_statement + + arrange tmp, sname.=__size__.#field - (=$ - field) + compute tmp, tmp + check tmp = 0 + jyes next_statement + check tmp > 0 + jyes fill_up + stringify field + err 'value too long to fit in ' bappend field + jump next_statement + fill_up: + arrange tmp, =rb tmp + assemble tmp + + next_statement: + compute i, i + 1 + jump process_statement + + finish: + asm end namespace + end calminstruction + + calminstruction initialize sname*, values& + + local j, a + compute j, 0 + arrange a, sname.=__argument + + local tmp, field, val, sub + process_argument: + match field=, values, values, <> + jyes got_argument + arrange field, values + arrange values, + got_argument: + match field:val?, field, <> + jyes labeled_argument + check j < 0 + jyes mixed_arguments + compute j, j + 1 + arrange val, field + match , val + arrange field, a#j + transform field + jno excess_arguments + match , field + jno got_argument_field + take a, tmp + compute tmp, 0 + take j, tmp + take values, val + jump process_argument + + excess_arguments: + err 'excess arguments' + jump arguments_processed + mixed_arguments: + err 'unsupported mixing of labeled and ordered values' + jump arguments_processed + + labeled_argument: + check j > 0 + jyes mixed_arguments + compute j, -1 + match , val + got_argument_field: + arrange tmp, sname.=__default__.#field + transform tmp + jyes argument_ok + match field.sub, field + jno unknown_field + arrange tmp, sname.=__default__.#field + transform tmp + jno unknown_field + arrange val, sub:val + arrange tmp, =__multi__.#field + transform tmp + jno append_value + arrange val, tmp, val + arrange tmp, =__multi__.#field + append_value: + publish tmp, val + jump argument_ok + unknown_field: + stringify field + arrange tmp, sname + stringify tmp + err tmp bappend ' has no field named ' bappend field + jump next_argument + + argument_ok: + arrange tmp, =__init__.#field + publish tmp, val + next_argument: + match , values + jno process_argument + arguments_processed: + take , values + take , j + take , a + take values, values + jyes next_argument + + end calminstruction + + define pname + define i + define j + define u + define a + + calminstruction (&label) collect? &definition& + local sym, default, tmp + match , definition + jyes plain + match :tmp?, definition + jyes ignored + match ==tmp?, definition + jyes ignored + arrange default, + match definition= default, definition + arrange sym, pname.=__definition#i + publish sym:, definition + arrange sym, pname.=__label#i + publish sym:, label + arrange sym, pname.=__default__.#label + publish sym:, default + arrange definition, label definition default + assemble definition + arrange definition, =__size__.#label == =$ - label + assemble definition + match , a + jyes done + compute j, j + 1 + arrange sym, a#j + publish sym:, label + done: + exit + ignored: + arrange label, label definition + plain: + assemble label + end calminstruction + + calminstruction collect? &statement& + local proto, sym, tmp + check i + jyes in_body + + compute u, 0 + compute i, 1 + compute j, 1 + asm virtual at 0 + match pname= proto, pname + arrange tmp, =namespace pname + assemble tmp + jno prototype_copied + use_prototype: + arrange a, + arrange tmp, proto.=__statement#i + transform tmp + jno prototype_arguments + arrange sym, pname.=__statement#i + publish sym:, tmp + assemble tmp + compute i, i + 1 + jump use_prototype + prototype_arguments: + arrange tmp, proto.=__argument#j + transform tmp + jno prototype_copied + arrange sym, pname.=__argument#j + publish sym:, tmp + compute j, j + 1 + jump prototype_arguments + prototype_copied: + compute j, j - 1 + arrange a, pname.=__argument + + in_body: + match =ends?, statement + jyes close + check u + jno process_definition + check u > 1 + jno union_divider_ok + arrange tmp, =__union_divider + arrange sym, pname.=__statement#i + publish sym:, tmp + assemble tmp + compute i, i + 1 + arrange a, + union_divider_ok: + compute u, u + 1 + process_definition: + match =struct?, statement + jyes open_struct + match =union?, statement + jyes open_union + arrange sym, pname.=__statement#i + publish sym:, statement + assemble statement + compute i, i + 1 + exit + open_union: + arrange tmp, =__union_start + arrange sym, pname.=__statement#i + publish sym:, tmp + assemble tmp + compute i, i + 1 + arrange tmp, a + take a, tmp + compute tmp, 1 + take u, tmp + exit + open_struct: + match , a + jyes unlisted_substruct + compute j, j + 1 + arrange sym, a#j + arrange tmp, a#j#=_ + take a, tmp + arrange tmp, + publish sym:, tmp + jump begin_substruct + unlisted_substruct: + arrange tmp, + take a, tmp + begin_substruct: + compute tmp, 0 + take j, tmp + compute tmp, 0 + take u, tmp + exit + close: + check u + jno close_struct + arrange tmp, =__union_end + arrange sym, pname.=__statement#i + publish sym:, tmp + assemble tmp + compute i, i + 1 + take , a + take , u + exit + close_struct: + take , a + take , j + take , u + take a, a + jyes done + asm end namespace + arrange sym, pname.=__size__ + compute tmp, $ + publish sym:, tmp + arrange tmp, #sym + arrange sym, =sizeof.pname + publish sym, tmp + asm end virtual + assemble statement + done: + end calminstruction + +end namespace + +macro struct? declaration*, attributes + if defined Struct.CheckAlignment & Struct.CheckAlignment + struct?.packed = 0 + else + struct?.packed = 1 + end if + match =packed?, attributes + struct?.packed = 1 + else match any, attributes + err 'unknown attribute ',`any + end match + + define struct?.pname declaration + struct?.i = 0 + mvstruc ?, struct?.collect? + mvmacro ?, struct?.collect? +end macro + +macro ends? + mvmacro struct?.collect?, ? + mvstruc struct?.collect?, ? + + match name, struct?.pname + + label name: name.__size__ at name.__size__ + + struct?.check name + + local sname + define sname name + + calminstruction (instance) name values& + call struct?.instantiate, instance, sname, values + end calminstruction + + calminstruction name &values& + local ic, iname + init ic + compute ic, ic + 1 + arrange iname, sname#ic + call struct?.instantiate, iname, sname, values + end calminstruction + + end match +end macro + +macro __union_start + local union + union: + union.i = 0 + union.size = 0 + union.initialized = 0 + macro __union_open + union.i = union.i + 1 + if (defined union.init & union.i <> union.init) | (~ defined union.init & union.i > 1) + virtual at union + end if + end macro + macro __union_close + if $@ > union + if union.i > 1 + union.init := union.i + end if + if union.initialized + err 'conflicting initialization of union' + else + union.initialized = union.i + end if + end if + if $ - union > union.size + union.size = $ - union + end if + if (defined union.init & union.i <> union.init) | (~ defined union.init & union.i > 1) + end virtual + end if + end macro + macro __union_divider + __union_close + __union_open + end macro + macro __union_end + __union_close + if $ - union < union.size + rb union.size - ($ - union) + end if + purge __union_open,__union_close,__union_divider,__union_end + end macro + __union_open +end macro + +calminstruction breakifndef? sym + transform sym + jyes ok + asm break + ok: +end calminstruction + +macro struct?.check name + if ~ struct?.packed + local alignment, maxalignment + maxalignment = 1 + while 1 + breakifndef name.__statement#% + match label, name.__label#% + if defined name.label + local alignment + alignment = 1 + if sizeof name.label > 0 + alignment = 1 shl (bsf sizeof name.label) + end if + match type, name.__definition#% + if defined type.__alignment + alignment = type.__alignment + end if + end match + if name.label mod alignment > 0 + repeat 1, natural: alignment + display 'warning: ',`name,'.',`label,' not aligned to its natural boundary (',`natural,')',13,10 + end repeat + else if alignment > maxalignment + maxalignment = alignment + end if + end if + end match + end while + if sizeof name mod maxalignment > 0 + repeat 1, size: sizeof name, natural: maxalignment + display 'warning: size of ',`name,' (',`size,') not aligned to its natural boundary (',`natural,')',13,10 + end repeat + end if + name.__alignment := maxalignment + end if +end macro \ No newline at end of file diff --git a/toolchain/fasm2/include/pcount/advapi32.inc b/toolchain/fasm2/include/pcount/advapi32.inc new file mode 100644 index 0000000..311655e --- /dev/null +++ b/toolchain/fasm2/include/pcount/advapi32.inc @@ -0,0 +1,340 @@ + +; ADVAPI32 API calls parameters' count + +AbortSystemShutdown% = 1 +AccessCheck% = 8 +AccessCheckAndAuditAlarm% = 11 +AccessCheckByType% = 11 +AccessCheckByTypeAndAuditAlarm% = 16 +AccessCheckByTypeResultList% = 11 +AccessCheckByTypeResultListAndAuditAlarm% = 16 +AddAccessAllowedAce% = 4 +AddAccessAllowedAceEx% = 5 +AddAccessAllowedObjectAce% = 7 +AddAccessDeniedAce% = 4 +AddAccessDeniedAceEx% = 5 +AddAccessDeniedObjectAce% = 7 +AddAce% = 5 +AddAuditAccessAce% = 6 +AddAuditAccessAceEx% = 7 +AddAuditAccessObjectAce% = 9 +AdjustTokenGroups% = 6 +AdjustTokenPrivileges% = 6 +AllocateAndInitializeSid% = 11 +AllocateLocallyUniqueId% = 1 +AreAllAccessesGranted% = 2 +AreAnyAccessesGranted% = 2 +BackupEventLog% = 2 +BuildExplicitAccessWithName% = 5 +BuildImpersonateExplicitAccessWithName% = 6 +BuildImpersonateTrustee% = 2 +BuildSecurityDescriptor% = 9 +BuildTrusteeWithName% = 2 +BuildTrusteeWithSid% = 2 +CancelOverlappedAccess% = 1 +ChangeServiceConfig2% = 3 +ChangeServiceConfig% = 11 +ClearEventLog% = 2 +CloseEventLog% = 1 +CloseRaw% = 1 +CloseServiceHandle% = 1 +ControlService% = 3 +ConvertAccessToSecurityDescriptor% = 5 +ConvertSecurityDescriptorToAccess% = 7 +ConvertSecurityDescriptorToAccessNamed% = 7 +ConvertToAutoInheritPrivateObjectSecurity% = 6 +CopySid% = 3 +CreatePrivateObjectSecurity% = 6 +CreatePrivateObjectSecurityEx% = 8 +CreateProcessAsUser% = 11 +CreateRestrictedToken% = 9 +CreateService% = 13 +CryptAcquireContext% = 5 +CryptContextAddRef% = 3 +CryptCreateHash% = 5 +CryptDecrypt% = 6 +CryptDeriveKey% = 5 +CryptDestroyHash% = 1 +CryptDestroyKey% = 1 +CryptDuplicateHash% = 4 +CryptDuplicateKey% = 4 +CryptEncrypt% = 7 +CryptEnumProviderTypes% = 6 +CryptEnumProviders% = 6 +CryptExportKey% = 6 +CryptGenKey% = 4 +CryptGenRandom% = 3 +CryptGetDefaultProvider% = 5 +CryptGetHashParam% = 5 +CryptGetKeyParam% = 5 +CryptGetProvParam% = 5 +CryptGetUserKey% = 3 +CryptHashData% = 4 +CryptHashSessionKey% = 3 +CryptImportKey% = 6 +CryptReleaseContext% = 2 +CryptSetHashParam% = 4 +CryptSetKeyParam% = 4 +CryptSetProvParam% = 4 +CryptSetProvider% = 2 +CryptSetProviderEx% = 4 +CryptSignHash% = 6 +CryptVerifySignature% = 6 +DecryptFile% = 2 +DeleteAce% = 2 +DeleteService% = 1 +DeregisterEventSource% = 1 +DestroyPrivateObjectSecurity% = 1 +DuplicateToken% = 3 +DuplicateTokenEx% = 6 +ElfBackupEventLogFile% = 2 +ElfChangeNotify% = 2 +ElfClearEventLogFile% = 2 +ElfCloseEventLog% = 1 +ElfDeregisterEventSource% = 1 +ElfNumberOfRecords% = 2 +ElfOldestRecord% = 2 +ElfOpenBackupEventLog% = 3 +ElfOpenEventLog% = 3 +ElfReadEventLog% = 7 +ElfRegisterEventSource% = 3 +ElfReportEvent% = 12 +EncryptFile% = 1 +EnumDependentServices% = 6 +EnumServicesStatus% = 8 +EqualPrefixSid% = 2 +EqualSid% = 2 +FindFirstFreeAce% = 2 +FreeSid% = 1 +GetAccessPermissionsForObject% = 9 +GetAce% = 3 +GetAclInformation% = 4 +GetAuditedPermissionsFromAcl% = 4 +GetCurrentHwProfile% = 1 +GetEffectiveRightsFromAcl% = 3 +GetExplicitEntriesFromAcl% = 3 +GetFileSecurity% = 5 +GetKernelObjectSecurity% = 5 +GetLengthSid% = 1 +GetMultipleTrustee% = 1 +GetMultipleTrusteeOperation% = 1 +GetNamedSecurityInfo% = 8 +GetNamedSecurityInfoEx% = 9 +GetNumberOfEventLogRecords% = 2 +GetOldestEventLogRecord% = 2 +GetOverlappedAccessResults% = 4 +GetPrivateObjectSecurity% = 5 +GetSecurityDescriptorControl% = 3 +GetSecurityDescriptorDacl% = 4 +GetSecurityDescriptorGroup% = 3 +GetSecurityDescriptorLength% = 1 +GetSecurityDescriptorOwner% = 3 +GetSecurityDescriptorSacl% = 4 +GetSecurityInfo% = 8 +GetSecurityInfoEx% = 9 +GetServiceDisplayName% = 4 +GetServiceKeyName% = 4 +GetSidLengthRequired% = 1 +GetSidSubAuthority% = 2 +GetSidSubAuthorityCount% = 1 +GetTokenInformation% = 5 +GetTrusteeName% = 1 +GetTrusteeType% = 1 +GetUserName% = 2 +I_ScSetServiceBits% = 5 +ImpersonateLoggedOnUser% = 1 +ImpersonateNamedPipeClient% = 1 +ImpersonateSelf% = 1 +InitializeAcl% = 3 +InitializeSecurityDescriptor% = 2 +InitializeSid% = 3 +InitiateSystemShutdown% = 5 +IsTextUnicode% = 3 +IsTokenRestricted% = 1 +IsValidAcl% = 1 +IsValidSecurityDescriptor% = 1 +IsValidSid% = 1 +LockServiceDatabase% = 1 +LogonUser% = 6 +LookupAccountName% = 7 +LookupAccountSid% = 7 +LookupPrivilegeDisplayName% = 5 +LookupPrivilegeName% = 4 +LookupPrivilegeValue% = 3 +LookupSecurityDescriptorParts% = 7 +LsaAddAccountRights% = 4 +LsaAddPrivilegesToAccount% = 2 +LsaClearAuditLog% = 1 +LsaClose% = 1 +LsaCreateAccount% = 4 +LsaCreateSecret% = 4 +LsaCreateTrustedDomain% = 4 +LsaCreateTrustedDomainEx% = 5 +LsaDelete% = 1 +LsaDeleteTrustedDomain% = 2 +LsaEnumerateAccountRights% = 4 +LsaEnumerateAccounts% = 5 +LsaEnumerateAccountsWithUserRight% = 4 +LsaEnumeratePrivileges% = 5 +LsaEnumeratePrivilegesOfAccount% = 2 +LsaEnumerateTrustedDomains% = 5 +LsaEnumerateTrustedDomainsEx% = 6 +LsaFreeMemory% = 1 +LsaGetQuotasForAccount% = 2 +LsaGetSystemAccessAccount% = 2 +LsaGetUserName% = 2 +LsaICLookupNames% = 7 +LsaICLookupSids% = 7 +LsaIGetTrustedDomainAuthInfoBlobs% = 4 +LsaISetTrustedDomainAuthInfoBlobs% = 4 +LsaLookupNames% = 5 +LsaLookupPrivilegeDisplayName% = 4 +LsaLookupPrivilegeName% = 3 +LsaLookupPrivilegeValue% = 3 +LsaLookupSids% = 5 +LsaNtStatusToWinError% = 1 +LsaOpenAccount% = 4 +LsaOpenPolicy% = 4 +LsaOpenSecret% = 4 +LsaOpenTrustedDomain% = 4 +LsaQueryDomainInformationPolicy% = 3 +LsaQueryInfoTrustedDomain% = 3 +LsaQueryInformationPolicy% = 3 +LsaQueryLocalInformationPolicy% = 3 +LsaQuerySecret% = 5 +LsaQuerySecurityObject% = 3 +LsaQueryTrustedDomainInfo% = 4 +LsaQueryTrustedDomainInfoByName% = 4 +LsaRemoveAccountRights% = 5 +LsaRemovePrivilegesFromAccount% = 3 +LsaRetrievePrivateData% = 3 +LsaSetDomainInformationPolicy% = 3 +LsaSetInformationPolicy% = 3 +LsaSetInformationTrustedDomain% = 3 +LsaSetLocalInformationPolicy% = 3 +LsaSetQuotasForAccount% = 2 +LsaSetSecret% = 3 +LsaSetSecurityObject% = 3 +LsaSetSystemAccessAccount% = 2 +LsaSetTrustedDomainInfoByName% = 4 +LsaSetTrustedDomainInformation% = 4 +LsaStorePrivateData% = 3 +MakeAbsoluteSD% = 11 +MakeSelfRelativeSD% = 3 +MapGenericMask% = 2 +NotifyBootConfigStatus% = 1 +NotifyChangeEventLog% = 2 +ObjectCloseAuditAlarm% = 3 +ObjectDeleteAuditAlarm% = 3 +ObjectOpenAuditAlarm% = 12 +ObjectPrivilegeAuditAlarm% = 6 +OpenBackupEventLog% = 2 +OpenEventLog% = 2 +OpenProcessToken% = 3 +OpenRaw% = 3 +OpenSCManager% = 3 +OpenService% = 3 +OpenThreadToken% = 4 +PrivilegeCheck% = 3 +PrivilegedServiceAuditAlarm% = 5 +QueryRecoveryAgents% = 3 +QueryServiceConfig2% = 5 +QueryServiceConfig% = 4 +QueryServiceLockStatus% = 4 +QueryServiceObjectSecurity% = 5 +QueryServiceStatus% = 2 +QueryWindows31FilesMigration% = 1 +ReadEventLog% = 7 +ReadRaw% = 3 +RegCloseKey% = 1 +RegConnectRegistry% = 3 +RegCreateKey% = 3 +RegCreateKeyEx% = 9 +RegDeleteKey% = 2 +RegDeleteValue% = 2 +RegEnumKey% = 4 +RegEnumKeyEx% = 8 +RegEnumValue% = 8 +RegFlushKey% = 1 +RegGetKeySecurity% = 4 +RegLoadKey% = 3 +RegNotifyChangeKeyValue% = 5 +RegOpenKey% = 3 +RegOpenKeyEx% = 5 +RegOverridePredefKey% = 2 +RegQueryInfoKey% = 12 +RegQueryMultipleValues% = 5 +RegQueryValue% = 4 +RegQueryValueEx% = 6 +RegReplaceKey% = 4 +RegRestoreKey% = 3 +RegSaveKey% = 3 +RegSetKeySecurity% = 3 +RegSetValue% = 5 +RegSetValueEx% = 6 +RegUnLoadKey% = 2 +RegisterEventSource% = 2 +RegisterServiceCtrlHandler% = 2 +ReportEvent% = 9 +RevertToSelf% = 0 +SetAclInformation% = 4 +SetEntriesInAccessList% = 6 +SetEntriesInAcl% = 4 +SetEntriesInAuditList% = 6 +SetFileSecurity% = 3 +SetKernelObjectSecurity% = 3 +SetNamedSecurityInfo% = 7 +SetNamedSecurityInfoEx% = 9 +SetPrivateObjectSecurity% = 5 +SetPrivateObjectSecurityEx% = 6 +SetSecurityDescriptorControl% = 3 +SetSecurityDescriptorDacl% = 4 +SetSecurityDescriptorGroup% = 3 +SetSecurityDescriptorOwner% = 3 +SetSecurityDescriptorSacl% = 4 +SetSecurityInfo% = 7 +SetSecurityInfoEx% = 9 +SetServiceBits% = 4 +SetServiceObjectSecurity% = 3 +SetServiceStatus% = 2 +SetThreadToken% = 2 +SetTokenInformation% = 4 +StartService% = 3 +StartServiceCtrlDispatcher% = 1 +SynchronizeWindows31FilesAndWindowsNTRegistry% = 4 +SystemFunction001% = 3 +SystemFunction002% = 3 +SystemFunction003% = 2 +SystemFunction004% = 3 +SystemFunction005% = 3 +SystemFunction006% = 2 +SystemFunction007% = 2 +SystemFunction008% = 3 +SystemFunction009% = 3 +SystemFunction010% = 3 +SystemFunction011% = 3 +SystemFunction012% = 3 +SystemFunction013% = 3 +SystemFunction014% = 3 +SystemFunction015% = 3 +SystemFunction016% = 3 +SystemFunction017% = 3 +SystemFunction018% = 3 +SystemFunction019% = 3 +SystemFunction020% = 3 +SystemFunction021% = 3 +SystemFunction022% = 3 +SystemFunction023% = 3 +SystemFunction024% = 3 +SystemFunction025% = 3 +SystemFunction026% = 3 +SystemFunction027% = 3 +SystemFunction028% = 2 +SystemFunction029% = 2 +SystemFunction030% = 2 +SystemFunction031% = 2 +SystemFunction032% = 2 +SystemFunction033% = 2 +TrusteeAccessToObject% = 6 +UnlockServiceDatabase% = 1 +WriteRaw% = 3 diff --git a/toolchain/fasm2/include/pcount/comctl32.inc b/toolchain/fasm2/include/pcount/comctl32.inc new file mode 100644 index 0000000..adf4032 --- /dev/null +++ b/toolchain/fasm2/include/pcount/comctl32.inc @@ -0,0 +1,69 @@ + +; COMCTL32 API calls parameters' count + +CreateMappedBitmap% = 5 +CreatePropertySheetPage% = 1 +CreateStatusWindow% = 4 +CreateToolbar% = 8 +CreateToolbarEx% = 13 +CreateUpDownControl% = 12 +DestroyPropertySheetPage% = 1 +DrawInsert% = 3 +DrawStatusText% = 4 +FlatSB_EnableScrollBar% = 3 +FlatSB_GetScrollInfo% = 3 +FlatSB_GetScrollPos% = 2 +FlatSB_GetScrollProp% = 3 +FlatSB_GetScrollRange% = 4 +FlatSB_SetScrollInfo% = 4 +FlatSB_SetScrollPos% = 4 +FlatSB_SetScrollProp% = 4 +FlatSB_SetScrollRange% = 5 +FlatSB_ShowScrollBar% = 3 +GetEffectiveClientRect% = 3 +ImageList_Add% = 3 +ImageList_AddIcon% = 2 +ImageList_AddMasked% = 3 +ImageList_BeginDrag% = 4 +ImageList_Copy% = 5 +ImageList_Create% = 5 +ImageList_Destroy% = 1 +ImageList_DragEnter% = 3 +ImageList_DragLeave% = 1 +ImageList_DragMove% = 2 +ImageList_DragShowNolock% = 1 +ImageList_Draw% = 6 +ImageList_DrawEx% = 10 +ImageList_DrawIndirect% = 1 +ImageList_Duplicate% = 1 +ImageList_EndDrag% = 0 +ImageList_GetBkColor% = 1 +ImageList_GetDragImage% = 2 +ImageList_GetIcon% = 3 +ImageList_GetIconSize% = 3 +ImageList_GetImageCount% = 1 +ImageList_GetImageInfo% = 3 +ImageList_GetImageRect% = 3 +ImageList_LoadImage% = 7 +ImageList_Merge% = 6 +ImageList_Read% = 1 +ImageList_Remove% = 2 +ImageList_Replace% = 4 +ImageList_ReplaceIcon% = 3 +ImageList_SetBkColor% = 2 +ImageList_SetDragCursorImage% = 4 +ImageList_SetFilter% = 3 +ImageList_SetIconSize% = 3 +ImageList_SetImageCount% = 2 +ImageList_SetOverlayImage% = 3 +ImageList_Write% = 2 +InitCommonControls% = 0 +InitCommonControlsEx% = 1 +InitializeFlatSB% = 1 +LBItemFromPt% = 4 +MakeDragList% = 1 +MenuHelp% = 7 +PropertySheet% = 1 +ShowHideMenuCtl% = 3 +UninitializeFlatSB% = 1 +_TrackMouseEvent% = 1 diff --git a/toolchain/fasm2/include/pcount/comdlg32.inc b/toolchain/fasm2/include/pcount/comdlg32.inc new file mode 100644 index 0000000..3417a8c --- /dev/null +++ b/toolchain/fasm2/include/pcount/comdlg32.inc @@ -0,0 +1,18 @@ + +; COMDLG32 API calls parameters' count + +ChooseColor% = 1 +ChooseFont% = 1 +CommDlgExtendedError% = 0 +FindText% = 1 +FormatCharDlgProc% = 4 +GetFileTitle% = 3 +GetOpenFileName% = 1 +GetSaveFileName% = 1 +LoadAlterBitmap% = 3 +PageSetupDlg% = 1 +PrintDlg% = 1 +ReplaceText% = 1 +WantArrows% = 4 +dwLBSubclass% = 4 +dwOKSubclass% = 4 diff --git a/toolchain/fasm2/include/pcount/gdi32.inc b/toolchain/fasm2/include/pcount/gdi32.inc new file mode 100644 index 0000000..6d5c76b --- /dev/null +++ b/toolchain/fasm2/include/pcount/gdi32.inc @@ -0,0 +1,319 @@ + +; GDI32 API calls parameters' count + +AbortDoc% = 1 +AbortPath% = 1 +AddFontMemResourceEx% = 4 +AddFontResource% = 1 +AddFontResourceEx% = 3 +AngleArc% = 6 +AnimatePalette% = 4 +Arc% = 9 +ArcTo% = 9 +BeginPath% = 1 +BitBlt% = 9 +CancelDC% = 1 +CheckColorsInGamut% = 4 +ChoosePixelFormat% = 2 +Chord% = 9 +CloseEnhMetaFile% = 1 +CloseFigure% = 1 +CloseMetaFile% = 1 +ColorCorrectPalette% = 4 +ColorMatchToTarget% = 3 +CombineRgn% = 4 +CombineTransform% = 3 +CopyEnhMetaFile% = 2 +CopyMetaFile% = 2 +CreateBitmap% = 5 +CreateBitmapIndirect% = 1 +CreateBrushIndirect% = 1 +CreateColorSpace% = 1 +CreateCompatibleBitmap% = 3 +CreateCompatibleDC% = 1 +CreateDC% = 4 +CreateDIBPatternBrush% = 2 +CreateDIBPatternBrushPt% = 2 +CreateDIBSection% = 6 +CreateDIBitmap% = 6 +CreateDiscardableBitmap% = 3 +CreateEllipticRgn% = 4 +CreateEllipticRgnIndirect% = 1 +CreateEnhMetaFile% = 4 +CreateFont% = 14 +CreateFontIndirect% = 1 +CreateFontIndirectEx% = 1 +CreateHalftonePalette% = 1 +CreateHatchBrush% = 2 +CreateIC% = 4 +CreateMetaFile% = 1 +CreatePalette% = 1 +CreatePatternBrush% = 1 +CreatePen% = 3 +CreatePenIndirect% = 1 +CreatePolyPolygonRgn% = 4 +CreatePolygonRgn% = 3 +CreateRectRgn% = 4 +CreateRectRgnIndirect% = 1 +CreateRoundRectRgn% = 6 +CreateScalableFontResource% = 4 +CreateSolidBrush% = 1 +DPtoLP% = 3 +DeleteColorSpace% = 1 +DeleteDC% = 1 +DeleteEnhMetaFile% = 1 +DeleteMetaFile% = 1 +DeleteObject% = 1 +DescribePixelFormat% = 4 +DeviceCapabilitiesEx% = 6 +DrawEscape% = 4 +Ellipse% = 5 +EnableEUDC% = 1 +EndDoc% = 1 +EndPage% = 1 +EndPath% = 1 +EnumEnhMetaFile% = 5 +EnumFontFamilies% = 4 +EnumFontFamiliesEx% = 5 +EnumFonts% = 4 +EnumICMProfiles% = 3 +EnumMetaFile% = 4 +EnumObjects% = 4 +EqualRgn% = 2 +Escape% = 5 +ExcludeClipRect% = 5 +ExtCreatePen% = 5 +ExtCreateRegion% = 3 +ExtEscape% = 6 +ExtFloodFill% = 5 +ExtSelectClipRgn% = 3 +ExtTextOut% = 8 +FillPath% = 1 +FillRgn% = 3 +FixBrushOrgEx% = 4 +FlattenPath% = 1 +FloodFill% = 4 +FrameRgn% = 5 +GdiComment% = 3 +GdiDeleteSpoolFileHandle% = 1 +GdiEndDocEMF% = 1 +GdiEndPageEMF% = 2 +GdiFlush% = 0 +GdiGetBatchLimit% = 0 +GdiGetDC% = 1 +GdiGetDevmodeForPage% = 4 +GdiGetPageCount% = 1 +GdiGetPageHandle% = 3 +GdiGetSpoolFileHandle% = 3 +GdiPlayDCScript% = 6 +GdiPlayEMF% = 5 +GdiPlayJournal% = 5 +GdiPlayPageEMF% = 4 +GdiPlayPrivatePageEMF% = 3 +GdiPlayScript% = 7 +GdiResetDCEMF% = 2 +GdiSetBatchLimit% = 1 +GdiStartDocEMF% = 2 +GdiStartPageEMF% = 1 +GetArcDirection% = 1 +GetAspectRatioFilterEx% = 2 +GetBitmapBits% = 3 +GetBitmapDimensionEx% = 2 +GetBkColor% = 1 +GetBkMode% = 1 +GetBoundsRect% = 3 +GetBrushOrgEx% = 2 +GetCharABCWidths% = 4 +GetCharABCWidthsFloat% = 4 +GetCharABCWidthsI% = 5 +GetCharWidth32% = 4 +GetCharWidth% = 4 +GetCharWidthFloat% = 4 +GetCharWidthI% = 5 +GetCharacterPlacement% = 6 +GetClipBox% = 2 +GetClipRgn% = 2 +GetColorAdjustment% = 2 +GetColorSpace% = 1 +GetCurrentObject% = 2 +GetCurrentPositionEx% = 2 +GetDCBrushColor% = 1 +GetDCOrgEx% = 2 +GetDCPenColor% = 1 +GetDIBColorTable% = 4 +GetDIBits% = 7 +GetDeviceCaps% = 2 +GetDeviceGammaRamp% = 2 +GetEnhMetaFile% = 1 +GetEnhMetaFileBits% = 3 +GetEnhMetaFileDescription% = 3 +GetEnhMetaFileHeader% = 3 +GetEnhMetaFilePaletteEntries% = 3 +GetEnhMetaFilePixelFormat% = 3 +GetFontAssocStatus% = 1 +GetFontData% = 5 +GetFontLanguageInfo% = 1 +GetFontUnicodeRanges% = 2 +GetGlyphIndices% = 5 +GetGlyphOutline% = 7 +GetGraphicsMode% = 1 +GetICMProfile% = 3 +GetKerningPairs% = 3 +GetLogColorSpace% = 3 +GetMapMode% = 1 +GetMetaFile% = 1 +GetMetaFileBitsEx% = 3 +GetMetaRgn% = 2 +GetMiterLimit% = 2 +GetNearestColor% = 2 +GetNearestPaletteIndex% = 2 +GetObject% = 3 +GetObjectType% = 1 +GetOutlineTextMetrics% = 3 +GetPaletteEntries% = 4 +GetPath% = 4 +GetPixel% = 3 +GetPixelFormat% = 1 +GetPolyFillMode% = 1 +GetROP2% = 1 +GetRandomRgn% = 3 +GetRasterizerCaps% = 2 +GetRegionData% = 3 +GetRelAbs% = 2 +GetRgnBox% = 2 +GetStockObject% = 1 +GetStretchBltMode% = 1 +GetSystemPaletteEntries% = 4 +GetSystemPaletteUse% = 1 +GetTextAlign% = 1 +GetTextCharacterExtra% = 1 +GetTextCharset% = 1 +GetTextCharsetInfo% = 3 +GetTextColor% = 1 +GetTextExtentExPoint% = 7 +GetTextExtentExPointI% = 7 +GetTextExtentPoint32% = 4 +GetTextExtentPoint% = 4 +GetTextExtentPointI% = 4 +GetTextFace% = 3 +GetTextMetrics% = 2 +GetViewportExtEx% = 2 +GetViewportOrgEx% = 2 +GetWinMetaFileBits% = 5 +GetWindowExtEx% = 2 +GetWindowOrgEx% = 2 +GetWorldTransform% = 2 +IntersectClipRect% = 5 +InvertRgn% = 2 +LPtoDP% = 3 +LineDD% = 6 +LineTo% = 3 +MaskBlt% = 12 +ModifyWorldTransform% = 3 +MoveToEx% = 4 +OffsetClipRgn% = 3 +OffsetRgn% = 3 +OffsetViewportOrgEx% = 4 +OffsetWindowOrgEx% = 4 +PaintRgn% = 2 +PatBlt% = 6 +PathToRegion% = 1 +Pie% = 9 +PlayEnhMetaFile% = 3 +PlayEnhMetaFileRecord% = 4 +PlayMetaFile% = 2 +PlayMetaFileRecord% = 4 +PlgBlt% = 10 +PolyBezier% = 3 +PolyBezierTo% = 3 +PolyDraw% = 4 +PolyPatBlt% = 5 +PolyPolygon% = 4 +PolyPolyline% = 4 +PolyTextOut% = 3 +Polygon% = 3 +Polyline% = 3 +PolylineTo% = 3 +PtInRegion% = 3 +PtVisible% = 3 +RealizePalette% = 1 +RectInRegion% = 2 +RectVisible% = 2 +Rectangle% = 5 +RemoveFontMemResourceEx% = 1 +RemoveFontResource% = 1 +RemoveFontResourceEx% = 3 +ResetDC% = 2 +ResizePalette% = 2 +RestoreDC% = 2 +RoundRect% = 7 +SaveDC% = 1 +ScaleViewportExtEx% = 6 +ScaleWindowExtEx% = 6 +SelectBrushLocal% = 2 +SelectClipPath% = 2 +SelectClipRgn% = 2 +SelectFontLocal% = 2 +SelectObject% = 2 +SelectPalette% = 3 +SetAbortProc% = 2 +SetArcDirection% = 2 +SetBitmapBits% = 3 +SetBitmapDimensionEx% = 4 +SetBkColor% = 2 +SetBkMode% = 2 +SetBoundsRect% = 3 +SetBrushOrgEx% = 4 +SetColorAdjustment% = 2 +SetColorSpace% = 2 +SetDCBrushColor% = 2 +SetDCPenColor% = 2 +SetDIBColorTable% = 4 +SetDIBits% = 7 +SetDIBitsToDevice% = 12 +SetDeviceGammaRamp% = 2 +SetEnhMetaFileBits% = 2 +SetFontEnumeration% = 1 +SetGraphicsMode% = 2 +SetICMMode% = 2 +SetICMProfile% = 2 +SetMagicColors% = 3 +SetMapMode% = 2 +SetMapperFlags% = 2 +SetMetaFileBitsEx% = 2 +SetMetaRgn% = 1 +SetMiterLimit% = 3 +SetPaletteEntries% = 4 +SetPixel% = 4 +SetPixelFormat% = 3 +SetPixelV% = 4 +SetPolyFillMode% = 2 +SetROP2% = 2 +SetRectRgn% = 5 +SetRelAbs% = 2 +SetStretchBltMode% = 2 +SetSystemPaletteUse% = 2 +SetTextAlign% = 2 +SetTextCharacterExtra% = 2 +SetTextColor% = 2 +SetTextJustification% = 3 +SetViewportExtEx% = 4 +SetViewportOrgEx% = 4 +SetWinMetaFileBits% = 4 +SetWindowExtEx% = 4 +SetWindowOrgEx% = 4 +SetWorldTransform% = 2 +StartDoc% = 2 +StartPage% = 1 +StretchBlt% = 11 +StretchDIBits% = 13 +StrokeAndFillPath% = 1 +StrokePath% = 1 +SwapBuffers% = 1 +TextOut% = 5 +TranslateCharsetInfo% = 3 +UnrealizeObject% = 1 +UpdateColors% = 1 +UpdateICMRegKey% = 4 +WidenPath% = 1 +gdiPlaySpoolStream% = 6 diff --git a/toolchain/fasm2/include/pcount/kernel32.inc b/toolchain/fasm2/include/pcount/kernel32.inc new file mode 100644 index 0000000..e7fec6f --- /dev/null +++ b/toolchain/fasm2/include/pcount/kernel32.inc @@ -0,0 +1,557 @@ + +; KERNEL32 API calls parameters' count + +AddAtom% = 1 +AddConsoleAlias% = 3 +AllocConsole% = 0 +AreFileApisANSI% = 0 +AssignProcessToJobObject% = 2 +BackupRead% = 7 +BackupSeek% = 6 +BackupWrite% = 7 +BaseAttachCompleteThunk% = 0 +Beep% = 2 +BeginUpdateResource% = 2 +BuildCommDCB% = 2 +BuildCommDCBAndTimeouts% = 3 +CallNamedPipe% = 7 +CancelIo% = 1 +CancelWaitableTimer% = 1 +ClearCommBreak% = 1 +ClearCommError% = 3 +CloseConsoleHandle% = 1 +CloseHandle% = 1 +CloseProfileUserMapping% = 0 +CmdBatNotification% = 1 +CommConfigDialog% = 3 +CompareFileTime% = 2 +CompareString% = 6 +ConnectNamedPipe% = 2 +ConsoleMenuControl% = 3 +ContinueDebugEvent% = 3 +ConvertDefaultLocale% = 1 +ConvertThreadToFiber% = 1 +CopyFile% = 3 +CopyFileEx% = 6 +CreateConsoleScreenBuffer% = 5 +CreateDirectory% = 2 +CreateDirectoryEx% = 3 +CreateEvent% = 4 +CreateFiber% = 3 +CreateFile% = 7 +CreateFileMapping% = 6 +CreateHardLink% = 3 +CreateIoCompletionPort% = 4 +CreateJobObject% = 2 +CreateMailslot% = 4 +CreateMutex% = 3 +CreateNamedPipe% = 8 +CreatePipe% = 4 +CreateProcess% = 10 +CreateRemoteThread% = 7 +CreateSemaphore% = 4 +CreateTapePartition% = 4 +CreateThread% = 6 +CreateToolhelp32Snapshot% = 2 +CreateVirtualBuffer% = 3 +CreateWaitableTimer% = 3 +DebugActiveProcess% = 1 +DebugBreak% = 0 +DefineDosDevice% = 3 +DeleteAtom% = 1 +DeleteCriticalSection% = 1 +DeleteFiber% = 1 +DeleteFile% = 1 +DeviceIoControl% = 8 +DisableThreadLibraryCalls% = 1 +DisconnectNamedPipe% = 1 +DosDateTimeToFileTime% = 3 +DuplicateConsoleHandle% = 4 +DuplicateHandle% = 7 +EndUpdateResource% = 2 +EnterCriticalSection% = 1 +EnumCalendarInfo% = 4 +EnumCalendarInfoEx% = 4 +EnumDateFormats% = 3 +EnumDateFormatsEx% = 3 +EnumResourceLanguages% = 5 +EnumResourceNames% = 4 +EnumResourceTypes% = 3 +EnumSystemCodePages% = 2 +EnumSystemLocales% = 2 +EnumTimeFormats% = 3 +EraseTape% = 3 +EscapeCommFunction% = 2 +ExitProcess% = 1 +ExitThread% = 1 +ExitVDM% = 2 +ExpandEnvironmentStrings% = 3 +ExpungeConsoleCommandHistory% = 1 +ExtendVirtualBuffer% = 2 +FatalAppExit% = 2 +FatalExit% = 1 +FileTimeToDosDateTime% = 3 +FileTimeToLocalFileTime% = 2 +FileTimeToSystemTime% = 2 +FillConsoleOutputAttribute% = 5 +FillConsoleOutputCharacter% = 5 +FindAtom% = 1 +FindClose% = 1 +FindCloseChangeNotification% = 1 +FindFirstChangeNotification% = 3 +FindFirstFile% = 2 +FindFirstFileEx% = 6 +FindNextChangeNotification% = 1 +FindNextFile% = 2 +FindResource% = 3 +FindResourceEx% = 4 +FlushConsoleInputBuffer% = 1 +FlushFileBuffers% = 1 +FlushInstructionCache% = 3 +FlushViewOfFile% = 2 +FoldString% = 5 +FormatMessage% = 7 +FreeConsole% = 0 +FreeEnvironmentStrings% = 1 +FreeLibrary% = 1 +FreeLibraryAndExitThread% = 2 +FreeResource% = 1 +FreeVirtualBuffer% = 1 +GenerateConsoleCtrlEvent% = 2 +GetACP% = 0 +GetAtomName% = 3 +GetBinaryType% = 2 +GetCPInfo% = 2 +GetCPInfoEx% = 3 +GetCommConfig% = 3 +GetCommMask% = 2 +GetCommModemStatus% = 2 +GetCommProperties% = 2 +GetCommState% = 2 +GetCommTimeouts% = 2 +GetCommandLine% = 0 +GetCompressedFileSize% = 2 +GetComputerName% = 2 +GetConsoleAlias% = 4 +GetConsoleAliasExes% = 2 +GetConsoleAliasExesLength% = 0 +GetConsoleAliases% = 3 +GetConsoleAliasesLength% = 1 +GetConsoleCP% = 0 +GetConsoleCommandHistory% = 3 +GetConsoleCommandHistoryLength% = 1 +GetConsoleCursorInfo% = 2 +GetConsoleDisplayMode% = 1 +GetConsoleFontInfo% = 4 +GetConsoleFontSize% = 2 +GetConsoleHardwareState% = 3 +GetConsoleInputExeName% = 2 +GetConsoleInputWaitHandle% = 0 +GetConsoleKeyboardLayoutName% = 1 +GetConsoleMode% = 2 +GetConsoleOutputCP% = 0 +GetConsoleScreenBufferInfo% = 2 +GetConsoleTitle% = 2 +GetConsoleWindow% = 0 +GetCurrencyFormat% = 6 +GetCurrentConsoleFont% = 3 +GetCurrentDirectory% = 2 +GetCurrentProcess% = 0 +GetCurrentProcessId% = 0 +GetCurrentThread% = 0 +GetCurrentThreadId% = 0 +GetDateFormat% = 6 +GetDefaultCommConfig% = 3 +GetDevicePowerState% = 1 +GetDiskFreeSpace% = 5 +GetDiskFreeSpaceEx% = 4 +GetDriveType% = 1 +GetEnvironmentStrings% = 0 +GetEnvironmentVariable% = 3 +GetExitCodeProcess% = 2 +GetExitCodeThread% = 2 +GetFileAttributes% = 1 +GetFileAttributesEx% = 3 +GetFileInformationByHandle% = 2 +GetFileSize% = 2 +GetFileTime% = 4 +GetFileType% = 1 +GetFullPathName% = 4 +GetHandleInformation% = 2 +GetLargestConsoleWindowSize% = 1 +GetLastError% = 0 +GetLocalTime% = 1 +GetLocaleInfo% = 4 +GetLogicalDriveStrings% = 2 +GetLogicalDrives% = 0 +GetLongPathName% = 3 +GetMailslotInfo% = 5 +GetModuleFileName% = 3 +GetModuleHandle% = 1 +GetNamedPipeHandleState% = 7 +GetNamedPipeInfo% = 5 +GetNextVDMCommand% = 1 +GetNumberFormat% = 6 +GetNumberOfConsoleFonts% = 0 +GetNumberOfConsoleInputEvents% = 2 +GetNumberOfConsoleMouseButtons% = 1 +GetOEMCP% = 0 +GetOverlappedResult% = 4 +GetPriorityClass% = 1 +GetPrivateProfileInt% = 4 +GetPrivateProfileSection% = 4 +GetPrivateProfileSectionNames% = 3 +GetPrivateProfileString% = 6 +GetPrivateProfileStruct% = 5 +GetProcAddress% = 2 +GetProcessAffinityMask% = 3 +GetProcessHeap% = 0 +GetProcessHeaps% = 2 +GetProcessPriorityBoost% = 2 +GetProcessShutdownParameters% = 2 +GetProcessTimes% = 5 +GetProcessVersion% = 1 +GetProcessWorkingSetSize% = 3 +GetProfileInt% = 3 +GetProfileSection% = 3 +GetProfileString% = 5 +GetQueuedCompletionStatus% = 5 +GetShortPathName% = 3 +GetStartupInfo% = 1 +GetStdHandle% = 1 +GetStringType% = 5 +GetStringTypeEx% = 5 +GetSystemDefaultLCID% = 0 +GetSystemDefaultLangID% = 0 +GetSystemDirectory% = 2 +GetSystemInfo% = 1 +GetSystemPowerStatus% = 1 +GetSystemTime% = 1 +GetSystemTimeAdjustment% = 3 +GetSystemTimeAsFileTime% = 1 +GetTapeParameters% = 4 +GetTapePosition% = 5 +GetTapeStatus% = 1 +GetTempFileName% = 4 +GetTempPath% = 2 +GetThreadContext% = 2 +GetThreadLocale% = 0 +GetThreadPriority% = 1 +GetThreadPriorityBoost% = 2 +GetThreadSelectorEntry% = 3 +GetThreadTimes% = 5 +GetTickCount% = 0 +GetTimeFormat% = 6 +GetTimeZoneInformation% = 1 +GetUserDefaultLCID% = 0 +GetUserDefaultLangID% = 0 +GetVDMCurrentDirectories% = 2 +GetVersion% = 0 +GetVersionEx% = 1 +GetVolumeInformation% = 8 +GetWindowsDirectory% = 2 +GlobalAddAtom% = 1 +GlobalAlloc% = 2 +GlobalCompact% = 1 +GlobalDeleteAtom% = 1 +GlobalFindAtom% = 1 +GlobalFix% = 1 +GlobalFlags% = 1 +GlobalFree% = 1 +GlobalGetAtomName% = 3 +GlobalHandle% = 1 +GlobalLock% = 1 +GlobalMemoryStatus% = 1 +GlobalMemoryStatusVlm% = 1 +GlobalReAlloc% = 3 +GlobalSize% = 1 +GlobalUnWire% = 1 +GlobalUnfix% = 1 +GlobalUnlock% = 1 +GlobalWire% = 1 +Heap32First% = 3 +Heap32ListFirst% = 2 +Heap32ListNext% = 2 +Heap32Next% = 1 +HeapAlloc% = 3 +HeapCompact% = 2 +HeapCreate% = 3 +HeapDestroy% = 1 +HeapExtend% = 4 +HeapFree% = 3 +HeapLock% = 1 +HeapReAlloc% = 4 +HeapSize% = 3 +HeapSummary% = 3 +HeapUnlock% = 1 +HeapUsage% = 5 +HeapValidate% = 3 +HeapWalk% = 2 +InitAtomTable% = 1 +InitializeCriticalSection% = 1 +InitializeCriticalSectionAndSpinCount% = 2 +InterlockedCompareExchange% = 3 +InterlockedDecrement% = 1 +InterlockedExchange% = 2 +InterlockedExchangeAdd% = 2 +InterlockedIncrement% = 1 +InvalidateConsoleDIBits% = 2 +IsBadCodePtr% = 1 +IsBadHugeReadPtr% = 2 +IsBadHugeWritePtr% = 2 +IsBadReadPtr% = 2 +IsBadStringPtr% = 2 +IsBadWritePtr% = 2 +IsDBCSLeadByte% = 1 +IsDBCSLeadByteEx% = 2 +IsDebuggerPresent% = 0 +IsProcessorFeaturePresent% = 1 +IsValidCodePage% = 1 +IsValidLocale% = 2 +LCMapString% = 6 +LeaveCriticalSection% = 1 +LoadLibrary% = 1 +LoadLibraryEx% = 3 +LoadModule% = 2 +LoadResource% = 2 +LocalAlloc% = 2 +LocalCompact% = 1 +LocalFileTimeToFileTime% = 2 +LocalFlags% = 1 +LocalFree% = 1 +LocalHandle% = 1 +LocalLock% = 1 +LocalReAlloc% = 3 +LocalShrink% = 2 +LocalSize% = 1 +LocalUnlock% = 1 +LockFile% = 5 +LockFileEx% = 6 +LockResource% = 1 +MapViewOfFile% = 5 +MapViewOfFileEx% = 6 +MapViewOfFileVlm% = 7 +Module32First% = 2 +Module32Next% = 2 +MoveFile% = 2 +MoveFileEx% = 3 +MoveFileWithProgress% = 5 +MulDiv% = 3 +MultiByteToWideChar% = 6 +OpenEvent% = 3 +OpenFile% = 3 +OpenFileMapping% = 3 +OpenJobObject% = 3 +OpenMutex% = 3 +OpenProcess% = 3 +OpenProfileUserMapping% = 0 +OpenSemaphore% = 3 +OpenWaitableTimer% = 3 +OutputDebugString% = 1 +PeekConsoleInput% = 4 +PeekNamedPipe% = 6 +PostQueuedCompletionStatus% = 4 +PrepareTape% = 3 +Process32First% = 2 +Process32Next% = 2 +PulseEvent% = 1 +PurgeComm% = 2 +QueryDosDevice% = 3 +QueryInformationJobObject% = 5 +QueryPerformanceCounter% = 1 +QueryPerformanceFrequency% = 1 +QueryWin31IniFilesMappedToRegistry% = 4 +QueueUserAPC% = 3 +RaiseException% = 4 +ReadConsole% = 5 +ReadConsoleInput% = 4 +ReadConsoleInputEx% = 5 +ReadConsoleOutput% = 5 +ReadConsoleOutputAttribute% = 5 +ReadConsoleOutputCharacter% = 5 +ReadFile% = 5 +ReadFileEx% = 5 +ReadFileScatter% = 5 +ReadFileVlm% = 5 +ReadProcessMemory% = 5 +ReadProcessMemoryVlm% = 5 +RegisterConsoleVDM% = 11 +RegisterWaitForInputIdle% = 1 +RegisterWowBaseHandlers% = 1 +RegisterWowExec% = 1 +ReleaseMutex% = 1 +ReleaseSemaphore% = 3 +RemoveDirectory% = 1 +RequestWakeupLatency% = 1 +ResetEvent% = 1 +ResumeThread% = 1 +RtlFillMemory% = 3 +RtlMoveMemory% = 3 +RtlUnwind% = 4 +RtlZeroMemory% = 2 +ScrollConsoleScreenBuffer% = 5 +SearchPath% = 6 +SetCommBreak% = 1 +SetCommConfig% = 3 +SetCommMask% = 2 +SetCommState% = 2 +SetCommTimeouts% = 2 +SetComputerName% = 1 +SetConsoleActiveScreenBuffer% = 1 +SetConsoleCP% = 1 +SetConsoleCommandHistoryMode% = 1 +SetConsoleCtrlHandler% = 2 +SetConsoleCursor% = 2 +SetConsoleCursorInfo% = 2 +SetConsoleCursorPosition% = 2 +SetConsoleDisplayMode% = 3 +SetConsoleFont% = 2 +SetConsoleHardwareState% = 3 +SetConsoleIcon% = 1 +SetConsoleInputExeName% = 1 +SetConsoleKeyShortcuts% = 4 +SetConsoleMaximumWindowSize% = 2 +SetConsoleMenuClose% = 1 +SetConsoleMode% = 2 +SetConsoleNumberOfCommands% = 2 +SetConsoleOutputCP% = 1 +SetConsolePalette% = 3 +SetConsoleScreenBufferSize% = 2 +SetConsoleTextAttribute% = 2 +SetConsoleTitle% = 1 +SetConsoleWindowInfo% = 3 +SetCriticalSectionSpinCount% = 2 +SetCurrentDirectory% = 1 +SetDefaultCommConfig% = 3 +SetEndOfFile% = 1 +SetEnvironmentVariable% = 2 +SetErrorMode% = 1 +SetEvent% = 1 +SetFileApisToANSI% = 0 +SetFileApisToOEM% = 0 +SetFileAttributes% = 2 +SetFilePointer% = 4 +SetFileTime% = 4 +SetHandleCount% = 1 +SetHandleInformation% = 3 +SetInformationJobObject% = 4 +SetLastConsoleEventActive% = 0 +SetLastError% = 1 +SetLocalTime% = 1 +SetLocaleInfo% = 3 +SetMailslotInfo% = 2 +SetNamedPipeHandleState% = 4 +SetPriorityClass% = 2 +SetProcessAffinityMask% = 2 +SetProcessPriorityBoost% = 2 +SetProcessShutdownParameters% = 2 +SetProcessWorkingSetSize% = 3 +SetStdHandle% = 2 +SetSystemPowerState% = 2 +SetSystemTime% = 1 +SetSystemTimeAdjustment% = 2 +SetTapeParameters% = 3 +SetTapePosition% = 6 +SetThreadAffinityMask% = 2 +SetThreadContext% = 2 +SetThreadExecutionState% = 1 +SetThreadIdealProcessor% = 2 +SetThreadLocale% = 1 +SetThreadPriority% = 2 +SetThreadPriorityBoost% = 2 +SetTimeZoneInformation% = 1 +SetUnhandledExceptionFilter% = 1 +SetVDMCurrentDirectories% = 2 +SetVolumeLabel% = 2 +SetWaitableTimer% = 6 +SetupComm% = 3 +ShowConsoleCursor% = 2 +SignalObjectAndWait% = 4 +SizeofResource% = 2 +Sleep% = 1 +SleepEx% = 2 +SuspendThread% = 1 +SwitchToFiber% = 1 +SwitchToThread% = 0 +SystemTimeToFileTime% = 2 +SystemTimeToTzSpecificLocalTime% = 3 +TerminateJobObject% = 2 +TerminateProcess% = 2 +TerminateThread% = 2 +Thread32First% = 2 +Thread32Next% = 2 +TlsAlloc% = 0 +TlsFree% = 1 +TlsGetValue% = 1 +TlsSetValue% = 2 +Toolhelp32ReadProcessMemory% = 5 +TransactNamedPipe% = 7 +TransmitCommChar% = 2 +TrimVirtualBuffer% = 1 +TryEnterCriticalSection% = 1 +UnhandledExceptionFilter% = 1 +UnlockFile% = 5 +UnlockFileEx% = 5 +UnmapViewOfFile% = 1 +UnmapViewOfFileVlm% = 1 +UpdateResource% = 6 +VDMConsoleOperation% = 2 +VDMOperationStarted% = 1 +VerLanguageName% = 3 +VerifyConsoleIoHandle% = 1 +VirtualAlloc% = 4 +VirtualAllocEx% = 5 +VirtualAllocVlm% = 6 +VirtualBufferExceptionHandler% = 3 +VirtualFree% = 3 +VirtualFreeEx% = 4 +VirtualFreeVlm% = 5 +VirtualLock% = 2 +VirtualProtect% = 4 +VirtualProtectEx% = 5 +VirtualProtectVlm% = 6 +VirtualQuery% = 3 +VirtualQueryEx% = 4 +VirtualQueryVlm% = 4 +VirtualUnlock% = 2 +WaitCommEvent% = 3 +WaitForDebugEvent% = 2 +WaitForMultipleObjects% = 4 +WaitForMultipleObjectsEx% = 5 +WaitForSingleObject% = 2 +WaitForSingleObjectEx% = 3 +WaitNamedPipe% = 2 +WideCharToMultiByte% = 8 +WinExec% = 2 +WriteConsole% = 5 +WriteConsoleInput% = 4 +WriteConsoleInputVDM% = 4 +WriteConsoleOutput% = 5 +WriteConsoleOutputAttribute% = 5 +WriteConsoleOutputCharacter% = 5 +WriteFile% = 5 +WriteFileEx% = 5 +WriteFileGather% = 5 +WriteFileVlm% = 5 +WritePrivateProfileSection% = 3 +WritePrivateProfileString% = 4 +WritePrivateProfileStruct% = 5 +WriteProcessMemory% = 5 +WriteProcessMemoryVlm% = 5 +WriteProfileSection% = 2 +WriteProfileString% = 3 +WriteTapemark% = 4 +_hread% = 3 +_hwrite% = 3 +_lclose% = 1 +_lcreat% = 2 +_llseek% = 3 +_lopen% = 2 +_lread% = 3 +_lwrite% = 3 +lstrcat% = 2 +lstrcmp% = 2 +lstrcmpi% = 2 +lstrcpy% = 2 +lstrcpyn% = 3 +lstrlen% = 1 diff --git a/toolchain/fasm2/include/pcount/shell32.inc b/toolchain/fasm2/include/pcount/shell32.inc new file mode 100644 index 0000000..1d0528d --- /dev/null +++ b/toolchain/fasm2/include/pcount/shell32.inc @@ -0,0 +1,73 @@ + +; SHELL32 API calls parameters' count + +CheckEscapes% = 2 +DoEnvironmentSubst% = 2 +DragAcceptFiles% = 2 +DragFinish% = 1 +DragQueryFile% = 4 +DragQueryPoint% = 2 +DuplicateIcon% = 2 +ExtractAssociatedIcon% = 3 +ExtractAssociatedIconEx% = 4 +ExtractIcon% = 3 +ExtractIconEx% = 5 +ExtractIconResInfo% = 5 +FindExeDlgProc% = 4 +FindExecutable% = 3 +FreeIconList% = 2 +InternalExtractIconList% = 3 +RealShellExecute% = 10 +RealShellExecuteEx% = 11 +RegenerateUserEnvironment% = 2 +SHAddToRecentDocs% = 2 +SHAppBarMessage% = 2 +SHBrowseForFolder% = 1 +SHChangeNotify% = 4 +SHEmptyRecycleBin% = 3 +SHFileOperation% = 1 +SHFormatDrive% = 4 +SHFreeNameMappings% = 1 +SHGetDataFromIDList% = 5 +SHGetDesktopFolder% = 1 +SHGetDiskFreeSpace% = 4 +SHGetFileInfo% = 5 +SHGetInstanceExplorer% = 1 +SHGetMalloc% = 1 +SHGetNewLinkInfo% = 5 +SHGetPathFromIDList% = 2 +SHGetSettings% = 2 +SHGetSpecialFolderLocation% = 3 +SHGetSpecialFolderPath% = 4 +SHInvokePrinterCommand% = 5 +SHLoadInProc% = 1 +SHQueryRecycleBin% = 2 +SHUpdateRecycleBinIcon% = 0 +SheChangeDir% = 1 +SheChangeDirEx% = 1 +SheFullPath% = 3 +SheGetCurDrive% = 0 +SheGetDir% = 2 +SheRemoveQuotes% = 1 +SheSetCurDrive% = 1 +SheShortenPath% = 2 +ShellAbout% = 4 +ShellExecute% = 6 +ShellExecuteEx% = 1 +ShellHookProc% = 3 +Shell_NotifyIcon% = 2 +StrChr% = 2 +StrChrI% = 2 +StrCmpN% = 3 +StrCmpNI% = 3 +StrCpyN% = 3 +StrNCmp% = 3 +StrNCmpI% = 3 +StrNCpy% = 3 +StrRChr% = 3 +StrRChrI% = 3 +StrRStr% = 3 +StrRStrI% = 3 +StrStr% = 2 +StrStrI% = 2 +WOWShellExecute% = 7 diff --git a/toolchain/fasm2/include/pcount/user32.inc b/toolchain/fasm2/include/pcount/user32.inc new file mode 100644 index 0000000..fc4ce05 --- /dev/null +++ b/toolchain/fasm2/include/pcount/user32.inc @@ -0,0 +1,477 @@ + +; USER32 API calls parameters' count + +ActivateKeyboardLayout% = 2 +AdjustWindowRect% = 3 +AdjustWindowRectEx% = 4 +AnimateWindow% = 3 +AnyPopup% = 0 +AppendMenu% = 4 +ArrangeIconicWindows% = 1 +AttachThreadInput% = 3 +BeginDeferWindowPos% = 1 +BeginPaint% = 2 +BlockInput% = 1 +BringWindowToTop% = 1 +BroadcastSystemMessage% = 5 +CallMsgFilter% = 2 +CallNextHookEx% = 4 +CallWindowProc% = 5 +CascadeChildWindows% = 2 +CascadeWindows% = 5 +ChangeClipboardChain% = 2 +ChangeDisplaySettings% = 2 +ChangeDisplaySettingsEx% = 5 +ChangeMenu% = 5 +CharLower% = 1 +CharLowerBuff% = 2 +CharNext% = 1 +CharNextEx% = 3 +CharPrev% = 2 +CharPrevEx% = 4 +CharToOem% = 2 +CharToOemBuff% = 3 +CharUpper% = 1 +CharUpperBuff% = 2 +CheckDlgButton% = 3 +CheckMenuItem% = 3 +CheckMenuRadioItem% = 5 +CheckRadioButton% = 4 +ChildWindowFromPoint% = 3 +ChildWindowFromPointEx% = 4 +ClientToScreen% = 2 +ClipCursor% = 1 +CloseClipboard% = 0 +CloseDesktop% = 1 +CloseWindow% = 1 +CloseWindowStation% = 1 +CopyAcceleratorTable% = 3 +CopyIcon% = 1 +CopyImage% = 5 +CopyRect% = 2 +CountClipboardFormats% = 0 +CreateAcceleratorTable% = 2 +CreateCaret% = 4 +CreateCursor% = 7 +CreateDesktop% = 6 +CreateDialogIndirectParam% = 5 +CreateDialogParam% = 5 +CreateIcon% = 7 +CreateIconFromResource% = 4 +CreateIconFromResourceEx% = 7 +CreateIconIndirect% = 1 +CreateMDIWindow% = 10 +CreateMenu% = 0 +CreatePopupMenu% = 0 +CreateWindowEx% = 12 +CreateWindowStation% = 4 +DdeAbandonTransaction% = 3 +DdeAccessData% = 2 +DdeAddData% = 4 +DdeClientTransaction% = 8 +DdeCmpStringHandles% = 2 +DdeConnect% = 4 +DdeConnectList% = 5 +DdeCreateDataHandle% = 7 +DdeCreateStringHandle% = 3 +DdeDisconnect% = 1 +DdeDisconnectList% = 1 +DdeEnableCallback% = 3 +DdeFreeDataHandle% = 1 +DdeFreeStringHandle% = 2 +DdeGetData% = 4 +DdeGetLastError% = 1 +DdeGetQualityOfService% = 3 +DdeImpersonateClient% = 1 +DdeInitialize% = 4 +DdeKeepStringHandle% = 2 +DdeNameService% = 4 +DdePostAdvise% = 3 +DdeQueryConvInfo% = 3 +DdeQueryNextServer% = 2 +DdeQueryString% = 5 +DdeReconnect% = 1 +DdeSetQualityOfService% = 3 +DdeSetUserHandle% = 3 +DdeUnaccessData% = 1 +DdeUninitialize% = 1 +DefDlgProc% = 4 +DefFrameProc% = 5 +DefMDIChildProc% = 4 +DefWindowProc% = 4 +DeferWindowPos% = 8 +DeleteMenu% = 3 +DestroyAcceleratorTable% = 1 +DestroyCaret% = 0 +DestroyCursor% = 1 +DestroyIcon% = 1 +DestroyMenu% = 1 +DestroyWindow% = 1 +DialogBoxIndirectParam% = 5 +DialogBoxParam% = 5 +DispatchMessage% = 1 +DlgDirList% = 5 +DlgDirListComboBox% = 5 +DlgDirSelectComboBoxEx% = 4 +DlgDirSelectEx% = 4 +DragDetect% = 3 +DragObject% = 5 +DrawAnimatedRects% = 4 +DrawCaption% = 4 +DrawEdge% = 4 +DrawFocusRect% = 2 +DrawFrame% = 4 +DrawFrameControl% = 4 +DrawIcon% = 4 +DrawIconEx% = 9 +DrawMenuBar% = 1 +DrawState% = 10 +DrawText% = 5 +DrawTextEx% = 6 +EditWndProc% = 4 +EmptyClipboard% = 0 +EnableMenuItem% = 3 +EnableScrollBar% = 3 +EnableWindow% = 2 +EndDeferWindowPos% = 1 +EndDialog% = 2 +EndMenu% = 0 +EndPaint% = 2 +EnumChildWindows% = 3 +EnumClipboardFormats% = 1 +EnumDesktopWindows% = 3 +EnumDesktops% = 3 +EnumDisplayMonitors% = 4 +EnumDisplaySettings% = 3 +EnumDisplaySettingsEx% = 4 +EnumProps% = 2 +EnumPropsEx% = 3 +EnumThreadWindows% = 3 +EnumWindowStations% = 2 +EnumWindows% = 2 +EqualRect% = 2 +ExcludeUpdateRgn% = 2 +ExitWindowsEx% = 2 +FillRect% = 3 +FindWindow% = 2 +FindWindowEx% = 4 +FlashWindow% = 2 +FrameRect% = 3 +FreeDDElParam% = 2 +GetActiveWindow% = 0 +GetAltTabInfo% = 5 +GetAncestor% = 2 +GetAsyncKeyState% = 1 +GetCapture% = 0 +GetCaretBlinkTime% = 0 +GetCaretPos% = 1 +GetClassInfo% = 3 +GetClassInfoEx% = 3 +GetClassLong% = 2 +GetClassName% = 3 +GetClassWord% = 2 +GetClientRect% = 2 +GetClipCursor% = 1 +GetClipboardData% = 1 +GetClipboardFormatName% = 3 +GetClipboardSequenceNumber% = 0 +GetClipboardViewer% = 0 +GetComboBoxInfo% = 2 +GetCursor% = 0 +GetCursorInfo% = 1 +GetCursorPos% = 1 +GetDC% = 1 +GetDCEx% = 3 +GetDesktopWindow% = 0 +GetDialogBaseUnits% = 0 +GetDlgCtrlID% = 1 +GetDlgItem% = 2 +GetDlgItemInt% = 4 +GetDlgItemText% = 4 +GetDoubleClickTime% = 0 +GetFocus% = 0 +GetForegroundWindow% = 0 +GetGUIThreadInfo% = 2 +GetGuiResources% = 2 +GetIconInfo% = 2 +GetInputDesktop% = 0 +GetInputState% = 0 +GetKBCodePage% = 0 +GetKeyNameText% = 3 +GetKeyState% = 1 +GetKeyboardLayout% = 1 +GetKeyboardLayoutList% = 2 +GetKeyboardLayoutName% = 1 +GetKeyboardState% = 1 +GetKeyboardType% = 1 +GetLastActivePopup% = 1 +GetLastInputInfo% = 1 +GetListBoxInfo% = 1 +GetMenu% = 1 +GetMenuBarInfo% = 4 +GetMenuCheckMarkDimensions% = 0 +GetMenuContextHelpId% = 1 +GetMenuDefaultItem% = 3 +GetMenuInfo% = 2 +GetMenuItemCount% = 1 +GetMenuItemID% = 2 +GetMenuItemInfo% = 4 +GetMenuItemRect% = 4 +GetMenuState% = 3 +GetMenuString% = 5 +GetMessage% = 4 +GetMessageExtraInfo% = 0 +GetMessagePos% = 0 +GetMessageTime% = 0 +GetMonitorInfo% = 2 +GetMouseMovePoints% = 5 +GetNextDlgGroupItem% = 3 +GetNextDlgTabItem% = 3 +GetOpenClipboardWindow% = 0 +GetParent% = 1 +GetPriorityClipboardFormat% = 2 +GetProcessWindowStation% = 0 +GetProp% = 2 +GetQueueStatus% = 1 +GetScrollBarInfo% = 3 +GetScrollInfo% = 3 +GetScrollPos% = 2 +GetScrollRange% = 4 +GetShellWindow% = 0 +GetSubMenu% = 2 +GetSysColor% = 1 +GetSysColorBrush% = 1 +GetSystemMenu% = 2 +GetSystemMetrics% = 1 +GetTabbedTextExtent% = 5 +GetThreadDesktop% = 1 +GetTitleBarInfo% = 2 +GetTopWindow% = 1 +GetUpdateRect% = 3 +GetUpdateRgn% = 3 +GetUserObjectInformation% = 5 +GetUserObjectSecurity% = 5 +GetWindow% = 2 +GetWindowContextHelpId% = 1 +GetWindowDC% = 1 +GetWindowInfo% = 2 +GetWindowLong% = 2 +GetWindowModuleFileName% = 3 +GetWindowPlacement% = 2 +GetWindowRect% = 2 +GetWindowRgn% = 2 +GetWindowText% = 3 +GetWindowTextLength% = 1 +GetWindowThreadProcessId% = 2 +GetWindowWord% = 2 +GrayString% = 9 +HideCaret% = 1 +HiliteMenuItem% = 4 +IMPGetIME% = 2 +IMPQueryIME% = 1 +IMPSetIME% = 2 +ImpersonateDdeClientWindow% = 2 +InSendMessage% = 0 +InSendMessageEx% = 1 +InflateRect% = 3 +InsertMenu% = 5 +InsertMenuItem% = 4 +IntersectRect% = 3 +InvalidateRect% = 3 +InvalidateRgn% = 3 +InvertRect% = 2 +IsCharAlpha% = 1 +IsCharAlphaNumeric% = 1 +IsCharLower% = 1 +IsCharUpper% = 1 +IsChild% = 2 +IsClipboardFormatAvailable% = 1 +IsDialogMessage% = 2 +IsDlgButtonChecked% = 2 +IsIconic% = 1 +IsMenu% = 1 +IsRectEmpty% = 1 +IsWindow% = 1 +IsWindowEnabled% = 1 +IsWindowUnicode% = 1 +IsWindowVisible% = 1 +IsZoomed% = 1 +KillSystemTimer% = 2 +KillTimer% = 2 +LoadAccelerators% = 2 +LoadBitmap% = 2 +LoadCursor% = 2 +LoadCursorFromFile% = 1 +LoadIcon% = 2 +LoadImage% = 6 +LoadKeyboardLayout% = 2 +LoadMenu% = 2 +LoadMenuIndirect% = 1 +LoadString% = 4 +LockWindowUpdate% = 1 +LockWorkStation% = 0 +LookupIconIdFromDirectory% = 2 +LookupIconIdFromDirectoryEx% = 5 +MapDialogRect% = 2 +MapVirtualKey% = 2 +MapVirtualKeyEx% = 3 +MapWindowPoints% = 4 +MenuItemFromPoint% = 4 +MessageBeep% = 1 +MessageBox% = 4 +MessageBoxEx% = 5 +MessageBoxIndirect% = 1 +ModifyMenu% = 5 +MonitorFromPoint% = 3 +MonitorFromRect% = 2 +MonitorFromWindow% = 2 +MoveWindow% = 6 +MsgWaitForMultipleObjects% = 5 +MsgWaitForMultipleObjectsEx% = 5 +NotifyWinEvent% = 4 +OemKeyScan% = 1 +OemToChar% = 2 +OemToCharBuff% = 3 +OffsetRect% = 3 +OpenClipboard% = 1 +OpenDesktop% = 4 +OpenIcon% = 1 +OpenInputDesktop% = 3 +OpenWindowStation% = 3 +PackDDElParam% = 3 +PaintDesktop% = 1 +PeekMessage% = 5 +PostMessage% = 4 +PostQuitMessage% = 1 +PostThreadMessage% = 4 +PtInRect% = 3 +RealChildWindowFromPoint% = 3 +RealGetWindowClass% = 3 +RedrawWindow% = 4 +RegisterClass% = 1 +RegisterClassEx% = 1 +RegisterClipboardFormat% = 1 +RegisterDeviceNotification% = 3 +RegisterHotKey% = 4 +RegisterWindowMessage% = 1 +ReleaseCapture% = 0 +ReleaseDC% = 2 +RemoveMenu% = 3 +RemoveProp% = 2 +ReplyMessage% = 1 +ReuseDDElParam% = 5 +ScreenToClient% = 2 +ScrollChildren% = 3 +ScrollDC% = 7 +ScrollWindow% = 5 +ScrollWindowEx% = 8 +SendDlgItemMessage% = 5 +SendIMEMessageEx% = 2 +SendInput% = 3 +SendMessage% = 4 +SendMessageCallback% = 6 +SendMessageTimeout% = 7 +SendNotifyMessage% = 4 +SetActiveWindow% = 1 +SetCapture% = 1 +SetCaretBlinkTime% = 1 +SetCaretPos% = 2 +SetClassLong% = 3 +SetClassWord% = 3 +SetClipboardData% = 2 +SetClipboardViewer% = 1 +SetCursor% = 1 +SetCursorPos% = 2 +SetDebugErrorLevel% = 1 +SetDeskWallpaper% = 1 +SetDlgItemInt% = 4 +SetDlgItemText% = 3 +SetDoubleClickTime% = 1 +SetFocus% = 1 +SetForegroundWindow% = 1 +SetKeyboardState% = 1 +SetLastErrorEx% = 2 +SetMenu% = 2 +SetMenuContextHelpId% = 2 +SetMenuDefaultItem% = 3 +SetMenuInfo% = 2 +SetMenuItemBitmaps% = 5 +SetMenuItemInfo% = 4 +SetMessageExtraInfo% = 1 +SetMessageQueue% = 1 +SetParent% = 2 +SetProcessWindowStation% = 1 +SetProp% = 3 +SetRect% = 5 +SetRectEmpty% = 1 +SetScrollInfo% = 4 +SetScrollPos% = 4 +SetScrollRange% = 5 +SetShellWindow% = 1 +SetSysColors% = 3 +SetSystemCursor% = 2 +SetSystemMenu% = 2 +SetSystemTimer% = 4 +SetThreadDesktop% = 1 +SetTimer% = 4 +SetUserObjectInformation% = 4 +SetUserObjectSecurity% = 3 +SetWinEventHook% = 7 +SetWindowContextHelpId% = 2 +SetWindowLong% = 3 +SetWindowPlacement% = 2 +SetWindowPos% = 7 +SetWindowRgn% = 3 +SetWindowText% = 2 +SetWindowWord% = 3 +SetWindowsHook% = 2 +SetWindowsHookEx% = 4 +ShowCaret% = 1 +ShowCursor% = 1 +ShowOwnedPopups% = 2 +ShowScrollBar% = 3 +ShowWindow% = 2 +ShowWindowAsync% = 2 +SubtractRect% = 3 +SwapMouseButton% = 1 +SwitchDesktop% = 1 +SystemParametersInfo% = 4 +TabbedTextOut% = 8 +TileChildWindows% = 2 +TileWindows% = 5 +ToAscii% = 5 +ToAsciiEx% = 6 +ToUnicode% = 6 +ToUnicodeEx% = 7 +TrackMouseEvent% = 1 +TrackPopupMenu% = 7 +TrackPopupMenuEx% = 6 +TranslateAccelerator% = 3 +TranslateMDISysAccel% = 2 +TranslateMessage% = 1 +UnhookWinEvent% = 1 +UnhookWindowsHook% = 2 +UnhookWindowsHookEx% = 1 +UnionRect% = 3 +UnloadKeyboardLayout% = 1 +UnpackDDElParam% = 4 +UnregisterClass% = 2 +UnregisterDeviceNotification% = 1 +UnregisterHotKey% = 2 +UpdateWindow% = 1 +UserHandleGrantAccess% = 2 +ValidateRect% = 2 +ValidateRgn% = 2 +VkKeyScan% = 1 +VkKeyScanEx% = 2 +WINNLSEnableIME% = 2 +WINNLSGetEnableStatus% = 1 +WINNLSGetIMEHotkey% = 1 +WaitForInputIdle% = 2 +WaitMessage% = 0 +WinHelp% = 4 +WindowFromDC% = 1 +WindowFromPoint% = 2 +keybd_event% = 4 +mouse_event% = 5 +wvsprintf% = 3 diff --git a/toolchain/fasm2/include/pcount/wsock32.inc b/toolchain/fasm2/include/pcount/wsock32.inc new file mode 100644 index 0000000..ea401d3 --- /dev/null +++ b/toolchain/fasm2/include/pcount/wsock32.inc @@ -0,0 +1,70 @@ + +; WSOCK32 API calls parameters' count + +AcceptEx% = 8 +EnumProtocols% = 3 +GetAcceptExSockaddrs% = 8 +GetAddressByName% = 10 +GetNameByType% = 3 +GetService% = 7 +GetTypeByName% = 2 +MigrateWinsockConfiguration% = 3 +NPLoadNameSpaces% = 3 +SetService% = 6 +TransmitFile% = 7 +WEP% = 0 +WSAAsyncGetHostByAddr% = 7 +WSAAsyncGetHostByName% = 5 +WSAAsyncGetProtoByName% = 5 +WSAAsyncGetProtoByNumber% = 5 +WSAAsyncGetServByName% = 6 +WSAAsyncGetServByPort% = 6 +WSACancelAsyncRequest% = 4 +WSACancelBlockingCall% = 0 +WSACleanup% = 0 +WSAGetLastError% = 0 +WSAIsBlocking% = 0 +WSARecvEx% = 4 +WSASetBlockingHook% = 1 +WSASetLastError% = 1 +WSAStartup% = 2 +WSAUnhookBlockingHook% = 0 +__WSAFDIsSet% = 2 +accept% = 3 +bind% = 3 +closesocket% = 1 +connect% = 3 +dn_expand% = 5 +gethostbyaddr% = 3 +gethostbyname% = 1 +gethostname% = 2 +getnetbyname% = 1 +getpeername% = 3 +getprotobyname% = 1 +getprotobynumber% = 1 +getservbyname% = 2 +getservbyport% = 2 +getsockname% = 3 +getsockopt% = 5 +htonl% = 1 +htons% = 1 +inet_addr% = 1 +inet_network% = 1 +inet_ntoa% = 1 +ioctlsocket% = 3 +listen% = 2 +ntohl% = 1 +ntohs% = 1 +rcmd% = 6 +recv% = 4 +recvfrom% = 6 +rexec% = 6 +rresvport% = 1 +s_perror% = 2 +select% = 5 +send% = 4 +sendto% = 6 +sethostname% = 2 +setsockopt% = 5 +shutdown% = 2 +socket% = 3 diff --git a/toolchain/fasm2/include/times.inc b/toolchain/fasm2/include/times.inc new file mode 100644 index 0000000..9096508 --- /dev/null +++ b/toolchain/fasm2/include/times.inc @@ -0,0 +1,30 @@ + +% = 0 + +calminstruction times?: statement + local number, instruction, limit + match number= statement, statement, () + jno incomplete_statement + take limit, number + compute limit, limit + take instruction, statement + compute number, 1 + take %, number + check limit < 0 + jyes negative_number + loop: + check % > limit + jyes done + assemble instruction + compute %, % + 1 + jump loop + incomplete_statement: + err 'incomplete statement' + exit + negative_number: + err 'the number of times must be positive' + done: + take , % + take , limit + take , instruction +end calminstruction diff --git a/toolchain/fasm2/include/win32a.inc b/toolchain/fasm2/include/win32a.inc new file mode 100644 index 0000000..11278e8 --- /dev/null +++ b/toolchain/fasm2/include/win32a.inc @@ -0,0 +1,33 @@ + +macro api names& + iterate name, names + if used name + label name:dword at name#A + end if + end iterate +end macro + +struc? TCHAR args:?& + . db args +end struc + +macro TCHAR args:?& + db args +end macro + +sizeof.TCHAR = 1 + +include 'macro/struct.inc' +include 'macro/proc32.inc' +include 'macro/com32.inc' +include 'macro/import32.inc' +include 'macro/export.inc' +include 'macro/resource.inc' + +include 'equates/kernel32.inc' +include 'equates/user32.inc' +include 'equates/gdi32.inc' +include 'equates/comctl32.inc' +include 'equates/comdlg32.inc' +include 'equates/shell32.inc' +include 'equates/wsock32.inc' diff --git a/toolchain/fasm2/include/win32ax.inc b/toolchain/fasm2/include/win32ax.inc new file mode 100644 index 0000000..d8fbdf1 --- /dev/null +++ b/toolchain/fasm2/include/win32ax.inc @@ -0,0 +1,62 @@ + +include 'win32a.inc' + +include 'macro/inline.inc' +include 'macro/if.inc' + +define _winx +define _winx.code? _code +define _winx.data? _data +define _winx.end? _end + +calminstruction (name) ? &a& + local cmd + match .cmd, name + jno pass + transform cmd, _winx + jno pass + arrange cmd, cmd a + assemble cmd + exit + pass: + arrange cmd, name a + assemble cmd +end calminstruction + +macro _data + section '.data' data readable writeable +end macro + +macro _code + section '.text' code readable executable +end macro + +macro _end label + + entry label + + section '.idata' import data readable writeable + + library kernel32,'KERNEL32.DLL',\ + user32,'USER32.DLL',\ + gdi32,'GDI32.DLL',\ + advapi32,'ADVAPI32.DLL',\ + comctl32,'COMCTL32.DLL',\ + comdlg32,'COMDLG32.DLL',\ + shell32,'SHELL32.DLL',\ + wsock32,'WSOCK32.DLL' + + include! 'api/kernel32.inc' + include! 'api/user32.inc' + include! 'api/gdi32.inc' + include! 'api/advapi32.inc' + include! 'api/comctl32.inc' + include! 'api/comdlg32.inc' + include! 'api/shell32.inc' + include! 'api/wsock32.inc' + +end macro + +if x86.mode = 16 + format PE GUI 4.0 +end if diff --git a/toolchain/fasm2/include/win32axp.inc b/toolchain/fasm2/include/win32axp.inc new file mode 100644 index 0000000..f73fea9 --- /dev/null +++ b/toolchain/fasm2/include/win32axp.inc @@ -0,0 +1,31 @@ + +include 'win32ax.inc' + +include 'pcount/kernel32.inc' +include 'pcount/user32.inc' +include 'pcount/gdi32.inc' +include 'pcount/advapi32.inc' +include 'pcount/comctl32.inc' +include 'pcount/comdlg32.inc' +include 'pcount/shell32.inc' +include 'pcount/wsock32.inc' + +macro pcountcheck? proc*,count* + local pname,pcount + match p, pcountsuffix + match [name], proc + define pcount name#p + else match name, proc + define pcount name#p + end match + end match + if defined pcount & count <> pcount + repeat 1, found:count, expected:pcount + match [name], proc + err 'invalid count of parameters for ',`name,' (',`found,' instead of ',`expected,')' + else + err 'invalid count of parameters for ',`proc,' (',`found,' instead of ',`expected,')' + end match + end repeat + end if +end macro \ No newline at end of file diff --git a/toolchain/fasm2/include/win32w.inc b/toolchain/fasm2/include/win32w.inc new file mode 100644 index 0000000..108bf7d --- /dev/null +++ b/toolchain/fasm2/include/win32w.inc @@ -0,0 +1,33 @@ + +macro api names& + iterate name, names + if used name + label name:dword at name#W + end if + end iterate +end macro + +struc? TCHAR args:?& + . du args +end struc + +macro TCHAR args:?& + du args +end macro + +sizeof.TCHAR = 2 + +include 'macro/struct.inc' +include 'macro/proc32.inc' +include 'macro/com32.inc' +include 'macro/import32.inc' +include 'macro/export.inc' +include 'macro/resource.inc' + +include 'equates/kernel32.inc' +include 'equates/user32.inc' +include 'equates/gdi32.inc' +include 'equates/comctl32.inc' +include 'equates/comdlg32.inc' +include 'equates/shell32.inc' +include 'equates/wsock32.inc' diff --git a/toolchain/fasm2/include/win32wx.inc b/toolchain/fasm2/include/win32wx.inc new file mode 100644 index 0000000..3baa49a --- /dev/null +++ b/toolchain/fasm2/include/win32wx.inc @@ -0,0 +1,62 @@ + +include 'win32w.inc' + +include 'macro/inline.inc' +include 'macro/if.inc' + +define _winx +define _winx.code? _code +define _winx.data? _data +define _winx.end? _end + +calminstruction (name) ? &a& + local cmd + match .cmd, name + jno pass + transform cmd, _winx + jno pass + arrange cmd, cmd a + assemble cmd + exit + pass: + arrange cmd, name a + assemble cmd +end calminstruction + +macro _data + section '.data' data readable writeable +end macro + +macro _code + section '.text' code readable executable +end macro + +macro _end label + + entry label + + section '.idata' import data readable writeable + + library kernel32,'KERNEL32.DLL',\ + user32,'USER32.DLL',\ + gdi32,'GDI32.DLL',\ + advapi32,'ADVAPI32.DLL',\ + comctl32,'COMCTL32.DLL',\ + comdlg32,'COMDLG32.DLL',\ + shell32,'SHELL32.DLL',\ + wsock32,'WSOCK32.DLL' + + include! 'api/kernel32.inc' + include! 'api/user32.inc' + include! 'api/gdi32.inc' + include! 'api/advapi32.inc' + include! 'api/comctl32.inc' + include! 'api/comdlg32.inc' + include! 'api/shell32.inc' + include! 'api/wsock32.inc' + +end macro + +if x86.mode = 16 + format PE GUI 4.0 +end if diff --git a/toolchain/fasm2/include/win32wxp.inc b/toolchain/fasm2/include/win32wxp.inc new file mode 100644 index 0000000..a2ab0f6 --- /dev/null +++ b/toolchain/fasm2/include/win32wxp.inc @@ -0,0 +1,31 @@ + +include 'win32wx.inc' + +include 'pcount/kernel32.inc' +include 'pcount/user32.inc' +include 'pcount/gdi32.inc' +include 'pcount/advapi32.inc' +include 'pcount/comctl32.inc' +include 'pcount/comdlg32.inc' +include 'pcount/shell32.inc' +include 'pcount/wsock32.inc' + +macro pcountcheck? proc*,count* + local pname,pcount + match p, pcountsuffix + match [name], proc + define pcount name#p + else match name, proc + define pcount name#p + end match + end match + if defined pcount & count <> pcount + repeat 1, found:count, expected:pcount + match [name], proc + err 'invalid count of parameters for ',`name,' (',`found,' instead of ',`expected,')' + else + err 'invalid count of parameters for ',`proc,' (',`found,' instead of ',`expected,')' + end match + end repeat + end if +end macro \ No newline at end of file diff --git a/toolchain/fasm2/include/win64a.inc b/toolchain/fasm2/include/win64a.inc new file mode 100644 index 0000000..559d8cc --- /dev/null +++ b/toolchain/fasm2/include/win64a.inc @@ -0,0 +1,35 @@ + +macro api names& + iterate name, names + if used name + label name:qword at name#A + end if + end iterate +end macro + +struc? TCHAR args:?& + . db args +end struc + +macro TCHAR args:?& + db args +end macro + +sizeof.TCHAR = 1 + +include 'macro/struct.inc' +include 'macro/proc64.inc' +include 'macro/com64.inc' +include 'macro/import64.inc' +include 'macro/export.inc' +include 'macro/resource.inc' + +Struct.CheckAlignment = 1 + +include 'equates/kernel64.inc' +include 'equates/user64.inc' +include 'equates/gdi64.inc' +include 'equates/comctl64.inc' +include 'equates/comdlg64.inc' +include 'equates/shell64.inc' +include 'equates/wsock32.inc' diff --git a/toolchain/fasm2/include/win64ax.inc b/toolchain/fasm2/include/win64ax.inc new file mode 100644 index 0000000..4d3c971 --- /dev/null +++ b/toolchain/fasm2/include/win64ax.inc @@ -0,0 +1,67 @@ + +include 'win64a.inc' + +include 'macro/inline.inc' +include 'macro/if.inc' + +define _winx +define _winx.code? _code +define _winx.data? _data +define _winx.end? _end + +calminstruction (name) ? &a& + local cmd + match .cmd, name + jno pass + transform cmd, _winx + jno pass + arrange cmd, cmd a + assemble cmd + exit + pass: + arrange cmd, name a + assemble cmd +end calminstruction + +macro _data + section '.data' data readable writeable +end macro + +macro _code + section '.text' code readable executable + entry $ + sub rsp,8 + if defined _winx.entry & ~ _winx.entry eq $ + jmp _winx.entry + end if +end macro + +macro _end label + + _winx.entry := label + + section '.idata' import data readable writeable + + library kernel32,'KERNEL32.DLL',\ + user32,'USER32.DLL',\ + gdi32,'GDI32.DLL',\ + advapi32,'ADVAPI32.DLL',\ + comctl32,'COMCTL32.DLL',\ + comdlg32,'COMDLG32.DLL',\ + shell32,'SHELL32.DLL',\ + wsock32,'WSOCK32.DLL' + + include! 'api/kernel32.inc' + include! 'api/user32.inc' + include! 'api/gdi32.inc' + include! 'api/advapi32.inc' + include! 'api/comctl32.inc' + include! 'api/comdlg32.inc' + include! 'api/shell32.inc' + include! 'api/wsock32.inc' + +end macro + +if x86.mode = 16 + format PE64 GUI 5.0 +end if diff --git a/toolchain/fasm2/include/win64axp.inc b/toolchain/fasm2/include/win64axp.inc new file mode 100644 index 0000000..49930d4 --- /dev/null +++ b/toolchain/fasm2/include/win64axp.inc @@ -0,0 +1,31 @@ + +include 'win64ax.inc' + +include 'pcount/kernel32.inc' +include 'pcount/user32.inc' +include 'pcount/gdi32.inc' +include 'pcount/advapi32.inc' +include 'pcount/comctl32.inc' +include 'pcount/comdlg32.inc' +include 'pcount/shell32.inc' +include 'pcount/wsock32.inc' + +macro pcountcheck? proc*,count* + local pname,pcount + match p, pcountsuffix + match [name], proc + define pcount name#p + else match name, proc + define pcount name#p + end match + end match + if defined pcount & count <> pcount + repeat 1, found:count, expected:pcount + match [name], proc + err 'invalid count of parameters for ',`name,' (',`found,' instead of ',`expected,')' + else + err 'invalid count of parameters for ',`proc,' (',`found,' instead of ',`expected,')' + end match + end repeat + end if +end macro \ No newline at end of file diff --git a/toolchain/fasm2/include/win64w.inc b/toolchain/fasm2/include/win64w.inc new file mode 100644 index 0000000..c2fd8cc --- /dev/null +++ b/toolchain/fasm2/include/win64w.inc @@ -0,0 +1,35 @@ + +macro api names& + iterate name, names + if used name + label name:qword at name#W + end if + end iterate +end macro + +struc? TCHAR args:?& + . du args +end struc + +macro TCHAR args:?& + du args +end macro + +sizeof.TCHAR = 2 + +include 'macro/struct.inc' +include 'macro/proc64.inc' +include 'macro/com64.inc' +include 'macro/import64.inc' +include 'macro/export.inc' +include 'macro/resource.inc' + +Struct.CheckAlignment = 1 + +include 'equates/kernel64.inc' +include 'equates/user64.inc' +include 'equates/gdi64.inc' +include 'equates/comctl64.inc' +include 'equates/comdlg64.inc' +include 'equates/shell64.inc' +include 'equates/wsock32.inc' diff --git a/toolchain/fasm2/include/win64wx.inc b/toolchain/fasm2/include/win64wx.inc new file mode 100644 index 0000000..138590f --- /dev/null +++ b/toolchain/fasm2/include/win64wx.inc @@ -0,0 +1,67 @@ + +include 'win64w.inc' + +include 'macro/inline.inc' +include 'macro/if.inc' + +define _winx +define _winx.code? _code +define _winx.data? _data +define _winx.end? _end + +calminstruction (name) ? &a& + local cmd + match .cmd, name + jno pass + transform cmd, _winx + jno pass + arrange cmd, cmd a + assemble cmd + exit + pass: + arrange cmd, name a + assemble cmd +end calminstruction + +macro _data + section '.data' data readable writeable +end macro + +macro _code + section '.text' code readable executable + entry $ + sub rsp,8 +; if defined _winx.entry & ~ _winx.entry eq $ + ; jmp _winx.entry + ; end if +end macro + +macro _end label + + _winx.entry := label + + section '.idata' import data readable writeable + + library kernel32,'KERNEL32.DLL',\ + user32,'USER32.DLL',\ + gdi32,'GDI32.DLL',\ + advapi32,'ADVAPI32.DLL',\ + comctl32,'COMCTL32.DLL',\ + comdlg32,'COMDLG32.DLL',\ + shell32,'SHELL32.DLL',\ + wsock32,'WSOCK32.DLL' + + include! 'api/kernel32.inc' + include! 'api/user32.inc' + include! 'api/gdi32.inc' + include! 'api/advapi32.inc' + include! 'api/comctl32.inc' + include! 'api/comdlg32.inc' + include! 'api/shell32.inc' + include! 'api/wsock32.inc' + +end macro + +if x86.mode = 16 + format PE64 GUI 5.0 +end if diff --git a/toolchain/fasm2/include/win64wxp.inc b/toolchain/fasm2/include/win64wxp.inc new file mode 100644 index 0000000..908d82a --- /dev/null +++ b/toolchain/fasm2/include/win64wxp.inc @@ -0,0 +1,31 @@ + +include 'win64wx.inc' + +include 'pcount/kernel32.inc' +include 'pcount/user32.inc' +include 'pcount/gdi32.inc' +include 'pcount/advapi32.inc' +include 'pcount/comctl32.inc' +include 'pcount/comdlg32.inc' +include 'pcount/shell32.inc' +include 'pcount/wsock32.inc' + +macro pcountcheck? proc*,count* + local pname,pcount + match p, pcountsuffix + match [name], proc + define pcount name#p + else match name, proc + define pcount name#p + end match + end match + if defined pcount & count <> pcount + repeat 1, found:count, expected:pcount + match [name], proc + err 'invalid count of parameters for ',`name,' (',`found,' instead of ',`expected,')' + else + err 'invalid count of parameters for ',`proc,' (',`found,' instead of ',`expected,')' + end match + end repeat + end if +end macro \ No newline at end of file diff --git a/toolchain/fasm2/include/x86-2.inc b/toolchain/fasm2/include/x86-2.inc new file mode 100644 index 0000000..6f69150 --- /dev/null +++ b/toolchain/fasm2/include/x86-2.inc @@ -0,0 +1,4168 @@ + +; Advanced x86 Encoder. + +define x86 x86 +define x87 x87 +define MMX MMX +define SSE SSE +define AVX AVX +define AVX_512 AVX_512 +define MPX MPX + +include 'xcalm.inc' + +repeat 3 + calminstruction c#% line& + local buffer, collection + match , line + jyes commit + take collection, line + exit + commit: + take buffer, collection + jyes commit + out: + take line, buffer + jno done + assemble line + jump out + done: + end calminstruction +end repeat + +macro ? line& + local proxy + define proxy line + match name: associations, proxy + c1 calminstruction x86.use.name? + c2 calminstruction x86.require.name? + c3 calminstruction x86.requireexact.name? + iterate association, associations + define proxy association + match item operator value, proxy + if ~ defined x86.item + restore x86.item + x86.item = 0 + define x86.settings item + end if + x86.name.item := value + match ==, operator + c1 compute x86.item, value + c2 check x86.item >= value + c2 jno unsatisfied + c3 check x86.item = value + c3 jno unsatisfied + else match |, operator + c1 compute x86.item, x86.item or 1 shl (value) + c2 check x86.item and 1 shl (value) + c2 jno unsatisfied + c3 check x86.item and 1 shl (value) + c3 jno unsatisfied + else match +, operator + c1 compute x86.item, x86.item or (value) + c2 check x86.item and (value) = value + c2 jno unsatisfied + c3 check x86.item and (value) = value + c3 jno unsatisfied + else + err 'unknown syntax (',`association,')' + end match + else + err 'incomplete expression (',`association,')' + end match + end iterate + c1 + end calminstruction + c2 + exit + unsatisfied: + err string `name + ' or higher required' shl (lengthof `name * 8) + end calminstruction + c3 + exit + unsatisfied: + err string `name + ' required' shl (lengthof `name * 8) + end calminstruction + else + c1 macro x86.settings.store + c2 macro x86.settings.restore + irpv item, x86.settings + c1 x86.item =: x86.item + c2 restore x86.item + end irpv + c1 end macro + c1 + c2 end macro + c2 + line + end match +end macro + + 16: mode = 16 + 32: mode = 32 + 64: mode = 64 + + bits16: mode = 16 + bits32: mode = 32 + bits64: mode = 64 + + 8086: cpu = 0 + 80186: cpu = 1 + 80286: cpu = 2 + 80386: cpu = 3 + 80486: cpu = 4 + P5: cpu = 5 + P6: cpu = 6 + P68: cpu = 7 + x64: cpu = 8 + + 8087: fpu = 1 + 80187: fpu = 2 + 80287: fpu = 3 + 80387: fpu = 4 + + MMX: simd = 5 + SSE: simd = 10 + SSE2: simd = 20 + SSE3: simd = 30 + SSSE3: simd = 31 + SSE4.1: simd = 41 + SSE4.2: simd = 42 + AVX: simd = 50 + AVX2: simd = 51 + AVX512F: simd = 60 + + PCLMULQDQ: ext | 1 + MONITOR: ext | 3 + VMX: ext | 5 + SMX: ext | 6 + FMA: ext | 12 + CMPXCHG16B: ext | 13 + MOVBE: ext | 22 + POPCNT: ext | 23 + AESNI: ext | 25 + XSAVE: ext | 26 + F16C: ext | 29 + RDRAND: ext | 30 + FSGSBASE: ext | 32 + 0 + BMI1: ext | 32 + 3 + HLE: ext | 32 + 4 + BMI2: ext | 32 + 8 + RTM: ext | 32 + 11 + MPX: ext | 32 + 14 + AVX512DQ: ext | 32 + 17 + RDSEED: ext | 32 + 18 + ADX: ext | 32 + 19 + AVX512_IFMA: ext | 32 + 21 + AVX512PF: ext | 32 + 26 + AVX512ER: ext | 32 + 27 + AVX512CD: ext | 32 + 28 + AVX512BW: ext | 32 + 30 + AVX512VL: ext | 32 + 31 + AVX512_VBMI: ext | 64 + 1 + AVX512_VBMI2: ext | 64 + 6 + CET_SS: ext | 64 + 7 + GFNI: ext | 64 + 8 + VAES: ext | 64 + 9 + VPCLMULQDQ: ext | 64 + 10 + AVX512_VNNI: ext | 64 + 11 + AVX512_BITALG: ext | 64 + 12 + AVX512_VPOPCNTDQ: ext | 64 + 14 + MOVDIRI: ext | 64 + 27 + MOVDIR64B: ext | 64 + 28 + AVX512_4VNNIW: ext | 96 + 2 + CET_IBT: ext | 96 + 20 + + 3DNow: ext | 128 + 31 + + ; Some CPU presets: + + i8086: cpu = 0, fpu = 0, simd = 0, ext = 0 + i186: cpu = 1, fpu = 0, simd = 0, ext = 0 + i286: cpu = 2, fpu = 0, simd = 0, ext = 0 + i386: cpu = 3, fpu = 0, simd = 0, ext = 0 + i486: cpu = 4, fpu = 0, simd = 0, ext = 0 + Pentium: cpu = 5, fpu = 5, simd = 0, ext = 0 + PentiumPro: cpu = 6, fpu = 5, simd = 0, ext = 0 + PentiumMMX: cpu = 5, fpu = 5, simd = 5, ext = 0 + Pentium2: cpu = 6, fpu = 5, simd = 5, ext = 0 + Pentium3: cpu = 6, fpu = 5, simd = 10, ext = 0 + Pentium4: cpu = 7, fpu = 5, simd = 30, ext = 0 + AMD64: cpu = 8, fpu = 5, simd = 20, ext = x86.3DNow.ext + + SSE4: simd = x86.SSE4.2.simd, ext + x86.POPCNT.ext + AVX512: simd = x86.AVX512F.simd, ext + x86.AVX512VL.ext + x86.AVX512BW.ext + x86.AVX512DQ.ext + x86.AVX512CD.ext + x86.AVX512_IFMA.ext + x86.AVX512_VBMI.ext + + everything: cpu = 8, fpu = 5, simd = 60, ext = -1 + + ; Following settings are just hints of a preference, instruction encoder may listen to them + ; when it is possible without altering the meaning of the instruction. + + immauto: immsize = 0 + imm8: immsize = 1 + imm16: immsize = 2 + imm32: immsize = 4 + imm64: immsize = 8 + + ; Following settings select the position of r/m operand for few instructions that + ; can be encoded either way, and are ignored otherwise. + + rmauto: rmposition = 0 + rm1: rmposition = 1 + rmdst: rmposition = 1 + rm2: rmposition = 2 + rmsrc: rmposition = 2 + + ; Enable or disable automatic RIP-relative addressing in long mode. + + ripauto: userip = 0 + rip: userip = 1 + norip: userip = -1 + absolute: userip = -1 + +purge ?, c1, c2, c3 + +; To select a group of settings: +; use i386 + +; To require a group of settings (with optional "+"): +; require i386+ + +; To check a single setting: +; if x86.simd >= x86.PentiumMMX.simd + +macro require? name* + match min+, name + x86.require.min + else + x86.requireexact.name + end match +end macro + +macro use? names*& + iterate name, names + x86.use.name + end iterate +end macro + +calminstruction ?? &line& + local settings, instruction + match {settings} instruction, line + jyes annotated + assemble line + exit + annotated: + asm x86.settings.store + arrange settings, =use settings + assemble settings + assemble instruction + asm x86.settings.restore +end calminstruction + +element x86.reg +element x86.r8 : x86.reg + 1 +element x86.r16 : x86.reg + 2 +element x86.r32 : x86.reg + 4 +element x86.r64 : x86.reg + 8 + +element al? : x86.r8 + 0 +element cl? : x86.r8 + 1 +element dl? : x86.r8 + 2 +element bl? : x86.r8 + 3 + +element spl? : x86.r8 + 4 +element bpl? : x86.r8 + 5 +element sil? : x86.r8 + 6 +element dil? : x86.r8 + 7 + +element ah? : x86.r8 - 4 +element ch? : x86.r8 - 5 +element dh? : x86.r8 - 6 +element bh? : x86.r8 - 7 + +repeat 8, i:8 + element r#i#b? : x86.r8 + i + element r#i#l? : x86.r8 + i +end repeat + +element ax? : x86.r16 + 0 +element cx? : x86.r16 + 1 +element dx? : x86.r16 + 2 +element bx? : x86.r16 + 3 +element sp? : x86.r16 + 4 +element bp? : x86.r16 + 5 +element si? : x86.r16 + 6 +element di? : x86.r16 + 7 + +repeat 8, i:8 + element r#i#w? : x86.r16 + i +end repeat + +element eax? : x86.r32 + 0 +element ecx? : x86.r32 + 1 +element edx? : x86.r32 + 2 +element ebx? : x86.r32 + 3 +element esp? : x86.r32 + 4 +element ebp? : x86.r32 + 5 +element esi? : x86.r32 + 6 +element edi? : x86.r32 + 7 + +repeat 8, i:8 + element r#i#d? : x86.r32 + i +end repeat + +element rax? : x86.r64 + 0 +element rcx? : x86.r64 + 1 +element rdx? : x86.r64 + 2 +element rbx? : x86.r64 + 3 +element rsp? : x86.r64 + 4 +element rbp? : x86.r64 + 5 +element rsi? : x86.r64 + 6 +element rdi? : x86.r64 + 7 + +repeat 8, i:8 + element r#i? : x86.r64 + i +end repeat + +element x86.ip + +element eip? : x86.ip + 4 +element rip? : x86.ip + 8 + +element x86.sreg + +element es? : x86.sreg + 0 +element cs? : x86.sreg + 1 +element ss? : x86.sreg + 2 +element ds? : x86.sreg + 3 +element fs? : x86.sreg + 4 +element gs? : x86.sreg + 5 + +element x86.creg + +element x86.crx : x86.creg + 0 +element x86.drx : x86.creg + 1 + +repeat 16, i:0 + element cr#i? : x86.crx + i + element dr#i? : x86.drx + i +end repeat + +define x86.byte? :1 +define x86.word? :2 +define x86.dword? :4 +define x86.pword? :6 +define x86.fword? :6 +define x86.qword? :8 +define x86.tword? :10 +define x86.tbyte? :10 +define x86.dqword? :16 +define x86.xword? :16 +define x86.qqword? :32 +define x86.yword? :32 +define x86.dqqword? :64 +define x86.zword? :64 + +x86.REX_REQUIRED = 100h +x86.REX_FORBIDDEN = 200h + +macro use16? + use bits16 +end macro + +macro use32? + use bits32 +end macro + +macro use64? + use bits64 +end macro + +macro useavx256? + use avx2 +end macro + +macro useavx512? + use avx512f +end macro + +use16 + + +define @dest @dest +define @src @src +define @src2 @src2 +define @aux @aux + +iterate context, @dest,@src,@src2,@aux + + namespace context + + iterate name, size, type, segment_prefix, prefix, opcode_prefix, rex_prefix, \ + imm, unresolved, displacement, displacement_size, auto_relative, \ + address, address_registers, segment, offset, jump_type, \ + mode, mod, rm, \ + scale, index, base + define name + end iterate + + calminstruction x86.parse_operand#context operand + + local i, pre, suf, sym + + compute segment_prefix, 0 + compute prefix, 0 + compute opcode_prefix, 0 + compute rex_prefix, 0 + + compute size, 0 + compute displacement_size, 0 + + transform operand + + match pre suf, operand + jno no_size_prefix + transform pre, x86 + jno no_size_prefix + match :size, pre + jno no_size_prefix + arrange operand, suf + no_size_prefix: + + match [address], operand + jyes memory_operand + match =ptr? address, operand + jyes memory_operand + match segment:offset, operand + jyes far_operand + + immediate_operand: + compute type, 'imm' + compute imm, +operand + + compute unresolved, 0 + check defined operand + jyes operand_resolved + compute unresolved, 1 + operand_resolved: + + check imm eq 1 elementof imm + jno operand_ready + check 1 metadataof (1 metadataof imm) relativeto x86.reg + jyes register_operand + check 1 metadataof imm relativeto x86.sreg + jyes segment_register_operand + + operand_ready: + exit + + register_operand: + + compute type, 'reg' + compute mode, x86.mode + compute mod, 11b + compute rm, 1 metadataof imm - 1 elementof (1 metadataof imm) + check size & size <> 1 metadataof (1 metadataof imm) - x86.reg + jyes operand_sizes_do_not_match + compute size, 1 metadataof (1 metadataof imm) - x86.reg + check rm < 0 + jyes register_precluding_rex + check size = 1 & rm >= 4 & rm < 8 + jyes register_requiring_rex + + exit + + register_precluding_rex: + compute rm, x86.REX_FORBIDDEN - rm + exit + + register_requiring_rex: + compute rm, x86.REX_REQUIRED + rm + exit + + segment_register_operand: + + compute type, 'sreg' + compute mode, x86.mode + compute mod, 11b + compute rm, 1 metadataof imm - x86.sreg + check size & size <> 2 & size <> 4 + jyes invalid_operand_size + check rm >= 4 + jno operand_ready + call x86.require.80386 + + exit + + memory_operand: + compute type, 'mem' + + match segment:address, address + jno segment_prefix_ok + check segment eq 1 elementof segment & 1 metadataof segment relativeto x86.sreg + jno invalid_operand + compute segment, 1 metadataof segment - x86.sreg + check segment >= 4 + jyes segment_prefix_386 + compute segment_prefix, 26h + segment shl 3 + jump segment_prefix_ok + segment_prefix_386: + call x86.require.80386 + compute segment_prefix, 64h + segment-4 + segment_prefix_ok: + + compute mode, 0 + + match pre suf, address + jno no_address_size_prefix + transform pre, x86 + jno no_address_size_prefix + match :pre, pre + jno no_address_size_prefix + arrange address, suf + check pre = 2 | pre = 4 | pre = 8 + jno invalid_address_size + compute mode, pre shl 3 + no_address_size_prefix: + + compute scale, 0 + compute index, 0 + compute base, 0 + + check size + jyes size_override + compute size, sizeof address + size_override: + + compute address, address + compute address_registers, 0 + compute i, 1 + extract_registers: + check i > elementsof address + jyes registers_extracted + check i metadataof address relativeto x86.r16 | i metadataof address relativeto x86.r32 | i metadataof address relativeto x86.r64 | i metadataof address relativeto x86.ip + jno next_term + compute address_registers, address_registers + i elementof address * i scaleof address + next_term: + compute i, i+1 + jump extract_registers + registers_extracted: + compute displacement, address - address_registers + compute auto_relative, 0 + + check address_registers eq 0 + jyes direct_address + check mode & mode <> 0 scaleof (1 metadataof (1 metadataof address_registers)) shl 3 & ~ 1 metadataof address_registers relativeto x86.ip + jyes invalid_address + check 1 metadataof address_registers relativeto x86.r64 | 1 metadataof address_registers relativeto x86.r32 + jyes address_32bit_64bit + check 1 metadataof address_registers relativeto x86.r16 + jyes address_16bit + check address_registers eq rip | address_registers eq eip + jyes rip_relative_address + jump invalid_address + + rip_relative_address: + compute mode, 0 scaleof (1 metadataof address_registers) shl 3 + compute mod, 0 + compute rm, 5 + compute displacement_size, 4 + exit + + direct_address: + compute mod, 0 + check x86.mode = 64 + jyes direct_address_in_long_mode + check mode = 0 + jno mode_ok + compute mode, x86.mode + check mode = 16 & displacement relativeto 0 & displacement >= 10000h + jno mode_ok + compute mode, 32 + mode_ok: + check mode = 16 + jyes direct_address_16bit + direct_address_32bit: + compute rm, 5 + compute displacement_size, 4 + exit + direct_address_16bit: + compute rm, 6 + compute displacement_size, 2 + exit + + direct_address_in_long_mode: + compute displacement_size, 4 + check (x86.userip = 0 & mode = 0 & segment_prefix < 64h) | x86.userip = 1 + jyes auto_relative_address + check mode = 16 + jyes invalid_address_size + compute rm, 4 + compute base, 5 + compute index, 4 + compute scale, 1 + check mode = 32 + jno direct_address_displacement_ready + check ~ displacement relativeto 0 | displacement >= 100000000h | displacement < -100000000h + jyes address_out_of_range + compute displacement, displacement and 0FFFFFFFFh + direct_address_displacement_ready: + check displacement relativeto 0 & displacement > 7FFFFFFFh & displacement < 100000000h + jyes direct_address_switch_to_32bit + compute mode, 64 + compute displacement_size, 8 + exit + direct_address_switch_to_32bit: + compute mode, 32 + exit + + auto_relative_address: + compute mode, 64 + compute rm, 5 + compute auto_relative, 1 + exit + + address_16bit: + compute mode, 16 + + check address_registers relativeto bx+si + jyes rm_0 + check address_registers relativeto bx+di + jyes rm_1 + check address_registers relativeto bp+si + jyes rm_2 + check address_registers relativeto bp+di + jyes rm_3 + check address_registers relativeto si + jyes rm_4 + check address_registers relativeto di + jyes rm_5 + check address_registers relativeto bp + jyes rm_6 + check address_registers relativeto bx + jyes rm_7 + jump invalid_address + + rm_0: + compute rm, 0 + jump rm_ok + rm_1: + compute rm, 1 + jump rm_ok + rm_2: + compute rm, 2 + jump rm_ok + rm_3: + compute rm, 3 + jump rm_ok + rm_4: + compute rm, 4 + jump rm_ok + rm_5: + compute rm, 5 + jump rm_ok + rm_6: + compute rm, 6 + jump rm_ok + rm_7: + compute rm, 7 + rm_ok: + + check displacement relativeto 0 + jno displacement_16bit + check displacement = 0 & rm <> 6 + jyes displacement_empty + check displacement<80h & displacement>=-80h + jyes displacement_8bit + check displacement-10000h>=-80h & displacement<10000h + jyes displacement_8bit_wrap_16bit + displacement_16bit: + compute displacement_size, 2 + compute mod, 2 + exit + displacement_empty: + compute displacement_size, 0 + compute mod, 0 + exit + displacement_8bit_wrap_16bit: + compute displacement, displacement-10000h + displacement_8bit: + compute displacement_size, 1 + compute mod, 1 + exit + + address_32bit_64bit: + + local address_registers_type + check 1 metadataof address_registers relativeto x86.r64 + jyes address_64bit + address_32bit: + compute mode, 32 + compute address_registers_type, x86.r32 + jump check_address_registers + address_64bit: + compute mode, 64 + compute address_registers_type, x86.r64 + check_address_registers: + check 2 scaleof address_registers = 0 + jyes one_register + check 3 scaleof address_registers = 0 & 2 metadataof address_registers relativeto address_registers_type + jyes two_registers + jump invalid_address + + one_register: + compute scale, 1 scaleof address_registers + compute base, 1 metadataof address_registers - address_registers_type + check scale = 1 + jyes one_register_unscaled + check base <> 4 & (scale = 4 | scale = 8) + jyes one_register_scaled + check base <> 4 & (scale = 2 | scale = 3 | scale = 5 | scale = 9) + jyes one_register_split + jump invalid_address + one_register_unscaled: + check base and 111b = 4 + jyes one_register_unscaled_in_sib + compute rm, base + jump setup_displacement + one_register_unscaled_in_sib: + compute rm, 4 + compute index, 4 + jump setup_displacement + one_register_scaled: + compute rm, 4 + compute index, base + compute base, 5 + jump index_only + one_register_split: + compute rm, 4 + compute index, base + compute scale, scale - 1 + jump setup_displacement + two_registers: + compute rm,4 + check 1 scaleof address_registers = 1 + jyes base_first + check 2 scaleof address_registers = 1 + jyes base_second + jump invalid_address + base_first: + compute base, 1 metadataof address_registers - address_registers_type + compute index, 2 metadataof address_registers - address_registers_type + compute scale, 2 scaleof address_registers + jump process_sib + base_second: + compute base, 2 metadataof address_registers - address_registers_type + compute index, 1 metadataof address_registers - address_registers_type + compute scale, 1 scaleof address_registers + process_sib: + check index = 4 + jyes forbidden_index + check (x86.mode <> 64 & segment_prefix = 36h) & index = 5 & scale = 1 + jyes switch_to_index + check (x86.mode = 64 | segment_prefix = 3Eh) & base = 5 & scale = 1 + jyes switch_to_base + check scale and (scale-1) | scale > 8 + jyes invalid_address + jump setup_displacement + forbidden_index: + check scale = 1 + jno invalid_address + compute index, base + compute base, 4 + jump setup_displacement + switch_to_index: + compute index, base + compute base,5 + jump setup_displacement + switch_to_base: + compute base, index + compute index, 5 + jump setup_displacement + + setup_displacement: + check displacement relativeto 0 + jno displacement_32bit + check displacement = 0 & rm and 111b <> 5 & (rm <> 4 | base and 111b <> 5) + jyes displacement_empty + check displacement < 80h & displacement >= -80h + jyes displacement_8bit + check displacement - 1 shl mode >= -80h & displacement < 1 shl mode + jyes displacement_8bit_wrap + check (x86.mode = 64 | segment_prefix = 3Eh) & base = 5 & index = 5 & scale = 1 + jno displacement_32bit + compute scale, 2 + jump index_only + displacement_32bit: + compute displacement_size, 4 + compute mod, 2 + exit + displacement_8bit_wrap: + compute displacement, displacement - 1 shl mode + jump displacement_8bit + index_only: + compute displacement_size, 4 + compute mod, 0 + exit + + far_operand: + compute type, 'far' + + check size & size <> 4 & size <> 6 & size <> 10 + jyes operand_sizes_do_not_match + + exit + + invalid_operand: + err 'invalid operand' + exit + invalid_operand_size: + err 'invalid operand size' + exit + operand_sizes_do_not_match: + err 'operand sizes do not match' + exit + invalid_address: + err 'invalid address' + exit + invalid_address_size: + err 'invalid address size' + exit + address_out_of_range: + err 'address out of range' + exit + + end calminstruction + + calminstruction x86.parse_jump_operand#context operand + + match =far? operand, operand + jyes far_jump + match =near? operand, operand + jyes near_jump + match =short? operand, operand + jyes short_jump + compute jump_type, '' + jump parse_operand + far_jump: + compute jump_type, 'far' + jump parse_operand + near_jump: + compute jump_type, 'near' + jump parse_operand + short_jump: + compute jump_type, 'short' + + parse_operand: + + call x86.parse_operand#context, operand + + check type = 'imm' + jno done + + check size = 0 + jno verify_target_address + + compute size, x86.mode shr 3 + + verify_target_address: + + check imm relativeto 0 + jno done + check imm < 0 + jyes negative + check imm >= 1 shl (size*8) + jno done + out_of_range: + err 'value out of range' + exit + negative: + check imm < - 1 shl (size*8-1) + jyes out_of_range + compute imm, imm and (1 shl (size*8) - 1) + + done: + + end calminstruction + + calminstruction x86.select_operand_prefix#context size* + + check size = 8 & x86.cpu < x86.x64.cpu + jyes required64 + check size = 4 & x86.cpu < x86.80386.cpu + jyes required32 + + check (size = 2 & x86.mode <> 16) | (size = 4 & x86.mode = 16) + jyes prefix_66h + check size = 8 + jyes prefix_48h + check size <> 0 & size <> 2 & size <> 4 + jyes invalid_size + exit + + prefix_66h: + compute prefix, 66h + exit + + prefix_48h: + compute prefix, 48h + exit + + invalid_size: + err 'invalid operand size' + exit + required64: + err 'instruction requires 64-bit processor' + exit + required32: + err 'instruction requires 32-bit processor' + exit + + end calminstruction + + calminstruction x86.store_instruction#context opcode*,reg*,imm_size:0,immediate + + check segment_prefix + jno segment_prefix_ok + + check mode = 64 + jyes segment_in_long_mode + check mode = 16 & ( rm = 2 | rm = 3 | ( mod > 0 & rm = 6 ) ) + jyes ss_segment_default + check mode = 32 & ( ( mod > 0 & rm = 5 ) | ( rm = 4 & base = 4 ) | ( mod > 0 & rm = 4 & base = 5 ) ) + jyes ss_segment_default + + ds_segment_default: + check segment_prefix = 3Eh + jyes segment_prefix_ok + jump store_segment_prefix + ss_segment_default: + check segment_prefix = 36h + jyes segment_prefix_ok + jump store_segment_prefix + segment_in_long_mode: + check segment_prefix < 64h + jyes segment_prefix_ok + store_segment_prefix: + emit 1, segment_prefix + segment_prefix_ok: + + check mod <> 11b & mode <> x86.mode + jno addressing_prefix_ok + check mode = 64 | (mode = 16 & x86.mode = 64) + jno store_addressing_prefix + err 'illegal addressing mode' + store_addressing_prefix: + emit 1, 67h + addressing_prefix_ok: + + check (reg or rm) and x86.REX_REQUIRED + jno rex_1 + compute rex_prefix, rex_prefix or 40h + rex_1: + check rm and 1000b | (mod <> 11b & mode > 16 & rm = 4 & base and 1000b) + jno rex_2 + compute rex_prefix, rex_prefix or 41h + rex_2: + check mod <> 11b & mode > 16 & rm = 4 & index and 1000b + jno rex_4 + compute rex_prefix, rex_prefix or 42h + rex_4: + check reg and 1000b + jno rex_8 + compute rex_prefix, rex_prefix or 44h + rex_8: + check prefix = 48h + jno operand_prefix + compute rex_prefix, rex_prefix or 48h + jump operand_prefix_ok + + operand_prefix: + check prefix + jno operand_prefix_ok + emit 1, prefix + operand_prefix_ok: + + check opcode_prefix + jno opcode_prefix_ok + emit 1, opcode_prefix + opcode_prefix_ok: + + check rex_prefix + jno rex_prefix_ok + check x86.mode < 64 + jyes instruction_requires_long_mode + check reg and x86.REX_FORBIDDEN + jno store_rex_prefix + err 'disallowed combination of registers' + jump store_rex_prefix + instruction_requires_long_mode: + call x86.require.bits64 + store_rex_prefix: + emit 1, rex_prefix + rex_prefix_ok: + + asm db opcode + emit 1, mod shl 6 + (reg and 111b) shl 3 + rm and 111b + + check mod <> 11b & rm = 4 & mode <> 16 + jno sib_ok + emit 1, (bsf scale) shl 6 + (index and 111b) shl 3 + base and 111b + sib_ok: + + check displacement_size = 1 + jyes displacement_8bit + check displacement_size = 2 + jyes displacement_16bit + check displacement_size = 4 | displacement_size = 8 + jno displacement_ok + + compute displacement, displacement + + check auto_relative + jno auto_relative_ok + check imm_size < 8 + jyes adjust_auto_relative_displacement + compute displacement, displacement - ($ + 4 + 4) + jump auto_relative_ok + adjust_auto_relative_displacement: + compute displacement, displacement - ($ + 4 + imm_size) + auto_relative_ok: + + check mode = 64 & displacement relativeto 0 + jno displacement_ready + check displacement - 1 shl 64 >= -80000000h & displacement < 1 shl 64 + jyes adjust_displacement_wrap + check displacement >= -80000000h & displacement < 80000000h + jyes displacement_ready + err 'address value out of signed range' + adjust_displacement_wrap: + compute displacement, displacement - 1 shl 64 + displacement_ready: + + call dword, displacement + + jump displacement_ok + displacement_16bit: + call word, displacement + jump displacement_ok + displacement_8bit: + emit 1, displacement + displacement_ok: + + check imm_size = 1 + jyes immediate_8bit + check imm_size = 2 + jyes immediate_16bit + check imm_size = 4 + jyes immediate_32bit + check imm_size = 8 + jno immediate_ok + call x86.simm32, immediate + jump immediate_ok + immediate_32bit: + compute imm, +immediate + call dword, imm + jump immediate_ok + immediate_16bit: + compute imm, +immediate + call word, imm + jump immediate_ok + immediate_8bit: + compute imm, +immediate + emit 1, imm + immediate_ok: + + end calminstruction + + end namespace + +end iterate + +calminstruction x86.store_operand_prefix size*, reg:0 + + check size = 8 & x86.cpu < x86.x64.cpu + jyes required64 + check size = 4 & x86.cpu < x86.80386.cpu + jyes required32 + + local rex_prefix + compute rex_prefix, 0 + + check (size = 2 & x86.mode <> 16) | (size = 4 & x86.mode = 16) + jyes prefix_66h + check size = 8 + jyes rex_8 + check size <> 0 & size <> 2 & size <> 4 + jno check_register + err 'invalid operand size' + jump check_register + + required64: + err 'instruction requires 64-bit processor' + exit + required32: + err 'instruction requires 32-bit processor' + exit + + prefix_66h: + emit 1, 66h + jump check_register + + rex_8: + compute rex_prefix, 48h + + check_register: + check reg and 1000b + jyes rex_1 + check reg and x86.REX_REQUIRED + jno rex_ready + compute rex_prefix, rex_prefix or 40h + jump rex_ready + rex_1: + compute rex_prefix, rex_prefix or 41h + + rex_ready: + check rex_prefix + jno rex_prefix_ok + check x86.mode < 64 + jyes instruction_requires_long_mode + check reg and x86.REX_FORBIDDEN + jno store_rex_prefix + err 'disallowed combination of registers' + jump store_rex_prefix + instruction_requires_long_mode: + call x86.require.bits64 + store_rex_prefix: + emit 1, rex_prefix + rex_prefix_ok: + +end calminstruction + +calminstruction x86.simm32 immediate* + compute immediate, +immediate + check immediate eqtype 0.0 + jno check_value + asm virtual at 0 + asm emit 8: immediate + asm load immediate:8 from 0 + asm end virtual + compute immediate, +immediate + check_value: + check immediate relativeto 0 + jyes check_range + call dword, immediate + exit + check_range: + check immediate - 1 shl 64 >= -80000000h & immediate < 1 shl 64 + jyes wrap + check immediate >= 80000000h | immediate < -80000000h + jyes out_of_range + emit 4, immediate + exit + wrap: + emit 4, immediate - 1 shl 64 + exit + out_of_range: + err 'immediate value out of signed range' +end calminstruction + + +iterate , add,0, or,8, adc,10h, sbb,18h, and,20h, sub,28h, xor,30h, cmp,38h + + calminstruction instr? dest*,src* + + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + + local opcode, rm, size + + compute opcode, basecode + + check @dest.size = 0 & @src.size = 0 + jyes operand_size_not_specified + check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size + jyes operand_sizes_do_not_match + + compute size, @dest.size or @src.size + + main: + + check @src.type = 'reg' & ( (@dest.type = 'reg' & x86.rmposition <> x86.rmsrc.rmposition) | @dest.type = 'mem' ) + jyes reg_rm + check (@src.type = 'mem' | @src.type = 'reg' ) & @dest.type = 'reg' + jyes rm_reg + check @src.type = 'imm' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes rm_imm + + err 'invalid combination of operands' + exit + + operand_size_not_specified: + err 'operand size not specified' + compute size, 0 + jump main + + operand_sizes_do_not_match: + err 'operand sizes do not match' + compute size, 0 + jump main + + reg_rm: + check size > 1 + jno reg_rm_store + call x86.select_operand_prefix@dest, size + compute opcode, opcode + 1 + reg_rm_store: + call x86.store_instruction@dest, opcode,@src.rm + exit + + rm_reg: + compute opcode, opcode + 2 + check size > 1 + jno rm_reg_store + call x86.select_operand_prefix@src, size + compute opcode, opcode + 1 + rm_reg_store: + call x86.store_instruction@src, opcode,@dest.rm + exit + + rm_imm: + check size > 1 + jyes rm_imm_word + check @dest.type = 'reg' & @dest.rm = 0 + jyes al_imm + + compute opcode, opcode shr 3 + xcall x86.store_instruction@dest, (80h),opcode,byte,@src.imm + exit + + al_imm: + emit 1, opcode+4 + emit 1, @src.imm + exit + + rm_imm_word: + + call x86.select_operand_prefix@dest, size + + check @src.imm eqtype 0.0 + jno rm_imm_optimize + + asm virtual at 0 + asm emit size: @src.imm + asm load @src.imm:size from 0 + asm end virtual + compute @src.imm, +@src.imm + + rm_imm_optimize: + check x86.immsize < 2 & @src.imm relativeto 0 & @src.imm < 80h & @src.imm >= -80h + jyes rm_simm + check x86.immsize < 2 & @src.imm relativeto 0 & @src.imm - 1 shl (size shl 3) >= -80h & @src.imm < 1 shl (size shl 3) + jyes rm_simm_wrap + check @dest.type = 'reg' & @dest.rm = 0 + jyes ax_imm + compute rm, opcode shr 3 + xcall x86.store_instruction@dest, (81h),rm,size,@src.imm + exit + + ax_imm: + check @dest.prefix + jno ax_imm_prefix_ok + emit 1, @dest.prefix + ax_imm_prefix_ok: + emit 1, opcode+5 + check size = 4 + jyes imm32 + check size = 8 + jyes simm32 + asm emit size: @src.imm + exit + imm32: + call dword, @src.imm + exit + simm32: + call x86.simm32, @src.imm + exit + + rm_simm_wrap: + compute @src.imm, @src.imm - 1 shl (size shl 3) + + rm_simm: + compute rm, opcode shr 3 + xcall x86.store_instruction@dest, (83h),rm,byte,@src.imm + + end calminstruction + +end iterate + +iterate , not,2, neg,3, mul,4, div,6, idiv,7 + + calminstruction instr? src* + + call x86.parse_operand@src, src + + check @src.size = 0 + jyes operand_size_not_specified + + main: + check @src.type = 'mem' | @src.type = 'reg' + jno invalid_operand + check @src.size > 1 + jyes rm_word + + xcall x86.store_instruction@src, (0F6h),(postbyte) + exit + + rm_word: + call x86.select_operand_prefix@src, @src.size + xcall x86.store_instruction@src, (0F7h),(postbyte) + exit + + operand_size_not_specified: + err 'operand size not specified' + jump main + + invalid_operand: + err 'invalid operand' + exit + + end calminstruction + +end iterate + +calminstruction mov? dest*,src* + + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + + local ext, rm, size + + check @dest.size = 0 & @src.size = 0 & @dest.type <> 'sreg' + jyes operand_size_not_specified + check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size + jyes operand_sizes_do_not_match + + compute size, @dest.size or @src.size + + main: + check @src.type = 'reg' & ( (@dest.type = 'reg' & x86.rmposition <> x86.rmsrc.rmposition) | @dest.type = 'mem' ) + jyes mov_rm_reg + check (@src.type = 'mem' | @src.type = 'reg') & @dest.type = 'reg' + jyes mov_reg_mem + check @src.type = 'imm' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes mov_rm_imm + check @src.type = 'reg' & @dest.type = 'imm' + jyes mov_creg_reg + check @src.type = 'sreg' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes mov_rm_sreg + check @dest.type = 'sreg' & @dest.rm <> 1 & ( @src.type = 'reg' | @src.type = 'mem' ) + jyes mov_sreg_rm + + invalid_combination_of_operands: + err 'invalid combination of operands' + exit + + operand_size_not_specified: + err 'operand size not specified' + compute size, 0 + jump main + + operand_sizes_do_not_match: + err 'operand sizes do not match' + compute size, 0 + jump main + + mov_rm_reg: + check @src.type = 'reg' & @dest.type = 'mem' & @src.rm = 0 & @dest.address_registers eq 0 & \ + ~ @dest.auto_relative & ( @dest.displacement_size <> 8 | ~ @dest.displacement relativeto 0 | @dest.displacement and 0FFFFFFFF80000000h <> 0FFFFFFFF80000000h) + jyes mov_dirmem_ax + check size > 1 + jno mov_reg_rm_8bit + call x86.select_operand_prefix@dest, size + xcall x86.store_instruction@dest, (89h),@src.rm + exit + mov_reg_rm_8bit: + xcall x86.store_instruction@dest, (88h),@src.rm + exit + + mov_reg_mem: + check @src.type = 'mem' & @dest.type = 'reg' & @dest.rm = 0 & @src.address_registers eq 0 & \ + ~ @src.auto_relative & ( @src.displacement_size <> 8 | ~ @src.displacement relativeto 0 | @src.displacement and 0FFFFFFFF80000000h <> 0FFFFFFFF80000000h) + jyes mov_ax_dirmem + check size > 1 + jno mov_mem_reg_8bit + call x86.select_operand_prefix@src, size + xcall x86.store_instruction@src, (8Bh),@dest.rm + exit + mov_mem_reg_8bit: + xcall x86.store_instruction@src, (8Ah),@dest.rm + exit + + mov_dirmem_ax: + check x86.mode = 64 + jyes mov_dirmem_ax_longmode + check @dest.segment_prefix = 0 | @dest.segment_prefix = 3Eh + jyes dest_seg_ok + emit 1, @dest.segment_prefix + dest_seg_ok: + check @dest.mode = x86.mode + jyes dest_addr_size_ok + emit 1, 67h + dest_addr_size_ok: + check size > 1 + jno mov_dirmem_al + call x86.store_operand_prefix, size + emit 1, 0A3h + jump dest_displacement + mov_dirmem_al: + emit 1, 0A2h + dest_displacement: + check @dest.mode = 16 + jyes dest_displacement_16bit + check @dest.displacement_size = 8 + jyes dest_displacement_64bit + call dword, @dest.address + exit + dest_displacement_16bit: + call word, @dest.address + exit + dest_displacement_64bit: + call qword, @dest.address + exit + mov_dirmem_ax_longmode: + check @dest.displacement_size = 8 & @dest.displacement relativeto 0 & @dest.displacement >= 0 & @dest.displacement < 100000000h + jno dest_displacement_size_ok + compute @dest.displacement_size, 4 + dest_displacement_size_ok: + check @dest.segment_prefix & @dest.segment_prefix >= 64h + jno dest_longmode_seg_ok + emit 1, @dest.segment_prefix + dest_longmode_seg_ok: + check @dest.mode = 16 + jyes illegal_addressing_mode + check @dest.displacement_size = 8 + jyes dest_addr_size_ok + emit 1, 67h + jump dest_addr_size_ok + + mov_ax_dirmem: + check x86.mode = 64 + jyes mov_ax_dirmem_longmode + check @src.segment_prefix = 0 | @src.segment_prefix = 3Eh + jyes src_seg_ok + emit 1, @src.segment_prefix + src_seg_ok: + check @src.mode = x86.mode + jyes src_addr_size_ok + emit 1, 67h + src_addr_size_ok: + check size > 1 + jno mov_al_dirmem + call x86.store_operand_prefix, size + emit 1, 0A1h + jump src_displacement + mov_al_dirmem: + emit 1, 0A0h + src_displacement: + check @src.mode = 16 + jyes src_displacement_16bit + check @src.displacement_size = 8 + jyes src_displacement_64bit + call dword, @src.address + exit + src_displacement_16bit: + call word, @src.address + exit + src_displacement_64bit: + call qword, @src.address + exit + mov_ax_dirmem_longmode: + check @src.displacement_size = 8 & @src.displacement relativeto 0 & @src.displacement >= 0 & @src.displacement < 100000000h + jno src_displacement_size_ok + compute @src.displacement_size, 4 + src_displacement_size_ok: + check @src.segment_prefix & @src.segment_prefix >= 64h + jno src_longmode_seg_ok + emit 1, @src.segment_prefix + src_longmode_seg_ok: + check @src.mode = 16 + jyes illegal_addressing_mode + check @src.displacement_size = 8 + jyes src_addr_size_ok + emit 1, 67h + jump src_addr_size_ok + + mov_rm_imm: + check @dest.type = 'mem' + jyes mov_mem_imm + check @dest.type = 'reg' & 1 metadataof (1 metadataof @src.imm) relativeto x86.creg & @src.imm relativeto 1 elementof @src.imm + jyes mov_reg_creg + + mov_reg_imm: + check size > 1 + jno mov_reg_imm_8bit + check @src.imm eqtype 0.0 + jno mov_reg_imm_optimize + asm virtual at 0 + asm emit size: @src.imm + asm load @src.imm:size from 0 + asm end virtual + compute @src.imm, +@src.imm + mov_reg_imm_optimize: + check size = 8 & @src.imm relativeto 0 & @src.imm < 80000000h & @src.imm >= -80000000h & x86.immsize < 8 + jyes mov_reg_simm + check size = 8 & @src.imm relativeto 0 & @src.imm - 1 shl 64 < 80000000h & @src.imm - 1 shl 64 >= -80000000h & x86.immsize < 8 + jyes mov_reg_simm_wrap + call x86.store_operand_prefix, size,@dest.rm + emit 1, 0B8h + @dest.rm and 111b + check size = 2 + jyes src_imm_16bit + check size = 4 + jyes src_imm_32bit + call qword, @src.imm + exit + src_imm_32bit: + call dword, @src.imm + exit + src_imm_16bit: + call word, @src.imm + exit + mov_reg_imm_8bit: + xcall x86.store_operand_prefix, (0),@dest.rm + emit 1, 0B0h + @dest.rm and 111b + emit 1, @src.imm + exit + mov_reg_simm_wrap: + compute @src.imm, @src.imm - 1 shl 64 + mov_reg_simm: + call x86.select_operand_prefix@dest, size + xcall x86.store_instruction@dest, (0C7h),(0),size,@src.imm + exit + + mov_mem_imm: + check size > 1 + jno mov_mem_imm_8bit + call x86.select_operand_prefix@dest, size + xcall x86.store_instruction@dest, (0C7h),(0),size,@src.imm + exit + mov_mem_imm_8bit: + xcall x86.store_instruction@dest, (0C6h),(0),byte,@src.imm + exit + + mov_reg_creg: + check (x86.mode <> 64 & @dest.size = 4) | (x86.mode = 64 & @dest.size = 8) + jno invalid_operand_size + compute ext, 20h + 1 metadataof (1 metadataof @src.imm) - x86.creg + compute rm, 1 metadataof @src.imm - 1 elementof (1 metadataof @src.imm) + xcall x86.store_instruction@dest, <0Fh,ext>,rm + check ext = 4 + jyes only386 + call x86.require.80386 + exit + only386: + call x86.requireexact.80386 + exit + + mov_creg_reg: + check 1 metadataof (1 metadataof @dest.imm) relativeto x86.creg & @dest.imm relativeto 1 elementof @dest.imm + jno invalid_combination_of_operands + check (x86.mode <> 64 & @src.size = 4) | (x86.mode = 64 & @src.size = 8) + jno invalid_operand_size + compute ext, 22h + 1 metadataof (1 metadataof @dest.imm) - x86.creg + compute rm, 1 metadataof @dest.imm - 1 elementof (1 metadataof @dest.imm) + xcall x86.store_instruction@src, <0Fh,ext>,rm + check ext = 4 + jyes only386 + call x86.require.80386 + exit + + mov_rm_sreg: + check @dest.type = 'mem' + jyes mov_mem_sreg + mov_reg_sreg: + check size > 1 + jno invalid_operand_size + call x86.select_operand_prefix@dest, size + jump mov_rm_sreg_store + mov_mem_sreg: + check size and not 2 + jyes invalid_operand_size + mov_rm_sreg_store: + xcall x86.store_instruction@dest, (8Ch),@src.rm + exit + + mov_sreg_rm: + check size = 1 + jyes invalid_operand_size + xcall x86.store_instruction@src, (8Eh),@dest.rm + exit + + invalid_operand_size: + err 'invalid operand size' + exit + + illegal_addressing_mode: + err 'illegal addressing mode' + exit + +end calminstruction + +calminstruction test? dest*,src* + + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + + local ext, rm, size + + check @dest.size = 0 & @src.size = 0 + jyes operand_size_not_specified + check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size + jyes operand_sizes_do_not_match + + compute size, @dest.size or @src.size + + main: + + check @src.type = 'reg' & ( (@dest.type = 'reg' & x86.rmposition <> x86.rmsrc.rmposition) | @dest.type = 'mem' ) + jyes test_reg_rm + check (@src.type = 'mem' | @src.type = 'reg') & @dest.type = 'reg' + jyes test_mem_reg + check @src.type = 'imm' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes test_rm_imm + + invalid_combination_of_operands: + err 'invalid combination of operands' + exit + + operand_size_not_specified: + err 'operand size not specified' + compute size, 0 + jump main + + operand_sizes_do_not_match: + err 'operand sizes do not match' + compute size, 0 + jump main + + test_reg_rm: + check size > 1 + jno test_reg_rm_8bit + call x86.select_operand_prefix@dest, size + xcall x86.store_instruction@dest, (85h),@src.rm + exit + test_reg_rm_8bit: + xcall x86.store_instruction@dest, (84h),@src.rm + exit + + test_mem_reg: + check size > 1 + jno test_mem_reg_8bit + call x86.select_operand_prefix@src, size + xcall x86.store_instruction@src, (85h),@dest.rm + exit + test_mem_reg_8bit: + xcall x86.store_instruction@src, (84h),@dest.rm + exit + + test_rm_imm: + check size > 1 + jno test_rm_imm_8bit + check @dest.type = 'reg' & @dest.rm = 0 + jyes test_ax_imm + call x86.select_operand_prefix@dest, size + xcall x86.store_instruction@dest, (0F7h),(0),size,@src.imm + exit + + test_ax_imm: + call x86.store_operand_prefix, size + emit 1, 0A9h + check size = 2 + jyes src_imm_16bit + check size = 4 + jyes src_imm_32bit + call x86.simm32, @src.imm + exit + src_imm_16bit: + call word, @src.imm + exit + src_imm_32bit: + call dword, @src.imm + exit + + test_rm_imm_8bit: + check @dest.type = 'reg' & @dest.rm = 0 + jyes test_al_imm + xcall x86.store_instruction@dest, (0F6h),(0),byte,@src.imm + exit + test_al_imm: + emit 1, 0A8h + emit 1, @src.imm + exit + +end calminstruction + +calminstruction xchg? dest*,src* + + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + + local ext, rm, size + + check @dest.size = 0 & @src.size = 0 + jyes operand_size_not_specified + check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size + jyes operand_sizes_do_not_match + + compute size, @dest.size or @src.size + + main: + + check @src.type = 'reg' & @dest.type = 'reg' + jyes xchg_reg_reg + check @src.type = 'reg' & @dest.type = 'mem' + jyes xchg_reg_rm + check @src.type = 'mem' & @dest.type = 'reg' + jyes xchg_rm_reg + + invalid_combination_of_operands: + err 'invalid combination of operands' + exit + + operand_size_not_specified: + err 'operand size not specified' + compute size, 0 + jump main + + operand_sizes_do_not_match: + err 'operand sizes do not match' + compute size, 0 + jump main + + xchg_reg_reg: + check (@src.rm & @dest.rm) | (size = 4 & @src.rm or @dest.rm = 0) | x86.rmposition = x86.rmdst.rmposition + jyes xchg_rm_reg + check x86.rmposition = x86.rmsrc.rmposition + jyes xchg_reg_rm + check size > 1 + jno xchg_rm_reg_8bit + compute @src.rm, @src.rm or @dest.rm + call x86.store_operand_prefix, size,@src.rm + emit 1, 90h + @src.rm and 111b + exit + + xchg_reg_rm: + check size > 1 + jno xchg_reg_rm_8bit + call x86.select_operand_prefix@dest, size + xcall x86.store_instruction@dest, (87h),@src.rm + exit + xchg_reg_rm_8bit: + xcall x86.store_instruction@dest, (86h),@src.rm + exit + + xchg_rm_reg: + check size > 1 + jno xchg_rm_reg_8bit + call x86.select_operand_prefix@src, size + xcall x86.store_instruction@src, (87h),@dest.rm + exit + xchg_rm_reg_8bit: + xcall x86.store_instruction@src, (86h),@dest.rm + exit + +end calminstruction + +iterate , inc,0 ,dec,1 + + calminstruction instr? dest* + + call x86.parse_operand@dest, dest + + check @dest.size + jyes main + + err 'operand size not specified' + + main: + check @dest.type = 'mem' | (x86.mode = 64 & @dest.type = 'reg') + jyes inc_rm + check @dest.type = 'reg' + jyes inc_reg + + err 'invalid operand' + exit + + inc_reg: + check @dest.size > 1 + jno inc_rm_8bit + call x86.store_operand_prefix, @dest.size + emit 1, 40h + @dest.rm + postbyte shl 3 + exit + + inc_rm: + check @dest.size > 1 + jno inc_rm_8bit + xcall x86.select_operand_prefix@dest, @dest.size + xcall x86.store_instruction@dest, (0FFh),(postbyte) + exit + inc_rm_8bit: + xcall x86.store_instruction@dest, (0FEh),(postbyte) + + end calminstruction + +end iterate + +calminstruction imul? dest*,src& + + local size + + call x86.parse_operand@dest, dest + + match , src + jyes imul_rm + + call x86.require.80186 + + local src1, src2 + + match src1 =, src2, src + jyes imul_second_source + + call x86.parse_operand@src, src + + check @dest.size = 0 & @src.size = 0 + jyes operand_size_not_specified + check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size + jyes operand_sizes_do_not_match + + compute size, @dest.size or @src.size + + check @dest.type = 'reg' & (@src.type = 'reg' | @src.type = 'mem') + jyes imul_reg_rm + + check @src.type = 'imm' & @dest.type = 'reg' + jno invalid_combination_of_operands + + compute @aux.type, @src.type + compute @aux.imm, @src.imm + compute @src.type, @dest.type + compute @src.mod, @dest.mod + compute @src.rm, @dest.rm + + jump main + + imul_second_source: + call x86.parse_operand@src, src1 + call x86.parse_operand@aux, src2 + + check @dest.size = 0 & @src.size = 0 & @aux.size = 0 + jyes operand_size_not_specified + + compute size, @dest.size or @src.size or @aux.size + + check (@dest.size & @dest.size <> size) | (@src.size & @src.size <> size) | (@aux.size & @aux.size <> size) + jyes operand_sizes_do_not_match + + jump main + + operand_size_not_specified: + err 'operand size not specified' + compute size, 0 + jump main + + operand_sizes_do_not_match: + err 'operand sizes do not match' + compute size, 0 + jump main + + main: + check @aux.type = 'imm' & ( @src.type = 'mem' | @src.type = 'reg' ) & @dest.type = 'reg' + jyes imul_reg_rm_imm + + invalid_combination_of_operands: + err 'invalid combination of operands' + exit + + imul_rm: + check @dest.size + jyes imul_rm_size_ok + err 'operand size not specified' + imul_rm_size_ok: + check @dest.type = 'mem' | @dest.type = 'reg' + jno invalid_combination_of_operands + check @dest.size > 1 + jno imul_rm_8bit + xcall x86.select_operand_prefix@dest, @dest.size + xcall x86.store_instruction@dest, (0F7h),(5) + exit + imul_rm_8bit: + xcall x86.store_instruction@dest, (0F6h),(5) + exit + + imul_reg_rm: + call x86.select_operand_prefix@src, size + xcall x86.store_instruction@src, <0Fh,0AFh>,@dest.rm + exit + + imul_reg_rm_imm: + call x86.select_operand_prefix@src, size + check @aux.imm eqtype 0.0 + jno imul_reg_rm_imm_optimize + asm virtual at 0 + asm emit size: @aux.imm + asm load @aux.imm:size from 0 + asm end virtual + compute @aux.imm, +@aux.imm + imul_reg_rm_imm_optimize: + check @aux.imm relativeto 0 & @aux.imm < 80h & @aux.imm >= -80h + jyes imul_reg_rm_simm + check @aux.imm relativeto 0 & @aux.imm - 1 shl (size shl 3) >= -80h & @aux.imm < 1 shl (size shl 3) + jyes imul_reg_rm_simm_wrap + xcall x86.store_instruction@src, (69h),@dest.rm,size,@aux.imm + exit + imul_reg_rm_simm_wrap: + compute @aux.imm, @aux.imm - 1 shl (size shl 3) + imul_reg_rm_simm: + xcall x86.store_instruction@src, (6Bh),@dest.rm,byte,@aux.imm + exit + +end calminstruction + +calminstruction x86.push_instruction size:0,src* + + call x86.parse_operand@src, src + + check size <> 0 & @src.size and not size + jyes invalid_operand_size + compute size, size or @src.size + check size = 0 | size = 2 | (size = 4 & x86.mode < 64) | (size = 8 & x86.mode = 64) + jyes main + + invalid_operand_size: + err 'invalid operand size' + + main: + check (x86.mode <> 16 & size = 2) | (x86.mode = 16 & size = 4) + jno prefix_ready + call x86.require.80386 + compute @src.prefix, 66h + prefix_ready: + + check @src.type = 'mem' + jyes push_mem + + check @src.prefix + jno prefix_stored + emit 1, @src.prefix + prefix_stored: + + check @src.type = 'reg' + jyes push_reg + check @src.type = 'sreg' + jyes push_sreg + check @src.type = 'imm' + jyes push_imm + + invalid_operand: + err 'invalid operand' + exit + + push_mem: + xcall x86.store_instruction@src, (0FFh),(110b) + exit + + push_reg: + check @src.rm and 1000b + jyes push_new_reg + emit 1, 50h + @src.rm + exit + push_new_reg: + emit 1, 41h + emit 1, 50h + @src.rm and 111b + exit + + push_sreg: + check @src.rm >= 4 + jyes push_sreg_386 + check x86.mode = 64 + jyes invalid_operand + emit 1, 6 + @src.rm shl 3 + exit + push_sreg_386: + emit 1, 0Fh + emit 1, 0A0h + (@src.rm-4) shl 3 + exit + + push_imm: + call x86.require.80186 + check size + jyes push_imm_size_ok + check x86.mode = 16 + jyes push_imm_16bit + check x86.mode = 32 + jyes push_imm_32bit + compute size, 8 + jump push_imm_size_ok + push_imm_32bit: + compute size, 4 + jump push_imm_size_ok + push_imm_16bit: + compute size, 2 + push_imm_size_ok: + + check @src.imm eqtype 0.0 + jno push_imm_check + asm virtual at 0 + asm emit size: @src.imm + asm load @src.imm:size from 0 + asm end virtual + compute @src.imm, +@src.imm + push_imm_check: + check size = 8 & @src.imm relativeto 0 + jno push_imm_optimize + check @src.imm - 10000000000000000h >= -80000000h & @src.imm < 10000000000000000h + jyes push_imm_wrap + check @src.imm >= 80000000h | @src.imm < -80000000h + jno push_imm_optimize + err 'immediate value out of signed range' + exit + push_imm_wrap: + compute @src.imm, @src.imm - 10000000000000000h + push_imm_optimize: + check x86.immsize < 2 & @src.imm relativeto 0 & @src.imm < 80h & @src.imm >= -80h + jyes push_simm + check x86.immsize < 2 & size = 2 & @src.imm relativeto 0 & @src.imm - 10000h >= -80h & @src.imm < 10000h + jyes push_simm_wrap + check x86.immsize < 2 & size = 4 & @src.imm relativeto 0 & @src.imm - 100000000h >= -80h & @src.imm < 100000000h + jyes push_simm_wrap + emit 1, 68h + check size = 2 + jyes src_imm_16bit + call dword, @src.imm + exit + src_imm_16bit: + call word, @src.imm + exit + push_simm_wrap: + compute @src.imm, @src.imm - 1 shl (size shl 3) + push_simm: + emit 1, 6Ah + emit 1, @src.imm + exit + +end calminstruction + +calminstruction x86.pop_instruction size:0,dest* + + call x86.parse_operand@dest, dest + + check size <> 0 & @dest.size and not size + jyes invalid_operand_size + compute size, size or @dest.size + check size = 0 | size = 2 | (size = 4 & x86.mode < 64) | (size = 8 & x86.mode = 64) + jyes main + + invalid_operand_size: + err 'invalid operand size' + + main: + check (x86.mode <> 16 & size = 2) | (x86.mode = 16 & size = 4) + jno prefix_ready + call x86.require.80386 + compute @dest.prefix, 66h + prefix_ready: + + check @dest.type = 'mem' + jyes pop_mem + + check @dest.prefix + jno prefix_stored + emit 1, @dest.prefix + prefix_stored: + + check @dest.type = 'reg' + jyes pop_reg + check @dest.type = 'sreg' + jyes pop_sreg + + invalid_operand: + err 'invalid operand' + exit + + pop_mem: + xcall x86.store_instruction@dest, (8Fh),(0) + exit + + pop_reg: + check @dest.rm and 1000b + jyes pop_new_reg + emit 1, 58h + @dest.rm + exit + pop_new_reg: + emit 1, 41h + emit 1, 58h + @dest.rm and 111b + exit + + pop_sreg: + check @dest.rm = 1 + jyes invalid_operand + check @dest.rm >= 4 + jyes pop_sreg_386 + check x86.mode = 64 + jyes invalid_operand + emit 1, 7 + @dest.rm shl 3 + exit + pop_sreg_386: + emit 1, 0Fh + emit 1, 0A1h + (@dest.rm-4) shl 3 + exit + +end calminstruction + +iterate reg, ax,cx,dx,bx,sp,bp,si,di,r8w,r9w,r10w,r11w,r12w,r13w,r14w,r15w, \ + eax,ecx,edx,ebx,esp,ebp,esi,edi,r8d,r9d,r10d,r11d,r12d,r13d,r14d,r15d, \ + rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15, \ + es,cs,ss,ds,fs,gs + define x86.compact.reg? {reg} +end iterate + +iterate , push,push_instruction,0, pushw,push_instruction,2, pushd,push_instruction,4, pushq,push_instruction,8, \ + pop,pop_instruction,0, popw,pop_instruction,2, popd,pop_instruction,4, popq,pop_instruction,8 + + calminstruction instr? operand + + local head, tail + + match head tail, operand + jno plain + transform head, x86.compact + jno plain + match {head}, head + jno plain + loop: + xcall x86.handler, (size),head + match head tail, tail + jno final + transform head, x86.compact + jno error + match {head}, head + jyes loop + error: + err 'only register operands allowed in compact syntax' + exit + final: + transform tail, x86.compact + jno error + match {operand}, tail + jno error + plain: + xcall x86.handler, (size),operand + + end calminstruction + +end iterate + +iterate , ret,0C2h, retn,0C2h, retf,0CAh + + calminstruction instr? operand + match , operand + jyes ret_short + check operand + jno ret_short + emit 1, opcode + call word, operand + exit + ret_short: + emit 1, opcode + 1 + end calminstruction + +end iterate + +iterate , retw,2,0C2h, retnw,2,0C2h, retd,4,0C2h, retnd,4,0C2h, retfw,2,0CAh, retfd,4,0CAh + + calminstruction instr? operand + check x86.mode = 64 + jyes illegal_instruction + xcall x86.store_operand_prefix, (size) + match , operand + jyes ret_short + emit 1, opcode + call word, operand + exit + ret_short: + emit 1, opcode + 1 + exit + illegal_instruction: + err 'illegal instruction' + end calminstruction + +end iterate + +iterate , retq,0C2h, retnq,0C2h, retfq,0CAh + + calminstruction instr? operand + call x86.require.bits64 + match , operand + jyes ret_short + emit 1, opcode + call word, operand + exit + ret_short: + emit 1, opcode + 1 + exit + end calminstruction + +end iterate + +calminstruction lea? dest*,src* + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @src.type = 'mem' & @dest.type = 'reg' + jno invalid_combination_of_operands + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, (8Dh),@dest.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' +end calminstruction + +iterate , les,0C4h, lds,0C5h + + calminstruction instr? dest*,src* + check x86.mode = 64 + jyes illegal_instruction + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check (@dest.size = 2 & (@src.size <> 0 & @src.size <> 4)) | (@dest.size = 4 & (@src.size <> 0 & @src.size <> 6)) + jyes invalid_operand_size + check @src.type = 'mem' & @dest.type = 'reg' + jno invalid_combination_of_operands + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, (opcode),@dest.rm + exit + illegal_instruction: + err 'illegal instruction' + exit + invalid_operand_size: + err 'invalid operand size' + exit + invalid_combination_of_operands: + err 'invalid combination of operands' + end calminstruction + +end iterate + +iterate , lss,<0Fh,0B2h>, lfs,<0Fh,0B4h>, lgs,<0Fh,0B5h> + + calminstruction instr? dest*,src* + call x86.require.80386 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check (@dest.size = 2 & (@src.size <> 0 & @src.size <> 4)) | (@dest.size = 4 & (@src.size <> 0 & @src.size <> 6)) | (@dest.size = 8 & (@src.size <> 0 & @src.size <> 10)) + jyes invalid_operand_size + check @src.type = 'mem' & @dest.type = 'reg' + jno invalid_combination_of_operands + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, ,@dest.rm + exit + invalid_operand_size: + err 'invalid operand size' + invalid_combination_of_operands: + err 'invalid combination of operands' + end calminstruction + +end iterate + +iterate , rol,0, ror,1, rcl,2, rcr,3, shl,4, sal, 4, shr,5, sar,7 + + calminstruction instr? dest*,cnt* + + call x86.parse_operand@dest, dest + call x86.parse_operand@src, cnt + + check @dest.size = 0 + jyes operand_size_not_specified + check @src.size and not 1 + jyes invalid_operand_size + + main: + check @src.type = 'reg' & @src.size = 1 & @src.rm = 1 & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes shift_rm_cl + check @src.type = 'imm' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes shift_rm_imm + + err 'invalid combination of operands' + exit + + shift_rm_cl: + check @dest.size > 1 + jno shift_r8_cl + xcall x86.select_operand_prefix@dest, @dest.size + xcall x86.store_instruction@dest, (0D3h),(postbyte) + exit + shift_r8_cl: + xcall x86.store_instruction@dest, (0D2h),(postbyte) + exit + shift_rm_imm: + check @dest.size > 1 + jno shift_rm8_imm + xcall x86.select_operand_prefix@dest, @dest.size + check @src.imm = 1 + jyes shift_rm_1 + call x86.require.80186 + xcall x86.store_instruction@dest, (0C1h),(postbyte),byte,@src.imm + exit + shift_rm_1: + xcall x86.store_instruction@dest, (0D1h),(postbyte) + exit + shift_rm8_imm: + check @src.imm = 1 + jyes shift_rm8_1 + call x86.require.80186 + xcall x86.store_instruction@dest, (0C0h),(postbyte),byte,@src.imm + exit + shift_rm8_1: + xcall x86.store_instruction@dest, (0D0h),(postbyte) + exit + + operand_size_not_specified: + err 'operand size not specified' + jump main + invalid_operand_size: + err 'invalid operand size' + jump main + + end calminstruction + +end iterate + +iterate , shld,0A4h, shrd,0ACh + + calminstruction instr? dest*,src*,cnt* + call x86.require.80386 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + call x86.parse_operand@aux, cnt + check @aux.size and not 1 + jyes invalid_operand_size + check @dest.size and not @src.size + jno main + err 'operand sizes do not match' + main: + check @aux.type = 'reg' & @aux.size = 1 & @aux.rm = 1 & @src.type = 'reg' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes shld_cl + check @aux.type = 'imm' & @src.type = 'reg' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes shld_imm + err 'invalid combination of operands' + exit + shld_cl: + xcall x86.select_operand_prefix@dest, @src.size + xcall x86.store_instruction@dest, <0Fh,ext+1>,@src.rm + exit + shld_imm: + xcall x86.select_operand_prefix@dest, @src.size + xcall x86.store_instruction@dest, <0Fh,ext>,@src.rm,byte,@aux.imm + exit + invalid_operand_size: + err 'invalid operand size' + end calminstruction + +end iterate + +iterate , bt,4, bts,5, btr,6, btc,7 + + calminstruction instr? dest*,src* + call x86.require.80386 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @src.type = 'reg' & (@dest.type = 'mem' | @dest.type = 'reg') + jyes bt_rm_reg + check @src.type = 'imm' & (@dest.type = 'mem' | @dest.type = 'reg') + jyes bt_rm_imm + err 'invalid combination of operands' + exit + bt_rm_reg: + local opcode + check @dest.size and not @src.size + jno bt_rm_reg_ok + err 'operand sizes do not match' + bt_rm_reg_ok: + compute opcode, 0A3h+(postbyte-4) shl 3 + xcall x86.select_operand_prefix@dest, @src.size + xcall x86.store_instruction@dest, <0Fh,opcode>,@src.rm + exit + bt_rm_imm: + check @src.size and not 1 + jno bt_rm_imm_ok + err 'invalid operand size' + bt_rm_imm_ok: + check @dest.size + jno operand_size_not_specified + xcall x86.select_operand_prefix@dest, @dest.size + xcall x86.store_instruction@dest, <0Fh,0BAh>,(postbyte),byte,@src.imm + exit + operand_size_not_specified: + err 'operand size not specified' + end calminstruction + +end iterate + +iterate , bsf,0BCh, bsr,0BDh + + calminstruction instr? dest*,src* + call x86.require.80386 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') + jyes bsf_rm_reg + err 'invalid combination of operands' + exit + bsf_rm_reg: + check @src.size and not @dest.size + jno bsf_rm_reg_ok + err 'operand sizes do not match' + bsf_rm_reg_ok: + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm + end calminstruction + +end iterate + +iterate , movzx,0B6h, movsx,0BEh + + calminstruction instr? dest*,src* + call x86.require.80386 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @dest.size > @src.size + jyes size_ok + err 'operand sizes do not match' + size_ok: + check @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') + jyes operands_ok + err 'invalid combination of operands' + exit + operands_ok: + check @src.size = 2 + jyes movzx_word + check @src.size = 1 | (@src.size = 0 & @dest.size = 2) + jyes movzx_byte + check @src.size + jyes invalid_operand_size + err 'operand size not specified' + movzx_word: + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, <0Fh,ext+1>,@dest.rm + exit + movzx_byte: + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm + exit + invalid_operand_size: + err 'invalid operand size' + end calminstruction + +end iterate + +calminstruction movsxd? dest*,src* + call x86.require.x64 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @dest.size > @src.size + jyes size_ok + err 'operand sizes do not match' + size_ok: + check @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') + jyes operands_ok + err 'invalid combination of operands' + exit + operands_ok: + check @src.size and not 4 + jyes invalid_operand_size + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, (63h),@dest.rm + exit + invalid_operand_size: + err 'invalid operand size' +end calminstruction + +iterate , o,0, no,1, c,2, b,2, nae,2, nc,3, nb,3, ae,3, z,4, e,4, nz,5, ne,5, na,6, be,6, a,7, nbe,7, \ + s,8, ns,9, p,0Ah, pe,0Ah, np,0Bh, po,0Bh, l,0Ch, nge,0Ch, nl,0Dh, ge,0Dh, ng,0Eh, le,0Eh, g,0Fh, nle,0Fh + + calminstruction set#cond? dest* + call x86.require.80386 + call x86.parse_operand@dest, dest + check @dest.size > 1 + jno size_ok + err 'invalid operand size' + size_ok: + check @dest.type = 'reg' | @dest.type = 'mem' + jyes operand_ok + err 'invalid operand' + exit + operand_ok: + xcall x86.store_instruction@dest, <0Fh,90h+code>,(0) + end calminstruction + + calminstruction cmov#cond? dest*,src* + call x86.require.P6 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') + jyes cmov_rm_reg + err 'invalid combination of operands' + exit + cmov_rm_reg: + check @src.size and not @dest.size + jno cmov_rm_reg_ok + err 'operand sizes do not match' + cmov_rm_reg_ok: + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, <0Fh,40h+code>,@dest.rm + end calminstruction + +end iterate + +calminstruction call? dest* + + call x86.parse_jump_operand@dest, dest + + check @dest.type = 'imm' + jyes call_imm + check @dest.type = 'mem' | @dest.type = 'reg' + jyes call_rm + check @dest.type = 'far' + jyes call_direct_far + + invalid_operand: + err 'invalid operand' + exit + illegal_instruction: + err 'illegal instruction' + exit + + call_direct_far: + check @dest.jump_type & @dest.jump_type <> 'far' + jyes invalid_operand + check x86.mode = 64 + jyes illegal_instruction + check @dest.size = 0 + jyes prefix_ok + local size + compute size, @dest.size - 2 + call x86.store_operand_prefix, size + prefix_ok: + check @dest.size and not 4 & @dest.size and not 6 + jyes invalid_operand + emit 1, 9Ah + check (@dest.size = 0 & x86.mode = 16) | @dest.size = 4 + jyes far_dword + call dword, @dest.offset + call word, @dest.segment + exit + far_dword: + call word, @dest.offset + call word, @dest.segment + exit + + call_rm: + check @dest.size = 6 | @dest.size = 10 + jyes call_rm_pword + check @dest.size = 8 & x86.mode = 64 + jyes call_rm_qword + check @dest.size = 4 & x86.mode < 64 + jyes call_rm_dword + check @dest.size = 2 & x86.mode < 64 + jyes call_rm_word + check @dest.size + jyes invalid_operand + check x86.mode = 64 + jno rex_prefix_ok + compute @dest.prefix, 48h + rex_prefix_ok: + check @dest.jump_type = 'far' + jyes call_rm_far + check @dest.jump_type = 'near' + jyes call_rm_near + err 'operand size not specified' + exit + + call_rm_pword: + check @dest.jump_type & @dest.jump_type <> 'far' + jyes invalid_operand + local size + compute size, @dest.size - 2 + call x86.select_operand_prefix@dest, size + call_rm_far: + xcall x86.store_instruction@dest, (0FFh),(11b) + exit + + call_rm_qword: + check @dest.jump_type & @dest.jump_type <> 'near' + jyes invalid_operand + jump call_rm_near + + call_rm_dword: + check @dest.jump_type | @dest.type = 'reg' + jno call_rm_dword_auto + check @dest.jump_type = 'far' + jyes call_rm_dword_far + call_rm_dword_near: + xcall x86.select_operand_prefix@dest, (4) + jump call_rm_near + call_rm_dword_auto: + check x86.mode = 16 + jno call_rm_dword_near + call_rm_dword_far: + xcall x86.select_operand_prefix@dest, (2) + jump call_rm_far + + call_rm_word: + check @dest.jump_type & @dest.jump_type <> 'near' + jyes invalid_operand + xcall x86.select_operand_prefix@dest, (2) + call_rm_near: + xcall x86.store_instruction@dest, (0FFh),(10b) + exit + + call_imm: + check @dest.jump_type & @dest.jump_type <> 'near' + jyes invalid_operand + check @dest.size = 8 & x86.mode = 64 + jyes call_imm_qword + check @dest.size = 2 & x86.mode < 64 + jyes call_imm_word + check @dest.size = 4 & x86.mode < 64 + jno invalid_operand + xcall x86.store_operand_prefix, (4) + emit 1, 0E8h + compute @dest.imm, @dest.imm-($+4) + call dword, @dest.imm + exit + call_imm_word: + xcall x86.store_operand_prefix, (2) + emit 1, 0E8h + compute @dest.imm, @dest.imm-($+2) + check @dest.imm relativeto 0 + jno store_word + compute @dest.imm, @dest.imm and 0FFFFh + store_word: + call word, @dest.imm + exit + call_imm_qword: + emit 1, 0E8h + compute @dest.imm, @dest.imm-($+4) + check @dest.imm relativeto 0 & (@dest.imm < -80000000h | @dest.imm >= 80000000h) + jno store_dword + err 'relative jump out of range' + store_dword: + call dword, @dest.imm + exit + +end calminstruction + +calminstruction jmp? dest* + + call x86.parse_jump_operand@dest, dest + + check @dest.type = 'imm' + jyes jmp_imm + check @dest.type = 'mem' | @dest.type = 'reg' + jyes jmp_rm + check @dest.type = 'far' + jyes jmp_direct_far + + invalid_operand: + err 'invalid operand' + exit + illegal_instruction: + err 'illegal instruction' + exit + + jmp_direct_far: + check @dest.jump_type & @dest.jump_type <> 'far' + jyes invalid_operand + check x86.mode = 64 + jyes illegal_instruction + check @dest.size = 0 + jyes prefix_ok + local size + compute size, @dest.size - 2 + call x86.store_operand_prefix, size + prefix_ok: + check @dest.size and not 4 & @dest.size and not 6 + jyes invalid_operand + emit 1, 0EAh + check (@dest.size = 0 & x86.mode = 16) | @dest.size = 4 + jyes far_dword + call dword, @dest.offset + call word, @dest.segment + exit + far_dword: + call word, @dest.offset + call word, @dest.segment + exit + + jmp_rm: + check @dest.size = 6 | @dest.size = 10 + jyes jmp_rm_pword + check @dest.size = 8 & x86.mode = 64 + jyes jmp_rm_qword + check @dest.size = 4 & x86.mode < 64 + jyes jmp_rm_dword + check @dest.size = 2 & x86.mode < 64 + jyes jmp_rm_word + check @dest.size + jyes invalid_operand + check x86.mode = 64 + jno rex_prefix_ok + compute @dest.prefix, 48h + rex_prefix_ok: + check @dest.jump_type = 'far' + jyes jmp_rm_far + check @dest.jump_type = 'near' + jyes jmp_rm_near + err 'operand size not specified' + exit + + jmp_rm_pword: + check @dest.jump_type & @dest.jump_type <> 'far' + jyes invalid_operand + local size + compute size, @dest.size - 2 + call x86.select_operand_prefix@dest, size + jmp_rm_far: + xcall x86.store_instruction@dest, (0FFh),(101b) + exit + + jmp_rm_qword: + check @dest.jump_type & @dest.jump_type <> 'near' + jyes invalid_operand + jump jmp_rm_near + + jmp_rm_dword: + check @dest.jump_type | @dest.type = 'reg' + jno jmp_rm_dword_auto + check @dest.jump_type = 'far' + jyes jmp_rm_dword_far + jmp_rm_dword_near: + xcall x86.select_operand_prefix@dest, (4) + jump jmp_rm_near + jmp_rm_dword_auto: + check x86.mode = 16 + jno jmp_rm_dword_near + jmp_rm_dword_far: + xcall x86.select_operand_prefix@dest, (2) + jump jmp_rm_far + + jmp_rm_word: + check @dest.jump_type & @dest.jump_type <> 'near' + jyes invalid_operand + xcall x86.select_operand_prefix@dest, (2) + jmp_rm_near: + xcall x86.store_instruction@dest, (0FFh),(100b) + exit + + jmp_imm: + check @dest.jump_type = 'far' + jyes invalid_operand + check (@dest.size = 8 & x86.mode < 64) | (@dest.size < 8 & x86.mode = 64) + jyes invalid_operand + check @dest.size = 8 + jyes jmp_imm_prefix_ok + call x86.store_operand_prefix, @dest.size + jmp_imm_prefix_ok: + check @dest.jump_type = 'short' + jyes jmp_imm_short_verify + check @dest.jump_type = 'near' + jyes jmp_imm_near + check ~ $ relativeto 0 & @dest.imm relativeto 0 + jno jmp_optimize + compute @dest.imm, @dest.imm + $ - 0 scaleof $ + err 'invalid address' + jmp_optimize: + check @dest.unresolved + jyes jmp_imm_short + check @dest.imm relativeto $ + jno jmp_imm_near + check (@dest.imm-($+2)) < 80h & (@dest.imm-($+2)) >= -80h + jyes jmp_imm_short + check (@dest.imm-($+2)) and (1 shl (@dest.size*8) - 1) < 80h | (@dest.imm-($+2)) and (1 shl (@dest.size*8) - 1) >= 1 shl (@dest.size*8) - 80h + jyes jmp_imm_short + jmp_imm_near: + check @dest.size = 8 + jyes jmp_imm_qword + check @dest.size = 2 + jyes jmp_imm_word + check @dest.size = 4 + jno invalid_operand + emit 1, 0E9h + compute @dest.imm, @dest.imm-($+4) + call dword, @dest.imm + exit + jmp_imm_word: + emit 1, 0E9h + compute @dest.imm, @dest.imm-($+2) + check @dest.imm relativeto 0 + jno store_word + compute @dest.imm, @dest.imm and 0FFFFh + store_word: + call word, @dest.imm + exit + jmp_imm_qword: + emit 1, 0E9h + compute @dest.imm, @dest.imm-($+4) + call dword, @dest.imm + check @dest.imm relativeto 0 & (@dest.imm < -80000000h | @dest.imm >= 80000000h) + jyes relative_jump_out_of_range + exit + jmp_imm_short_verify: + check (@dest.imm-($+2)) < 80h & (@dest.imm-($+2)) >= -80h + jyes jmp_imm_short + check (@dest.imm-($+2)) and (1 shl (@dest.size*8) - 1) < 80h | (@dest.imm-($+2)) and (1 shl (@dest.size*8) - 1) >= 1 shl (@dest.size*8) - 80h + jyes jmp_imm_short + emit 1, 0EBh + emit 1 + relative_jump_out_of_range: + err 'relative jump out of range' + exit + jmp_imm_short: + emit 1, 0EBh + compute @dest.imm, (@dest.imm-($+1)) and 0FFh + emit 1, @dest.imm + exit + +end calminstruction + +iterate , jo,70h, jno,71h, jc,72h, jb,72h, jnae,72h, jnc,73h, jnb,73h, jae,73h, jz,74h, je,74h, jnz,75h, jne,75h, jna,76h, jbe,76h, ja,77h, jnbe,77h, \ + js,78h, jns,79h, jp,7Ah, jpe,7Ah, jnp,7Bh, jpo,7Bh, jl,7Ch, jnge,7Ch, jnl,7Dh, jge,7Dh, jng,7Eh, jle,7Eh, jg,7Fh, jnle,7Fh + + calminstruction instr? dest* + + call x86.parse_jump_operand@dest, dest + + check @dest.type <> 'imm' | @dest.jump_type = 'far' + jyes invalid_operand + + check x86.mode = 64 | @dest.size = 8 + jyes long + call x86.store_operand_prefix, @dest.size + jump prefix_ok + long: + check x86.mode < 64 | @dest.size <> 8 + jyes invalid_operand + prefix_ok: + + check ~ $ relativeto 0 & @dest.imm relativeto 0 + jno optimize + compute @dest.imm, @dest.imm + $ - 0 scaleof $ + err 'invalid address' + optimize: + + check @dest.jump_type = 'near' + jyes explicit_near + + check @dest.unresolved | ( @dest.imm relativeto $ & @dest.imm-($+2) < 80h & @dest.imm-($+2) >= -80h ) + jyes short + check @dest.imm relativeto $ & ( (@dest.imm-($+2)) and (1 shl (@dest.size*8) - 1) < 80h | (@dest.imm-($+2)) and (1 shl (@dest.size*8) - 1) >= 1 shl (@dest.size*8) - 80h ) + jyes short + check @dest.jump_type = 'short' | x86.cpu < x86.80386.cpu + jno near + emit 2 + err 'relative jump out of range' + exit + + explicit_near: + call x86.require.80386 + + near: + emit 1, 0Fh + emit 1, 10h+opcode + + check @dest.size = 2 + jyes relative_word + compute @dest.imm, @dest.imm-($+4) + call dword, @dest.imm + exit + relative_word: + compute @dest.imm, @dest.imm-($+2) + check @dest.imm relativeto 0 + jno store_word + compute @dest.imm, @dest.imm and 0FFFFh + store_word: + call word, @dest.imm + exit + + short: + compute @dest.imm, (@dest.imm-($+2)) and 0FFh + emit 1, opcode + emit 1, @dest.imm + exit + + + invalid_operand: + err 'invalid operand' + exit + + end calminstruction +end iterate + +iterate , loopnz,0E0h,0, loopne,0E0h,0, loopz,0E1h,0, loope,0E1h,0, loop,0E2h,0, \ + loopnzw,0E0h,2, loopnew,0E0h,2, loopzw,0E1h,2, loopew,0E1h,2, loopw,0E2h,2, \ + loopnzd,0E0h,4, loopned,0E0h,4, loopzd,0E1h,4, looped,0E1h,4, loopd,0E2h,4, \ + loopnzq,0E0h,8, loopneq,0E0h,8, loopzq,0E1h,8, loopeq,0E1h,8, loopq,0E2h,8, \ + jcxz,0E3h,2, jecxz,0E3h,4, jrcxz,0E3h,8 + calminstruction instr? dest* + + call x86.parse_jump_operand@dest, dest + + check @dest.type = 'imm' & ( @dest.jump_type = 'short' | ~ @dest.jump_type ) + jno invalid_operand + + check len shl 3 and not x86.mode + jno address_prefix_ok + check len = 8 | (len = 2 & x86.mode = 64) + jyes illegal_instruction + call x86.require.80386 + emit 1, 67h + address_prefix_ok: + check @dest.size shl 3 <> x86.mode + jno operand_prefix_ok + check @dest.size = 8 | x86.mode = 64 + jyes invalid_operand + call x86.require.80386 + emit 1, 66h + operand_prefix_ok: + + emit 1, opcode + + check @dest.imm-($+1) < 80h & @dest.imm-($+1) >= -80h + jyes relative_offset_ok + check (@dest.imm-($+2)) and (1 shl (@dest.size*8) - 1) < 80h | (@dest.imm-($+2)) and (1 shl (@dest.size*8) - 1) >= 1 shl (@dest.size*8) - 80h + jyes relative_offset_ok + emit 1 + err 'relative jump out of range' + exit + relative_offset_ok: + compute @dest.imm, (@dest.imm-($+1)) and 0FFh + emit 1, @dest.imm + exit + + illegal_instruction: + err 'illegal instruction' + exit + invalid_operand: + err 'invalid operand' + exit + + end calminstruction +end iterate + +iterate , nop,90h, int3,0CCh, into,0CEh, int1,0F1h, salc,0D6h, \ + hlt,0F4h, cmc,0F5h, clc,0F8h, stc,0F9h, cli,0FAh, sti,0FBh, cld,0FCh, std,0FDh, \ + pushf,9Ch, popf,9Dh, sahf,9Eh, lahf,9Fh, \ + movsb,0A4h, cmpsb,0A6h, stosb,0AAh, lodsb,0ACh, scasb,0AEh, xlatb,0D7h + + calminstruction instr? + emit 1, opcode + end calminstruction + +end iterate + +iterate , leave,0C9h, insb,6Ch, outsb,6Eh + + calminstruction instr? + call x86.require.80186 + emit 1, opcode + end calminstruction + +end iterate + +iterate , clts,<0Fh,6>,80286, invd,<0Fh,8>,80486, wbinvd,<0Fh,9>,80486, \ + wrmsr,<0Fh,30h>,P5, rdtsc,<0Fh,31h>,P5, rdmsr,<0Fh,32h>,P5, rdpmc,<0Fh,33h>,P5, \ + cpuid,<0Fh,0A2h>,P5, rsm,<0Fh,0AAh>,P5, sysenter,<0Fh,34h>,P6, sysexit,<0Fh,35h>,P6 + + match byte1=,byte2, opcode + calminstruction instr? + call x86.require.cpu + emit 1, byte1 + emit 1, byte2 + end calminstruction + end match + +end iterate + +iterate , cbw,98h, cwd,99h, iretw,0CFh, movsw,0A5h, cmpsw,0A7h, stosw,0ABh, lodsw,0ADh, scasw,0AFh + + calminstruction instr? + xcall x86.store_operand_prefix, (2) + emit 1, opcode + end calminstruction + +end iterate + +iterate , cwde,98h, cdq,99h, iretd,0CFh, movsd,0A5h, cmpsd,0A7h, stosd,0ABh, lodsd,0ADh, scasd,0AFh + + calminstruction instr? + xcall x86.store_operand_prefix, (4) + emit 1, opcode + end calminstruction + +end iterate + +iterate , insw,6Dh, outsw,6Fh + + calminstruction instr? + call x86.require.80186 + xcall x86.store_operand_prefix, (2) + emit 1, opcode + end calminstruction + +end iterate + +iterate , insd,6Dh, outsd,6Fh + + calminstruction instr? + call x86.require.80186 + xcall x86.store_operand_prefix, (4) + emit 1, opcode + end calminstruction + +end iterate + +iterate , cdqe,98h, cqo,99h, iretq,0CFh, \ + movsq,0A5h, cmpsq,0A7h, stosq,0ABh, lodsq,0ADh, scasq,0AFh, \ + sysretq,<0Fh,7>, wrmsrq,<0Fh,30h>, rdmsrq,<0Fh,32h>, sysexitq,<0Fh,35h> + + match byte1=,byte2, opcode + calminstruction instr? + xcall x86.store_operand_prefix, (8) + emit 1, byte1 + emit 1, byte2 + end calminstruction + else + calminstruction instr? + xcall x86.store_operand_prefix, (8) + emit 1, opcode + end calminstruction + end match + +end iterate + +iterate , swapgs,<0Fh,1,0F8h>, syscall,<0Fh,5>, sysret,<0Fh,7> + + calminstruction instr? + call x86.require.bits64 + asm db opcode + end calminstruction + +end iterate + +iterate , lock,0F0h, repnz,0F2h, repne,0F2h, rep,0F3h, repz,0F3h, repe,0F3h + + calminstruction prefix? instr& + emit 1, opcode + assemble instr + end calminstruction + +end iterate + +calminstruction int? number* + emit 1, 0CDh + emit 1, number +end calminstruction + +calminstruction iret? + check x86.mode < 64 + jyes prefix_ok + emit 1, 48h + prefix_ok: + emit 1, 0CFh +end calminstruction + +iterate , daa,27h, das,2Fh, aaa,37h, aas,3Fh, pusha,60h, popa,61h + + calminstruction instr? + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + emit 1, opcode + end calminstruction + +end iterate + +calminstruction aam? number:10 + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + emit 1, 0D4h + emit 1, number +end calminstruction + +calminstruction aad? number:10 + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + emit 1, 0D5h + emit 1, number +end calminstruction + +iterate , pushfw,9Ch, popfw,9Dh + + calminstruction instr? + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + xcall x86.store_operand_prefix, (2) + emit 1, opcode + end calminstruction + +end iterate + +iterate , pushfd,9Ch, popfd,9Dh + + calminstruction instr? + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + xcall x86.store_operand_prefix, (4) + emit 1, opcode + end calminstruction + +end iterate + +iterate , pushfq,9Ch, popfq,9Dh + + calminstruction instr? + call x86.require.bits64 + emit 1, opcode + end calminstruction + +end iterate + +iterate , pushaw,60h, popaw,61h + + calminstruction instr? + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + call x86.require.80186 + xcall x86.store_operand_prefix, (2) + emit 1, opcode + end calminstruction + +end iterate + +iterate , pushad,60h, popad,61h + + calminstruction instr? + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + call x86.require.80186 + xcall x86.store_operand_prefix, (4) + emit 1, opcode + end calminstruction + +end iterate + +calminstruction movs? dest*,src* + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + local size + check @dest.size = 0 & @src.size = 0 + jyes operand_size_not_specified + check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size + jyes operand_sizes_do_not_match + compute size, @dest.size or @src.size + size_ok: + check @src.type = 'mem' & @src.mod = 0 & @dest.type = 'mem' & @dest.mod = 0 & ( (x86.mode < 64 & @src.mode = 16 & @src.rm = 4 & @dest.mode = 16 & @dest.rm = 5) | (@src.mode > 16 & @src.rm = 6 & @dest.mode = @src.mode & @dest.rm = 7) ) & ( @dest.segment_prefix = 0 | @dest.segment_prefix = 26h | (x86.mode = 64 & @dest.segment_prefix < 64h)) + jno invalid_combination_of_operands + check @src.segment_prefix = 0 | @src.segment_prefix = 3Eh | (x86.mode = 64 & @src.segment_prefix < 64h) + jyes segment_prefix_ok + emit 1, @src.segment_prefix + segment_prefix_ok: + check @dest.mode = x86.mode + jyes address_prefix_ok + emit 1, 67h + address_prefix_ok: + check size > 1 + jyes movs_word + emit 1, 0A4h + exit + movs_word: + call x86.store_operand_prefix, size + emit 1, 0A5h + exit + operand_size_not_specified: + err 'operand size not specified' + compute size, 0 + jump size_ok + operand_sizes_do_not_match: + err 'operand sizes do not match' + compute size, 0 + jump size_ok + invalid_combination_of_operands: + err 'invalid combination of operands' + exit +end calminstruction + +calminstruction cmps? src*,dest* + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + local size + check @dest.size = 0 & @src.size = 0 + jyes operand_size_not_specified + check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size + jyes operand_sizes_do_not_match + compute size, @dest.size or @src.size + size_ok: + check @src.type = 'mem' & @src.mod = 0 & @dest.type = 'mem' & @dest.mod = 0 & ( (x86.mode < 64 & @src.mode = 16 & @src.rm = 4 & @dest.mode = 16 & @dest.rm = 5) | (@src.mode > 16 & @src.rm = 6 & @dest.mode = @src.mode & @dest.rm = 7) ) & ( @dest.segment_prefix = 0 | @dest.segment_prefix = 26h | (x86.mode = 64 & @dest.segment_prefix < 64h)) + jno invalid_combination_of_operands + check @src.segment_prefix = 0 | @src.segment_prefix = 3Eh | (x86.mode = 64 & @src.segment_prefix < 64h) + jyes segment_prefix_ok + emit 1, @src.segment_prefix + segment_prefix_ok: + check @dest.mode = x86.mode + jyes address_prefix_ok + emit 1, 67h + address_prefix_ok: + check size > 1 + jyes cmps_word + emit 1, 0A6h + exit + cmps_word: + call x86.store_operand_prefix, size + emit 1, 0A7h + exit + operand_size_not_specified: + err 'operand size not specified' + compute size, 0 + jump size_ok + operand_sizes_do_not_match: + err 'operand sizes do not match' + compute size, 0 + jump size_ok + invalid_combination_of_operands: + err 'invalid combination of operands' + exit +end calminstruction + +calminstruction stos? dest* + call x86.parse_operand@dest, dest + check @dest.size + jyes size_ok + err 'operand size not specified' + size_ok: + check @dest.type = 'mem' & @dest.mod = 0 & ( (x86.mode < 64 & @dest.mode = 16 & @dest.rm = 5) | (@dest.mode > 16 & @dest.rm = 7) ) & ( @dest.segment_prefix = 0 | @dest.segment_prefix = 26h | (x86.mode = 64 & @dest.segment_prefix < 64h)) + jno invalid_operand + check @dest.mode = x86.mode + jyes address_prefix_ok + emit 1, 67h + address_prefix_ok: + check @dest.size > 1 + jyes stos_word + emit 1, 0AAh + exit + stos_word: + call x86.store_operand_prefix, @dest.size + emit 1, 0ABh + exit + invalid_operand: + err 'invalid operand' + exit +end calminstruction + +calminstruction lods? src* + call x86.parse_operand@src, src + check @src.size + jyes size_ok + err 'operand size not specified' + size_ok: + check @src.type = 'mem' & @src.mod = 0 & ( (x86.mode < 64 & @src.mode = 16 & @src.rm = 4) | (@src.mode > 16 & @src.rm = 6) ) + jno invalid_operand + check @src.segment_prefix = 0 | @src.segment_prefix = 3Eh | (x86.mode = 64 & @src.segment_prefix < 64h) + jyes segment_prefix_ok + emit 1, @src.segment_prefix + segment_prefix_ok: + check @src.mode = x86.mode + jyes address_prefix_ok + emit 1, 67h + address_prefix_ok: + check @src.size > 1 + jyes lods_word + emit 1, 0ACh + exit + lods_word: + call x86.store_operand_prefix, @src.size + emit 1, 0ADh + exit + invalid_operand: + err 'invalid operand' + exit +end calminstruction + +calminstruction scas? dest* + call x86.parse_operand@dest, dest + check @dest.size + jyes size_ok + err 'operand size not specified' + size_ok: + check @dest.type = 'mem' & @dest.mod = 0 & ( (x86.mode < 64 & @dest.mode = 16 & @dest.rm = 5) | (@dest.mode > 16 & @dest.rm = 7) ) & ( @dest.segment_prefix = 0 | @dest.segment_prefix = 26h | (x86.mode = 64 & @dest.segment_prefix < 64h)) + jno invalid_operand + check @dest.mode = x86.mode + jyes address_prefix_ok + emit 1, 67h + address_prefix_ok: + check @dest.size > 1 + jyes scas_word + emit 1, 0AEh + exit + scas_word: + call x86.store_operand_prefix, @dest.size + emit 1, 0AFh + exit + invalid_operand: + err 'invalid operand' + exit +end calminstruction + +calminstruction ins? dest*,src* + call x86.require.80186 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @dest.size + jyes size_ok + err 'operand size not specified' + compute size, 0 + size_ok: + check @src.type = 'reg' & @src.size = 2 & @src.rm = 2 & @dest.type = 'mem' & @dest.mod = 0 & ( (x86.mode < 64 & @dest.mode = 16 & @dest.rm = 5) | (@dest.mode > 16 & @dest.rm = 7) ) & ( @dest.segment_prefix = 0 | @dest.segment_prefix = 26h | (x86.mode = 64 & @dest.segment_prefix < 64h)) + jno invalid_combination_of_operands + check @dest.mode = x86.mode + jyes address_prefix_ok + emit 1, 67h + address_prefix_ok: + check @dest.size > 1 + jyes ins_word + emit 1, 6Ch + exit + ins_word: + call x86.store_operand_prefix, @dest.size + emit 1, 6Dh + exit + invalid_combination_of_operands: + err 'invalid combination of operands' + exit +end calminstruction + +calminstruction outs? dest*,src* + call x86.require.80186 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @src.size + jyes size_ok + err 'operand size not specified' + size_ok: + check @dest.type = 'reg' & @dest.size = 2 & @dest.rm = 2 & @src.type = 'mem' & @src.mod = 0 & ( (x86.mode < 64 & @src.mode = 16 & @src.rm = 4) | (@src.mode > 16 & @src.rm = 6) ) + jno invalid_combination_of_operands + check @src.segment_prefix = 0 | @src.segment_prefix = 3Eh | (x86.mode = 64 & @src.segment_prefix < 64h) + jyes segment_prefix_ok + emit 1, @src.segment_prefix + segment_prefix_ok: + check @src.mode = x86.mode + jyes address_prefix_ok + emit 1, 67h + address_prefix_ok: + check @src.size > 1 + jyes outs_word + emit 1, 6Eh + exit + outs_word: + call x86.store_operand_prefix, @src.size + emit 1, 6Fh + exit + operand_size_not_specified: + err 'operand size not specified' + compute size, 0 + jump size_ok + operand_sizes_do_not_match: + err 'operand sizes do not match' + compute size, 0 + jump size_ok + invalid_combination_of_operands: + err 'invalid combination of operands' + exit +end calminstruction + +calminstruction xlat? src* + call x86.parse_operand@src, src + check @src.size > 1 + jno size_ok + err 'invalid operand size' + size_ok: + check @src.type = 'mem' & @src.mod = 0 & ( (x86.mode < 64 & @src.mode = 16 & @src.rm = 7) | (@src.mode > 16 & @src.rm = 3) ) + jno invalid_operand + check @src.segment_prefix = 0 | @src.segment_prefix = 3Eh | (x86.mode = 64 & @src.segment_prefix < 64h) + jyes segment_prefix_ok + emit 1, @src.segment_prefix + segment_prefix_ok: + check @src.mode = x86.mode + jyes address_prefix_ok + emit 1, 67h + address_prefix_ok: + emit 1, 0D7h + exit + invalid_operand: + err 'invalid operand' + exit +end calminstruction + +calminstruction in? dest*,src* + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @dest.size = 8 + jyes invalid_size + check @dest.size + jyes size_ok + err 'operand size not specified' + jump size_ok + invalid_size: + err 'invalid_operand_size' + size_ok: + check @src.type = 'reg' & @src.size = 2 & @src.rm = 2 & @dest.type = 'reg' & @dest.rm = 0 + jyes in_ax_dx + check @src.type = 'imm' & @dest.type = 'reg' & @dest.rm = 0 + jyes in_ax_imm + err 'invalid combination of operands' + exit + in_ax_dx: + check @dest.size > 1 + jno in_al_dx + call x86.store_operand_prefix, @dest.size + emit 1, 0EDh + exit + in_al_dx: + emit 1, 0ECh + exit + in_ax_imm: + check @dest.size > 1 + jno in_al_imm + call x86.store_operand_prefix, @dest.size + emit 1, 0E5h + emit 1, @src.imm + exit + in_al_imm: + emit 1, 0E4h + emit 1, @src.imm + exit +end calminstruction + +calminstruction out? dest*,src* + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @src.size = 8 + jyes invalid_size + check @src.size + jyes size_ok + err 'operand size not specified' + jump size_ok + invalid_size: + err 'invalid_operand_size' + size_ok: + check @dest.type = 'reg' & @dest.size = 2 & @dest.rm = 2 & @src.type = 'reg' & @src.rm = 0 + jyes out_dx_ax + check @dest.type = 'imm' & @src.type = 'reg' & @src.rm = 0 + jyes out_imm_ax + err 'invalid combination of operands' + exit + out_dx_ax: + check @src.size > 1 + jno out_dx_al + call x86.store_operand_prefix, @src.size + emit 1, 0EFh + exit + out_dx_al: + emit 1, 0EEh + exit + out_imm_ax: + check @src.size > 1 + jno out_imm_al + call x86.store_operand_prefix, @src.size + emit 1, 0E7h + emit 1, @dest.imm + exit + out_imm_al: + emit 1, 0E6h + emit 1, @dest.imm + exit +end calminstruction + +calminstruction enter? alloc*,nesting* + call x86.require.80186 + call x86.parse_operand@src, alloc + call x86.parse_operand@aux, nesting + check (@src.size and not 2) | (@aux.size and not 1) + jno size_ok + err 'invalid operand size' + size_ok: + check @src.type = 'imm' & @aux.type = 'imm' + jyes operand_ok + err 'invalid operand' + exit + operand_ok: + emit 1, 0C8h + call word, @src.imm + emit 1, @aux.imm +end calminstruction + +calminstruction bound? dest*,src* + call x86.require.80186 + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @src.type = 'mem' & @dest.type = 'reg' + jno invalid_combination_of_operands + check @src.size and not @dest.size + jno size_ok + err 'operand sizes do not match' + size_ok: + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, (62h),@dest.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' + exit +end calminstruction + +calminstruction arpl? dest*,src* + check x86.mode < 64 + jyes allowed + err 'illegal instruction' + exit + allowed: + call x86.require.80286 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @src.type = 'reg' & (@dest.type = 'mem' | @dest.type = 'reg') + jno invalid_combination_of_operands + check @src.size = 2 + jno invalid_operand_size + check @dest.size and not @src.size + jno size_ok + err 'operand sizes do not match' + jump size_ok + invalid_operand_size: + err 'invalid operand size' + size_ok: + xcall x86.store_instruction@dest, (63h),@src.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' + exit + exit +end calminstruction + +iterate , lldt,0,2, ltr,0,3, verr,0,4, verw,0,5, lmsw,1,6 + + calminstruction instr? dest* + call x86.require.80286 + call x86.parse_operand@dest, dest + check @dest.size and not 2 + jno size_ok + err 'invalid operand size' + size_ok: + check @dest.type = 'reg' | @dest.type = 'mem' + jyes operand_ok + err 'invalid operand' + exit + operand_ok: + xcall x86.store_instruction@dest, <0Fh,ext>,(postbyte) + end calminstruction + +end iterate + +iterate , sldt,0,0, str,0,1, smsw,1,4 + + calminstruction instr? dest* + call x86.require.80286 + call x86.parse_operand@dest, dest + check @dest.type = 'reg' + jyes select_operand_prefix + check @dest.size and not 2 + jno size_ok + err 'invalid operand size' + size_ok: + check @dest.type = 'mem' + jyes store_instruction + err 'invalid combination of operands' + exit + select_operand_prefix: + xcall x86.select_operand_prefix@dest, @dest.size + store_instruction: + xcall x86.store_instruction@dest, <0Fh,ext>,(postbyte) + end calminstruction + +end iterate + +iterate , lgdt,2, lidt,3, sgdt,0, sidt,1 + + calminstruction instr? dest* + call x86.require.80286 + call x86.parse_operand@dest, dest + check @dest.type = 'mem' + jyes operand_ok + err 'invalid operand' + exit + operand_ok: + check x86.mode = 64 & @dest.size = 10 + jyes store_instruction + check x86.mode < 64 & @dest.size = 6 + jyes o32 + check x86.mode < 64 & @dest.size = 5 + jyes o16 + check @dest.size + jno store_instruction + err 'invalid operand size' + jump store_instruction + o16: + xcall x86.select_operand_prefix@dest, (2) + jump store_instruction + o32: + xcall x86.select_operand_prefix@dest, (4) + store_instruction: + xcall x86.store_instruction@dest, <0Fh,1>,(postbyte) + end calminstruction + +end iterate + +iterate , lar,2, lsl,3 + + calminstruction instr? dest*,src* + call x86.require.80286 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') + jno invalid_combination_of_operands + check @src.size and not 2 + jno size_ok + err 'invalid operand size' + size_ok: + xcall x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, <0Fh,ext>,@dest.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' + end calminstruction + +end iterate + +iterate , cmpxchg,0B0h, xadd,0C0h + + calminstruction instr? dest*,src* + call x86.require.80486 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + check @src.type = 'reg' & ( @dest.type = 'reg' | @dest.type = 'mem' ) + jyes xadd_rm_reg + err 'invalid combination of operands' + exit + xadd_rm_reg: + check @dest.size and not @src.size + jno size_ok + err 'operand sizes do not match' + size_ok: + check @src.size > 1 + jno xadd_rm_reg_8bit + xcall x86.select_operand_prefix@dest, @src.size + xcall x86.store_instruction@dest, <0Fh,ext+1>,@src.rm + exit + xadd_rm_reg_8bit: + xcall x86.store_instruction@dest, <0Fh,ext>,@src.rm + end calminstruction + +end iterate + +calminstruction cmpxchg8b? dest* + call x86.require.P5 + call x86.parse_operand@dest, dest + check @dest.type = 'mem' + jyes operand_ok + err 'invalid operand' + exit + operand_ok: + check @dest.size and not 8 + jno size_ok + err 'invalid operand size' + size_ok: + xcall x86.store_instruction@dest, <0Fh,0C7h>,(1) +end calminstruction + +calminstruction cmpxchg16b? dest* + call x86.require.CMPXCHG16B + call x86.parse_operand@dest, dest + check @dest.type = 'mem' + jyes operand_ok + err 'invalid operand' + exit + operand_ok: + check @dest.size and not 16 + jno size_ok + err 'invalid operand size' + size_ok: + xcall x86.store_operand_prefix, (8) + xcall x86.store_instruction@dest, <0Fh,0C7h>,(1) +end calminstruction + +calminstruction bswap? dest* + call x86.require.80486 + call x86.parse_operand@dest, dest + check @dest.type = 'reg' & @dest.size > 2 + jyes operand_ok + err 'invalid operand' + exit + operand_ok: + call x86.store_operand_prefix, @dest.size,@dest.rm + emit 1, 0Fh + emit 1, 0C8h + @dest.rm and 111b +end calminstruction + +calminstruction invlpg? dest* + call x86.require.80486 + call x86.parse_operand@dest, dest + check @dest.type = 'mem' + jyes operand_ok + err 'invalid operand' + exit + operand_ok: + xcall x86.store_instruction@dest, <0Fh,1>,(7) +end calminstruction + +calminstruction loadall? + check x86.cpu = x86.80286.cpu + jyes loadall286 + check x86.cpu = x86.80386.cpu + jyes loadall386 + err 'illegal instruction' + exit + loadall286: + emit 1, 0Fh + emit 1, 05h + exit + loadall386: + emit 1, 0Fh + emit 1, 07h +end calminstruction + +calminstruction xbts? dest*,src*,offs*,len* + call x86.requireexact.80386 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + call x86.parse_operand@src2, offs + call x86.parse_operand@aux, len + check @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') & \ + @src2.type = 'reg' & @src2.rm = 0 & @aux.type = 'reg' & @aux.size = 1 & @aux.rm = 1 + jno invalid_combination_of_operands + check @src.size and not @dest.size | @src2.size <> @dest.size + jyes operand_sizes_no_not_match + check @dest.size > 1 + jyes size_ok + err 'invalid operand size' + jump size_ok + operand_sizes_no_not_match: + err 'operand sizes do not match' + size_ok: + call x86.select_operand_prefix@src, @dest.size + xcall x86.store_instruction@src, <0Fh,0A6h>,@dest.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' +end calminstruction + +calminstruction ibts? dest*,offs*,len*,src* + call x86.requireexact.80386 + call x86.parse_operand@dest, dest + call x86.parse_operand@src, src + call x86.parse_operand@src2, offs + call x86.parse_operand@aux, len + check @src.type = 'reg' & (@dest.type = 'mem' | @dest.type = 'reg') & \ + @src2.type = 'reg' & @src2.rm = 0 & @aux.type = 'reg' & @aux.size = 1 & @aux.rm = 1 + jno invalid_combination_of_operands + check @dest.size and not @src.size | @src2.size <> @src.size + jyes operand_sizes_no_not_match + check @src.size > 1 + jyes size_ok + err 'invalid operand size' + jump size_ok + operand_sizes_no_not_match: + err 'operand sizes do not match' + size_ok: + call x86.select_operand_prefix@dest, @src.size + xcall x86.store_instruction@dest, <0Fh,0A7h>,@src.rm + exit + invalid_combination_of_operands: + err 'invalid combination of operands' +end calminstruction + +calminstruction pause? + emit 1, 0F3h + emit 1, 90h +end calminstruction + +include 'iset/fpu.inc' + +iterate , fcmovb,0DAh,0C0h, fcmove,0DAh,0C8h, fcmovbe,0DAh,0D0h, fcmovu,0DAh,0D8h, \ + fcmovnb,0DBh,0C0h, fcmovne,0DBh,0C8h, fcmovnbe,0DBh,0D0h, fcmovnu,0DBh,0D8h + + calminstruction instr? dest*,src* + call x86.require.P6 + call x87.parse_operand@dest, dest + call x87.parse_operand@src, src + check @dest.type = 'streg' & @dest.rm = 0 & @src.type = 'streg' + jyes ok + err 'invalid operand' + exit + ok: + emit 1, opcode + emit 1, postbyte + @src.rm + end calminstruction + +end iterate + +iterate , fucomi,0DBh,5, fucomip,0DFh,5, fcomi,0DBh,6, fcomip,0DFh,6 + + calminstruction instr? src:st1 + call x86.require.P6 + call x87.parse_operand@src, src + check @src.type = 'streg' + jyes ok + err 'invalid operand' + exit + ok: + emit 1, opcode + emit 1, 11b shl 6 + postbyte shl 3 + @src.rm + end calminstruction + +end iterate + +calminstruction nop? src + match , src + jno multibyte + emit 1, 90h + exit + multibyte: + call x86.require.P68 + call x86.parse_operand@src, src + check @src.type = 'mem' | @src.type = 'reg' + jyes nop_rm_reg + err 'invalid operand' + exit + nop_rm_reg: + xcall x86.select_operand_prefix@src, @src.size + xcall x86.store_instruction@src, <0Fh,1Fh>,(0) +end calminstruction + +calminstruction ud2? + emit 2, 0B0Fh +end calminstruction + +iterate , fxsave64,0, fxrstor64,1 + + calminstruction instr? src* + call x86.require.x64 + call x86.require.bits64 + call x86.parse_operand@src, src + check @src.type = 'mem' + jno invalid_operand + check @src.size and not 512 + jno size_ok + err 'invalid operand size' + size_ok: + xcall x86.select_operand_prefix@src, (8) + xcall x86.store_instruction@src, <0Fh,0AEh>,(postbyte) + exit + invalid_operand: + err 'invalid operand' + end calminstruction + +end iterate + +iterate , xsave,4, xrstor,5 + + macro instr? src* + require XSAVE + x86.parse_operand@src src + if @src.type = 'mem' + x86.store_instruction@src <0Fh,0AEh>,postbyte + else + err 'invalid operand' + end if + end macro + + macro instr#64? src* + require XSAVE + require bits64 + x86.parse_operand@src src + if @src.type = 'mem' + x86.select_operand_prefix@src 8 + x86.store_instruction@src <0Fh,0AEh>,postbyte + else + err 'invalid operand' + end if + end macro + +end iterate + +macro xgetbv? + require XSAVE + db 0Fh,1,0D0h +end macro + +macro xsetbv? + require XSAVE + db 0Fh,1,0D1h +end macro + +macro getsec? + require SMX + db 0Fh,37h +end macro + +macro monitor? arg1,arg2,arg3 + require MONITOR + match any, arg1 arg2 arg3 + if ~ arg1 eq eax | ~ arg2 eq ecx | ~ arg3 eq edx + err 'invalid combination of operands' + end if + end match + db 0Fh,01h,0C8h +end macro + +macro mwait? arg1,arg2 + require MONITOR + match any, arg1 arg2 + if ~ arg1 eq eax | ~ arg2 eq ecx + err 'invalid combination of operands' + end if + end match + db 0Fh,01h,0C9h +end macro + +iterate , rdfsbase,0, rdgsbase,1, wrfsbase,2, wrgsbase,3 + + macro instr? dest* + require FSGSBASE + require bits64 + x86.parse_operand@dest dest + if @dest.type = 'reg' + if @dest.size >= 4 + @dest.opcode_prefix = 0F3h + x86.select_operand_prefix@dest @dest.size + x86.store_instruction@dest <0Fh,0AEh>,postbyte + else + err 'invalid operand size' + end if + else + err 'invalid operand' + end if + end macro + +end iterate + +macro rdrand? dest* + require RDRAND + x86.parse_operand@dest dest + if @dest.type = 'reg' + x86.select_operand_prefix@dest @dest.size + x86.store_instruction@dest <0Fh,0C7h>,6 + else + err 'invalid operand' + end if +end macro + +macro rdseed? dest* + require RDSEED + x86.parse_operand@dest dest + if @dest.type = 'reg' + x86.select_operand_prefix@dest @dest.size + x86.store_instruction@dest <0Fh,0C7h>,7 + else + err 'invalid operand' + end if +end macro + +include 'iset/vmx.inc' +include 'iset/mpx.inc' +include 'iset/cet.inc' + +macro xacquire? instr& + require HLE + db 0F2h + instr +end macro + +macro xrelease? instr& + require HLE + db 0F3h + instr +end macro + +macro xtest? + require HLE + db 0Fh,1,0D6h +end macro + +macro xbegin? dest* + require RTM + x86.parse_jump_operand@dest dest + if @dest.type = 'imm' & ~ @dest.jump_type + if x86.mode shr 3 <> @dest.size + err 'invalid operand size' + end if + if x86.mode = 16 + db 0C7h,0F8h + dw @dest.imm-($+2) + else + if ~ $ relativeto 0 & @dest.imm relativeto 0 + @dest.imm = @dest.imm + $ - 0 scaleof $ + err 'invalid address' + end if + if @dest.unresolved | ( @dest.imm relativeto $ & @dest.imm-($+5) < 8000h & @dest.imm-($+5) >= -8000h ) + db 66h,0C7h,0F8h + dw @dest.imm-($+2) + else + db 0C7h,0F8h + dd @dest.imm-($+4) + end if + end if + else + err 'invalid operand' + end if +end macro + +macro xabort? imm* + require RTM + db 0C6h,0F8h,imm +end macro + +macro xend? + require RTM + db 0Fh,1,0D5h +end macro + +macro xtest? + require RTM + db 0Fh,1,0D6h +end macro + +iterate , adcx,66h, adox,0F3h + + macro instr? dest*,src* + require ADX + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'reg') + if @src.size <> 0 & @src.size <> @dest.size + err 'operand sizes do not match' + end if + if @dest.size = 8 & x86.mode = 64 + @src.prefix = 48h + else if @dest.size <> 4 + err 'invalid operand size' + end if + @src.opcode_prefix = pfx + x86.store_instruction@src <0Fh,38h,0F6h>,@dest.rm + else + err 'invalid combination of operands' + end if + end macro + +end iterate + +macro movbe? dest*,src* + require MOVBE + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.size & @src.size & @src.size <> @dest.size + err 'operand sizes do not match' + end if + if @dest.type = 'reg' & @src.type = 'mem' & @dest.size > 1 + x86.select_operand_prefix@src @dest.size + x86.store_instruction@src <0Fh,38h,0F0h>,@dest.rm + else if @dest.type = 'mem' & @src.type = 'reg' & @src.size > 1 + x86.select_operand_prefix@dest @src.size + x86.store_instruction@dest <0Fh,38h,0F1h>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro movdiri? dest*,src* + require MOVDIRI + x86.parse_operand@dest dest + x86.parse_operand@src src + if @src.type = 'reg' & @dest.type = 'mem' + if @dest.size <> 0 & @src.size <> @dest.size + err 'operand sizes do not match' + end if + if @src.size = 8 & x86.mode = 64 + @dest.prefix = 48h + else if @src.size <> 4 + err 'invalid operand size' + end if + x86.store_instruction@dest <0Fh,38h,0F9h>,@src.rm + else + err 'invalid combination of operands' + end if +end macro + +macro movdir64b? dest*,src* + require MOVDIR64B + x86.parse_operand@dest dest + x86.parse_operand@src src + if @dest.type = 'reg' & @src.type = 'mem' + if @src.size and not 64 + err 'invalid operand size' + end if + if (@src.mode = 16 & @dest.size <> 2) | (@src.mode = 32 & @dest.size <> 4) | (@src.mode = 64 & @dest.size <> 8) + err 'invalid operand size' + end if + @src.opcode_prefix = 66h + x86.store_instruction@src <0Fh,38h,0F8h>,@dest.rm + else + err 'invalid combination of operands' + end if +end macro + +include 'iset/mmx.inc' +include 'iset/sse.inc' +include 'iset/sse2.inc' +include 'iset/sse3.inc' +include 'iset/sse4.inc' + +include 'iset/avx.inc' +include 'iset/bmi.inc' + +include 'iset/aes.inc' +include 'iset/gfni.inc' +include 'iset/pclmulqdq.inc' + +include 'iset/3dnow.inc' diff --git a/toolchain/fasm2/include/xcalm.inc b/toolchain/fasm2/include/xcalm.inc new file mode 100644 index 0000000..4b7ba89 --- /dev/null +++ b/toolchain/fasm2/include/xcalm.inc @@ -0,0 +1,69 @@ + +; Helper commands for writing CALM instructions + +; INIT +; this command can be used to give an initial numeric value to local variable +; at the time when the CALM instruction is defined +calminstruction calminstruction?.init? var*, val:0 + compute val, val + publish var, val +end calminstruction + +; INITSYM +; this command can be used to give an initial symbolic value to local variable +; at the time when the CALM instruction is defined +; (any symbols in the value also keep the context of that instruction's namespace) +calminstruction calminstruction?.initsym? var*, val& + publish var, val +end calminstruction + +; ASM +; generates code to assemble given line of text as-is +; (any symbols in this text keep the context of the instruction's namespace) +calminstruction calminstruction?.asm? line& + local name, i + initsym name, name.0 + match name.i, name + compute i, i+1 + arrange name, name.i + publish name:, line + arrange line, =assemble name + assemble line +end calminstruction + +; XCALL +; extends the CALL command with the ability to define some arguments as literal values; +; arguments enclosed with () are treated as numeric, +; ones enclosed with <> are treated as a text of symbolic value +calminstruction calminstruction?.xcall? instruction*, arguments& + arrange instruction, =call instruction + convert: + match , arguments + jyes ready + local v + match v?=,arguments?, arguments, <> + jyes recognize + arrange v, arguments + arrange arguments, + recognize: + match (v), v + jyes numeric + match , v + jyes symbolic + append: + arrange instruction, instruction=,v + jump convert + numeric: + compute v, v + symbolic: + local proxy, base, i + initsym base, proxy + initsym i, 0 + compute i, i+1 + arrange proxy, base.i + publish proxy, v + arrange instruction, instruction=,proxy + jump convert + ready: + assemble instruction +end calminstruction diff --git a/toolchain/fasm2/license.txt b/toolchain/fasm2/license.txt new file mode 100644 index 0000000..b995270 --- /dev/null +++ b/toolchain/fasm2/license.txt @@ -0,0 +1,25 @@ +flat assembler 2 +flat assembler g +Copyright (c) 1999-2024, Tomasz Grysztar +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/toolchain/fasm2/source/assembler.inc b/toolchain/fasm2/source/assembler.inc new file mode 100644 index 0000000..2eaba21 --- /dev/null +++ b/toolchain/fasm2/source/assembler.inc @@ -0,0 +1,3383 @@ + +; general note: +; with the ability to run in various environments in mind, the entire assembler core +; does not use ebp register and never directly touches esp; the stack is managed +; with push and pop instructions, occasionally [esp] may be used to access the top value, +; but no other assumptions about the stack layout are made + +struct Workspace + memory_start dd ? + memory_end dd ? +ends + +struct SourceContext + number_of_entries dd ? + ; entries SourceEntry[] +ends + +struct SourceEntry + type db ? ; SOURCE_# + flags db ? ; SRCF_# + saved_result db ? + reserved db ? + name dd ? + name_length dd ? + text dd ? + offset dd ? + line_number dd ? + number_of_attached_lines dd ? + line_offset dd ? + local_namespace dd ? +ends + +struct RecognitionContext + base_namespace dd ? ; SymbolTree_Root + base_label dd ? ; SymbolTree_Foliage +ends + +struct LineEmbedding + previous_pointer dd ? + previous_end dd ? + recognition_context dd ? + definition dd ? + whitespace dd ? +ends + +struct LineExcerpt + data_start dd ? + data_end dd ? + recognition_context dd ? + leftover_context dd ? +ends + +SOURCE_FILE = 0 +SOURCE_MEMORY = 1 +SOURCE_MACRO = 2 +SOURCE_CALM = 3 + +SRCF_PREPROCESSED = 1 +SRCF_ALM_STATEMENT = 2 + +PMODE_RETAIN_COMMENTS = 1 +PMODE_ISOLATE_LINES = 2 + +AMODE_SKIP = 1 +AMODE_DEFINITION = 2 +AMODE_POSTPONED = 4 +AMODE_CALM_DEFINITION = 8 + +TRACE_ERROR_STACK = 1 +TRACE_DISPLAY = 2 + +assembly_init: +; in: +; al = any combination of TRACE_# flags + + mov [trace_mode],al + + xor eax,eax + mov edi,variables + mov ecx,(variables_end - variables) shr 2 + rep stosd + if (variables_end - variables) and 11b + mov cl,(variables_end - variables) and 11b + rep stosb + end if + mov edi,characters + prepare_characters: + stosb + inc al + jnz prepare_characters + mov esi,characters+'a' + mov edi,characters+'A' + mov ecx,'z'+1-'a' + rep movsb + mov edi,characters + mov esi,control_characters + mov cl,control_characters.count + mark_control_characters: + lodsb + mov byte [edi+eax],20h + loop mark_control_characters + mov esi,syntactical_characters + mov cl,syntactical_characters.count + mark_syntactical_characters: + lodsb + mov byte [edi+eax],0 + loop mark_syntactical_characters + + mov esi,include_variable + xor ecx,ecx + call get_environment_variable + mov ecx,eax + call malloc_fixed + mov [include_paths],eax + mov edi,eax + call get_environment_variable + + mov cl,10 + call create_string_map + mov [file_source_cache],ebx + + mov cl,12 + call create_string_map + mov [memory_source_cache],ebx + + mov cl,10 + call create_string_map + mov [file_data_cache],ebx + + mov cl,7 + call create_string_map + mov [auxiliary_output_areas],ebx + + mov ecx,sizeof.SymbolTree_Root + sizeof.SymbolTree_Node + call create_tree_element + mov [root_namespace],eax + + call create_parameter_namespace + mov [root_parameter_namespace],eax + + mov ecx,4*sizeof.SymbolTree_Leaf + call create_tree_element + mov [eax+SymbolTree_Leaf.class],SYMCLASS_INSTRUCTION + mov [eax+SymbolTree_Leaf.flags],SYM_VARIABLE + mov [interceptor_symbol],eax + add eax,sizeof.SymbolTree_Leaf + mov [eax+SymbolTree_Leaf.class],SYMCLASS_STRUCTURE + mov [eax+SymbolTree_Leaf.flags],SYM_VARIABLE + mov [label_interceptor_symbol],eax + add eax,sizeof.SymbolTree_Leaf + mov [eax+SymbolTree_Leaf.class],SYMCLASS_INSTRUCTION + mov [eax+SymbolTree_Leaf.flags],SYM_VARIABLE + mov [other_interceptor_symbol],eax + add eax,sizeof.SymbolTree_Leaf + mov [void_symbol],eax + + mov ecx,400 + call malloc_growable + mov [tree_stack_base],eax + add eax,ecx + mov [tree_stack_end],eax + + mov ecx,4000 + call malloc_growable + mov [source_context],eax + mov [source_context_maximum_length],ecx + + mov ecx,1000 + call malloc_growable + mov [line_embeddings],eax + mov [line_embeddings_maximum_length],ecx + + mov ecx,1000 + call malloc_growable + mov [display_buffer],eax + mov [display_buffer_length],ecx + + mov ecx,1000 + call malloc_growable + mov [macro_buffer],eax + mov [macro_buffer_length],ecx + + mov ecx,32*6*sizeof.ExpressionTerm + call malloc_fixed + mov [temporary_terms],eax + mov [free_temporary_terms],eax + + mov ecx,4*sizeof.FloatData + call malloc_fixed + mov [temporary_floats],eax + + mov ecx,400 + call malloc_growable + mov [output_areas_list],eax + mov edi,eax + add eax,ecx + mov [output_areas_list_end],eax + xor eax,eax + shr ecx,2 + rep stosd + mov [number_of_line_embeddings],eax + mov [virtual_area],eax + + mov ecx,1000 + call malloc_growable + mov [directives_stack_base],eax + add eax,ecx + mov [directives_stack_end],eax + + mov ecx,1000 + call malloc_growable + mov [counters_stack_base],eax + add eax,ecx + mov [counters_stack_end],eax + + mov ecx,400 + call malloc_growable + mov [operator_stack_base],eax + add eax,ecx + mov [operator_stack_end],eax + + mov ecx,400 + call malloc_growable + mov [condition_stack_base],eax + add eax,ecx + mov [condition_stack_end],eax + + mov ecx,400 + call malloc_growable + mov [assembly_stack_base],eax + add eax,ecx + mov [assembly_stack_end],eax + + mov edx,preprocessing_workspace + call initialize_workspace + + mov edx,assembly_workspace + call initialize_workspace + + mov edx,identifier_workspace + call initialize_workspace + + mov edx,auxiliary_workspace + call initialize_workspace + + mov edx,value_workspace + call initialize_workspace + + mov edx,expression_workspace + call initialize_workspace + + mov edx,calculation_workspace + call initialize_workspace + + mov edx,calm_code_buffer + call initialize_workspace + + mov edx,calm_literals_buffer + call initialize_workspace + + mov edx,calm_auxiliary_buffer + call initialize_workspace + + mov ecx,256*4 + call malloc_fixed + mov [operator_table],eax + mov edi,eax + mov ecx,256 + xor eax,eax + rep stosd + mov esi,separating_operators + register_operators: + lodsb + test al,al + jz operators_registered + movzx ebx,al + shl ebx,2 + add ebx,[operator_table] + mov ecx,sizeof.ValueDefinition + call create_tree_element + mov edx,eax + xchg [ebx],eax + mov [edx+ValueDefinition.previous],eax + inc [edx+ValueDefinition.reference_count] + lodsb + mov [edx+ValueDefinition.type],al + lodsb + mov [edx+ValueDefinition.flags],al + lodsb + mov [edx+ValueDefinition.attribute],al + lodsd + mov [edx+ValueDefinition.value],eax + jmp register_operators + operators_registered: + + xor eax,eax + mov [name_volatile],al + mov [name_token],eax + mov [name_kind],NAME_CASEINSENSITIVE + or [symbol_required],1 + or [symbol_expected],1 + mov eax,[root_namespace] + mov [current_context.base_namespace],eax + mov esi,symbols + register_internal_symbols: + lodsb + test al,al + jnz prepare_internal_symbol + lodsb + test al,al + jz internal_symbols_registered + and [current_context.base_namespace],0 + prepare_internal_symbol: + movzx ecx,al + + xor ebx,ebx + mov edx,FNV_OFFSET + hash_internal_symbol: + movzx eax,byte [esi+ebx] + xor dl,[characters+eax] + imul edx,FNV_PRIME + inc ebx + cmp ebx,ecx + jb hash_internal_symbol + + mov ebx,[current_context.base_namespace] + test ebx,ebx + jz register_internal_namespace + mov al,[esi+ecx] + mov [symbol_class],al + push esi + call scan_namespace + pop esi + add esi,ecx + mov ecx,sizeof.ValueDefinition + call create_tree_element + mov edx,eax + xchg [ebx+SymbolTree_Leaf.definition],eax + mov [edx+ValueDefinition.previous],eax + inc [edx+ValueDefinition.reference_count] + lodsb + lodsb + mov [edx+ValueDefinition.type],al + lodsb + mov [edx+ValueDefinition.flags],al + lodsb + mov [edx+ValueDefinition.attribute],al + lodsd + mov [edx+ValueDefinition.value],eax + jmp register_internal_symbols + register_internal_namespace: + mov [symbol_class],SYMCLASS_EXPRESSION + mov ebx,[root_namespace] + push esi + call scan_namespace + pop esi + add esi,ecx + mov ecx,sizeof.ValueDefinition + call create_tree_element + mov [ebx+SymbolTree_Leaf.definition],eax + inc [eax+ValueDefinition.reference_count] + mov [eax+ValueDefinition.type],VALTYPE_RESERVED + mov [eax+ValueDefinition.flags],VAL_INTERNAL + call get_symbol_namespace + mov [current_context.base_namespace],ebx + jmp register_internal_symbols + internal_symbols_registered: + + retn + +assembly_shutdown: + + call discard_errors + + mov ebx,[auxiliary_output_areas] + test ebx,ebx + jz auxiliary_output_areas_released + call destroy_string_map + auxiliary_output_areas_released: + + mov ebx,[value_definition_chain] + release_values_from_chain: + test ebx,ebx + jz values_released + cmp [ebx+ValueDefinition.block_length],0 + je release_next_value + mov eax,[ebx+ValueDefinition.value] + call mfree + release_next_value: + mov ebx,[ebx+ValueDefinition.interlink] + jmp release_values_from_chain + values_released: + + mov eax,[include_paths] + call mfree + + mov ebx,[file_source_cache] + test ebx,ebx + jz file_source_cache_released + mov edi,mfree + call iterate_through_map + mov ebx,[file_source_cache] + call destroy_string_map + file_source_cache_released: + + mov ebx,[file_data_cache] + test ebx,ebx + jz file_data_cache_released + mov edi,release_file_data + call iterate_through_map + mov ebx,[file_data_cache] + call destroy_string_map + file_data_cache_released: + + mov ebx,[memory_source_cache] + test ebx,ebx + jz memory_source_cache_released + mov edi,mfree + call iterate_through_map + mov ebx,[memory_source_cache] + call destroy_string_map + memory_source_cache_released: + + mov eax,[tree_stack_base] + call mfree + mov eax,[source_context] + call mfree + mov eax,[line_embeddings] + call mfree + mov eax,[output_areas_list] + call mfree + mov eax,[directives_stack_base] + call mfree + mov eax,[counters_stack_base] + call mfree + mov eax,[operator_stack_base] + call mfree + mov eax,[condition_stack_base] + call mfree + mov eax,[assembly_stack_base] + call mfree + + mov eax,[preprocessing_workspace.memory_start] + call mfree + mov eax,[assembly_workspace.memory_start] + call mfree + mov eax,[identifier_workspace.memory_start] + call mfree + mov eax,[value_workspace.memory_start] + call mfree + mov eax,[expression_workspace.memory_start] + call mfree + mov eax,[calculation_workspace.memory_start] + call mfree + mov eax,[auxiliary_workspace.memory_start] + call mfree + mov eax,[calm_code_buffer.memory_start] + call mfree + mov eax,[calm_literals_buffer.memory_start] + call mfree + mov eax,[calm_auxiliary_buffer.memory_start] + call mfree + + mov eax,[display_buffer] + call mfree + mov eax,[macro_buffer] + call mfree + mov eax,[temporary_terms] + call mfree + mov eax,[temporary_floats] + call mfree + mov eax,[operator_table] + call mfree + + mov eax,[tree_blocks] + call release_chained_blocks + + mov eax,[storage_blocks] + call release_chained_blocks + + retn + + release_chained_blocks: + test eax,eax + jz blocks_released + mov ebx,[eax] + call mfree + mov eax,ebx + jmp release_chained_blocks + blocks_released: + retn + + release_file_data: + test eax,eax + jz file_data_released + mov ebx,[eax+FileData.cache] + call mfree + release_file_cache: + mov eax,ebx + test eax,eax + jz file_data_released + mov ebx,[ebx+FileCache.next] + call mfree + jmp release_file_cache + file_data_released: + retn + + release_auxiliary_output: + test eax,eax + jz auxiliary_output_released + dec [eax+ValueDefinition.reference_count] + xor eax,eax + mov [edx+MapEntry.value],eax + auxiliary_output_released: + retn + +assembly_pass: +; in: +; esi - ASCIIZ string containing source text +; edx - path to source file +; out: +; cf clear if another pass is needed +; note: +; if both string and file sources are present, they are assembled as combined text + mov [source_file],edx + inc [current_pass] + call discard_errors + mov eax,[directives_stack_base] + mov [directives_stack],eax + mov eax,[root_namespace] + mov [current_context.base_namespace],eax + mov edx,[counters_stack_base] + mov [current_counter],edx + xor eax,eax + mov [edx],al + mov [preprocessing_mode],al + mov [next_pass_needed],al + mov [assembly_mode],al + mov [use_raw_values],al + mov [shift_tracking],al + mov [current_area],eax + mov [current_output_area_entry],eax + mov [initial_output_area_entry],eax + mov [predicted_shift],eax + mov [display_data_length],eax + mov [macro_end_position],eax + mov [proxy_number],eax + mov [output_extension],eax + mov [output_extension_length],eax + mov ebx,[source_context] + mov [ebx+SourceContext.number_of_entries],eax + add ebx,sizeof.SourceContext + mov edi,ebx + mov ecx,sizeof.SourceEntry shr 2 + assert sizeof.SourceEntry and 11b = 0 + rep stosd + mov [line_start],eax + mov [line_end],eax + test esi,esi + jz read_main_source_file + cmp byte [esi],0 + je read_main_source_file + push ebx + call use_source + pop ebx + mov [ebx+SourceEntry.type],SOURCE_MEMORY + jmp fill_main_source_entry + read_main_source_file: + mov esi,[source_file] + test esi,esi + jz no_source_to_assemble + cmp byte [esi],0 + je no_source_to_assemble + push ebx + call read_source + pop ebx + test eax,eax + jz main_source_file_not_found + mov [ebx+SourceEntry.type],SOURCE_FILE + fill_main_source_entry: + mov [ebx+SourceEntry.name],esi + mov [ebx+SourceEntry.text],eax + mov eax,[root_parameter_namespace] + and [eax+SymbolTree_Root.parameters],0 + mov [local_parameter_namespace],eax + mov [ebx+SourceEntry.local_namespace],eax + mov ebx,[source_context] + inc [ebx+SourceContext.number_of_entries] + mov esi,zero_value + mov ecx,4+4 + call create_output_area + mov [current_area],edx + inc [edx+ValueDefinition.reference_count] + mov ebx,[auxiliary_output_areas] + mov edi,release_auxiliary_output + call iterate_through_map +assembly_line: + xor eax,eax + mov [value_position],eax + mov [current_constituent],al + call clear_line_embeddings + get_line: + xor eax,eax + mov [symbol_class],SYMCLASS_PARAMETER + mov [symbol_expected],al + mov [symbol_required],al + mov [name_volatile],al + mov [preprocessed_context],eax + mov [alm_statement],al + mov ebx,[source_context] + mov ecx,[ebx+SourceContext.number_of_entries] + dec ecx + imul ecx,sizeof.SourceEntry + lea ebx,[ebx+sizeof.SourceContext+ecx] + xchg eax,[ebx+SourceEntry.number_of_attached_lines] + inc eax + add [ebx+SourceEntry.line_number],eax + cmp [ebx+SourceEntry.type],SOURCE_CALM + je calm_virtual_machine + mov eax,[ebx+SourceEntry.local_namespace] + mov [parameter_namespace],eax + xor edx,edx + test [eax+SymbolTree_Root.flags],NAMESPACE_UNATTACHED + jnz no_local_namespace + mov edx,eax + mov ecx,[eax+SymbolTree_Root.current_label] + test ecx,ecx + jnz local_namespace_ok + no_local_namespace: + mov eax,[current_context.base_namespace] + mov ecx,[eax+SymbolTree_Root.current_label] + local_namespace_ok: + mov [local_namespace],edx + mov [current_context.base_label],ecx + cmp [ebx+SourceEntry.type],SOURCE_MACRO + je get_line_from_macro + and [name_token],0 + mov esi,[ebx+SourceEntry.text] + mov eax,[ebx+SourceEntry.offset] + add esi,eax + mov [ebx+SourceEntry.line_offset],eax + cmp byte [esi],0 + je source_ended + mov edi,[preprocessing_workspace.memory_start] + preprocess_line_from_file: + mov ecx,14 + mov edx,preprocessing_workspace + call reserve_workspace + lodsb + cmp al,1Ah + je convert_name_symbol + cmp al,22h + je convert_quoted_string + cmp al,27h + je convert_quoted_string + test al,al + jz file_ended + cmp al,0Ah + je line_ended + cmp al,';' + jne preprocess_syntactical_character + xor edx,edx + test [preprocessing_mode],PMODE_RETAIN_COMMENTS + jz skip_comment + preprocess_syntactical_character: + stosb + cmp al,'`' + je convert_parameter + cmp al,'\' + jne preprocess_line_from_file + test [preprocessing_mode],PMODE_ISOLATE_LINES + jnz preprocess_line_from_file + mov edx,esi + detect_line_concatenation: + mov al,[edx] + inc edx + cmp al,0Ah + je concatenate_line + cmp al,';' + je concatenation_comment + cmp al,20h + jne preprocess_line_from_file + jmp detect_line_concatenation + concatenate_line: + mov byte [edi-1],20h + inc esi + inc [ebx+SourceEntry.number_of_attached_lines] + jmp preprocess_line_from_file + concatenation_comment: + test [preprocessing_mode],PMODE_RETAIN_COMMENTS + jnz preprocess_line_from_file + mov byte [edi-1],20h + mov esi,edx + inc [ebx+SourceEntry.number_of_attached_lines] + skip_comment: + lodsb + test al,al + jz file_ended + cmp al,0Ah + je comment_ended + cmp al,22h + je skip_quoted_string + cmp al,27h + je skip_quoted_string + cmp al,1Ah + jne skip_comment + lodsd + lea esi,[esi+eax+12] + jmp skip_comment + comment_ended: + test edx,edx + jnz preprocess_line_from_file + jmp line_ended + skip_quoted_string: + lodsd + add esi,eax + jmp skip_comment + convert_quoted_string: + stosb + mov eax,esi + stosd + lodsd + add esi,eax + jmp preprocess_line_from_file + convert_name_symbol: + mov ecx,[esi] + lea eax,[esi+4+ecx+12] + push eax ebx + mov eax,[eax-4] + test eax,eax + jz name_symbol_not_cached + mov esi,eax + name_symbol_not_cached: + call preprocess_symbol + name_symbol_converted: + pop ebx esi + jmp preprocess_line_from_file + convert_parameter: + cmp byte [esi],1Ah + jne preprocess_line_from_file + lodsb + mov ecx,[esi] + lea eax,[esi+4+ecx+12] + push eax ebx + mov eax,[eax-4] + test eax,eax + jz parameter_to_convert_not_cached + mov esi,eax + parameter_to_convert_not_cached: + call preprocess_symbol + jc name_symbol_converted + call convert_parameter_to_string + jmp name_symbol_converted + file_ended: + dec esi + line_ended: + sub esi,[ebx+SourceEntry.text] + mov [ebx+SourceEntry.offset],esi + jmp line_preprocessed + source_ended: + mov ebx,[source_context] + dec [ebx+SourceContext.number_of_entries] + jnz get_line + cmp [ebx+sizeof.SourceContext+SourceEntry.type],SOURCE_MEMORY + jne no_more_lines + mov esi,[source_file] + test esi,esi + jz no_more_lines + cmp byte [esi],0 + je no_more_lines + lea edi,[ebx+sizeof.SourceContext] + mov ecx,sizeof.SourceEntry shr 2 + assert sizeof.SourceEntry and 11b = 0 + xor eax,eax + rep stosd + call read_source + test eax,eax + jz main_source_file_not_found + mov ebx,[source_context] + inc [ebx+SourceContext.number_of_entries] + add ebx,sizeof.SourceContext + mov [ebx+SourceEntry.type],SOURCE_FILE + mov [ebx+SourceEntry.name],esi + mov [ebx+SourceEntry.text],eax + mov eax,[parameter_namespace] + mov [ebx+SourceEntry.local_namespace],eax + jmp get_line + no_more_lines: + jmp pass_done + get_line_from_macro: + mov edx,[ebx+SourceEntry.text] + mov esi,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + mov eax,[ebx+SourceEntry.offset] + test [ebx+SourceEntry.flags],SRCF_PREPROCESSED + jnz use_preprocessed_line + add ecx,esi + mov [source_end],ecx + add esi,eax + cmp esi,[source_end] + je macro_ended + mov [ebx+SourceEntry.line_offset],eax + mov edi,[preprocessing_workspace.memory_start] + preprocess_line_from_macro: + cmp esi,[source_end] + je macro_line_ended + mov ecx,14 + mov edx,preprocessing_workspace + call reserve_workspace + lodsb + cmp al,1Ah + je reproduce_name_symbol + test al,al + jz macro_line_ended + stosb + cmp al,22h + je reproduce_quoted_string + cmp al,27h + je reproduce_quoted_string + cmp al,30h + je reproduce_internal_token + cmp al,40h + je reproduce_context_token + cmp al,'`' + je conversion_operator_in_macro + jmp preprocess_line_from_macro + reproduce_quoted_string: + movsd + jmp preprocess_line_from_macro + reproduce_internal_token: + mov ecx,[esi] + add ecx,4 + mov edx,preprocessing_workspace + call reserve_workspace + lodsd + stosd + mov ecx,eax + rep movsb + jmp preprocess_line_from_macro + reproduce_context_token: + mov [preprocessed_context],esi + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + cmp esi,[source_end] + je macro_line_ended + cmp byte [esi],40h + jne preprocess_line_from_macro + inc esi + sub edi,sizeof.RecognitionContext + jmp reproduce_context_token + reproduce_name_symbol: + mov [name_token],esi + lodsd + push esi ebx + mov esi,eax + call preprocess_symbol + name_symbol_reproduced: + pop ebx esi + jmp preprocess_line_from_macro + conversion_operator_in_macro: + cmp esi,[source_end] + je macro_ended + cmp byte [esi],1Ah + jne preprocess_line_from_macro + inc esi + mov [name_token],esi + lodsd + push esi ebx + mov esi,eax + call preprocess_symbol + jc name_symbol_reproduced + call convert_parameter_to_string + jmp name_symbol_reproduced + convert_parameter_to_string: + call convert_symbolic_value_to_string + mov ebx,[memory_source_cache] + xor eax,eax + call put_into_map + mov edi,[symbol_value_start] + dec edi + mov al,22h + stosb + mov eax,esi + stosd + retn + macro_ended: + mov edx,[ebx+SourceEntry.text] + and [edx+ValueDefinition.flags],not VAL_IN_USE + dec [edx+ValueDefinition.reference_count] + mov ebx,[source_context] + dec [ebx+SourceContext.number_of_entries] + jnz get_line + jmp pass_done + use_preprocessed_line: + test eax,eax + jnz macro_ended + dec eax + mov [ebx+SourceEntry.offset],eax + add ecx,esi + mov [line_start],esi + mov [line_end],ecx + jmp got_line + macro_line_ended: + mov edx,[ebx+SourceEntry.text] + sub esi,[edx+ValueDefinition.value] + mov [ebx+SourceEntry.offset],esi + line_preprocessed: + mov [line_end],edi + mov esi,[preprocessing_workspace.memory_start] + mov [line_start],esi + got_line: + and [line_context],0 +assemble_instruction: + mov ebx,[interceptor_symbol] + call get_available_value + jc no_interceptor + test [edx+ValueDefinition.flags],VAL_UNCONDITIONAL + jz weak_interceptor + jmp execute_instruction + no_interceptor: + xor edx,edx + weak_interceptor: + mov [interceptor],edx + xor eax,eax + mov [label_interceptor],eax + test [assembly_mode],AMODE_CALM_DEFINITION + jnz assemble_alm_instruction + mov [symbol_definition],al + mov [instruction_branch],eax + mov dl,SYMCLASS_INSTRUCTION + call identify_symbol + jc empty_line + mov [label_branch],edx + mov al,[symbol_independent] + mov [label_independent],al + test ebx,ebx + jz unrecognized_instruction + cmp [ebx+SymbolTree_Leaf.class],SYMCLASS_INSTRUCTION + jne labeled_instruction + cmp [symbol_independent],-1 + je unrecognized_instruction + call get_available_value + jc unrecognized_instruction + test [edx+ValueDefinition.flags],VAL_UNCONDITIONAL + jnz execute_instruction + cmp [interceptor],0 + jne unrecognized_instruction + test [assembly_mode],AMODE_SKIP or AMODE_DEFINITION + jnz unrecognized_instruction + execute_instruction: + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_CALM + je launch_calm + cmp al,VALTYPE_NATIVE_COMMAND + je execute_native_instruction + cmp al,VALTYPE_SYMBOLIC + je use_macro + cmp al,VALTYPE_RESERVED + jne unrecognized_instruction + mov edx,_symbolic_self_reference + call register_error + unrecognized_instruction: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + cmp [interceptor],0 + jne execute_interceptor + cmp [label_interceptor],0 + jne execute_label_interceptor + mov ebx,[other_interceptor_symbol] + call get_available_value + jnc execute_other_interceptor + mov edx,_illegal_instruction + call register_error + mov ebx,[label_branch] + test ebx,ebx + jz assembly_line + mov [symbol_class],SYMCLASS_INSTRUCTION + or [symbol_required],1 + or [symbol_expected],1 + call scan_symbol_branch + xor edx,edx + call mark_symbol_as_used + mov ebx,[instruction_branch] + test ebx,ebx + jz assembly_line + mov [symbol_class],SYMCLASS_STRUCTURE + or [symbol_required],1 + or [symbol_expected],1 + call scan_symbol_branch + xor edx,edx + call mark_symbol_as_used + jmp assembly_line + labeled_instruction: + mov [label_leaf],ebx + mov [label_instruction_start],esi + mov ebx,[label_interceptor_symbol] + call get_available_value + jc no_label_interceptor + test [edx+ValueDefinition.flags],VAL_UNCONDITIONAL + jnz execute_labeled_instruction + mov [label_interceptor],edx + mov eax,[embedded_context] + mov [label_instruction_context],eax + jmp identify_structure_instruction + no_label_interceptor: + call move_to_next_symbol + jc unrecognized_instruction ; orphan label + cmp al,':' + je define_label + cmp al,'=' + je define_numeric_symbol + identify_structure_instruction: + mov dl,SYMCLASS_STRUCTURE + call identify_symbol + mov [instruction_branch],edx + test ebx,ebx + jz unrecognized_instruction + cmp [ebx+SymbolTree_Leaf.class],SYMCLASS_STRUCTURE + jne unrecognized_instruction + call get_available_value + jc unrecognized_instruction + test [edx+ValueDefinition.flags],VAL_UNCONDITIONAL + jnz execute_labeled_instruction + test [assembly_mode],AMODE_SKIP or AMODE_DEFINITION + jnz unrecognized_instruction + cmp [interceptor],0 + jne execute_interceptor + cmp [label_interceptor],0 + jne execute_label_interceptor + execute_labeled_instruction: + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_CALM + je launch_calm + cmp al,VALTYPE_SYMBOLIC + je use_struc + cmp al,VALTYPE_NATIVE_COMMAND + jne unrecognized_instruction + execute_native_instruction: + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + jmp [edx+ValueDefinition.value] + empty_line: + mov al,[assembly_mode] + and al,AMODE_SKIP or AMODE_DEFINITION + cmp al,AMODE_DEFINITION + je add_line_to_macro + jmp assembly_line + execute_interceptor: + mov ebx,[interceptor_symbol] + mov edx,[interceptor] + xor eax,eax + mov [embedded_context],eax + mov esi,[line_start] + jmp execute_instruction + execute_label_interceptor: + mov ebx,[label_interceptor_symbol] + mov edx,[label_interceptor] + mov eax,[label_instruction_context] + mov [embedded_context],eax + mov esi,[label_instruction_start] + cmp [edx+ValueDefinition.type],VALTYPE_CALM + je launch_calm + jmp use_struc + execute_other_interceptor: + mov ebx,[other_interceptor_symbol] + xor eax,eax + mov [embedded_context],eax + mov esi,[line_start] + jmp execute_instruction +instruction_assembled: + cmp [current_constituent],0 + jne extra_characters_on_line + call warp_to_next_symbol + jc assembly_line + extra_characters_on_line: + mov edx,_extra_characters_on_line + call register_error + jmp assembly_line + pass_done: + mov dl,DBLOCK_CONTROL + call find_directive_block + jc assemble_postponed_block + mov esi,edi + sub esi,[edi+DirectiveBlock.length_of_data] + mov edx,_missing_end_directive + call register_delayed_error + call close_control_directive_block + jmp pass_done + assemble_postponed_block: + mov dl,DBLOCK_POSTPONED + call find_directive_block + jc no_postponed_blocks + mov ebx,edi + mov esi,edi + sub esi,[edi+DirectiveBlock.length_of_data] + mov edi,[source_context] + call clone_source_context + mov edi,ebx + call close_directive_block + or [assembly_mode],AMODE_POSTPONED + jmp assembly_line + no_postponed_blocks: + mov ebx,[root_namespace] + call detect_mispredictions + assemble_suspended_block: + mov dl,DBLOCK_SUSPENDED + call find_directive_block + jc no_suspended_blocks + cmp [next_pass_needed],0 + jne ignore_suspended_block + mov ebx,edi + mov esi,edi + sub esi,[edi+DirectiveBlock.length_of_data] + mov edi,[source_context] + call clone_source_context + mov edi,ebx + call close_directive_block + or [assembly_mode],AMODE_POSTPONED + jmp assembly_line + ignore_suspended_block: + call close_directive_block + jmp assemble_suspended_block + no_suspended_blocks: + mov esi,[directives_stack] + signal_unclosed_blocks: + cmp esi,[directives_stack_base] + je unclosed_blocks_signalled + sub esi,sizeof.DirectiveBlock + mov eax,[esi+DirectiveBlock.length_of_data] + sub esi,eax + mov edx,_missing_end_directive + call register_delayed_error + jmp signal_unclosed_blocks + unclosed_blocks_signalled: + xor eax,eax + xchg eax,[current_area] + dec [eax+ValueDefinition.reference_count] + mov al,[next_pass_needed] + sub al,1 + retn + main_source_file_not_found: + mov ebx,esi + mov edx,_source_file_not_found + call register_error + no_source_to_assemble: + mov esi,zero_value + mov ecx,4+4 + call create_output_area + mov [current_area],edx + inc [edx+ValueDefinition.reference_count] + stc + retn + +initialize_workspace: +; in: +; edx - Workspace +; preserves: ebx, edx, esi, edi + push edx + mov ecx,1000h + call malloc_growable + pop edx + mov [edx+Workspace.memory_start],eax + add eax,ecx + mov [edx+Workspace.memory_end],eax + retn + +reserve_workspace: +; in: +; edx - Workspace +; edi - top of used workspace area +; ecx = size of required reserve +; out: +; cf set if workspace had to be expanded +; edi - top of used workspace area (possibly relocated when cf is set) +; preserves: ebx, edx, esi + mov eax,[edx+Workspace.memory_end] + sub eax,ecx + jc not_enough_workspace + cmp edi,eax + ja not_enough_workspace + clc + retn + not_enough_workspace: + add ecx,edi + jc allocation_overflow + sub ecx,[edx+Workspace.memory_start] + push ecx + bsr eax,ecx + xchg ecx,eax + dec cl + shr eax,cl + inc eax + shl eax,cl + mov ecx,eax + pop eax + cmp ecx,eax + jbe allocation_overflow + cmp edi,[edx+Workspace.memory_start] + je reestablish_workspace + expand_workspace: + mov eax,[edx+Workspace.memory_start] + sub edi,eax + push edx + call realloc + pop edx + update_workspace: + mov [edx+Workspace.memory_start],eax + add edi,eax + add eax,ecx + mov [edx+Workspace.memory_end],eax + stc + retn + reestablish_workspace: + push edx ecx + xor eax,eax + xchg eax,[edx+Workspace.memory_start] + call mfree + pop ecx + call malloc_growable + pop edx + xor edi,edi + jmp update_workspace + allocation_overflow: + jmp out_of_memory + +grow_stack: +; in: +; eax = base address of memory block containing stack data +; ecx = required minimum size of memory block +; out: +; eax = new base address of memory block containing stack data +; ecx = new size of memory block +; preserves: ebx, esi, edi + push ecx + bsr edx,ecx + xchg ecx,edx + sub cl,2 + shr edx,cl + inc edx + shl edx,cl + mov ecx,edx + pop edx + cmp ecx,edx + jbe allocation_overflow + call realloc + retn + +create_source_entry: +; out: +; cf set when the maximum number of entries in context has been exceeded +; when cf = 0: +; ebx - new SourceEntry in the main SourceContext +; preserves: edx, esi + mov ebx,[source_context] + mov eax,[ebx+SourceContext.number_of_entries] + cmp eax,[maximum_depth_of_stack] + jae source_context_full + inc [ebx+SourceContext.number_of_entries] + imul eax,sizeof.SourceEntry + add eax,sizeof.SourceContext + mov edi,eax + add eax,sizeof.SourceEntry + cmp eax,[source_context_maximum_length] + jbe source_context_length_ok + mov ecx,eax + mov eax,ebx + mov ebx,edx + call realloc + mov [source_context],eax + mov [source_context_maximum_length],ecx + mov edx,ebx + mov ebx,eax + source_context_length_ok: + add ebx,edi + mov edi,ebx + mov ecx,sizeof.SourceEntry shr 2 + assert sizeof.SourceEntry and 11b = 0 + xor eax,eax + rep stosd + cmp [alm_statement],0 + je source_entry_created + mov [edi-sizeof.SourceEntry+SourceEntry.flags],SRCF_ALM_STATEMENT + source_entry_created: + clc + retn + source_context_full: + stc + retn + +create_parameter_namespace: +; out: +; eax - SymbolTree_Root +; preserves: ebx, edx, esi, edi + mov ecx,sizeof.SymbolTree_Root + sizeof.SymbolTree_LocalNode + call create_tree_element + or [eax+SymbolTree_Root.attributes],SYMTREE_LOCAL + or [eax+SymbolTree_Root.flags],NAMESPACE_UNATTACHED + retn + +clone_source_context: +; in: +; esi - SourceContext +; edi - buffer +; out: +; edi = pointer advanced past the stored data +; preserves: ebx + cmp edi,[source_context] + sete [source_context_affected] + mov eax,[esi+SourceContext.number_of_entries] + assert sizeof.SourceContext and 11b = 0 + mov ecx,sizeof.SourceContext shr 2 + rep movsd + test eax,eax + jnz clone_source_entry + retn + clone_source_entry: + assert SOURCE_FILE < SOURCE_MACRO & SOURCE_MEMORY < SOURCE_MACRO & SOURCE_CALM > SOURCE_MACRO + cmp [esi+SourceEntry.type],SOURCE_MACRO + jb copy_source_entry + mov edx,[esi+SourceEntry.text] + inc [edx+ValueDefinition.reference_count] + cmp [source_context_affected],0 + je copy_source_entry + or [edx+ValueDefinition.flags],VAL_IN_USE + copy_source_entry: + assert sizeof.SourceEntry and 11b = 0 + mov ecx,sizeof.SourceEntry shr 2 + rep movsd + dec eax + jnz clone_source_entry + retn + +release_source_context: +; in: +; eax - SourceContext +; preserves: eax, ebx, esi, edi + cmp eax,[source_context] + sete [source_context_affected] + push eax + mov ecx,[eax+SourceContext.number_of_entries] + add eax,sizeof.SourceContext + test ecx,ecx + jnz release_source_entry + pop eax + retn + release_source_entry: + assert SOURCE_FILE < SOURCE_MACRO & SOURCE_MEMORY < SOURCE_MACRO & SOURCE_CALM > SOURCE_MACRO + cmp [eax+SourceEntry.type],SOURCE_MACRO + jb source_entry_released + mov edx,[eax+SourceEntry.text] + dec [edx+ValueDefinition.reference_count] + cmp [source_context_affected],0 + je source_entry_released + and [edx+ValueDefinition.flags],not VAL_IN_USE + source_entry_released: + add eax,sizeof.SourceEntry + loop release_source_entry + pop eax + retn + +get_file_source_entry: +; out: +; ebx - SourceEntry in the main SourceContext +; preserves: edx, esi, edi + mov ebx,[source_context] + mov ecx,[ebx+SourceContext.number_of_entries] + mov eax,ecx + imul eax,sizeof.SourceEntry + lea ebx,[ebx+sizeof.SourceContext+eax] + find_file_source_entry: + sub ebx,sizeof.SourceEntry + cmp [ebx+SourceEntry.type],SOURCE_FILE + loopne find_file_source_entry + retn + +preprocess_symbol: +; in: +; esi - contents of the name token (32-bit length and name followed by two hashes) +; edi - pointer into preprocessing_workspace where the preprocessed text should be stored +; out: +; edi - just after the preprocessed text +; cf set when symbol was used as-is (was not recognized as a parameter) +; when cf = 0: +; [symbol_value_start] - start of the preprocessed text +; [symbol_value_end] - end of the preprocessed text (the same as edi) + mov eax,edi + sub eax,[preprocessing_workspace.memory_start] + mov [symbol_value_start],eax + mov [symbol_data],esi + lodsd + mov ecx,eax + mov eax,[esi+ecx+4] + mov [case_insensitive_hash],eax + mov edx,[esi+ecx] + mov [name_kind],NAME_CASESENSITIVE + mov ebx,[parameter_namespace] + call scan_namespace + jnc parameter_found + mov [name_kind],NAME_CASEINSENSITIVE + mov ebx,[parameter_namespace] + test [ebx+SymbolTree_Root.attributes],SYMTREE_WITH_CASEINSENSITIVE_PARAMETERS + jz no_local_parameter_recognized + mov edx,[case_insensitive_hash] + call scan_namespace + jnc parameter_found + no_local_parameter_recognized: + cmp byte [esi],'%' + jne no_parameter_recognized + cmp ecx,2 + ja no_parameter_recognized + jb current_counter_value + cmp byte [esi+1],'%' + je current_limit_value + no_parameter_recognized: + mov edi,[preprocessing_workspace.memory_start] + add edi,[symbol_value_start] + mov al,1Ah + stosb + mov eax,[symbol_data] + stosd + stc + retn + parameter_found: + mov edi,[preprocessing_workspace.memory_start] + add edi,[symbol_value_start] + mov edx,[ebx+SymbolTree_Leaf.definition] + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_SYMBOLIC + je simple_parameter_value + cmp al,VALTYPE_SYMBOLIC_SEQUENCE + je iterator_value + cmp al,VALTYPE_NUMERIC_SEQUENCE + je named_counter_value + cmp al,VALTYPE_NATIVE_COMMAND + jne no_parameter_recognized + jmp [edx+ValueDefinition.value] + current_counter_value: + mov ebx,[parameter_namespace] + test [ebx+SymbolTree_Root.parameters],SPECPARM_COUNTER + jz no_parameter_recognized + mov esi,[current_counter] + mov dl,DBLOCK_CONTROL + call find_directive_block + find_breakable_block: + jc no_parameter_recognized + test [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + jz look_deeper_for_breakable_block + mov eax,[parameter_namespace] + cmp eax,[edi+DirectiveBlock.parameter_namespace] + je found_breakable_block + look_deeper_for_breakable_block: + mov esi,[edi+DirectiveBlock.prior_counter_position] + add esi,[counters_stack_base] + call find_next_directive_block + jmp find_breakable_block + found_breakable_block: + cmp byte [esi],0 + je no_parameter_recognized + mov edi,[preprocessing_workspace.memory_start] + add edi,[symbol_value_start] + movzx ecx,byte [esi] + add ecx,6 + mov edx,preprocessing_workspace + call reserve_workspace + mov al,30h + stosb + mov edx,edi + xor eax,eax + lodsb + stosd + mov ecx,eax + rep movsb + test byte [edi-1],80h + jz parameter_replaced + xor al,al + stosb + inc dword [edx] + jmp parameter_replaced + current_limit_value: + mov ebx,[parameter_namespace] + test [ebx+SymbolTree_Root.parameters],SPECPARM_LIMIT + jz no_parameter_recognized + mov dl,DBLOCK_CONTROL + call find_directive_block + find_block_with_limit: + jc no_parameter_recognized + test [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + jz look_deeper_for_block_with_limit + test [edi+DirectiveBlock.flags],CTRLF_HAS_REPEAT_DATA + jz look_deeper_for_block_with_limit + mov eax,[parameter_namespace] + cmp eax,[edi+DirectiveBlock.parameter_namespace] + je found_block_with_limit + look_deeper_for_block_with_limit: + call find_next_directive_block + jmp find_block_with_limit + found_block_with_limit: + mov ebx,edi + sub ebx,sizeof.RepeatData + mov edi,[preprocessing_workspace.memory_start] + add edi,[symbol_value_start] + mov ecx,[ebx+RepeatData.limit_length] + add ecx,6 + mov edx,preprocessing_workspace + call reserve_workspace + mov al,30h + stosb + mov edx,edi + mov eax,[ebx+RepeatData.limit_length] + stosd + sub ebx,eax + mov esi,ebx + mov ecx,eax + rep movsb + test byte [edi-1],80h + jz parameter_replaced + xor al,al + stosb + inc dword [edx] + jmp parameter_replaced + named_counter_value: + mov edx,[edx+ValueDefinition.value] + mov ebx,[edx] + add ebx,[counters_stack_base] + cmp byte [ebx],0 + je no_parameter_recognized + add edx,4 + movzx ecx,byte [ebx] + cmp ecx,[edx] + jae estimate_counter_length + mov ecx,[edx] + estimate_counter_length: + add ecx,6 + mov esi,edx + mov edx,preprocessing_workspace + call reserve_workspace + mov al,30h + stosb + xor eax,eax + stosd + push edi + movzx ecx,byte [ebx] + inc ebx + lodsd + sub eax,ecx + jnc counter_base_selected + add ecx,eax + neg eax + xchg ebx,esi + counter_base_selected: + mov edx,eax + jecxz counter_added_to_base + xor ah,ah + add_counter_to_base: + lodsb + add al,ah + setc ah + add al,[ebx] + adc ah,0 + inc ebx + add al,-1 + adc ah,0 + stosb + loop add_counter_to_base + counter_added_to_base: + mov ecx,edx + jecxz counter_carried + carry_counter: + lodsb + add al,ah + setc ah + add al,-1 + adc ah,0 + stosb + loop carry_counter + counter_carried: + pop edx + mov al,ah + dec al + jnz extend_counter_value + cmp edx,edi + je counter_value_finished + test byte [edi-1],80h + jz counter_value_finished + extend_counter_value: + stosb + counter_value_finished: + mov ecx,edi + sub ecx,edx + mov [edx-4],ecx + jmp parameter_replaced + iterator_value: + mov edx,[edx+ValueDefinition.value] + mov ebx,[edx] + add ebx,[counters_stack_base] + movzx ecx,byte [ebx] + test ecx,ecx + jz no_parameter_recognized + push edi + mov edi,value_index + xor eax,eax + mov [edi],eax + mov esi,ebx + inc esi + rep movsb + mov eax,[value_index] + pop edi + shl eax,2 + mov esi,[edx+eax] + mov ecx,[edx+eax+4] + sub ecx,esi + add esi,edx + jmp copy_parameter_value + simple_parameter_value: + mov esi,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + copy_parameter_value: + push ecx + mov edx,preprocessing_workspace + call reserve_workspace + pop ecx + cmp [preprocessed_context],0 + jne copy_with_preprocessed_context + rep movsb + jmp parameter_replaced + copy_token_pointer: + movsd + sub ecx,4 + copy_with_preprocessed_context: + test ecx,ecx + jz parameter_replaced + lodsb + stosb + dec ecx + cmp al,1Ah + je copy_token_pointer + cmp al,22h + je copy_token_pointer + cmp al,27h + je copy_token_pointer + cmp al,30h + je copy_token_data + cmp al,40h + jne copy_with_preprocessed_context + mov eax,ecx + cmp dword [esi],0 + jne copy_parameter_context + mov edx,esi + mov esi,[preprocessed_context] + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + lea esi,[edx+sizeof.RecognitionContext] + mov ecx,eax + sub ecx,sizeof.RecognitionContext + jmp copy_with_preprocessed_context + copy_parameter_context: + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + mov ecx,eax + sub ecx,sizeof.RecognitionContext + jmp copy_with_preprocessed_context + copy_token_data: + lodsd + stosd + sub ecx,4 + sub ecx,eax + xchg ecx,eax + rep movsb + xchg ecx,eax + jmp copy_with_preprocessed_context + local_symbol_name: + mov ecx,1+sizeof.RecognitionContext+1+4+1+sizeof.RecognitionContext + mov edx,preprocessing_workspace + call reserve_workspace + mov al,40h + stosb + mov eax,[local_namespace] + mov [edi+RecognitionContext.base_namespace],eax + xor eax,eax + mov [edi+RecognitionContext.base_label],eax + add edi,sizeof.RecognitionContext + mov al,1Ah + stosb + mov eax,[symbol_data] + stosd + mov al,40h + stosb + mov esi,[preprocessed_context] + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + test esi,esi + jz reset_context + rep movsd + stc + retn + reset_context: + xor eax,eax + rep stosd + stc + retn + parameter_replaced: + mov [symbol_value_end],edi + mov eax,[preprocessing_workspace.memory_start] + add [symbol_value_start],eax + clc + retn + +convert_symbolic_value_to_string: +; in: +; [symbol_value_start] - start of the preprocessed text to convert +; [symbol_value_end] - end of the preprocessed text to convert +; out: +; esi - 32-bit length followed by string data +; ecx = total length of string data (including the length prefix) + mov esi,[symbol_value_start] + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + add edi,4 + convert_token_to_text: + mov ecx,[symbol_value_end] + sub ecx,esi + jbe finish_conversion + mov edx,assembly_workspace + call reserve_workspace + lodsb + cmp al,1Ah + je convert_name_token_to_text + cmp al,22h + je convert_string_token_to_text + cmp al,27h + je convert_string_token_to_text + cmp al,30h + je convert_internal_number_to_text + cmp al,40h + je ignore_context_token + stosb + jmp convert_token_to_text + ignore_context_token: + add esi,sizeof.RecognitionContext + jmp convert_token_to_text + convert_name_token_to_text: + lodsd + mov ebx,esi + mov esi,eax + mov ecx,[esi] + mov edx,assembly_workspace + call reserve_workspace + lodsd + mov ecx,eax + rep movsb + mov esi,ebx + jmp convert_token_to_text + convert_string_token_to_text: + lodsd + mov ebx,esi + mov esi,eax + call enclose_string + mov esi,ebx + cmp byte [esi-4-1],27h + jne convert_token_to_text + dec edi + jmp convert_token_to_text + enclose_string: + mov ecx,[esi] + inc ecx + shl ecx,1 + mov edx,assembly_workspace + call reserve_workspace + lodsd + mov ecx,eax + mov al,27h + stosb + copy_string_characters: + jecxz string_characters_copied + lodsb + stosb + dec ecx + cmp al,27h + jne copy_string_characters + stosb + jmp copy_string_characters + string_characters_copied: + mov al,27h + stosb + retn + convert_internal_number_to_text: + mov edx,esi + lodsd + add esi,eax + push esi edi + call convert_number_back + pop edi + mov esi,edx + mov ecx,[esi] + mov edx,assembly_workspace + call reserve_workspace + lodsd + mov ecx,eax + rep movsb + pop esi + jmp convert_token_to_text + finish_conversion: + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + lea eax,[ecx-4] + mov [esi],eax + retn + +compare_symbolic_values: +; in: +; esi - first symbolic value +; edi - second symbolic value +; ecx = length to compare +; out: +; ecx = zero when values equal, or a number of bytes following the point of difference +; esi - the point of difference in first value +; edi - the point of difference in second value + mov al,[esi] + cmp al,[edi] + jne symbolic_values_compared + inc esi + inc edi + cmp al,1Ah + je compare_tokens_with_data + cmp al,22h + je compare_tokens_with_data + cmp al,27h + je compare_tokens_with_data + cmp al,30h + je compare_internal_tokens + cmp al,40h + je compare_context_tokens + loop compare_symbolic_values + symbolic_values_compared: + retn + compare_tokens_with_data: + dec ecx + mov eax,[esi] + mov edx,[edi] + cmp eax,edx + jne compare_token_data + add esi,4 + add edi,4 + sub ecx,4 + jnz compare_symbolic_values + retn + compare_token_data: + mov ebx,[eax] + cmp ebx,[edx] + jne symbolic_values_compared + add eax,ebx + add edx,ebx + xchg esi,eax + xchg edi,edx + xchg ecx,ebx + dec ecx + shr ecx,2 + inc ecx + cmp byte [eax-1],1Ah + jne compare_token_dwords + inc ecx + add esi,4 + add edi,4 + compare_token_dwords: + std + repe cmpsd + cld + jne token_data_content_differs + lea esi,[eax+4] + lea edi,[edx+4] + mov ecx,ebx + sub ecx,4 + jnz compare_symbolic_values + retn + token_data_content_differs: + mov esi,eax + mov edi,edx + mov ecx,ebx + retn + compare_internal_tokens: + mov eax,[esi] + cmp eax,[edi] + jne symbolic_values_compared + add esi,4 + add edi,4 + sub ecx,1+4 + sub ecx,eax + xchg ecx,eax + repe cmpsb + je internal_tokens_equal + inc ecx + dec esi + dec edi + add ecx,eax + retn + internal_tokens_equal: + add ecx,eax + jnz compare_symbolic_values + retn + compare_context_tokens: + dec ecx + assert sizeof.RecognitionContext and 11b = 0 + mov edx,sizeof.RecognitionContext shr 2 + compare_contexts: + mov eax,[esi] + cmp eax,[edi] + jne symbolic_values_compared + add esi,4 + add edi,4 + sub ecx,4 + jz symbolic_values_compared + dec edx + jnz compare_contexts + jmp compare_symbolic_values + +move_to_next_symbol: +; in: +; esi = pointer into preprocessed line or current embedded value +; zeroed ecx is recommended for whitespace detection +; out: +; esi = pointer advanced past the whitespace and context tokens +; cf set when reached end of line or embedded value +; ecx increased when there was whitespace on the way, preserved otherwise +; when cf = 0: +; esi - next symbol +; al = initial byte of the next symbol +; preserves: ebx, edx, edi +; note: +; [embedded_context] is updated to point to a RecognitionContext that should be in force at the new position (null means current namespace context); + cmp esi,[line_end] + jb next_token_available + stc + retn + next_token_available: + mov al,[esi] + cmp al,40h + je set_embedded_context + cmp al,20h + je pass_whitespace + clc + retn + pass_whitespace: + inc esi + inc ecx + jmp move_to_next_symbol + set_embedded_context: + inc esi + cmp [esi+RecognitionContext.base_namespace],0 + je restore_embedded_context + mov [embedded_context],esi + add esi,sizeof.RecognitionContext + jmp move_to_next_symbol + restore_embedded_context: + add esi,sizeof.RecognitionContext + mov eax,[number_of_line_embeddings] + test eax,eax + jz clear_embedded_context + dec eax + imul eax,sizeof.LineEmbedding + add eax,[line_embeddings] + mov eax,[eax+LineEmbedding.recognition_context] + mov [embedded_context],eax + jmp move_to_next_symbol + clear_embedded_context: + and [embedded_context],0 + jmp move_to_next_symbol + +warp_to_next_symbol: +; in: +; esi = pointer into preprocessed line or current embedded value +; zeroed ecx is recommended for whitespace detection +; out: +; esi - next symbol +; cf set when end of line reached +; ecx increased when there was whitespace on the way, preserved otherwise +; when cf = 0: +; al = initial byte of the next symbol +; preserves: ebx, edx, edi +; note: +; [embedded_context] is updated to point to a RecognitionContext that should be in force at the new position (null means current namespace context); + call move_to_next_symbol + jc warp_through_embedding_boundary + retn + warp_through_embedding_boundary: + mov eax,[number_of_line_embeddings] + sub eax,1 + jc reached_end_of_line + mov [number_of_line_embeddings],eax + imul eax,sizeof.LineEmbedding + add eax,[line_embeddings] + mov esi,eax + push edx + add ecx,[esi+LineEmbedding.whitespace] + mov edx,[esi+LineEmbedding.recognition_context] + mov [embedded_context],edx + mov edx,[esi+LineEmbedding.definition] + dec [edx+ValueDefinition.reference_count] + and [edx+ValueDefinition.flags],not VAL_IN_USE + mov edx,[esi+LineEmbedding.previous_end] + mov [line_end],edx + mov esi,[esi+LineEmbedding.previous_pointer] + pop edx + jmp warp_to_next_symbol + reached_end_of_line: + ; stc + retn + +cut_piece_of_line: +; in: +; esi = pointer into preprocessed line or current embedded value +; edi - LineExcerpt to be filled with information about cut piece of line +; dl = initial byte of symbol that should end the cut value, zero to cut up to the end of line (or current embedded value) +; dh = initial byte of symbol that would open the nested piece, zero for no nesting +; [breakpoint_token] = initial byte of symbol that should unconditionally end the cut value if it is met +; out: +; esi = pointer advanced past the cut piece +; al = initial byte of symbol at pointer, zero when no more symbols there +; preserves: ebx, edx, edi +; note: when [breakpoint_token] has the same value as either dl or dh, it has no effect + mov [number_of_enclosings],1 + call move_to_next_symbol + mov [edi+LineExcerpt.data_start],esi + mov [edi+LineExcerpt.data_end],esi + jc last_piece_in_line + mov ecx,[embedded_context] + mov [edi+LineExcerpt.recognition_context],ecx + cut_piece: + cmp al,dh + je nested_piece + cmp al,dl + je close_nested_piece + cmp al,[breakpoint_token] + jne cut_token + retn + nested_piece: + inc [number_of_enclosings] + jmp cut_token + close_nested_piece: + dec [number_of_enclosings] + jz end_of_piece + cut_token: + cmp al,1Ah + je cut_token_with_data + cmp al,22h + je cut_token_with_data + cmp al,27h + je cut_token_with_data + cmp al,30h + je cut_internal_token + inc esi + cut_next_token: + mov [edi+LineExcerpt.data_end],esi + call move_to_next_symbol + jnc cut_piece + last_piece_in_line: + xor al,al + end_of_piece: + mov ecx,[embedded_context] + mov [edi+LineExcerpt.leftover_context],ecx + retn + cut_token_with_data: + add esi,1+4 + jmp cut_next_token + cut_internal_token: + inc esi + lodsd + add esi,eax + jmp cut_next_token + +extract_piece_of_line: +; in: +; esi = pointer into preprocessed line (not an embedded value) +; edi - buffer for token sequence, must be large enough to hold all the remaining tokens in line and an additional context token +; dl = initial byte of symbol that should end the cut value, zero to cut up to the end of line +; dh = initial byte of symbol that would open the nested piece, zero for no nesting +; [breakpoint_token] = initial byte of symbol that should unconditionally end the cut value if it is met +; [contextless_processing] = zero to have current context added to the extracted value +; out: +; esi = pointer advanced past the processed piece +; edi - end of the extracted sequence of tokens in provided buffer +; al = initial byte of symbol at pointer, zero when no more symbols there +; [context_boundary] = equal to edi if the extracted sequence ends with a context token +; preserves: ebx, edx +; note: +; when [breakpoint_token] has the same value as either dl or dh, it has no effect + and [context_boundary],0 + call move_to_next_symbol + jc no_piece_to_extract + mov [number_of_enclosings],1 + mov [whitespace_boundary],edi + mov al,40h + stosb + mov eax,[embedded_context] + test eax,eax + jz extract_current_context + xchg esi,eax + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + mov esi,eax + mov [context_boundary],edi + jmp extract_piece + extract_contextless: + dec edi + jmp extract_piece + extract_current_context: + cmp [contextless_processing],0 + jne extract_contextless + call store_current_context + extract_piece: + lodsb + cmp al,dh + je nested_piece_to_extract + cmp al,dl + je close_extracted_nested_piece + cmp al,[breakpoint_token] + je extraction_breakpoint + extract_token: + cmp al,40h + je extract_context_token + cmp al,20h + je extract_whitespace + and [whitespace_boundary],0 + stosb + cmp al,1Ah + je extract_token_with_data + cmp al,22h + je extract_token_with_data + cmp al,27h + je extract_token_with_data + cmp al,30h + je extract_internal_token + extract_next_token: + cmp esi,[line_end] + jne extract_piece + xor al,al + cmp [whitespace_boundary],0 + jne drop_final_whitespace + retn + nested_piece_to_extract: + inc [number_of_enclosings] + jmp extract_token + close_extracted_nested_piece: + dec [number_of_enclosings] + jnz extract_token + extraction_breakpoint: + dec esi + cmp [whitespace_boundary],0 + jne drop_final_whitespace + retn + drop_final_whitespace: + mov edi,[whitespace_boundary] + retn + no_piece_to_extract: + xor al,al + retn + extract_whitespace: + cmp [whitespace_boundary],0 + jne whitespace_boundary_ok + mov [whitespace_boundary],edi + whitespace_boundary_ok: + stosb + jmp extract_next_token + extract_token_with_data: + movsd + jmp extract_next_token + extract_internal_token: + lodsd + stosd + mov ecx,eax + rep movsb + jmp extract_next_token + extract_context_token: + cmp [whitespace_boundary],0 + jne context_whitespace_boundary_ok + mov [whitespace_boundary],edi + context_whitespace_boundary_ok: + mov [embedded_context],esi + cmp dword [esi],0 + jne embedded_context_for_extraction_ok + and [embedded_context],0 + embedded_context_for_extraction_ok: + call make_recognition_context_token + jmp extract_next_token + +make_recognition_context_token: +; in: +; al = 40h +; esi - RecognitionContext (contents of the context token) +; edi - buffer for the context token +; [context_boundary] = equal to edi if it is at the end of another context token +; [contextless_processing] = zero to convert context reset into a context switch capturing the current context +; out: +; esi - past the processed RecognitionContext +; edi - past the extracted context token +; [context_boundary] - past the extracted context token +; preserves: ebx, edx + cmp edi,[context_boundary] + je reuse_recognition_context + stosb + jmp store_recognition_context + reuse_recognition_context: + sub edi,sizeof.RecognitionContext + store_recognition_context: + ; in: + ; esi - RecognitionContext to read (may have base namespace zeroed to indicate context reset) + ; edi - RecognitionContext to fill + ; out: + ; esi - past the processed RecognitionContext + ; edi - past the filled RecognitionContext + ; [context_boundary] - past the filled RecognitionContext + ; [contextless_processing] = zero to convert context reset into a context switch capturing the current context + ; preserves: ebx, edx + cmp [contextless_processing],0 + jne copy_recognition_context + cmp [esi+RecognitionContext.base_namespace],0 + je capture_context_reset + copy_recognition_context: + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + mov [context_boundary],edi + retn + capture_context_reset: + add esi,sizeof.RecognitionContext + store_current_context: + ; in: + ; edi - RecognitionContext to fill + ; out: + ; edi - past the filled RecognitionContext + ; [context_boundary] - past the filled RecognitionContext + ; preserves: ebx, edx, esi + mov eax,[current_context.base_namespace] + mov ecx,[current_context.base_label] + mov [edi+RecognitionContext.base_namespace],eax + mov [edi+RecognitionContext.base_label],ecx + add edi,sizeof.RecognitionContext + mov [context_boundary],edi + retn + +embed_symbolic_value: +; in: +; ebx - SymbolTree_Leaf +; edx - ValueDefinition +; esi = pointer into preprocessed line or current embedded value +; ecx = number of whitespace tokens to imply after emdedding +; out: +; esi = pointer into embedded value +; preserves: ebx, edx + mov eax,[number_of_line_embeddings] + inc eax + mov [number_of_line_embeddings],eax + imul eax,sizeof.LineEmbedding + cmp eax,[line_embeddings_maximum_length] + jbe line_embedding_allocated + push eax ecx edx + mov ecx,sizeof.LineEmbedding + add ecx,[line_embeddings_maximum_length] + mov eax,[line_embeddings] + call grow_stack + mov [line_embeddings_maximum_length],ecx + mov [line_embeddings],eax + pop edx ecx eax + line_embedding_allocated: + sub eax,sizeof.LineEmbedding + add eax,[line_embeddings] + mov [eax+LineEmbedding.whitespace],ecx + mov edi,[line_end] + mov [eax+LineEmbedding.previous_pointer],esi + mov [eax+LineEmbedding.previous_end],edi + mov ecx,[embedded_context] + mov [eax+LineEmbedding.recognition_context],ecx + and [embedded_context],0 + mov esi,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + add ecx,esi + mov [line_end],ecx + mov [eax+LineEmbedding.definition],edx + inc [edx+ValueDefinition.reference_count] + or [edx+ValueDefinition.flags],VAL_IN_USE + retn + +clear_line_embeddings: +; preserves: ebx, ecx, edx, esi, edi +; note: +; when esi is said to point into preprocessed line or current embedded value, it must be between [line_start] and [line_end]; +; these two pointers change upon entering a symbolic value of evaluated identifier (with embed_symbolic_value) +; and are restored when warp_to_next_symbol goes past the end of that embedded value; +; this function needs to be called before setting up a new line for the assembly +; and it discards the stack of stored [line_start] and [line_end] boundaries + xor eax,eax + mov [line_start],eax + mov [line_end],eax + mov [embedded_context],eax + cmp eax,[number_of_line_embeddings] + je embedded_values_ok + push ecx + discard_line_embedding: + mov ecx,eax + imul ecx,sizeof.LineEmbedding + add ecx,[line_embeddings] + mov ecx,[ecx+LineEmbedding.definition] + dec [ecx+ValueDefinition.reference_count] + and [ecx+ValueDefinition.flags],not VAL_IN_USE + inc eax + cmp eax,[number_of_line_embeddings] + jne discard_line_embedding + and [number_of_line_embeddings],0 + pop ecx + embedded_values_ok: + retn + +identify_symbol_in_namespace: +; in: +; ebx - SymbolTree_Root +; esi = pointer into preprocessed line or current embedded value +; dl = SYMCLASS_# +; [symbol_definition] = non-zero when symbol needs to be identified for the purpose of definition +; out: +; cf set when there were no more symbols in preprocessed line or current embedded value +; esi = pointer advanced past the processed identifier and following whitespace or to the first token of a different symbol +; ecx = number of whitespace tokens encountered immediately before the new position +; when cf = 0: +; ebx - SymbolTree_Leaf, null when no symbol was identified +; edx - SymbolTree_Foliage, may be null if either ebx or edi is null +; edi - SymbolTree_Root, null when there was no identifier at all or when identified symbol is not in a namespace +; [symbol_start] - first token of identified symbol +; [symbol_independent] = zero when identifier is relative to current label, all bits set for special identifiers +; note: +; when ebx is null but edi is not, the identifier was malformed +; when edi is null but ebx is not, a special symbol was identified; this is possible only for SYMCLASS_INSTRUCTION and SYMCLASS_STRUCTURE + mov [expected_class],dl + xor ecx,ecx + call move_to_next_symbol + jnc namespaces_ok + retn +identify_symbol: +; in: +; esi = pointer into preprocessed line or current embedded value +; dl = SYMCLASS_# +; [symbol_definition] = non-zero when symbol needs to be identified for the purpose of definition +; out: +; cf set when there were no more symbols in preprocessed line or current embedded value +; esi = pointer advanced past the processed identifier and following whitespace or to the first token of a different symbol +; ecx = number of whitespace tokens encountered immediately before the new position +; [recognition_context] = applied recognition context +; when cf = 0: +; ebx - SymbolTree_Leaf, null when no symbol was identified +; edx - SymbolTree_Foliage, may be null if either ebx or edi is null +; edi - SymbolTree_Root, null when there was no identifier at all or when identified symbol is not in a namespace +; [symbol_start] - first token of identified symbol (within current embedded value or preprocessed line) +; [symbol_independent] = zero when identifier is relative to current label, all bits set for special identifiers +; note: +; when ebx is null but edi is not, the identifier was malformed +; when edi is null but ebx is not, a special symbol was identified; this is possible only for SYMCLASS_INSTRUCTION and SYMCLASS_STRUCTURE + mov [expected_class],dl + xor ecx,ecx + call move_to_next_symbol + jc identification_finished + xor ebx,ebx + mov edx,[embedded_context] + test edx,edx + jnz use_namespace + mov edx,current_context + use_namespace: + mov eax,[edx+RecognitionContext.base_namespace] + mov [recognition_context.base_namespace],eax + mov eax,[edx+RecognitionContext.base_label] + mov [recognition_context.base_label],eax + namespaces_ok: + mov [symbol_start],esi + and [symbol_independent],0 + cmp [symbol_definition],0 + setnz al + shl al,bsf RECOGNIZE_DEFINITION + mov [recognizer_setting],al + xor edx,edx + xor edi,edi + mov al,[esi] + cmp al,1Ah + je starting_with_name + cmp al,'.' + je starting_dot + cmp al,'#' + je starting_with_concatenation + cmp al,'?' + je starting_question_mark + return_no_identifier: + xor ebx,ebx + return_no_namespace: + xor edx,edx + xor edi,edi + clc + retn + starting_with_name: + call detect_numeric_symbol + jc return_no_identifier + valid_starting_name: + or [symbol_independent],1 + valid_name: + inc esi + mov [name_token],esi + lodsd + mov edi,eax + and [name_volatile],0 + xor ecx,ecx + identify_name: + mov dh,[recognizer_setting] + call move_to_next_symbol + jc run_recognizer + cmp al,'#' + jne name_complete + call check_concatenation + jnc name_concatenation + xor al,al + name_complete: + test ecx,ecx + jnz run_recognizer + cmp al,'?' + jne run_recognizer + or dh,RECOGNIZE_CASE_INSENSITIVE + inc esi + call move_to_next_symbol + jc run_recognizer + cmp al,'#' + jne name_modifiers_complete + call check_concatenation + jc run_recognizer + name_modifiers_complete: + test ecx,ecx + jnz run_recognizer + cmp al,1Ah + je malformed_identifier + run_recognizer: + push esi ecx + cmp esi,[line_end] + je recognize_final_symbol + test ecx,ecx + jnz recognize_final_symbol + cmp byte [esi],'.' + jne recognize_final_symbol + mov esi,edi + lodsd + mov ecx,eax + mov dl,SYMCLASS_EXPRESSION + and dh,not RECOGNIZE_DEFINITION + call recognize_symbol + pop ecx esi + dot_operator: + inc esi + xor ecx,ecx + call move_to_next_symbol + jc ending_with_dot + cmp al,'#' + je name_concatenation_after_dot + test ecx,ecx + jnz ending_with_dot + cmp al,'.' + je multiple_dot_operator + identify_name_after_dot: + cmp al,30h + je number_after_dot + cmp al,1Ah + jne ending_with_dot + call get_symbol_namespace + xor edi,edi + jmp valid_name + name_concatenation_after_dot: + call check_concatenation + jc ending_with_dot + cmp al,'.' + je multiple_dot_operator + number_after_dot: + call get_symbol_namespace + mov al,[esi] + xor edi,edi + jmp name_concatenation + recognize_final_symbol: + mov dl,[expected_class] + mov esi,edi + lodsd + mov ecx,eax + call recognize_symbol + pop ecx esi + symbol_identified: + clc + identification_finished: + retn + ending_with_dot: + mov al,[expected_class] + cmp al,SYMCLASS_EXPRESSION + jne find_expected_class + clc + retn + starting_question_mark: + inc esi + xor ecx,ecx + call move_to_next_symbol + jc alone_question_mark + cmp al,'#' + jne symbol_after_question_mark + call check_concatenation + jc alone_question_mark + symbol_after_question_mark: + test ecx,ecx + jnz alone_question_mark + cmp al,'?' + je repeated_question_mark + cmp [symbol_definition],0 + jne no_forced_definition + mov [expected_class],SYMCLASS_EXPRESSION + or [recognizer_setting],RECOGNIZE_DEFINITION + no_forced_definition: + cmp al,'.' + je starting_dot + cmp al,1Ah + je valid_starting_name + cmp al,30h + je concatenation_with_internal_number + alone_question_mark: + mov dl,[expected_class] + cmp dl,SYMCLASS_INSTRUCTION + je return_interceptor_symbol + cmp dl,SYMCLASS_STRUCTURE + je return_label_interceptor_symbol + mov eax,[symbol_start] + cmp byte [eax],'?' + jne malformed_identifier + mov esi,eax + jmp return_no_identifier + return_label_interceptor_symbol: + mov ebx,[label_interceptor_symbol] + jmp return_special_symbol + return_interceptor_symbol: + mov ebx,[interceptor_symbol] + return_special_symbol: + or [symbol_independent],-1 + jmp return_no_namespace + repeated_question_mark: + inc esi + xor ecx,ecx + call move_to_next_symbol + jc return_other_interceptor_symbol + cmp al,'#' + jne return_other_interceptor_symbol + call check_concatenation + jnc symbol_after_question_mark + return_other_interceptor_symbol: + cmp [expected_class],SYMCLASS_INSTRUCTION + jne malformed_identifier + mov ebx,[other_interceptor_symbol] + jmp return_special_symbol + multiple_dot_operator: + mov ebx,edi + xor edi,edi + jmp starting_dot + additional_dot: + inc edi + starting_dot: + inc esi + xor ecx,ecx + call move_to_next_symbol + jc alone_dot + cmp al,'#' + jne symbol_after_starting_dot + call check_concatenation + jc alone_dot + symbol_after_starting_dot: + test ecx,ecx + jnz alone_dot + cmp al,'.' + je additional_dot + cmp al,30h + je name_after_starting_dot + cmp al,1Ah + jne alone_dot + name_after_starting_dot: + test ebx,ebx + jnz name_after_multiple_dot_operator + call get_base_label + mov edi,ebx + mov al,[esi] + jmp identify_name_after_dot + name_after_multiple_dot_operator: + test edx,edx + jz parent_namespace_ready + call get_symbol_namespace + parent_namespace_ready: + call synthesize_dot_label + mov edi,ebx + mov al,[esi] + jmp identify_name_after_dot + alone_dot: + test ebx,ebx + jz identify_current_label + test edx,edx + jz malformed_identifier + push ecx + call get_symbol_namespace + pop ecx + call synthesize_dot_label + jmp get_label_symbol + malformed_identifier: + xor ebx,ebx + xor edx,edx + mov edi,[recognition_context.base_namespace] + jmp symbol_identified + identify_current_label: + call get_base_label + mov eax,[local_namespace] + test eax,eax + jz get_label_symbol + cmp edx,[eax+SymbolTree_Root.current_label] + jne get_label_symbol + test [eax+SymbolTree_Root.flags],NAMESPACE_LABEL_FORWARDING + setnz [symbol_independent] + get_label_symbol: + mov edi,ebx + mov al,[expected_class] + find_expected_class: + mov [symbol_class],al + mov al,[symbol_definition] + mov [symbol_required],al + mov [symbol_expected],al + mov ebx,edx + call scan_symbol_branch + jnc current_label_identified + mov [symbol_class],SYMCLASS_EXPRESSION + or [symbol_required],1 + or [symbol_expected],1 + mov ebx,edx + call scan_symbol_branch + current_label_identified: + clc + retn + get_base_label: + mov edx,[recognition_context.base_label] + test edi,edi + jnz synthesize_dot_label + test edx,edx + jnz current_label_ready + synthesize_dot_label: + push ecx esi + mov esi,[identifier_workspace.memory_start] + mov eax,edi + mov [esi],eax + mov edx,FNV_OFFSET + xor ecx,ecx + hash_dot_label: + test eax,eax + jz dot_label_synthesised + xor dl,al + imul edx,FNV_PRIME + inc ecx + shr eax,8 + jmp hash_dot_label + dot_label_synthesised: + or [name_volatile],1 + and [name_token],0 + mov [name_kind],NAME_NUMERIC + mov [symbol_class],SYMCLASS_EXPRESSION + or [symbol_required],1 + or [symbol_expected],1 + test ebx,ebx + jnz identify_dot_label + mov ebx,[recognition_context.base_namespace] + identify_dot_label: + call scan_namespace + pop esi ecx + current_label_ready: + mov ebx,[edx+SymbolTree_Foliage.root] + retn + starting_with_concatenation: + xor ecx,ecx + call check_concatenation + jc empty_concatenation + name_concatenation: + cmp al,30h + je concatenation_with_internal_number + cmp al,1Ah + jne empty_concatenation + test edi,edi + jz starting_with_name + inc esi + lodsd + push ebx esi + mov ebx,eax + attach_to_name: + mov esi,edi + mov edi,[identifier_workspace.memory_start] + cmp esi,edi + jne initial_concatenation + lodsd + add esi,eax + mov edi,esi + jmp get_precalculated_hashes + initial_concatenation: + test esi,esi + jz initial_conversion + mov ecx,[esi] + add ecx,4+8 + mov edx,identifier_workspace + call reserve_workspace + lodsd + stosd + mov ecx,eax + rep movsb + get_precalculated_hashes: + xchg ebx,esi + mov ecx,[esi] + mov eax,[identifier_workspace.memory_start] + add [eax],ecx + add ecx,8 + mov edx,identifier_workspace + call reserve_workspace + mov ecx,[ebx] + mov edx,[ebx+4] + lodsd + lea ebx,[esi+eax] + xor eax,eax + concatenation_hash: + lodsb + xor cl,al + xor dl,[characters+eax] + imul ecx,FNV_PRIME + imul edx,FNV_PRIME + stosb + cmp esi,ebx + jne concatenation_hash + mov eax,ecx + stosd + mov eax,edx + stosd + pop esi ebx + mov edi,[identifier_workspace.memory_start] + or [name_volatile],1 + and [name_token],0 + xor ecx,ecx + jmp identify_name + initial_conversion: + xor eax,eax + stosd + mov esi,edi + mov eax,FNV_OFFSET + mov [esi],eax + mov [esi+4],eax + jmp get_precalculated_hashes + concatenation_with_internal_number: + inc esi + mov edx,esi + lodsd + add esi,eax + push ebx esi + push edi + call convert_number_back + pop edi + mov ebx,edx + jmp attach_to_name + empty_concatenation: + test edi,edi + jnz identify_name_with_empty_concatenation + call move_to_next_symbol + jc malformed_identifier + cmp al,'.' + je starting_dot + cmp al,'?' + je starting_question_mark + jmp malformed_identifier + identify_name_with_empty_concatenation: + mov dh,[recognizer_setting] + call move_to_next_symbol + jc run_recognizer + jmp name_complete + +detect_numeric_symbol: +; in: +; esi - name token in preprocessed line or in current embedded value +; out: +; cf set when symbol starting with this token should be considered numeric +; preserves: ebx, ecx, edx, esi, edi + mov eax,[esi+1] + mov al,[eax+4] + cmp al,'$' + je detect_pascal_hexadecimal + sub al,'0' + cmp al,10 + jb numeric_symbol_detected + not_a_numeric_symbol: + clc + retn + detect_pascal_hexadecimal: + mov eax,[esi+1] + cmp dword [eax],2 + jb not_a_numeric_symbol + movzx eax,byte [eax+4+1] + mov al,[characters+eax] + sub al,'0' + cmp al,10 + jb numeric_symbol_detected + sub al,'a'-'0' + jc not_a_numeric_symbol + cmp al,16-10 + jae not_a_numeric_symbol + numeric_symbol_detected: + stc + retn + +check_concatenation: +; in: +; esi - concatenation character in preprocessed line or in current embedded value +; ecx = number of whitespace tokens encountered immediately before current position +; out: +; cf set when there is no concatenation applicable to previous symbol +; esi = pointer advanced past the processed operator and the whitespace that follows it +; ecx = number of whitespace tokens encountered immediately before the new position +; when cf = 0: +; esi - symbol that follows concatenation operator +; al = initial byte of symbol following concatenation operator +; preserves: ebx, edx, edi + test ecx,ecx + jnz no_concatenation + inc esi + call move_to_next_symbol + jc no_concatenation + cmp al,'#' + je check_concatenation + test ecx,ecx + jnz no_concatenation + ; clc + retn + no_concatenation: + stc + retn + +get_literal: +; in: +; esi - token in preprocessed line or in current embedded value +; out: +; al = type of value +; esi = pointer advanced past the processed literal and the whitespace that follows it +; ecx = number of whitespace tokens encountered immediately before the new position +; when al = 22h: +; edx - 32-bit length followed by string data +; when al = 30h: +; edx - 32-bit length followed by numeric data, null when invalid number +; when al = 2Eh: +; edx - FloatData, null when invalid number +; when al is any other value, it is a simple special character, and edx is zero + xor ecx,ecx + mov al,[esi] + cmp al,1Ah + je get_literal_number + cmp al,22h + je get_literal_string + cmp al,27h + je missing_end_quote + cmp al,30h + je get_internal_number + inc esi + mov dl,al + call move_to_next_symbol + mov al,dl + xor edx,edx + retn + get_literal_number: + mov edx,[esi+1] + add esi,5 + check_for_more_parts_of_number: + call move_to_next_symbol + jc number_ready_for_conversion + test ecx,ecx + jnz check_for_number_concatenation + cmp al,'.' + je get_literal_float + check_for_number_concatenation: + cmp al,'#' + jne number_ready_for_conversion + call check_concatenation + jc number_ready_for_conversion + number_concatenation: + cmp al,30h + je attach_internal_number_to_number + cmp al,'.' + je get_literal_float + cmp al,1Ah + jne number_ready_for_conversion + attach_name_to_number: + mov ebx,[esi+1] + add esi,5 + push esi + attach_to_number: + mov esi,edx + mov edi,[identifier_workspace.memory_start] + cmp esi,edi + jne initial_concatenation_of_number + lodsd + add esi,eax + mov edi,esi + jmp attach_segment_of_number + initial_concatenation_of_number: + mov ecx,[esi] + add ecx,4 + mov edx,identifier_workspace + call reserve_workspace + lodsd + stosd + mov ecx,eax + rep movsb + attach_segment_of_number: + mov esi,ebx + mov ecx,[esi] + mov eax,[identifier_workspace.memory_start] + add [eax],ecx + mov edx,identifier_workspace + call reserve_workspace + lodsd + mov ecx,eax + rep movsb + pop esi + mov edx,[identifier_workspace.memory_start] + jmp check_for_more_parts_of_number + attach_internal_number_to_number: + mov ebx,edx + inc esi + mov edx,esi + lodsd + add esi,eax + push esi + push ebx + call convert_number_back + mov ebx,edx + pop edx + jmp attach_to_number + number_ready_for_conversion: + push ecx + call convert_number + pop ecx + jc get_literal_float + mov al,30h + retn + missing_end_quote: + mov edx,_missing_end_quote + call register_error + get_literal_string: + mov edx,[esi+1] + add esi,5 + call move_to_next_symbol + mov al,22h + retn + get_internal_number: + lea edx,[esi+1] + mov eax,[edx] + lea esi,[esi+1+4+eax] + call move_to_next_symbol + jc internal_number_ready + test ecx,ecx + jnz check_for_internal_number_concatenation + cmp al,'.' + je convert_internal_number_back + check_for_internal_number_concatenation: + cmp al,'#' + jne internal_number_ready + call check_concatenation + jc internal_number_ready + cmp al,1Ah + je convert_internal_number_back + cmp al,30h + jne internal_number_ready + convert_internal_number_back: + push esi + call convert_number_back + mov esi,edx + mov ecx,[esi] + add ecx,4 + mov edi,[identifier_workspace.memory_start] + mov edx,identifier_workspace + call reserve_workspace + lodsd + stosd + mov ecx,eax + rep movsb + pop esi + mov edx,[identifier_workspace.memory_start] + mov al,[esi] + jmp number_concatenation + internal_number_ready: + mov al,30h + retn + get_literal_float: + xor eax,eax + mov [zero_digits],eax + mov [decimal_places],eax + mov [literal_exponent],eax + mov [literal_exponent_sign],al + mov [literal_fractional_part],al + mov [waiting_for_digit],al + mov [float_literal_status],al + push esi ecx + mov ebx,edx + call start_decimal_converter + lea esi,[ebx+4] + mov ecx,[ebx] + get_float_digit: + lodsb + cmp al,27h + je skip_float_digit + cmp al,'_' + je skip_float_digit + cmp al,'9' + ja float_nondigit + sub al,'0' + jz float_digit_zero + jc float_nondigit + test [float_literal_status],1 + jnz reject_float_digit + inc [decimal_places] + push esi ecx + xor ecx,ecx + xchg ecx,[zero_digits] + call convert_decimal_digit + pop ecx esi + and [waiting_for_digit],0 + skip_float_digit: + loop get_float_digit + jmp float_digits_ok + float_digit_zero: + test [float_literal_status],1 + jnz reject_float_digit + inc [decimal_places] + inc [zero_digits] + and [waiting_for_digit],0 + loop get_float_digit + float_digits_ok: + pop ecx esi + call move_to_next_symbol + jc no_more_tokens_in_float + cmp al,'.' + je decimal_point + cmp al,'#' + jne no_more_tokens_in_float + call check_concatenation + jc no_more_tokens_in_float + jmp next_token_in_float + decimal_point: + test ecx,ecx + jnz no_more_tokens_in_float + mov al,[literal_fractional_part] + or al,[literal_exponent_sign] + jz decimal_point_allowed + or [float_literal_status],-1 + decimal_point_allowed: + or [literal_fractional_part],1 + or [waiting_for_digit],1 + and [decimal_places],0 + get_following_digits: + inc esi + xor ecx,ecx + call move_to_adjacent_symbol + jc invalid_float_value + next_token_in_float: + cmp al,1Ah + je next_digits_section + cmp al,30h + je internal_number_as_digits + no_more_tokens_in_float: + cmp [waiting_for_digit],0 + jne invalid_float_value + cmp [float_literal_status],-1 + je invalid_float_value + call finish_decimal_conversion + push esi ecx + mov esi,edi + xor ecx,ecx + cmp [literal_fractional_part],0 + je float_decimal_places_ok + mov ecx,[decimal_places] + float_decimal_places_ok: + sub ecx,[zero_digits] + neg ecx + add ecx,[literal_exponent] + jo float_conversion_failed + call multiply_float_by_power_of_ten + test [edi+FloatData.attributes],FLOAT_INFINITE or FLOAT_INDETERMINATE or FLOAT_UNDERFLOW + jnz float_conversion_failed + mov edx,edi + pop ecx esi + mov al,2Eh + retn + float_conversion_failed: + pop ecx esi + invalid_float_value: + xor edx,edx + mov al,2Eh + retn + next_digits_section: + inc esi + lodsd + xor ecx,ecx + push esi ecx + mov esi,eax + lodsd + mov ecx,eax + cmp [literal_exponent_sign],0 + jne get_exponent_digit + jmp get_float_digit + internal_number_as_digits: + inc esi + mov edx,esi + lodsd + add esi,eax + xor ecx,ecx + push esi ecx + call convert_number_back + mov esi,edx + lodsd + mov ecx,eax + cmp [literal_exponent_sign],0 + jne get_exponent_digit + jmp get_float_digit + get_literal_exponent: + mov al,1 + xchg al,[literal_exponent_sign] + test al,al + jnz reject_exponent_digit + or [waiting_for_digit],1 + loop get_exponent_digit + pop ecx esi + call move_to_adjacent_symbol + jc invalid_float_value + cmp al,1Ah + je next_digits_section + cmp al,30h + je internal_number_as_digits + cmp al,'+' + je get_following_digits + cmp al,'-' + jne invalid_float_value + neg [literal_exponent_sign] + jmp get_following_digits + get_exponent_digit: + xor eax,eax + lodsb + cmp al,27h + je skip_exponent_digit + cmp al,'_' + je skip_exponent_digit + sub al,'0' + jc reject_exponent_digit + cmp al,10 + jae reject_exponent_digit + test [float_literal_status],1 + jnz reject_exponent_digit + mov edx,[literal_exponent] + imul edx,10 + jo reject_exponent_digit + cmp [literal_exponent_sign],0 + jnl exponent_digit_ok + neg eax + exponent_digit_ok: + add edx,eax + jo reject_exponent_digit + mov [literal_exponent],edx + and [waiting_for_digit],0 + skip_exponent_digit: + loop get_exponent_digit + jmp float_digits_ok + reject_exponent_digit: + or [float_literal_status],-1 + jmp skip_exponent_digit + float_nondigit: + cmp [waiting_for_digit],0 + jne reject_float_digit + movzx eax,byte [esi-1] + mov al,[characters+eax] + cmp al,'e' + je get_literal_exponent + cmp al,'f' + jne reject_float_digit + or [float_literal_status],1 + jmp skip_float_digit + reject_float_digit: + or [float_literal_status],-1 + jmp skip_float_digit + move_to_adjacent_symbol: + call move_to_next_symbol + jc adjacent_symbol_ok + cmp al,'#' + je check_concatenation + neg ecx + adjacent_symbol_ok: + retn + +skip_literal: +; in: +; esi - token in preprocessed line or in current embedded value +; out: +; esi = pointer advanced past the processed literal and the whitespace that follows it +; ecx = number of whitespace tokens encountered immediately before the new position + xor ecx,ecx + mov al,[esi] + cmp al,1Ah + je skip_literal_number + cmp al,22h + je skip_literal_string + cmp al,27h + je skip_literal_string + cmp al,30h + je skip_internal_number + inc esi + call move_to_next_symbol + retn + skip_literal_string: + add esi,5 + call move_to_next_symbol + retn + skip_literal_number: + xor dh,dh + inc esi + lodsd + mov dl,[eax+4] + cmp dl,'0' + jb skip_number_segments + cmp dl,'9' + ja skip_number_segments + or dh,1 + check_for_possible_exponent: + mov ecx,[eax] + mov dl,[eax+4+ecx-1] + cmp dl,'e' + je possible_exponent + cmp dl,'E' + jne skip_number_segments + possible_exponent: + or dh,2 + jmp skip_number_segments + skip_internal_number: + inc esi + lodsd + add esi,eax + mov dh,1 + skip_number_segments: + xor ecx,ecx + call move_to_next_symbol + jc literal_symbol_skipped + cmp al,'#' + je check_literal_concatenation + test ecx,ecx + jnz literal_symbol_skipped + cmp al,'.' + jne check_for_exponent + skip_decimal_point: + inc esi + xor ecx,ecx + call move_to_next_symbol + jc literal_symbol_skipped + cmp al,'#' + je check_literal_concatenation + test ecx,ecx + jnz literal_symbol_skipped + skip_attached_segment: + cmp al,'.' + je skip_decimal_point + cmp al,30h + je skip_attached_internal_number + cmp al,1Ah + jne check_for_exponent + skip_attached_number: + inc esi + lodsd + test dh,1 + jnz check_for_possible_exponent + jmp skip_number_segments + skip_attached_internal_number: + inc esi + lodsd + add esi,eax + and dh,not 2 + jmp skip_number_segments + check_for_exponent: + cmp dh,1+2 + jne literal_symbol_skipped + cmp al,'+' + je skip_exponent + cmp al,'-' + jne literal_symbol_skipped + skip_exponent: + xor dh,dh + jmp skip_decimal_point + check_literal_concatenation: + call check_concatenation + jnc skip_attached_segment + literal_symbol_skipped: + retn + +get_processed_value: +; in: +; esi = pointer into preprocessed line or current embedded value +; out: +; cf set when there were no more symbols on the line +; when cf = 0: +; al = type of value +; esi = pointer advanced past the processed element and the whitespace that follows it within the boundaries of current embedded value or preprocessed line +; ecx = number of whitespace tokens encountered immediately before the new position +; when al = 1Ah: +; ebx - SymbolTree_Leaf, null when malformed identifier +; edx - ValueDefinition, null when symbol with no valid value +; additional variables set as by identify_symbol +; when al = 22h: +; edx - 32-bit length followed by string data +; when al = 30h: +; edx - 32-bit length followed by numeric data, null when invalid number +; when al = 2Eh: +; edx - FloatData, null when invalid number +; when al is any other value, it is a simple special character, and edx is zero +; note: +; to detect whitespace between two consecutive symbols, warp_to_next_symbol should be called after this function, +; since it may further increase ecx when there is additional whitespace outside of current embedded value +; when [use_raw_values] flag is set, this function is identical to get_raw_value + call get_raw_value + jc no_more_values + cmp al,1Ah + jne value_ok + test edx,edx + jz value_ok + cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC + je symbolic_value + value_ok: + clc + retn + symbolic_value: + cmp [use_raw_values],0 + jne value_ok + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + test [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz no_infinite_regress + test [edx+ValueDefinition.flags],VAL_IN_USE + jz no_infinite_regress + push edx + mov edx,_symbolic_self_reference + call register_error + pop edx + retn + no_infinite_regress: + call embed_symbolic_value + jmp get_processed_value + +get_raw_value: +; same as get_processed_value, but it does not expand symbolic value and returns it just like any other + call warp_to_next_symbol + jc no_more_values + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc get_raw_value + test edi,edi + jz literal_value + mov edi,edx + test ebx,ebx + jz invalid_symbol_value + call get_available_value + jc invalid_symbol_value + mov al,1Ah + clc + retn + invalid_symbol_value: + xor edx,edx + mov al,1Ah + clc + retn + literal_value: + call get_literal + clc + retn + no_more_values: + ; stc + retn diff --git a/toolchain/fasm2/source/calm.inc b/toolchain/fasm2/source/calm.inc new file mode 100644 index 0000000..64f0f2e --- /dev/null +++ b/toolchain/fasm2/source/calm.inc @@ -0,0 +1,3293 @@ + +struct CompiledMacroHeader + shared_namespace dd ? + literals_offset dd ? + label_argument_leaf dd ? + label_argument_contextless db ? + reserved db ? + reserved2 dw ? +ends + +struct CompiledMacroArgument + symbol_leaf dd ? + contextless db ? + reserved db ? + reserved2 dw ? + default_value_length dd ? + default_value_offset dd ? +ends + +struct UnresolvedJump + offset dd ? + entry_length dd ? + ; source_context SourceContext +ends + +struct MatchedExcerpt + data_start dd ? + data_end dd ? + recognition_context dd ? + symbol_leaf dd ? +ends + +BOOL_NEG = -1 +BOOL_AND = -2 +BOOL_OR = -3 + +define_calm_instruction: + mov dl,DBLOCK_CALMINSTRUCTION + mov ecx,sizeof.MacroData + call add_directive_block + mov edx,[ebx+SymbolTree_Leaf.branch] + call get_symbol_namespace + mov [alm_namespace],ebx + or [assembly_mode],AMODE_CALM_DEFINITION + mov [calm_definition_active],0 + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + mov eax,[calm_code_buffer.memory_start] + mov [calm_code_cursor],eax + mov eax,[calm_literals_buffer.memory_start] + mov [calm_literals_cursor],eax + mov eax,[calm_auxiliary_buffer.memory_start] + mov [calm_auxiliary_cursor],eax + call move_to_next_symbol + jc missing_argument + cmp al,'(' + je calm_labeled_instruction + and [argument_start],0 + mov dl,SYMCLASS_INSTRUCTION + get_calm_instruction_identifier: + call get_macro_definition_symbol + jc invalid_identifier + push esi + mov eax,ebx + mov ecx,[alm_namespace] + call get_local_anchor + call get_symbol_namespace + or [ebx+SymbolTree_Root.flags],NAMESPACE_CALM + mov [new_local_namespace],ebx + pop esi + mov edi,[calm_code_buffer.memory_start] + mov [edi+CompiledMacroHeader.shared_namespace],ebx + or [symbol_definition],1 + mov ebx,[argument_start] + test ebx,ebx + jz calm_instruction_label_argument_ok + push esi edi + mov esi,ebx + cmp byte [esi],'&' + sete al + mov [edi+CompiledMacroHeader.label_argument_contextless],al + jne calm_instruction_label_prefix_ok + inc esi + calm_instruction_label_prefix_ok: + mov dl,SYMCLASS_EXPRESSION + mov ebx,[new_local_namespace] + call identify_symbol_in_namespace + mov eax,esi + pop edi esi + jc invalid_argument + test ebx,ebx + jz invalid_argument + cmp byte [eax],')' + jne invalid_argument + call update_value_definition + push esi edi + mov [value_type],VALTYPE_RESERVED + xor ecx,ecx + call assign_value + pop edi esi + calm_instruction_label_argument_ok: + mov [edi+CompiledMacroHeader.label_argument_leaf],ebx + add edi,sizeof.CompiledMacroHeader + calm_instruction_argument_declaration: + call move_to_next_symbol + jc calm_instruction_arguments_declared + cmp al,'&' + sete al + mov [contextless_processing],al + jne calm_instruction_argument_name + inc esi + calm_instruction_argument_name: + mov dl,SYMCLASS_EXPRESSION + push edi + mov ebx,[new_local_namespace] + call identify_symbol_in_namespace + pop edi + jc invalid_argument + test ebx,ebx + jz invalid_argument + mov edx,calm_code_buffer + mov ecx,sizeof.CompiledMacroArgument+4 + call reserve_workspace + mov [edi+CompiledMacroArgument.symbol_leaf],ebx + mov al,[contextless_processing] + mov [edi+CompiledMacroArgument.contextless],al + call update_value_definition + test edx,edx + jz calm_instruction_argument_prepared + push esi edi + mov [value_type],VALTYPE_RESERVED + xor ecx,ecx + call assign_value + pop edi esi + xor edx,edx + calm_instruction_argument_prepared: + call move_to_next_symbol + jc calm_instruction_argument_ready + cmp al,':' + je calm_instruction_argument_default_value + cmp al,'=' + je calm_instruction_argument_default_value + cmp al,'*' + jne calm_instruction_argument_ready + dec edx + inc esi + calm_instruction_argument_ready: + mov [edi+CompiledMacroArgument.default_value_length],edx + add edi,sizeof.CompiledMacroArgument + call move_to_next_symbol + jc calm_instruction_arguments_declared + inc esi + cmp al,'&' + je calm_instruction_greedy_argument + cmp al,',' + jne invalid_argument + call move_to_next_symbol + jc invalid_argument + jmp calm_instruction_argument_declaration + calm_instruction_argument_default_value: + inc esi + mov [calm_code_cursor],edi + mov edx,calm_literals_buffer + mov edi,[calm_literals_cursor] + mov ecx,[line_end] + sub ecx,esi + add ecx,1+sizeof.RecognitionContext + call reserve_workspace + mov [calm_literals_cursor],edi + call move_to_next_symbol + jc calm_plain_default_value + cmp al,'<' + je calm_enclosed_default_value + calm_plain_default_value: + mov dl,',' + xor dh,dh + mov [breakpoint_token],'&' + call extract_piece_of_line + jmp calm_default_value_ready + calm_enclosed_default_value: + inc esi + mov dl,'>' + mov dh,'<' + mov [breakpoint_token],0 + call extract_piece_of_line + cmp al,'>' + jne invalid_argument + inc esi + calm_default_value_ready: + mov edx,edi + xchg edi,[calm_literals_cursor] + mov eax,edi + sub edx,edi + sub eax,[calm_literals_buffer.memory_start] + mov edi,[calm_code_cursor] + mov [edi+CompiledMacroArgument.default_value_offset],eax + jmp calm_instruction_argument_ready + calm_instruction_greedy_argument: + assert CompiledMacroArgument.symbol_leaf = 0 + or eax,-1 + stosd + jmp call_instruction_begin_code + calm_labeled_instruction: + inc esi + call move_to_next_symbol + jc missing_argument + mov [argument_start],esi + mov edi,[expression_workspace.memory_start] + mov dl,')' + xor dh,dh + mov [breakpoint_token],dh + call cut_piece_of_line + cmp al,')' + jne invalid_argument + inc esi + mov dl,SYMCLASS_STRUCTURE + jmp get_calm_instruction_identifier + calm_instruction_arguments_declared: + assert CompiledMacroArgument.symbol_leaf = 0 + xor eax,eax + stosd + call_instruction_begin_code: + mov [calm_code_cursor],edi + mov eax,[new_local_namespace] + mov [current_context.base_namespace],eax + and [calm_line_number],0 + mov [calm_definition_active],1 + jmp instruction_assembled + +assemble_alm_instruction: + or [alm_statement],1 + mov ebx,[source_context] + mov eax,[ebx+SourceContext.number_of_entries] + dec eax + imul eax,sizeof.SourceEntry + test [ebx+sizeof.SourceContext+eax+SourceEntry.flags],SRCF_ALM_STATEMENT + jnz identify_alm_instruction + inc [calm_line_number] + identify_alm_instruction: + call move_to_next_symbol + jc empty_line + call get_alm_identifier + jc unrecognized_alm_instruction + mov dl,SYMCLASS_INSTRUCTION + call identify_alm_symbol + jc alm_label + call get_available_value + jc alm_label + test [edx+ValueDefinition.flags],VAL_UNCONDITIONAL + jnz execute_alm_instruction + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + execute_alm_instruction: + cmp [edx+ValueDefinition.type],VALTYPE_CALM + je launch_calm + cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC + je use_macro + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_COMMAND + jne unrecognized_alm_instruction + jmp [edx+ValueDefinition.value] + alm_label: + call move_to_next_symbol + jc unrecognized_alm_instruction + cmp al,':' + jne unrecognized_alm_instruction + inc esi + test [assembly_mode],AMODE_SKIP + jnz identify_alm_instruction + test [assembly_mode],AMODE_DEFINITION + jnz add_label_to_macro + call identify_calm_location + jc unrecognized_alm_instruction + call create_constant_value_definition + test edx,edx + jz assembly_line + mov [edx+ValueDefinition.type],VALTYPE_PLAIN + mov eax,[calm_code_cursor] + sub eax,[calm_code_buffer.memory_start] + mov [edx+ValueDefinition.value],eax + mov eax,[current_pass] + mov [edx+ValueDefinition.pass],eax + jmp identify_alm_instruction + unrecognized_alm_instruction: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + mov edx,_unexpected_instruction + call register_error + jmp assembly_line + get_alm_identifier: + xor ecx,ecx + call move_to_next_symbol + jc malformed_alm_identifier + cmp al,1Ah + je alm_plain_name + cmp al,30h + je alm_numeric_name + cmp al,'#' + jne malformed_alm_identifier + call check_concatenation + jnc get_alm_identifier + malformed_alm_identifier: + stc + retn + alm_plain_name: + inc esi + lodsd + mov ebx,eax + mov ecx,[ebx] + mov eax,[ebx+4+ecx] + mov [case_sensitive_hash],eax + mov eax,[ebx+4+ecx+4] + mov [case_insensitive_hash],eax + alm_check_for_concatenation: + xor ecx,ecx + call move_to_next_symbol + jc alm_identifier_ok + cmp al,'#' + jne alm_identifier_ok + call check_concatenation + jc alm_identifier_ok + call move_to_next_symbol + jc alm_identifier_ok + cmp al,1Ah + je alm_concatenation + cmp al,30h + je alm_concatenation + alm_identifier_ok: + mov [symbol_data],ebx + cmp ebx,[assembly_workspace.memory_start] + je alm_identifier_volatile + mov [name_volatile],0 + clc + retn + alm_identifier_volatile: + sub edi,ebx + sub edi,4 + mov [ebx],edi + mov [name_volatile],1 + clc + retn + alm_concatenation: + mov edx,assembly_workspace + cmp ebx,[edx+Workspace.memory_start] + je alm_name_segment + mov edi,[edx+Workspace.memory_start] + add edi,4 + mov ecx,[ebx] + call reserve_workspace + xchg ebx,esi + lodsd + mov ecx,eax + rep movsb + mov esi,ebx + mov ebx,[edx+Workspace.memory_start] + alm_name_segment: + lodsb + cmp al,30h + je alm_attach_numeric_segment + lodsd + push ebx esi + alm_append_name: + mov esi,eax + mov ecx,[esi] + mov edx,assembly_workspace + call reserve_workspace + lodsd + lea ebx,[esi+eax] + mov ecx,[case_sensitive_hash] + mov edx,[case_insensitive_hash] + xor eax,eax + alm_name_hash: + lodsb + xor cl,al + xor dl,[characters+eax] + imul ecx,FNV_PRIME + imul edx,FNV_PRIME + stosb + cmp esi,ebx + jne alm_name_hash + mov [case_sensitive_hash],ecx + mov [case_insensitive_hash],edx + pop esi ebx + jmp alm_check_for_concatenation + alm_numeric_name: + inc esi + mov ebx,[assembly_workspace.memory_start] + lea edi,[ebx+4] + mov eax,FNV_OFFSET + mov [case_sensitive_hash],eax + mov [case_insensitive_hash],eax + alm_attach_numeric_segment: + mov edx,esi + mov ecx,[edx] + lea esi,[esi+4+ecx] + push ebx esi + push edi + call convert_number_back + pop edi + mov eax,edx + jmp alm_append_name + identify_alm_symbol: + mov [symbol_class],dl + push esi + mov esi,[symbol_data] + lodsd + mov ecx,eax + mov edx,[case_insensitive_hash] + mov ebx,[alm_namespace] + mov [name_kind],NAME_CASEINSENSITIVE + and [name_token],0 + and [symbol_required],0 + and [symbol_expected],0 + call scan_namespace + pop esi + retn + identify_calm_location: + mov [symbol_class],SYMCLASS_CALM_LOCATION + push esi + mov esi,[symbol_data] + lodsd + mov ecx,eax + mov edx,[case_sensitive_hash] + mov ebx,[current_context.base_namespace] + and [name_kind],0 + and [name_token],0 + or [symbol_required],1 + or [symbol_expected],1 + call scan_namespace + pop esi + retn + +alm_jyes: + mov [value],calm_jyes + jmp assemble_alm_jump +alm_jno: + mov [value],calm_jno + jmp assemble_alm_jump +alm_jump: + mov [value],calm_jump + assemble_alm_jump: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + call move_to_next_symbol + jc missing_argument + call get_alm_identifier + jc invalid_argument + call identify_calm_location + jc invalid_argument + mov edx,[ebx+SymbolTree_Leaf.definition] + test edx,edx + jz alm_unresolved_jump + mov eax,[edx+ValueDefinition.pass] + cmp eax,[current_pass] + jne alm_unresolved_jump + mov ebx,[edx+ValueDefinition.value] + emit_calm_jump: + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+4 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,[value] + stosd + mov eax,ebx + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + alm_unresolved_jump: + push esi + mov edx,calm_auxiliary_buffer + mov edi,[calm_auxiliary_cursor] + mov esi,[source_context] + mov ecx,[esi+SourceContext.number_of_entries] + imul ecx,sizeof.SourceEntry + add ecx,sizeof.SourceContext + add ecx,sizeof.UnresolvedJump + call reserve_workspace + mov [calm_auxiliary_cursor],edi + mov eax,[calm_code_cursor] + add eax,8 + sub eax,[calm_code_buffer.memory_start] + mov [edi+UnresolvedJump.offset],eax + add edi,sizeof.UnresolvedJump + call clone_source_context + mov ecx,edi + xchg edi,[calm_auxiliary_cursor] + sub ecx,edi + mov [edi+UnresolvedJump.entry_length],ecx + pop esi + jmp emit_calm_jump + +alm_end: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_unconditional_alm_instruction + call move_to_next_symbol + jc finish_calm_definition + call get_alm_identifier + jc invalid_argument + mov dl,SYMCLASS_STRUCTURE + call identify_alm_symbol + jc invalid_argument + mov edx,[ebx+SymbolTree_Leaf.definition] + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_COMMAND + jne invalid_argument + cmp [edx+ValueDefinition.value],alm_end + jne invalid_argument + finish_calm_definition: + mov dl,DBLOCK_CALMINSTRUCTION + call find_directive_block + jc unexpected_unconditional_alm_instruction + call close_directive_block + and [assembly_mode],not AMODE_CALM_DEFINITION + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + cmp [calm_definition_active],0 + je instruction_assembled + push esi + mov esi,[calm_auxiliary_buffer.memory_start] + resolve_calm_jumps: + cmp esi,[calm_auxiliary_cursor] + je calm_jumps_resolved + mov eax,[esi+UnresolvedJump.offset] + add eax,[calm_code_buffer.memory_start] + mov ebx,[eax] + mov edx,[ebx+SymbolTree_Leaf.definition] + test edx,edx + jz unresolvable_calm_jump + mov ecx,[edx+ValueDefinition.pass] + cmp ecx,[current_pass] + jne unresolvable_calm_jump + mov ebx,[edx+ValueDefinition.value] + mov [eax],ebx + resolve_next_calm_jump: + add esi,[esi+UnresolvedJump.entry_length] + jmp resolve_calm_jumps + unresolvable_calm_jump: + mov edx,[calm_code_cursor] + sub edx,[calm_code_buffer.memory_start] + mov [eax],edx + add esi,sizeof.UnresolvedJump + mov edx,_undefined_jump_target + call register_delayed_error + sub esi,sizeof.UnresolvedJump + jmp resolve_next_calm_jump + calm_jumps_resolved: + mov ebx,[current_context.base_namespace] + mov edx,[ebx+SymbolTree_Root.parent_branch] + mov eax,[edx+SymbolTree_Foliage.root] + mov [current_context.base_namespace],eax + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,[calm_literals_cursor] + mov esi,[calm_literals_buffer.memory_start] + sub ecx,esi + add ecx,8 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_end + stosd + mov ebx,[calm_code_buffer.memory_start] + mov eax,edi + sub eax,ebx + mov [ebx+CompiledMacroHeader.literals_offset],eax + mov ecx,[calm_literals_cursor] + sub ecx,esi + rep movsb + mov ebx,[macro_leaf] + test ebx,ebx + jz calm_definition_done + call create_value_definition + test edx,edx + jz calm_definition_done + mov esi,[calm_code_buffer.memory_start] + mov ecx,edi + sub ecx,esi + mov [value_type],VALTYPE_CALM + call assign_value + mov al,[macro_flags] + or [edx+ValueDefinition.flags],al + calm_definition_done: + pop esi + jmp instruction_assembled + unexpected_unconditional_alm_instruction: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + jmp unexpected_instruction + +alm_local: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + call move_to_next_symbol + jc missing_argument + or [symbol_definition],1 + mov dl,SYMCLASS_EXPRESSION + mov ebx,[current_context.base_namespace] + call identify_symbol_in_namespace + jc invalid_argument + test ebx,ebx + jz invalid_argument + call update_value_definition + test edx,edx + jz alm_next_local + push esi + mov [value_type],VALTYPE_RESERVED + xor ecx,ecx + call assign_value + pop esi + alm_next_local: + call move_to_next_symbol + jc instruction_assembled + cmp al,',' + jne invalid_argument + inc esi + jmp alm_local + +alm_assemble: + mov [value],calm_assemble + jmp assemble_alm_operation_on_variable +alm_stringify: + mov [value],calm_stringify + assemble_alm_operation_on_variable: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+4 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,[value] + stosd + mov eax,ebx + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + +alm_arrange: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + call move_to_next_symbol + jc missing_argument + cmp al,',' + jne instruction_assembled + inc esi + call move_to_next_symbol + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+12 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_arrange + stosd + mov eax,ebx + stosd + mov edx,calm_literals_buffer + mov ebx,[calm_literals_cursor] + mov eax,ebx + sub eax,[edx+Workspace.memory_start] + stosd + mov [calm_code_cursor],edi + mov edi,ebx + mov ecx,[line_end] + sub ecx,esi + shl ecx,1 + call reserve_workspace + mov [breakpoint_token],0 + call parse_pattern + mov [calm_literals_cursor],edi + mov eax,edi + mov edi,[calm_code_cursor] + sub eax,[calm_literals_buffer.memory_start] + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + parse_pattern: + ; in: + ; esi - first token of the pattern in the preprocessed line + ; edi - buffer with enough space to hold twice the length of the preprocessed text left in line + ; [breakpoint_token] = initial byte of symbol that should end the pattern + ; out: + ; esi - after the processed portion of line (might be at [line_end]) + ; edi - in the buffer after the stored pattern + cmp esi,[line_end] + je pattern_parsed + lodsb + token_available: + cmp al,[breakpoint_token] + je pattern_breakpoint + token_in_pattern: + cmp al,'=' + je parse_pattern_literal + cmp al,1Ah + je parse_reference_in_pattern + cmp al,40h + je ignore_context_in_pattern + cmp al,20h + je whitespace_in_pattern + stosb + literal_token_in_pattern: + cmp al,22h + je copy_pattern_data + cmp al,27h + je copy_pattern_data + cmp al,30h + jne parse_pattern + lodsd + mov ecx,eax + stosd + rep movsb + jmp parse_pattern + whitespace_in_pattern: + cmp esi,[line_end] + je pattern_parsed + lodsb + cmp al,20h + je whitespace_in_pattern + cmp al,[breakpoint_token] + je pattern_breakpoint + cmp al,40h + jne store_whitespace_in_pattern + call pass_context + jmp whitespace_in_pattern + store_whitespace_in_pattern: + mov byte [edi],20h + inc edi + jmp token_in_pattern + pattern_breakpoint: + dec esi + pattern_parsed: + retn + pass_context: + mov eax,esi + add esi,sizeof.RecognitionContext + cmp dword [eax],0 + je zero_context + mov [embedded_context],eax + retn + zero_context: + and [embedded_context],0 + retn + copy_pattern_data: + movsd + jmp parse_pattern + ignore_context_in_pattern: + call pass_context + jmp parse_pattern + ignore_context_in_pattern_literal: + call pass_context + parse_pattern_literal: + cmp esi,[line_end] + je error_in_parsed_pattern + lodsb + cmp al,40h + je ignore_context_in_pattern_literal + cmp al,20h + je parse_hard_space_in_pattern + stosb + cmp al,1Ah + jne literal_token_in_pattern + movsd + jmp parsed_name_in_pattern + parse_hard_space_in_pattern: + mov al,0A0h + stosb + jmp parse_pattern + parse_reference_in_pattern: + dec esi + call detect_numeric_symbol + jc numeric_name_in_pattern + inc esi + mov [name_token],esi + lodsd + mov dx,SYMCLASS_EXPRESSION + mov [name_volatile],0 + push esi edi + mov esi,eax + lodsd + mov ecx,eax + xor ebx,ebx + mov eax,[embedded_context] + test eax,eax + jz use_current_namespace_in_pattern + mov eax,[eax+RecognitionContext.base_namespace] + jmp namespace_in_pattern_ok + use_current_namespace_in_pattern: + mov eax,[current_context.base_namespace] + namespace_in_pattern_ok: + mov [recognition_context.base_namespace],eax + call recognize_symbol + pop edi esi + mov al,1Bh + stosb + mov eax,[name_token] + mov eax,[eax] + stosd + mov eax,ebx + stosd + parsed_name_in_pattern: + cmp esi,[line_end] + je pattern_parsed + lodsb + cmp al,40h + je ignore_context_after_name_in_pattern + cmp al,'?' + jne token_available + mov al,0BFh + stosb + jmp parse_pattern + ignore_context_after_name_in_pattern: + call pass_context + jmp parsed_name_in_pattern + numeric_name_in_pattern: + movsb + movsd + jmp parsed_name_in_pattern + error_in_parsed_pattern: + mov edx,_invalid_argument + call register_error + jmp parse_pattern + +alm_match: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + call move_to_next_symbol + jc missing_argument + mov edx,calm_literals_buffer + mov edi,[calm_literals_cursor] + mov ecx,[line_end] + sub ecx,esi + shl ecx,1 + call reserve_workspace + mov [calm_literals_cursor],edi + mov [breakpoint_token],',' + call parse_pattern + xchg edi,[calm_literals_cursor] + mov [pattern_start],edi + cmp esi,[line_end] + je missing_argument + lodsb + cmp al,',' + jne invalid_argument + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + and [brackets],0 + call move_to_next_symbol + jc no_brackets + cmp al,',' + jne no_brackets + inc esi + call move_to_next_symbol + jc invalid_argument + mov dl,al + lea edi,[esi+1] + call skip_token + cmp esi,edi + jne invalid_argument + call move_to_next_symbol + jc invalid_argument + mov dh,al + lea edi,[esi+1] + call skip_token + cmp esi,edi + jne invalid_argument + mov word [brackets],dx + no_brackets: + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+16 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_match + stosd + mov eax,ebx + stosd + mov ebx,[calm_literals_buffer.memory_start] + mov eax,[pattern_start] + sub eax,ebx + stosd + mov eax,[calm_literals_cursor] + sub eax,ebx + stosd + mov eax,[brackets] + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + +alm_compute: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + call move_to_next_symbol + jc missing_argument + cmp al,',' + jne instruction_assembled + inc esi + call move_to_next_symbol + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+8 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_compute + stosd + mov eax,ebx + stosd + call compile_expression + jnc instruction_assembled + sub [calm_code_cursor],8+8 + jmp instruction_assembled + compile_expression: + xor eax,eax + stosd + mov [calm_code_cursor],edi + mov edi,[expression_workspace.memory_start] + and [leave_opening_parentheses],0 + or [use_raw_values],1 + call parse_expression + and [use_raw_values],0 + push esi + mov esi,[expression_workspace.memory_start] + mov ecx,edi + sub ecx,esi + add ecx,4 + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + call reserve_workspace + mov [calm_code_cursor],edi + call convert_parsed_expression + pop esi + jc no_computable_expression + mov ecx,edi + xchg edi,[calm_code_cursor] + sub ecx,edi + mov [edi-4],ecx + ; clc + retn + no_computable_expression: + retn + convert_parsed_expression: + xor ebx,ebx + xor ecx,ecx + xor dl,dl + mov [subexpression_end],esi + scan_reducible_subexpression: + mov eax,[esi+ebx] + test eax,eax + jz end_subexpression + cmp al,EXPR_OPERATOR + je scan_operator + cmp al,EXPR_SYMBOL_VALUE + je scan_parsed_symbol + cmp al,EXPR_NUMBER + je scan_parsed_value + cmp al,EXPR_STRING + je scan_parsed_value + cmp al,EXPR_FLOAT + je scan_parsed_value + jmp end_subexpression + scan_parsed_value: + add ebx,8 + inc ecx + jmp scan_reducible_subexpression + scan_parsed_symbol: + mov eax,[esi+ebx+4] + test eax,eax + jz end_subexpression + test [eax+SymbolTree_Leaf.flags],SYM_CONSTANT + jz end_subexpression + mov eax,[esi+ebx+8] + test eax,eax + jz end_subexpression + cmp [eax+ValueDefinition.type],VALTYPE_SYMBOLIC + je end_subexpression + add ebx,12 + inc ecx + jmp scan_reducible_subexpression + scan_operator: + test eax,EXPRF_OPERATOR_UNARY + setz al + movzx eax,al + cmp ecx,eax + jbe end_subexpression + sub ecx,eax + add ebx,8 + or dl,1 + jmp scan_reducible_subexpression + end_subexpression: + add ebx,esi + mov [subexpression_end],ebx + test dl,dl + jz convert_irreducible_expression + cmp ecx,1 + jne convert_irreducible_expression + push edi + xor eax,eax + xchg eax,[ebx] + push eax + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + mov esi,[subexpression_end] + pop dword [esi] + call pop_terms + mov ebx,edi + pop edi + jc convert_irreducible_expression + cmp [ebx+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + jne embed_numeric_value + mov eax,[ebx+ExpressionTerm.attributes] + mov ebx,[ebx+ExpressionTerm.value] + jmp copy_expression_literal + embed_numeric_value: + push edi + mov edi,ebx + call convert_terms_to_numeric_value + pop edi + mov ebx,esi + mov esi,[subexpression_end] + mov eax,EXPR_POLYNOMIAL + EXPRF_CALM_LITERAL + jmp parsed_value_length_ok + convert_irreducible_expression: + lodsd + test eax,eax + jz parsed_expression_converted + cmp al,EXPR_SYMBOL_VALUE + je copy_parsed_symbol + cmp al,EXPR_OPERATOR + je copy_parsed_operator + cmp al,EXPR_NUMBER + je copy_parsed_value + cmp al,EXPR_STRING + je copy_parsed_value + cmp al,EXPR_FLOAT + je copy_parsed_value + cmp al,EXPR_MISSING_PARENTHESIS + je expression_missing_parenthesis + jmp invalid_expression + copy_parsed_value: + mov ebx,[esi] + add esi,4 + copy_expression_literal: + or eax,EXPRF_CALM_LITERAL + test eax,EXPRF_VALUE_IN_WORKSPACE + jnz parsed_value_in_workspace + test ebx,ebx + jnz parsed_value_pointer_ok + jmp invalid_expression + parsed_value_in_workspace: + add ebx,[value_workspace.memory_start] + and eax,not EXPRF_VALUE_IN_WORKSPACE + parsed_value_pointer_ok: + cmp al,EXPR_FLOAT + je parsed_float_to_copy + mov ecx,[ebx] + add ecx,4 + jmp parsed_value_length_ok + parsed_float_to_copy: + mov ecx,sizeof.FloatData + parsed_value_length_ok: + stosd + mov edx,[calm_literals_cursor] + mov eax,edx + sub eax,[calm_literals_buffer.memory_start] + stosd + push edi + push ecx + mov edi,edx + mov edx,calm_literals_buffer + call reserve_workspace + pop ecx + xchg esi,ebx + rep movsb + mov [calm_literals_cursor],edi + mov esi,ebx + pop edi + parsed_item_converted: + cmp esi,[subexpression_end] + jbe convert_irreducible_expression + jmp convert_parsed_expression + copy_parsed_symbol: + mov al,EXPR_SYMBOL + stosd + lodsd + test eax,eax + jz invalid_expression + stosd + add esi,4 + jmp parsed_item_converted + copy_parsed_operator: + stosd + movsd + jmp parsed_item_converted + parsed_expression_converted: + stosd + clc + retn + +alm_check: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov eax,edi + sub eax,[edx+Workspace.memory_start] + mov [calm_rollback_offset],eax + mov ecx,8 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_check + stosd + mov [calm_code_cursor],edi + or [use_raw_values],1 + mov ebx,[condition_stack_base] + and dword [ebx],0 + add ebx,4 + mov [condition_stack],ebx + parse_alm_condition: + call peek_at_constituent_value + jc calm_condition_parsed + cmp al,'~' + jne parse_alm_logical_value + and [current_constituent],0 + mov ecx,BOOL_NEG + call push_to_condition_stack + jmp parse_alm_condition + alm_logical_value_empty: + test ecx,ecx + jz calm_condition_parsed + call push_to_condition_stack + jmp parse_alm_condition + parse_alm_logical_value: + call parse_logical_value + jc alm_logical_value_empty + jecxz convert_logical_value + call push_to_condition_stack + convert_logical_value: + mov [calm_source_pointer],esi + mov esi,[expression_workspace.memory_start] + mov ecx,edi + sub ecx,esi + add ecx,8 + add ecx,[condition_stack] + sub ecx,[condition_stack_base] + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + call reserve_workspace + xor eax,eax + stosd + mov [calm_code_cursor],edi + mov eax,[comparator] + stosd + mov eax,[expression_end] + convert_argument_sequences: + push eax + call convert_parsed_expression + pop eax + jc condition_malformed + cmp esi,eax + jb convert_argument_sequences + mov ecx,edi + xchg edi,[calm_code_cursor] + sub ecx,edi + mov [edi-4],ecx + mov esi,[calm_source_pointer] + parse_alm_logical_operator: + call get_constituent_value + jc calm_condition_parsed + cmp al,')' + je close_subconditions + cmp al,'|' + je parse_or + cmp al,'&' + jne condition_malformed + parse_and: + mov ecx,BOOL_AND + jmp prepare_stack_for_logical_operator + parse_or: + mov ecx,BOOL_OR + prepare_stack_for_logical_operator: + mov ebx,[condition_stack] + sub ebx,4 + cmp dword [ebx],0 + jge push_logical_operator + mov [condition_stack],ebx + mov edi,[calm_code_cursor] + mov eax,[ebx] + stosd + mov [calm_code_cursor],edi + jmp prepare_stack_for_logical_operator + push_logical_operator: + call push_to_condition_stack + jmp parse_alm_condition + close_subconditions: + mov ebx,[condition_stack] + sub ebx,4 + cmp dword [ebx],0 + jl store_logical_operator + je condition_malformed + dec dword [ebx] + jnz parse_alm_logical_operator + mov [condition_stack],ebx + jmp parse_alm_logical_operator + store_logical_operator: + mov edi,[calm_code_cursor] + mov eax,[ebx] + mov [condition_stack],ebx + stosd + mov [calm_code_cursor],edi + jmp close_subconditions + push_to_condition_stack: + mov ebx,[condition_stack] + mov [ebx],ecx + add ebx,4 + cmp [condition_stack_end],ebx + je grow_condition_stack + mov [condition_stack],ebx + retn + grow_condition_stack: + mov eax,[condition_stack_base] + sub ebx,eax + lea ecx,[ebx+4] + call grow_stack + mov [condition_stack_base],eax + add ebx,eax + mov [condition_stack],ebx + add ecx,eax + mov [condition_stack_end],ecx + retn + calm_condition_parsed: + mov edi,[calm_code_cursor] + mov ebx,[condition_stack] + mov ecx,ebx + sub ecx,[condition_stack_base] + mov edx,calm_code_buffer + call reserve_workspace + finish_calm_condition: + sub ebx,4 + mov eax,[ebx] + cmp eax,0 + jg condition_malformed + stosd + jne finish_calm_condition + mov [calm_code_cursor],edi + and [use_raw_values],0 + jmp instruction_assembled + condition_malformed: + and [use_raw_values],0 + mov edx,_invalid_expression + alm_abort: + call register_error + mov eax,[calm_rollback_offset] + add eax,[calm_code_buffer.memory_start] + mov [calm_code_cursor],eax + jmp assembly_line + +alm_publish: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + mov [value],calm_publish_variable + call move_to_next_symbol + jc missing_argument + cmp al,':' + jne get_identifier_variable + inc esi + mov [value],calm_publish_stack + get_identifier_variable: + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + mov [label_leaf],ebx + call move_to_next_symbol + jc missing_argument + cmp al,':' + jne get_value_variable + mov eax,calm_publish_constant + xchg [value],eax + cmp eax,calm_publish_variable + jne invalid_argument + inc esi + call move_to_next_symbol + jc missing_argument + get_value_variable: + cmp al,',' + jne missing_argument + inc esi + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+8 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,[value] + stosd + mov eax,[label_leaf] + stosd + mov eax,ebx + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + +alm_transform: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + call move_to_next_symbol + jc missing_argument + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + mov [label_leaf],ebx + xor ebx,ebx + call move_to_next_symbol + jc alm_transform_arguments_ready + cmp al,',' + jne alm_transform_arguments_ready + inc esi + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test edx,edx + jz invalid_identifier + call get_symbol_namespace + alm_transform_arguments_ready: + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+8 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_transform + stosd + mov eax,[label_leaf] + stosd + mov eax,ebx + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + +alm_take: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + call move_to_next_symbol + jc missing_argument + xor ebx,ebx + and [symbol_definition],0 + cmp al,',' + je alm_take_destination_ready + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + call move_to_next_symbol + jc missing_argument + cmp al,',' + jne missing_argument + alm_take_destination_ready: + mov [label_leaf],ebx + inc esi + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+8 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_take + stosd + mov eax,[label_leaf] + stosd + mov eax,ebx + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + +alm_err: + mov [value],calm_err + jmp assemble_alm_operation_on_expression +alm_display: + mov [value],calm_display + assemble_alm_operation_on_expression: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+4 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,[value] + stosd + call compile_expression + jmp instruction_assembled + +alm_emit: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+4 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_emit + stosd + call compile_expression + mov edi,[calm_code_cursor] + call peek_at_constituent_value + jc alm_call_arguments_ready + cmp al,',' + jne alm_call_arguments_ready + and [current_constituent],0 + call compile_expression + jmp instruction_assembled + +alm_load: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov eax,edi + sub eax,[edx+Workspace.memory_start] + mov [calm_rollback_offset],eax + mov ecx,12+4 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_load + stosd + mov eax,ebx + stosd + call move_to_next_symbol + jc alm_missing_argument + cmp al,',' + jne alm_malformed_argument + inc esi + call move_to_next_symbol + call compile_expression + push ecx + call get_constituent_value + pop ecx + jc alm_missing_argument + cmp al,':' + je alm_load_offset + cmp al,',' + jne alm_malformed_argument + mov edi,[calm_rollback_offset] + add edi,[calm_code_buffer.memory_start] + mov dword [edi+4],calm_load_from_output + jmp alm_load_length + alm_load_offset: + mov edi,[calm_code_cursor] + call compile_expression + call get_constituent_value + jc alm_missing_argument + cmp al,',' + jne alm_malformed_argument + alm_load_length: + mov edi,[calm_code_cursor] + call compile_expression + jmp instruction_assembled + alm_missing_argument: + mov edx,_missing_argument + jmp alm_abort + alm_malformed_argument: + mov edx,_invalid_argument + jmp alm_abort + +alm_store: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov eax,edi + sub eax,[edx+Workspace.memory_start] + mov [calm_rollback_offset],eax + mov ecx,8+4 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_store + stosd + call compile_expression + call get_constituent_value + jc alm_missing_argument + cmp al,':' + je alm_store_offset + cmp al,',' + jne alm_malformed_argument + mov edi,[calm_rollback_offset] + add edi,[calm_code_buffer.memory_start] + mov dword [edi+4],calm_store_in_output + jmp alm_store_length + alm_store_offset: + mov edi,[calm_code_cursor] + call compile_expression + call get_constituent_value + jc alm_missing_argument + cmp al,',' + jne alm_malformed_argument + alm_store_length: + mov edi,[calm_code_cursor] + call compile_expression + call get_constituent_value + jc alm_missing_argument + cmp al,',' + jne alm_malformed_argument + mov edi,[calm_code_cursor] + call compile_expression + jmp instruction_assembled + +alm_call: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + and [symbol_definition],0 + mov edx,[embedded_context] + mov [line_context],edx + test edx,edx + jnz alm_call_context_adjust + mov edx,current_context + alm_call_context_adjust: + mov ebx,[edx+RecognitionContext.base_namespace] + test [ebx+SymbolTree_Root.flags],NAMESPACE_CALM + jz alm_call_context_ready + mov eax,[ebx+SymbolTree_Root.parent_branch] + test eax,eax + jz alm_call_context_ready + mov ebx,[eax+SymbolTree_Foliage.root] + mov eax,alm_adjusted_context + mov [eax+RecognitionContext.base_namespace],ebx + mov ecx,[edx+RecognitionContext.base_label] + mov [eax+RecognitionContext.base_label],ecx + mov [embedded_context],eax + alm_call_context_ready: + mov dl,SYMCLASS_INSTRUCTION + call identify_symbol + jc invalid_identifier + test ebx,ebx + jz invalid_identifier + cmp [ebx+SymbolTree_Leaf.class],SYMCLASS_INSTRUCTION + je alm_call_instruction_ok + mov ebx,edx + mov [symbol_class],SYMCLASS_INSTRUCTION + or [symbol_required],1 + or [symbol_expected],1 + call scan_symbol_branch + jc invalid_identifier + mov edi,ebx + mark_instruction_fallbacks: + mov edx,[edi+SymbolTree_Leaf.fallback_neighbour] + test edx,edx + jz instruction_fallback_neighbour_ok + or [edx+SymbolTree_Leaf.extra_flags],SYMX_INSTRUCTION_PREDICTED + instruction_fallback_neighbour_ok: + mov edi,[edi+SymbolTree_Leaf.fallback_parent] + test edi,edi + jz alm_call_instruction_ok + or [edi+SymbolTree_Leaf.extra_flags],SYMX_INSTRUCTION_PREDICTED + jmp mark_instruction_fallbacks + alm_call_instruction_ok: + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8+8 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_call + stosd + mov eax,ebx + stosd + mov eax,alm_adjusted_context + cmp [embedded_context],eax + jne alm_call_argument + mov eax,[line_context] + mov [embedded_context],eax + alm_call_argument: + call move_to_next_symbol + jc alm_call_arguments_ready + cmp al,',' + jne alm_call_invalid_argument + inc esi + mov edx,calm_code_buffer + mov ecx,8 + call reserve_workspace + call move_to_next_symbol + jc alm_call_empty_argument + cmp al,',' + je alm_call_empty_argument + push edi + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + pop edi + jc alm_call_invalid_argument + test ebx,ebx + jz alm_call_invalid_argument + mov eax,ebx + stosd + jmp alm_call_argument + alm_call_empty_argument: + or eax,-1 + stosd + jmp alm_call_argument + alm_call_invalid_argument: + mov edx,_invalid_argument + call register_error + alm_call_arguments_ready: + xor eax,eax + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + +alm_exit: + test [assembly_mode],AMODE_CALM_DEFINITION + jz unexpected_instruction + mov edi,[calm_code_cursor] + mov edx,calm_code_buffer + mov ecx,8 + call reserve_workspace + mov eax,[calm_line_number] + stosd + mov eax,calm_end + stosd + mov [calm_code_cursor],edi + jmp instruction_assembled + +launch_calm: + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + mov eax,[ebx+SymbolTree_Leaf.branch] + mov [instruction_branch],eax + mov [calm_value],edx + mov [calm_source_pointer],esi + mov esi,[edx+ValueDefinition.value] + mov eax,[esi+CompiledMacroHeader.literals_offset] + add eax,esi + mov [calm_literals],eax + mov [breakpoint_token],0 + mov ebx,[esi+CompiledMacroHeader.label_argument_leaf] + test ebx,ebx + jz calm_label_argument_ok + test [assembly_mode],AMODE_DEFINITION + setnz al + or al,[esi+CompiledMacroHeader.label_argument_contextless] + mov [contextless_processing],al + call update_value_definition + test edx,edx + jz calm_label_argument_ok + push esi + push edx + push [line_end] + push [embedded_context] + mov eax,[line_context] + mov [embedded_context],eax + mov esi,[line_start] + mov ecx,[label_instruction_start] + mov [line_end],ecx + sub ecx,esi + add ecx,1+sizeof.RecognitionContext + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + call reserve_workspace + xor edx,edx + mov [breakpoint_token],dl + call extract_piece_of_line + pop [embedded_context] + pop [line_end] + pop edx + mov [value_type],VALTYPE_SYMBOLIC + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + call assign_value + pop esi + calm_label_argument_ok: + add esi,sizeof.CompiledMacroHeader + mov eax,[esi] + inc eax + cmp eax,1 + jbe calm_arguments_defined + get_calm_argument: + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + mov ecx,[line_end] + sub ecx,[calm_source_pointer] + add ecx,1+sizeof.RecognitionContext + call reserve_workspace + test [assembly_mode],AMODE_DEFINITION + setnz al + or al,[esi+CompiledMacroArgument.contextless] + mov [contextless_processing],al + mov eax,[esi+sizeof.CompiledMacroArgument] + xchg esi,[calm_source_pointer] + inc eax + jz get_calm_greedy_argument + call extract_argument_value + jmp calm_argument_value_cut + get_calm_greedy_argument: + xor edx,edx + call extract_piece_of_line + calm_argument_value_cut: + xchg esi,[calm_source_pointer] + mov ebx,[esi+CompiledMacroArgument.symbol_leaf] + call update_value_definition + test edx,edx + jz calm_argument_ok + mov ecx,edi + sub ecx,[assembly_workspace.memory_start] + test ecx,ecx + jnz calm_argument_value_ready + or ecx,[esi+CompiledMacroArgument.default_value_length] + jz calm_argument_value_ready + cmp ecx,-1 + je missing_argument + push esi + mov esi,[esi+CompiledMacroArgument.default_value_offset] + add esi,[calm_literals] + jmp calm_assign_argument_value + calm_argument_value_ready: + push esi + mov esi,[assembly_workspace.memory_start] + calm_assign_argument_value: + mov [value_type],VALTYPE_SYMBOLIC + call assign_value + pop esi + calm_argument_ok: + add esi,sizeof.CompiledMacroArgument + mov eax,[esi] + inc eax + cmp eax,1 + jbe calm_arguments_defined + xchg esi,[calm_source_pointer] + call move_to_next_symbol + jc calm_next_argument + cmp al,',' + jne invalid_argument + inc esi + calm_next_argument: + xchg esi,[calm_source_pointer] + jmp get_calm_argument + calm_arguments_defined: + add esi,4 + and [calm_instruction_number],0 + call create_source_entry + jc calm_exceeded_stack_limit + mov edx,[calm_value] + mov [ebx+SourceEntry.type],SOURCE_CALM + mov [ebx+SourceEntry.text],edx + sub esi,[edx+ValueDefinition.value] + mov [ebx+SourceEntry.offset],esi + or [edx+ValueDefinition.flags],VAL_IN_USE + inc [edx+ValueDefinition.reference_count] + mov eax,[parameter_namespace] + mov [ebx+SourceEntry.local_namespace],eax + mov esi,[calm_source_pointer] + mov ecx,[instruction_branch] + test ecx,ecx + jz instruction_assembled + mov [ebx+SourceEntry.name],ecx + or [ebx+SourceEntry.name_length],-1 + jmp instruction_assembled + calm_exceeded_stack_limit: + mov edx,_stack_limit_exceeded + call register_error + jmp assembly_line + +calm_virtual_machine: + mov al,[ebx+SourceEntry.saved_result] + mov [calm_result],al + mov edx,[ebx+SourceEntry.text] + mov [calm_value],edx + mov esi,[edx+ValueDefinition.value] + mov eax,[esi+CompiledMacroHeader.literals_offset] + add eax,esi + mov [calm_literals],eax + add esi,[ebx+SourceEntry.offset] + calm_execution_unit: + lodsd + mov [calm_instruction_number],eax + lodsd + jmp eax + +calm_end: + mov ebx,[source_context] + mov ecx,[ebx+SourceContext.number_of_entries] + dec ecx + ; jz internal_error + mov [ebx+SourceContext.number_of_entries],ecx + imul ecx,sizeof.SourceEntry + mov edx,[ebx+sizeof.SourceContext+ecx+SourceEntry.text] + and [edx+ValueDefinition.flags],not VAL_IN_USE + dec [edx+ValueDefinition.reference_count] + jmp assembly_line + +calm_arrange: + lodsd + mov [label_leaf],eax + lodsd + mov ecx,eax + lodsd + push esi + mov esi,[calm_literals] + add eax,esi + add esi,ecx + mov [pattern_end],eax + mov edi,[assembly_workspace.memory_start] + arrange_by_pattern: + mov edx,assembly_workspace + mov ecx,[pattern_end] + sub ecx,esi + call reserve_workspace + arrange_token: + cmp esi,[pattern_end] + je assign_arranged_value + lodsb + cmp al,1Bh + je arrange_by_reference + cmp al,0A0h + je downgrade_hard_space + cmp al,0BFh + je restore_question_mark + stosb + cmp al,1Ah + je copy_arranged_token_data + cmp al,22h + je copy_arranged_token_data + cmp al,27h + je copy_arranged_token_data + cmp al,30h + jne arrange_token + lodsd + stosd + mov ecx,eax + rep movsb + jmp arrange_token + copy_arranged_token_data: + movsd + jmp arrange_token + downgrade_hard_space: + mov al,20h + stosb + jmp arrange_token + restore_question_mark: + mov al,'?' + stosb + jmp arrange_token + arrange_by_reference: + mov ebx,[esi+4] + call use_available_value + jc arrange_missing_value + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_NUMERIC + je arrange_numeric_value + cmp al,VALTYPE_PLAIN + je arrange_plain_value + cmp al,VALTYPE_SYMBOLIC + jne arrange_unsupported_value + mov ecx,[edx+ValueDefinition.value_length] + jecxz arrange_empty_value + add ecx,1+sizeof.RecognitionContext + mov ebx,edx + mov edx,assembly_workspace + call reserve_workspace + mov edx,ebx + mov ebx,esi + mov esi,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + rep movsb + lea esi,[ebx+8] + cmp esi,[pattern_end] + je assign_arranged_value + mov al,40h + stosb + xor eax,eax + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep stosd + jmp arrange_by_pattern + arrange_numeric_value: + mov eax,[edx+ValueDefinition.value] + mov ecx,[eax] + cmp dword [eax+4+ecx],0 + jne arrange_unsupported_value + test byte [eax+4+ecx-1],80h + jnz arrange_unsupported_value + mov ebx,esi + mov esi,eax + mov edx,assembly_workspace + add ecx,1+4 + call reserve_workspace + mov al,30h + stosb + lodsd + stosd + mov ecx,eax + rep movsb + lea esi,[ebx+8] + jmp arrange_by_pattern + arrange_empty_value: + add esi,8 + jmp arrange_token + arrange_plain_value: + mov edx,[edx+ValueDefinition.value] + mov al,30h + stosb + mov ebx,edi + xor eax,eax + stosd + mov eax,edx + store_plain_bytes: + inc dword [ebx] + stosb + shr eax,8 + jnz store_plain_bytes + test byte [edi-1],80h + jnz store_plain_bytes + add esi,8 + jmp arrange_by_pattern + arrange_unsupported_value: + mov edx,_invalid_symbol_value + jmp arrange_failed_reference + arrange_missing_value: + mov edx,_undefined_symbol + arrange_failed_reference: + call register_error + mov al,1Ah + stosb + movsd + lodsd + mov eax,[eax+SymbolTree_Leaf.branch] + cmp [eax+SymbolTree_Foliage.name_kind],NAME_CASEINSENSITIVE + jne arrange_token + mov al,'?' + stosb + jmp arrange_token + assign_arranged_value: + mov ebx,[label_leaf] + call update_value_definition + test edx,edx + jz arranged_value_assigned + mov [value_type],VALTYPE_SYMBOLIC + mov ecx,edi + mov esi,[assembly_workspace.memory_start] + sub ecx,esi + call assign_value + arranged_value_assigned: + pop esi + jmp calm_execution_unit + +calm_match: + and [calm_result],0 + lodsd + mov ebx,eax + lodsd + mov ecx,eax + lodsd + mov edi,[calm_literals] + add eax,edi + add edi,ecx + mov [pattern_end],eax + lodsd + mov [brackets],eax + call use_available_value + jc calm_undefined_symbol + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_RESERVED + je calm_undefined_symbol + cmp al,VALTYPE_SYMBOLIC + jne calm_invalid_value + push esi + mov [value],edx + inc [edx+ValueDefinition.reference_count] + mov esi,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + add ecx,esi + mov [line_end],ecx + mov ebx,[expression_workspace.memory_start] + and [matched_context],0 + and [stored_position],0 + calm_match_with_pattern: + cmp edi,[pattern_end] + je calm_end_of_pattern + mov ah,[edi] + cmp ah,1Bh + jne calm_exact_match + calm_wildcard_match: + and [stored_position],0 + add edi,1+8 + cmp edi,[pattern_end] + je calm_required_wildcard_match + cmp byte [edi],0BFh + je calm_optional_wildcard_match + calm_required_wildcard_match: + cmp esi,[line_end] + je calm_match_done + call calm_consume_whitespace + jz calm_match_done + xchg edi,ebx + mov edx,expression_workspace + mov ecx,sizeof.MatchedExcerpt + call reserve_workspace + xchg edi,ebx + mov eax,[edi-4] + mov ecx,[matched_context] + mov [ebx+MatchedExcerpt.symbol_leaf],eax + mov [ebx+MatchedExcerpt.recognition_context],ecx + mov [ebx+MatchedExcerpt.data_start],esi + mov al,[esi] + call calm_consume_token + jc calm_match_done + mov [ebx+MatchedExcerpt.data_end],esi + add ebx,sizeof.MatchedExcerpt + jmp calm_match_with_pattern + calm_optional_wildcard_match: + xchg edi,ebx + mov edx,expression_workspace + mov ecx,sizeof.MatchedExcerpt + call reserve_workspace + xchg edi,ebx + mov eax,[edi-4] + inc edi + mov ecx,[matched_context] + mov [ebx+MatchedExcerpt.symbol_leaf],eax + mov [ebx+MatchedExcerpt.recognition_context],ecx + mov [ebx+MatchedExcerpt.data_start],esi + mov [ebx+MatchedExcerpt.data_end],esi + add ebx,sizeof.MatchedExcerpt + jmp calm_match_with_pattern + calm_exact_match: + cmp esi,[line_end] + je calm_end_of_text + mov al,[esi] + cmp al,40h + jne found_token_to_match + inc esi + mov [matched_context],esi + add esi,sizeof.RecognitionContext + jmp calm_exact_match + found_token_to_match: + cmp [stored_position],0 + jne calm_match_position_stored + mov [stored_position],esi + mov ecx,[matched_context] + mov [stored_context],ecx + mov [stored_pattern],edi + calm_match_position_stored: + cmp al,20h + je calm_match_whitespace + cmp ah,20h + je calm_skip_pattern_whitespace + cmpsb + jne calm_token_mismatch + cmp ah,1Ah + je calm_match_name_tokens + cmp ah,22h + je calm_match_string_tokens + cmp ah,27h + je calm_match_string_tokens + cmp ah,30h + jne calm_match_with_pattern + mov ecx,esi + mov edx,edi + lodsd + add esi,eax + mov eax,[edi] + lea edi,[edi+4+eax] + cmp byte [edi],0BFh + jne calm_compare_token_contents + inc edi + jmp calm_compare_token_contents + calm_match_string_tokens: + lodsd + mov ecx,eax + mov edx,[edi] + add edi,4 + calm_compare_token_contents: + cmp ecx,edx + je calm_match_with_pattern + push esi edi + mov esi,ecx + mov edi,edx + mov ecx,[esi] + add ecx,4 + repe cmpsb + pop edi esi + jne calm_retract_match + jmp calm_match_with_pattern + calm_match_name_tokens: + lodsd + mov ecx,eax + mov edx,[edi] + add edi,4 + cmp byte [edi],0BFh + je calm_case_insensitive_match + cmp ecx,edx + je calm_match_with_pattern + push esi edi + mov esi,ecx + mov edi,edx + lodsd + scasd + jne calm_name_mismatch + mov ecx,eax + mov eax,[esi+ecx] + cmp eax,[edi+ecx] + jne calm_name_mismatch + repe cmpsb + jne calm_name_mismatch + pop edi esi + jmp calm_match_with_pattern + calm_name_mismatch: + pop edi esi + jmp calm_retract_match + calm_case_insensitive_match: + inc edi + cmp ecx,edx + je calm_match_with_pattern + push esi edi + mov esi,ecx + mov edi,edx + lodsd + scasd + jne calm_name_mismatch + mov ecx,eax + mov eax,[esi+ecx+4] + cmp eax,[edi+ecx+4] + jne calm_name_mismatch + xor eax,eax + calm_compare_case_insensitively: + lodsb + mov dl,[characters+eax] + mov al,[edi] + inc edi + cmp dl,[characters+eax] + jne name_mismatch + loop calm_compare_case_insensitively + pop edi esi + jmp calm_match_with_pattern + calm_match_converted_number: + call convert_number_to_match + jmp calm_compare_token_contents + calm_match_with_converted_number: + xchg esi,edi + call convert_number_to_match + xchg esi,edi + jmp calm_compare_token_contents + calm_match_whitespace: + cmp ah,20h + je calm_optional_whitespace + cmp ah,0A0h + je calm_required_whitespace + cmp [stored_pattern],edi + jne calm_retract_match + call calm_consume_whitespace + jz calm_match_done + and [stored_position],0 + jmp calm_match_with_pattern + calm_optional_whitespace: + inc edi + cmp edi,[pattern_end] + je calm_whitespace_matched + cmp byte [edi],0A0h + jne calm_whitespace_matched + calm_required_whitespace: + inc edi + cmp edi,[pattern_end] + je calm_whitespace_matched + cmp byte [edi],20h + jne calm_whitespace_matched + inc edi + calm_whitespace_matched: + call calm_consume_whitespace + jz calm_end_of_text + jmp calm_match_with_pattern + calm_skip_pattern_whitespace: + inc edi + jmp calm_match_with_pattern + calm_token_mismatch: + cmp ax,1A30h + je calm_match_converted_number + cmp ax,301Ah + je calm_match_with_converted_number + calm_retract_match: + xor esi,esi + xchg esi,[stored_position] + mov ecx,[stored_context] + mov [matched_context],ecx + mov edi,[stored_pattern] + call calm_consume_whitespace + jz calm_match_done + calm_expand_wildcard_match: + cmp ebx,[expression_workspace.memory_start] + je calm_match_done + call calm_consume_token + jc calm_match_done + mov [ebx-sizeof.MatchedExcerpt+MatchedExcerpt.data_end],esi + jmp calm_match_with_pattern + calm_consume_whitespace: + mov al,[esi] + cmp al,40h + je calm_consume_context_token + cmp al,20h + jne calm_whitespace_consumed + inc esi + cmp esi,[line_end] + jne calm_consume_whitespace + calm_whitespace_consumed: + retn + calm_consume_context_token: + inc esi + mov [matched_context],esi + add esi,sizeof.RecognitionContext + cmp esi,[line_end] + jne calm_consume_whitespace + retn + calm_consume_token: + xor ecx,ecx + mov edx,[brackets] + inc esi + consume_token_content: + cmp al,dh + je consume_closing + cmp al,dl + je consume_opening + cmp al,1Ah + je consume_token_with_data + cmp al,22h + je consume_token_with_data + cmp al,27h + je consume_token_with_data + cmp al,30h + je consume_internal_token + cmp al,40h + je consume_context_token + test ecx,ecx + jnz consume_more + retn + consume_token_with_data: + add esi,4 + test ecx,ecx + jnz consume_more + retn + consume_internal_token: + lodsd + add esi,eax + test ecx,ecx + jnz consume_more + retn + consume_context_token: + add esi,sizeof.RecognitionContext + test ecx,ecx + jnz consume_more + retn + consume_closing: + sub ecx,1 + jg consume_more + retn + consume_opening: + inc ecx + consume_more: + cmp esi,[line_end] + je consume_unsatisfied + lodsb + jmp consume_token_content + consume_unsatisfied: + stc + retn + calm_end_of_pattern: + cmp esi,[line_end] + je calm_match_found + lodsb + cmp al,20h + je calm_end_of_pattern + cmp al,40h + jne calm_another_token_to_match + add esi,sizeof.RecognitionContext + jmp calm_end_of_pattern + calm_another_token_to_match: + dec esi + cmp [stored_position],0 + je calm_expand_wildcard_match + jmp calm_retract_match + calm_end_of_text: + cmp edi,[pattern_end] + je calm_match_found + mov ah,[edi] + cmp ah,1Bh + je calm_wildcard_match + cmp ah,20h + jne calm_match_done + inc edi + jmp calm_end_of_text + calm_match_found: + or [calm_result],1 + mov esi,ebx + mov [value_type],VALTYPE_SYMBOLIC + calm_assign_matched_values: + cmp esi,[expression_workspace.memory_start] + je calm_match_done + sub esi,sizeof.MatchedExcerpt + mov ebx,[esi+MatchedExcerpt.symbol_leaf] + call update_value_definition + test edx,edx + jz calm_assign_matched_values + push esi + mov eax,[esi+MatchedExcerpt.recognition_context] + mov ecx,[esi+MatchedExcerpt.data_end] + mov esi,[esi+MatchedExcerpt.data_start] + sub ecx,esi + jz calm_matched_value_ready + test eax,eax + jz calm_matched_value_ready + cmp dword [eax],0 + je calm_matched_value_ready + push esi ecx edx + mov esi,eax + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + add ecx,1+sizeof.RecognitionContext + call reserve_workspace + mov al,40h + stosb + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + pop edx ecx esi + rep movsb + mov ecx,edi + mov esi,[assembly_workspace.memory_start] + sub ecx,esi + calm_matched_value_ready: + call assign_value + pop esi + jmp calm_assign_matched_values + calm_match_done: + mov edx,[value] + dec [edx+ValueDefinition.reference_count] + pop esi + jmp calm_execution_unit + +calm_compute: + lodsd + mov [label_leaf],eax + lodsd + add eax,esi + push eax + mov edi,[calculation_workspace.memory_start] + and [value_position],0 + call calculate_parsed_expression + call pop_terms + jc calm_compute_done + mov al,byte [edi+ExpressionTerm.attributes] + cmp al,EXPR_STRING + je calm_computed_string + cmp al,EXPR_FLOAT + je calm_computed_float + call convert_terms_to_numeric_value + mov [value_type],VALTYPE_NUMERIC + calm_computed_value_ready: + mov edi,ecx + mov ebx,[label_leaf] + call update_value_definition + test edx,edx + jz calm_compute_done + mov ecx,edi + call assign_value + calm_compute_done: + pop esi + jmp calm_execution_unit + calm_computed_string: + call get_term_value + mov esi,edx + mov ecx,[esi] + add ecx,4 + mov [value_type],VALTYPE_STRING + jmp calm_computed_value_ready + calm_computed_float: + call get_term_value + mov esi,edx + mov ecx,sizeof.FloatData + mov [value_type],VALTYPE_FLOAT + jmp calm_computed_value_ready + +calm_check: + lodsd + test eax,eax + jz calm_execution_unit + js calm_check + calm_evaluate_logical_value: + call evaluate_stored_logical_value + mov [calm_result],al + add esi,[esi-4] + find_next_logical_value: + lodsd + test eax,eax + jz calm_execution_unit + jns next_logical_value_found + cmp eax,BOOL_NEG + jne find_next_logical_value + xor [calm_result],1 + jmp find_next_logical_value + next_logical_value_found: + mov ebx,esi + xor ecx,ecx + skip_next_logical_value: + inc ecx + add esi,eax + skip_logical_operator: + lodsd + assert BOOL_NEG = -1 + cmp eax,BOOL_NEG + jg skip_next_logical_value + je skip_logical_operator + dec ecx + jnz skip_logical_operator + cmp eax,BOOL_AND + je calm_and + calm_or: + cmp [calm_result],0 + jne find_next_logical_value + mov esi,ebx + jmp calm_evaluate_logical_value + calm_and: + cmp [calm_result],0 + je find_next_logical_value + mov esi,ebx + jmp calm_evaluate_logical_value + +calm_jyes: + cmp [calm_result],0 + jne calm_jump + add esi,4 + jmp calm_execution_unit +calm_jno: + cmp [calm_result],0 + je calm_jump + add esi,4 + jmp calm_execution_unit +calm_jump: + lodsd + mov edx,[calm_value] + add eax,[edx+ValueDefinition.value] + mov esi,eax + jmp calm_execution_unit + +calm_assemble: + lodsd + mov ebx,eax + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + mov eax,[ebx+SymbolTree_Leaf.branch] + mov [instruction_branch],eax + call use_available_value + jc calm_undefined_symbol + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_SYMBOLIC + jne calm_invalid_value + call create_source_entry + jc calm_assemble_exceeded_stack_limit + mov [ebx+SourceEntry.type],SOURCE_MACRO + or [ebx+SourceEntry.flags],SRCF_PREPROCESSED + mov [ebx+SourceEntry.text],edx + or [edx+ValueDefinition.flags],VAL_IN_USE + inc [edx+ValueDefinition.reference_count] + mov eax,[calm_instruction_number] + mov [ebx-sizeof.SourceEntry+SourceEntry.line_number],eax + mov edx,[ebx-sizeof.SourceEntry+SourceEntry.text] + mov ecx,[edx+ValueDefinition.value] + sub esi,ecx + mov [ebx-sizeof.SourceEntry+SourceEntry.offset],esi + mov eax,[ebx-sizeof.SourceEntry+SourceEntry.local_namespace] + mov [ebx+SourceEntry.local_namespace],eax + mov al,[calm_result] + mov [ebx-sizeof.SourceEntry+SourceEntry.saved_result],al + mov ecx,[instruction_branch] + test ecx,ecx + jz assembly_line + mov [ebx+SourceEntry.name],ecx + or [ebx+SourceEntry.name_length],-1 + jmp assembly_line + calm_undefined_symbol: + mov edx,_undefined_symbol + jmp calm_execution_error + calm_invalid_value: + mov edx,_invalid_symbol_value + jmp calm_execution_error + calm_assemble_exceeded_stack_limit: + mov edx,_stack_limit_exceeded + calm_execution_error: + call register_error + jmp calm_execution_unit + +calm_transform: + mov [calm_result],0 + lodsd + mov [label_leaf],eax + mov ebx,eax + lodsd + mov [transforming_namespace],eax + call get_available_value + jc calm_undefined_symbol + cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC + jne calm_invalid_value + push esi + call clear_line_embeddings + mov esi,[edx+ValueDefinition.value] + mov [line_start],esi + xor eax,eax + mov [embedded_context],eax + mov [line_context],eax + mov ecx,[edx+ValueDefinition.value_length] + add ecx,esi + mov [line_end],ecx + mov edi,[assembly_workspace.memory_start] + mov [hidden_context],0 + transform_symbolic_value: + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + push edi + mov eax,[embedded_context] + mov [line_context],eax + mov ebx,[transforming_namespace] + test ebx,ebx + jz transform_identify + call identify_symbol_in_namespace + jmp transform_identification_done + transform_identify: + call identify_symbol + transform_identification_done: + jc symbolic_value_transformed + test edi,edi + jnz ready_to_transform + call skip_literal + xor ebx,ebx + ready_to_transform: + pop edi + test ebx,ebx + jz untransformed_literal + mov [further_whitespace],ecx + call get_available_value + jc untransformed_literal + cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC + jne untransformed_literal + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + mov [calm_result],1 + mov [line_start],esi + mov esi,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + mov ebx,ecx + add ecx,[further_whitespace] + add ecx,1+sizeof.RecognitionContext + mov edx,assembly_workspace + call reserve_workspace + test ebx,ebx + jz symbol_transformed + mov al,1 + xchg al,[hidden_context] + test al,al + jnz reset_hidden_context + cmp [line_context],0 + je copy_transformed_value + reset_hidden_context: + xor edx,edx + call reset_transformed_context + copy_transformed_value: + mov ecx,ebx + rep movsb + symbol_transformed: + mov ecx,[further_whitespace] + mov al,20h + rep stosb + mov esi,[line_start] + jmp transform_symbolic_value + untransformed_literal: + mov ecx,esi + xchg esi,[line_start] + sub ecx,esi + mov ebx,ecx + add ecx,1+sizeof.RecognitionContext + mov edx,assembly_workspace + call reserve_workspace + xor al,al + xchg al,[hidden_context] + test al,al + jz copy_untransformed_literal + mov edx,[line_context] + call reset_transformed_context + copy_untransformed_literal: + mov ecx,ebx + rep movsb + jmp transform_symbolic_value + reset_transformed_context: + mov al,40h + cmp [esi],al + je transformed_context_ok + stosb + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + test edx,edx + jz clear_transformed_context + xchg esi,edx + rep movsd + mov esi,edx + transformed_context_ok: + retn + clear_transformed_context: + xor eax,eax + rep stosd + retn + symbolic_value_transformed: + pop edi + cmp [calm_result],0 + je calm_transform_done + mov ebx,[label_leaf] + call update_value_definition + test edx,edx + jz calm_transform_done + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + mov [value_type],VALTYPE_SYMBOLIC + call assign_value + calm_transform_done: + pop esi + jmp calm_execution_unit + +calm_stringify: + lodsd + mov [label_leaf],eax + mov ebx,eax + call get_available_value + jc calm_undefined_symbol + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_SYMBOLIC + jne calm_invalid_value + mov eax,[edx+ValueDefinition.value] + mov [symbol_value_start],eax + mov ecx,[edx+ValueDefinition.value_length] + add ecx,eax + mov [symbol_value_end],ecx + push esi + call convert_symbolic_value_to_string + mov edi,ecx + mov ebx,[label_leaf] + call update_value_definition + test edx,edx + jz calm_stringify_done + mov ecx,edi + mov [value_type],VALTYPE_STRING + call assign_value + calm_stringify_done: + pop esi + jmp calm_execution_unit + +calm_publish_constant: + mov edi,create_constant_value_definition + jmp calm_publish +calm_publish_stack: + mov edi,create_value_definition + jmp calm_publish +calm_publish_variable: + mov edi,update_value_definition + calm_publish: + lodsd + mov ebx,eax + lodsd + mov [label_leaf],eax + call use_available_value + jc calm_undefined_symbol + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_SYMBOLIC + jne calm_invalid_value + push esi edi + call clear_line_embeddings + mov esi,[edx+ValueDefinition.value] + mov [line_start],esi + mov ecx,[edx+ValueDefinition.value_length] + add ecx,esi + mov [line_end],ecx + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + mov eax,esi + pop edi esi + jc calm_invalid_identifier + test ebx,ebx + jz calm_invalid_identifier + cmp eax,[line_end] + jne calm_invalid_identifier + xchg ebx,[label_leaf] + call use_available_value + jc calm_undefined_symbol + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_SYMBOLIC + jb calm_invalid_value + cmp al,VALTYPE_PLAIN + je calm_value_type_ok + cmp al,VALTYPE_AREA + ja calm_invalid_value + calm_value_type_ok: + mov [value_type],al + mov [value],edx + mov ebx,[label_leaf] + call edi + test edx,edx + jz calm_execution_unit + push esi + mov eax,[value] + mov esi,[eax+ValueDefinition.value] + mov ecx,[eax+ValueDefinition.value_length] + call assign_value + pop esi + jmp calm_execution_unit + calm_invalid_identifier: + mov edx,_invalid_identifier + call register_error + jmp calm_execution_unit + +calm_take: + lodsd + mov edi,eax + lodsd + mov ebx,eax + xor edx,edx + call remove_value_definition + setnc [calm_result] + jmp calm_execution_unit + +calm_display: + call compute_calm_constant + jc calm_execution_unit + cmp al,EXPR_STRING + je calm_display_string + cmp al,EXPR_NUMBER + je calm_display_character + calm_invalid_argument: + mov edx,_invalid_argument + call register_error + jmp calm_execution_unit + calm_display_string: + call display_string_data + jmp calm_execution_unit + calm_display_character: + call display_single_byte_data + jmp calm_execution_unit + +calm_err: + call compute_calm_constant + jc calm_execution_unit + cmp al,EXPR_STRING + jne calm_invalid_argument + call register_volatile_error + test edx,edx + jz calm_execution_unit + or [edx+Error.flags],ERR_CUSTOM + jmp calm_execution_unit + +calm_emit: + call compute_calm_constant + jc calm_invalid_data_unit + cmp al,EXPR_NUMBER + jne calm_invalid_data_unit + mov edi,data_unit_length + mov ecx,4 + call fit_value + jc calm_invalid_data_unit + jns calm_emit_data + calm_invalid_data_unit: + mov edx,_invalid_argument + call register_error + mov [data_unit_length],1 + calm_emit_data: + lodsd + test eax,eax + jz calm_reserve_data + add eax,esi + push eax + mov edi,[calculation_workspace.memory_start] + and [value_position],0 + call calculate_parsed_expression + pop esi + call pop_terms + jc calm_execution_unit + push edi + mov ecx,[data_unit_length] + call initialize_output + xchg edi,[esp] + call get_calculated_constant_value + pop edi + cmp al,EXPR_FLOAT + je calm_emit_float + cmp al,EXPR_STRING + je calm_emit_string + cmp al,EXPR_NUMBER + jne calm_invalid_argument + mov ecx,[data_unit_length] + call fit_value + jnc calm_execution_unit + calm_emit_out_of_range: + mov edx,_value_out_of_range + call register_error + jmp calm_execution_unit + calm_emit_string: + mov eax,[data_unit_length] + mov ecx,[edx] + sub eax,ecx + jc calm_emit_out_of_range + xchg esi,edx + add esi,4 + rep movsb + mov ecx,eax + xor al,al + rep stosb + mov esi,edx + jmp calm_execution_unit + calm_emit_float: + push esi + mov esi,edx + mov ecx,[data_unit_length] + call fit_float + pop esi + jmp calm_execution_unit + calm_reserve_data: + mov ecx,[data_unit_length] + call uninitialized_output + jmp calm_execution_unit + compute_calm_constant: + lodsd + test eax,eax + jz calm_constant_invalid + add eax,esi + push eax + mov edi,[calculation_workspace.memory_start] + and [value_position],0 + call calculate_parsed_expression + pop esi + call pop_terms + jc calm_constant_invalid + call get_calculated_constant_value + clc + retn + calm_constant_invalid: + stc + retn + +calm_load: + lodsd + mov [label_leaf],eax + lodsd + add eax,esi + push eax + mov edi,esi + and [value_position],0 + call get_area_value + pop esi + jc calm_load_area_invalid + mov [data_area_symbol],ebx + mov [data_area],edx + call compute_calm_constant + jc calm_load_offset_invalid + cmp al,EXPR_NUMBER + jne calm_load_offset_invalid + mov edi,data_offset + mov ecx,4 + call fit_value + jc calm_load_offset_invalid + js calm_load_offset_invalid + call compute_calm_constant + jc calm_load_length_invalid + cmp al,EXPR_NUMBER + jne calm_load_length_invalid + mov edi,value_length + mov ecx,4 + call fit_value + jc calm_load_length_invalid + js calm_load_length_invalid + mov ebx,[label_leaf] + call update_value_definition + test edx,edx + jz calm_execution_unit + mov ecx,[value_length] + add ecx,4 + mov [value_type],VALTYPE_STRING + push edx esi + xor esi,esi + call assign_value + mov edi,[edx+ValueDefinition.value] + mov eax,[value_length] + mov ecx,eax + stosd + mov edx,[data_area] + call load_from_area + pop esi edx + jnc calm_execution_unit + mov [edx+ValueDefinition.value_length],4 + mov edi,[edx+ValueDefinition.value] + and dword [edi],0 + jmp calm_execution_unit + calm_load_area_invalid: + lodsd + add esi,eax + calm_load_offset_invalid: + lodsd + add esi,eax + calm_load_length_invalid: + jmp calm_invalid_argument +calm_load_from_output: + lodsd + mov [label_leaf],eax + call compute_calm_constant + jc calm_load_offset_invalid + cmp al,EXPR_NUMBER + jne calm_load_offset_invalid + mov edi,file_offset + mov ecx,8 + call fit_value + jc calm_load_offset_invalid + js calm_load_offset_invalid + call compute_calm_constant + jc calm_load_length_invalid + cmp al,EXPR_NUMBER + jne calm_load_length_invalid + mov edi,value_length + mov ecx,4 + call fit_value + jc calm_load_length_invalid + js calm_load_length_invalid + mov ebx,[label_leaf] + call update_value_definition + test edx,edx + jz calm_execution_unit + mov ecx,[value_length] + add ecx,4 + mov [value_type],VALTYPE_STRING + push esi + xor esi,esi + call assign_value + mov edi,[edx+ValueDefinition.value] + mov eax,[value_length] + mov ecx,eax + stosd + push edx + call read_from_output + pop edx esi + mov ecx,[value_length] + test ecx,ecx + jz calm_execution_unit + sub [edx+ValueDefinition.value_length],ecx + mov edi,[edx+ValueDefinition.value] + sub [edi],ecx + calm_address_out_of_range: + mov edx,_address_out_of_range + call register_error + jmp calm_execution_unit + +calm_store: + lodsd + add eax,esi + push eax + mov edi,esi + and [value_position],0 + call get_area_value + pop esi + jc calm_store_area_invalid + mov [data_area_symbol],ebx + mov [data_area],edx + call compute_calm_constant + jc calm_store_offset_invalid + cmp al,EXPR_NUMBER + jne calm_store_offset_invalid + mov edi,data_offset + mov ecx,4 + call fit_value + jc calm_store_offset_invalid + js calm_store_offset_invalid + call compute_calm_constant + jc calm_store_length_invalid + cmp al,EXPR_NUMBER + jne calm_store_length_invalid + mov edi,value_length + mov ecx,4 + call fit_value + jc calm_store_length_invalid + js calm_store_length_invalid + call prepare_area_to_write + jc calm_store_not_possible + push edi + call compute_calm_constant + pop edi + jc calm_store_value_invalid + mov ecx,[value_length] + cmp al,EXPR_STRING + je calm_store_string + cmp al,EXPR_NUMBER + jne calm_store_value_invalid + call fit_value + jc calm_emit_out_of_range + jmp calm_execution_unit + calm_store_string: + mov eax,ecx + mov ecx,[edx] + sub eax,ecx + jc calm_emit_out_of_range + push esi + lea esi,[edx+4] + rep movsb + xchg ecx,eax + rep stosb + pop esi + jmp calm_execution_unit + calm_store_area_invalid: + lodsd + add esi,eax + calm_store_offset_invalid: + lodsd + add esi,eax + calm_store_length_invalid: + lodsd + add esi,eax + calm_store_value_invalid: + jmp calm_invalid_argument + calm_store_not_possible: + lodsd + add esi,eax + jmp calm_execution_unit +calm_store_in_output: + call compute_calm_constant + jc calm_store_offset_invalid + cmp al,EXPR_NUMBER + jne calm_store_offset_invalid + mov edi,file_offset + mov ecx,8 + call fit_value + jc calm_store_offset_invalid + js calm_store_offset_invalid + call compute_calm_constant + jc calm_store_length_invalid + cmp al,EXPR_NUMBER + jne calm_store_length_invalid + mov edi,value_length + mov ecx,4 + call fit_value + jc calm_store_length_invalid + js calm_store_length_invalid + call compute_calm_constant + mov ecx,[value_length] + cmp al,EXPR_STRING + je try_exact_store + cmp al,EXPR_NUMBER + jne calm_store_value_invalid + try_exact_store: + cmp ecx,[edx] + jne indirect_store + push esi + lea esi,[edx+4] + jmp calm_rewrite_output + indirect_store: + push eax ecx edx + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + call reserve_workspace + pop edx ecx eax + cmp al,EXPR_STRING + je calm_store_string_in_output + call fit_value + jc calm_emit_out_of_range + push esi + calm_store_finish: + mov esi,[assembly_workspace.memory_start] + calm_rewrite_output: + call rewrite_output + pop esi + cmp [value_length],0 + jne calm_address_out_of_range + jmp calm_execution_unit + calm_store_string_in_output: + mov eax,ecx + mov ecx,[edx] + sub eax,ecx + jc calm_emit_out_of_range + push esi + lea esi,[edx+4] + rep movsb + xchg ecx,eax + rep stosb + jmp calm_store_finish + +calm_call: + lodsd + mov ebx,eax + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + mov eax,[ebx+SymbolTree_Leaf.branch] + mov [instruction_branch],eax + call use_available_value + jc calm_call_undefined + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_CALM + jne calm_call_invalid + call create_source_entry + jc calm_call_exceeded_stack_limit + xor eax,eax + xchg eax,[calm_instruction_number] + mov [ebx-sizeof.SourceEntry+SourceEntry.line_number],eax + mov eax,[parameter_namespace] + mov [ebx+SourceEntry.local_namespace],eax + mov ecx,[instruction_branch] + test ecx,ecx + jz called_name_ok + mov [ebx+SourceEntry.name],ecx + or [ebx+SourceEntry.name_length],-1 + called_name_ok: + mov [ebx+SourceEntry.type],SOURCE_CALM + mov [ebx+SourceEntry.text],edx + or [edx+ValueDefinition.flags],VAL_IN_USE + inc [edx+ValueDefinition.reference_count] + mov edi,esi + mov esi,[edx+ValueDefinition.value] + mov eax,[esi+CompiledMacroHeader.literals_offset] + add eax,esi + mov [calm_value],edx + mov [calm_literals],eax + add esi,sizeof.CompiledMacroHeader + push ebx + process_call_arguments: + mov eax,[esi] + inc eax + cmp eax,1 + jbe call_arguments_ready + mov ebx,[edi] + test ebx,ebx + jz omitted_call_argument + add edi,4 + cmp ebx,-1 + je omitted_call_argument + call use_available_value + jc missing_argument_value + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_COMMAND + jae unassignable_value + push edx + mov ebx,[esi+CompiledMacroArgument.symbol_leaf] + call update_value_definition + pop eax + push esi edi + mov esi,[eax+ValueDefinition.value] + mov ecx,[eax+ValueDefinition.value_length] + mov al,[eax+ValueDefinition.type] + cmp al,VALTYPE_ELEMENT + je assign_element + cmp al,VALTYPE_AREA + je assign_element + assign_call_argument: + test edx,edx + jz call_argument_assigned + mov [value_type],al + call assign_value + call_argument_assigned: + pop edi esi + next_call_argument: + add esi,sizeof.CompiledMacroArgument + jmp process_call_arguments + missing_argument_value: + mov edx,_undefined_symbol + call register_error + jmp next_call_argument + unassignable_value: + mov edx,_invalid_symbol_value + call register_error + jmp next_call_argument + omitted_call_argument: + mov ebx,[esi+CompiledMacroArgument.symbol_leaf] + call update_value_definition + push esi edi + mov ecx,[esi+CompiledMacroArgument.default_value_length] + mov esi,[esi+CompiledMacroArgument.default_value_offset] + add esi,[calm_literals] + mov al,VALTYPE_SYMBOLIC + cmp ecx,-1 + jne assign_call_argument + inc ecx + push edx + mov edx,_invalid_argument + call register_error + pop edx + jmp assign_call_argument + assign_element: + mov ecx,[edi-4] + mov edi,[assembly_workspace.memory_start] + mov esi,edi + xor eax,eax + stosd + mov eax,ecx + stosd + xor eax,eax + inc eax + stosd + stosb + dec eax + stosd + mov ecx,17 + mov al,VALTYPE_NUMERIC + jmp assign_call_argument + call_arguments_ready: + add esi,4 + mov eax,[edi] + add edi,4 + test eax,eax + jz call_arguments_ok + mov edx,_invalid_argument + call register_error + skip_excess_arguments: + mov eax,[edi] + add edi,4 + test eax,eax + jnz skip_excess_arguments + call_arguments_ok: + pop ebx + mov eax,[ebx-sizeof.SourceEntry+SourceEntry.text] + mov ecx,[eax+ValueDefinition.value] + sub edi,ecx + mov [ebx-sizeof.SourceEntry+SourceEntry.offset],edi + mov al,[calm_result] + mov [ebx-sizeof.SourceEntry+SourceEntry.saved_result],al + jmp calm_execution_unit + calm_call_undefined: + mov edx,_undefined_symbol + jmp calm_call_error + calm_call_invalid: + mov edx,_invalid_symbol_value + jmp calm_call_error + calm_call_exceeded_stack_limit: + mov edx,_stack_limit_exceeded + calm_call_error: + call register_error + skip_call_arguments: + lodsd + test eax,eax + jnz skip_call_arguments + jmp calm_execution_unit \ No newline at end of file diff --git a/toolchain/fasm2/source/conditions.inc b/toolchain/fasm2/source/conditions.inc new file mode 100644 index 0000000..2ed713e --- /dev/null +++ b/toolchain/fasm2/source/conditions.inc @@ -0,0 +1,669 @@ + +COND_NEGATED = 1 ; only with COND_EVALUATE +COND_TRUE = 1 ; only with COND_DETERMINED +COND_EVALUATE = 2 +COND_DETERMINED = 4 + +get_condition_value: +; in: +; esi = pointer into preprocessed line or the last embedded line +; out: +; esi = pointer advanced past the processed line +; al = logical value + mov ebx,[condition_stack_base] + mov [condition_stack],ebx + mov byte [ebx],COND_EVALUATE + get_logical_value: + call peek_at_constituent_value + cmp al,'~' + jne negation_registered + and [current_constituent],0 + mov ebx,[condition_stack] + mov al,[ebx] + test byte [ebx],COND_EVALUATE + jz get_logical_value + xor byte [ebx],COND_NEGATED + jmp get_logical_value + negation_registered: + call parse_logical_value + setnc dh + mov dl,al + jecxz get_logical_operator + mov ebx,[condition_stack] + lea eax,[ebx+ecx+1] + cmp eax,[condition_stack_end] + jbe condition_stack_ready + push ecx edx + mov ecx,eax + mov eax,[condition_stack_base] + sub ecx,eax + sub ebx,eax + call grow_stack + mov [condition_stack_base],eax + add ebx,eax + mov [condition_stack],ebx + add eax,ecx + mov [condition_stack_end],eax + pop edx ecx + condition_stack_ready: + xor al,al + test byte [ebx],COND_EVALUATE + jz store_opening_parentheses + or al,COND_EVALUATE + store_opening_parentheses: + inc ebx + mov [ebx],al + loop store_opening_parentheses + mov [condition_stack],ebx + cmp dx,'~' + je get_logical_value + get_logical_operator: + call peek_at_constituent_value + jc end_of_logical_expression + cmp al,')' + je close_logical_subexpression + cmp al,'|' + je logical_or + cmp al,'&' + jne end_of_logical_expression + logical_and: + and [current_constituent],0 + mov ebx,[condition_stack] + mov al,[ebx] + test al,COND_EVALUATE + jnz evaluate_logical_and + test al,COND_DETERMINED + jz get_logical_value + test al,COND_TRUE + jz determined_false + jmp continue_evaluation + evaluate_logical_and: + test al,COND_NEGATED + jnz evaluate_negated_logical_and + call evaluate_logical_value + mov ebx,[condition_stack] + test al,al + jnz continue_evaluation + determined_false: + mov byte [ebx],COND_DETERMINED + jmp get_logical_value + evaluate_negated_logical_and: + call evaluate_logical_value + mov ebx,[condition_stack] + test al,al + jnz determined_false + continue_evaluation: + mov byte [ebx],COND_EVALUATE + jmp get_logical_value + logical_or: + and [current_constituent],0 + mov ebx,[condition_stack] + mov al,[ebx] + test al,COND_EVALUATE + jnz evaluate_logical_or + test al,COND_DETERMINED + jz get_logical_value + test al,COND_TRUE + jnz determined_true + jmp continue_evaluation + evaluate_logical_or: + test al,COND_NEGATED + jnz evaluate_negated_logical_or + call evaluate_logical_value + mov ebx,[condition_stack] + test al,al + jnz determined_true + jmp continue_evaluation + evaluate_negated_logical_or: + call evaluate_logical_value + mov ebx,[condition_stack] + test al,al + jnz continue_evaluation + determined_true: + mov byte [ebx],COND_DETERMINED + COND_TRUE + jmp get_logical_value + close_logical_subexpression: + and [current_constituent],0 + mov ebx,[condition_stack] + cmp ebx,[condition_stack_base] + je excess_parenthesis + mov al,[ebx] + dec ebx + mov [condition_stack],ebx + test al,COND_DETERMINED + jnz subexpression_determined + cmp al,COND_EVALUATE + COND_NEGATED + jne get_logical_operator + test byte [ebx],COND_EVALUATE + jz get_logical_operator + xor byte [ebx],COND_NEGATED + jmp get_logical_operator + subexpression_determined: + test al,COND_TRUE + jnz subexpression_determined_true + mov [comparator],evaluated_false + jmp get_logical_operator + subexpression_determined_true: + mov [comparator],evaluated_true + jmp get_logical_operator + end_of_logical_expression: + mov ebx,[condition_stack] + cmp ebx,[condition_stack_base] + jne missing_parenthesis + mov al,[ebx] + test al,COND_DETERMINED + jnz condition_determined + test al,COND_NEGATED + jz evaluate_logical_value + call evaluate_logical_value + test al,al + setz al + retn + condition_determined: + and al,COND_TRUE + retn + excess_parenthesis: + mov edx,_excess_closing_parenthesis + call register_error + jmp unknown_condition + missing_parenthesis: + mov edx,_missing_closing_parenthesis + call register_error + unknown_condition: + xor al,al + retn + +parse_logical_value: +; in: +; esi = pointer into preprocessed line or the last embedded line +; out: +; [comparator] - evaluating routine +; [expression_workspace.memory_start] - parsed argument sequences +; [expression_end] - end of the parsed argument sequences +; esi = pointer advanced past the parsed value +; al = special character that follows parsed value, zero if no more symbols in line +; ecx = number of parentheses opened before the value that did not get closed +; cf set if value was empty + mov edi,[expression_workspace.memory_start] + xor eax,eax + mov [comparator],eax + or [leave_opening_parentheses],1 + call parse_expression + mov [initial_parentheses],ecx + mov [expression_end],edi + call peek_at_constituent_value + jc end_of_line + cmp al,'&' + je end_of_logical_value + cmp al,'|' + je end_of_logical_value + cmp al,'~' + je end_of_logical_value + cmp al,')' + je end_of_logical_value + cmp al,1Ah + je identify_comparator + cmp al,'=' + je parse_equal + cmp al,'<' + je parse_less + cmp al,'>' + je parse_greater + jmp end_of_logical_value + identify_comparator: + test edx,edx + jz end_of_logical_value + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_COMPARATOR + jne end_of_logical_value + and [current_constituent],0 + mov eax,[edx+ValueDefinition.value] + jmp set_comparator + parse_less: + and [current_constituent],0 + call warp_to_next_symbol + jc parse_less_than + test ecx,ecx + jnz parse_less_than + call peek_at_constituent_value + jc parse_less_than + cmp al,'=' + je parse_less_or_equal + cmp al,'>' + je parse_not_equal + parse_less_than: + mov eax,check_if_less + jmp set_comparator + parse_less_or_equal: + and [current_constituent],0 + mov eax,check_if_not_greater + jmp set_comparator + parse_not_equal: + and [current_constituent],0 + mov eax,check_if_not_equal + jmp set_comparator + parse_greater: + and [current_constituent],0 + call warp_to_next_symbol + jc parse_greater_than + test ecx,ecx + jnz parse_greater_than + call peek_at_constituent_value + jc parse_greater_than + cmp al,'=' + je parse_greater_or_equal + parse_greater_than: + mov eax,check_if_greater + jmp set_comparator + parse_greater_or_equal: + and [current_constituent],0 + mov eax,check_if_not_less + jmp set_comparator + parse_equal: + and [current_constituent],0 + mov eax,check_if_equal + set_comparator: + mov edi,[expression_end] + mov [comparator],eax + and [leave_opening_parentheses],0 + call parse_expression + mov [expression_end],edi + call peek_at_constituent_value + jnc end_of_logical_value + end_of_line: + xor al,al + end_of_logical_value: + mov ecx,[initial_parentheses] + cmp [comparator],0 + jnz logical_value_not_empty + mov [comparator],check_if_not_zero + mov ebx,[expression_workspace.memory_start] + cmp dword [ebx],0 + jne logical_value_not_empty + stc + retn + logical_value_not_empty: + clc + retn + +evaluate_logical_value: +; in: +; [comparator] - evaluating routine +; [expression_workspace.memory_start] - parsed argument sequences +; out: al = logical value +; note: evaluates value prepared by previous call to parse_logical_value +; preserves: esi + push esi + mov esi,[expression_workspace.memory_start] + jmp [comparator] + evaluated_false: + pop esi + xor al,al + retn + evaluated_true: + pop esi + mov al,1 + retn + +evaluate_stored_logical_value: +; in: esi - pointer to evaluating routine followed by parsed argument sequences +; out: al = logical value +; preserves: esi + push esi + lodsd + jmp eax + +invalid_logical_value: + mov edx,_invalid_expression + call register_error + jmp evaluated_false + +check_if_equal: + call get_difference_signum + test al,al + jz evaluated_true + jmp evaluated_false +check_if_not_equal: + call get_difference_signum + test al,al + jnz evaluated_true + jmp evaluated_false +check_if_less: + call get_difference_signum + cmp al,0 + jl evaluated_true + jmp evaluated_false +check_if_not_less: + call get_difference_signum + cmp al,0 + jnl evaluated_true + jmp evaluated_false +check_if_greater: + call get_difference_signum + cmp al,0 + jg evaluated_true + jmp evaluated_false +check_if_not_greater: + call get_difference_signum + cmp al,0 + jng evaluated_true + jmp evaluated_false + get_difference_signum: + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + jc signum_error + call calculate_parsed_expression + jc signum_error + mov esi,subtraction_operator + call calculate_parsed_expression + call pop_terms + mov eax,edi + jnc check_difference_for_variable_terms + signum_error: + xor al,al + retn + check_difference_for_variable_terms: + add eax,sizeof.ExpressionTerm + cmp [eax+ExpressionTerm.attributes],0 + je difference_terms_ok + cmp [eax+ExpressionTerm.metadata],0 + je check_difference_for_variable_terms + mov edx,_values_not_comparable + call register_error + difference_terms_ok: + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je get_float_signum + call get_numeric_term_value + mov ecx,1 + call fit_value + js signum_negative + jc signum_positive + xor al,al + cmp [edi],al + jne signum_positive + retn + get_float_signum: + call get_term_value + mov esi,edx + call get_float_exponent + jz signum_zero + test [esi+FloatData.attributes],FLOAT_NEGATIVE + jnz signum_negative + signum_positive: + mov al,1 + retn + signum_negative: + or al,-1 + retn + signum_zero: + xor al,al + retn + +check_if_not_zero: + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + jc evaluated_false + call pop_terms + jc evaluated_false + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je check_if_not_zero_float + call get_numeric_term_value + mov ecx,1 + call fit_value + js evaluated_true + jc evaluated_true + cmp byte [edi],0 + jne evaluated_true + check_if_has_variable_terms: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je evaluated_false + cmp [edi+ExpressionTerm.metadata],0 + je check_if_has_variable_terms + jmp evaluated_true + check_if_not_zero_float: + call get_term_value + mov esi,edx + call get_float_exponent + jz check_if_has_variable_terms + jmp evaluated_true + +check_if_relative: + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + jc evaluated_false + call calculate_parsed_expression + jc evaluated_false + mov ebx,edi + call pop_terms + jc evaluated_false + mov edx,edi + call pop_terms + jc evaluated_false + cmp [edx+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + je check_difference_terms + xchg edi,edx + cmp [edx+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + je check_difference_terms + mov esi,subtraction_operator + mov edi,ebx + call calculate_parsed_expression + call pop_terms + jc evaluated_false + check_difference_terms: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je evaluated_true + cmp [edi+ExpressionTerm.metadata],0 + je check_difference_terms + jmp evaluated_false + undefined_condition: + mov edx,_invalid_value + call register_error + jmp evaluated_false + +check_if_type_equal: + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + jc evaluated_false + call pop_terms + jc evaluated_false + mov eax,[edi+ExpressionTerm.attributes] + mov [result_type],al + call calculate_parsed_expression + jc evaluated_false + call pop_terms + jc evaluated_false + mov eax,[edi+ExpressionTerm.attributes] + cmp al,[result_type] + je evaluated_true + jmp evaluated_false + +check_if_value_equal: + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + jc evaluated_false + mov ebx,edi + call pop_terms + jc evaluated_false + mov eax,[edi+ExpressionTerm.attributes] + mov [result_type],al + mov edi,ebx + call calculate_parsed_expression + jc evaluated_false + mov ebx,edi + call pop_terms + jc evaluated_false + mov eax,[edi+ExpressionTerm.attributes] + cmp al,[result_type] + jne evaluated_false + cmp al,EXPR_STRING + jne compare_values_numerically + call get_term_value + mov ecx,[edx] + call pop_terms + call get_term_value + cmp ecx,[edx] + jne evaluated_false + compare_values_numerically: + mov esi,subtraction_operator + mov edi,ebx + call calculate_parsed_expression + call pop_terms + jc evaluated_false + mov eax,edi + check_if_terms_equal: + add eax,sizeof.ExpressionTerm + cmp [eax+ExpressionTerm.attributes],0 + je check_if_constant_term_equal + cmp [eax+ExpressionTerm.metadata],0 + je check_if_terms_equal + jmp evaluated_false + check_if_constant_term_equal: + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je check_if_float_equal + call get_numeric_term_value + xor ecx,ecx + xor edi,edi + call fit_value + jc evaluated_false + jmp evaluated_true + check_if_float_equal: + call get_term_value + mov esi,edx + call get_float_exponent + jnz evaluated_false + jmp evaluated_true + +check_if_defined: + xor ecx,ecx + jmp check_if_expression_defined +check_if_defined_earlier: + mov ecx,[current_pass] + check_if_expression_defined: + and [outer_expression],0 + and [defined_element],0 + lodsd + test eax,eax + jnz checked_expression_invalid + check_expression_element: + lodsd + test eax,eax + jz check_expression_end + cmp al,EXPR_SYMBOL + je check_if_subexpression_defined + cmp al,EXPR_SYMBOL_VALUE + je check_if_symbol_defined + or [defined_element],1 + add esi,4 + cmp al,EXPR_NUMBER + je check_expression_element + cmp al,EXPR_STRING + je check_expression_element + cmp al,EXPR_FLOAT + je check_expression_element + cmp al,EXPR_OPERATOR + je check_expression_element + cmp al,EXPR_POLYNOMIAL + je check_expression_element + checked_expression_invalid: + jmp invalid_logical_value + check_expression_end: + xor esi,esi + xchg esi,[outer_expression] + test esi,esi + jnz check_expression_element + jecxz checked_expression_defined + cmp [defined_element],0 + je checked_expression_invalid + checked_expression_defined: + jmp evaluated_true + check_if_symbol_defined: + lodsd + test eax,eax + jz evaluated_false + lodsd + test eax,eax + jz evaluated_false + check_symbol_value: + or [defined_element],1 + jecxz check_expression_element + test [eax+ValueDefinition.flags],VAL_INTERNAL + jnz check_expression_element + cmp [eax+ValueDefinition.pass],ecx + jne evaluated_false + jmp check_expression_element + check_if_subexpression_defined: + mov ebx,[esi] + test ebx,ebx + jz evaluated_false + add esi,4 + call get_available_value + mov eax,edx + test eax,eax + jz evaluated_false + cmp [eax+ValueDefinition.type],VALTYPE_SYMBOLIC + jne check_symbol_value + mov [outer_expression],esi + push ecx + call get_subexpression + pop ecx + jnc invalid_logical_value + jmp check_expression_element + get_subexpression: + call clear_line_embeddings + xor esi,esi + xor ecx,ecx + call embed_symbolic_value + mov edi,[expression_workspace.memory_start] + and [leave_opening_parentheses],0 + call parse_expression + call get_constituent_value + mov esi,[expression_workspace.memory_start] + retn + +check_if_used: + lodsd + test eax,eax + jnz invalid_logical_value + check_if_expression_is_used_symbol: + lodsd + cmp al,EXPR_SYMBOL + je check_for_indirect_symbol + cmp al,EXPR_SYMBOL_VALUE + jne invalid_logical_value + lodsd + mov ebx,eax + lodsd + check_if_used_symbol: + lodsd + test eax,eax + jnz invalid_logical_value + test ebx,ebx + jz evaluated_false + mov ecx,[ebx+SymbolTree_Leaf.last_use_pass] + jecxz symbol_predicted_unused + mov eax,[current_pass] + sub eax,ecx + jz evaluated_true + cmp eax,1 + ja symbol_predicted_unused + symbol_predicted_used: + or [ebx+SymbolTree_Leaf.flags],SYM_USAGE_PREDICTED + SYM_PREDICTED_USED + jmp evaluated_true + symbol_predicted_unused: + mov al,[ebx+SymbolTree_Leaf.flags] + or al,SYM_USAGE_PREDICTED + and al,not SYM_PREDICTED_USED + mov [ebx+SymbolTree_Leaf.flags],al + jmp evaluated_false + check_for_indirect_symbol: + lodsd + mov ebx,eax + call get_available_value + test edx,edx + jz check_if_used_symbol + cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC + jne check_if_used_symbol + call get_subexpression + jnc invalid_logical_value + jmp check_if_expression_is_used_symbol diff --git a/toolchain/fasm2/source/console.inc b/toolchain/fasm2/source/console.inc new file mode 100644 index 0000000..5b9eea2 --- /dev/null +++ b/toolchain/fasm2/source/console.inc @@ -0,0 +1,560 @@ + +display_string_data: +; in: +; edx - 32-bit length followed by string data +; preserves: esi + test [trace_mode],TRACE_DISPLAY + jnz bypass_display_buffer + cmp [next_pass_needed],0 + jne display_ok + mov ecx,[edx] + call reserve_display_buffer + mov ebx,esi + mov esi,edx + lodsd + mov ecx,eax + rep movsb + string_displayed: + mov esi,ebx + display_ok: + retn + bypass_display_buffer: + mov ebx,esi + mov esi,edx + lodsd + mov ecx,eax + jecxz string_displayed + call display_string + jmp string_displayed + reserve_display_buffer: + mov edi,[display_data_length] + add ecx,edi + add edi,[display_buffer] + mov [display_data_length],ecx + cmp ecx,[display_buffer_length] + jbe display_buffer_reserve_ok + mov eax,[display_buffer] + sub edi,eax + push edx + call grow_stack + pop edx + add edi,eax + mov [display_buffer],eax + mov [display_buffer_length],ecx + display_buffer_reserve_ok: + retn + +display_single_byte_data: +; in: +; edx - 32-bit length followed by numeric data +; preserves: esi + test [trace_mode],TRACE_DISPLAY + jnz byte_bypassing_display_buffer + cmp [next_pass_needed],0 + jne display_ok + mov ecx,1 + call reserve_display_buffer + mov ecx,1 + call fit_value + jc byte_out_of_range + retn + byte_bypassing_display_buffer: + mov edi,displayed_byte + mov ecx,1 + call fit_value + jc byte_out_of_range + mov ebx,esi + mov esi,edi + mov ecx,1 + call display_string + jmp string_displayed + byte_out_of_range: + mov edx,_value_out_of_range + call register_error + retn + +show_display_data: + test [trace_mode],TRACE_DISPLAY + jnz display_line_feed + mov ecx,[display_data_length] + jecxz display_data_shown + mov esi,[display_buffer] + call display_string + display_line_feed: + mov esi,_new_line + xor ecx,ecx + call display_string + display_data_shown: + retn + +show_errors: + mov esi,[first_error] + display_error: + test esi,esi + jz display_data_shown + push esi + mov eax,[esi+sizeof.Error+SourceContext.number_of_entries] + test eax,eax + jz display_error_message + lea ebx,[esi+sizeof.Error+sizeof.SourceContext] + dec eax + imul eax,sizeof.SourceEntry + lea eax,[ebx+eax] + mov [last_source_entry],eax + test [trace_mode],TRACE_ERROR_STACK + jnz show_source_context + and [last_file_source_entry],0 + find_last_file_entry: + cmp [eax+SourceEntry.type],SOURCE_FILE + je last_file_entry_found + cmp eax,ebx + je show_source_context + sub eax,sizeof.SourceEntry + jmp find_last_file_entry + last_file_entry_found: + mov [last_file_source_entry],eax + show_source_context: + push ebx + cmp [ebx+SourceEntry.type],SOURCE_MEMORY + je display_memory_source + cmp [ebx+SourceEntry.type],SOURCE_MACRO + jne display_source_name + mov esi,_macro_source + test [ebx+SourceEntry.flags],SRCF_PREPROCESSED + jz display_source_type + mov esi,_preprocessed_source + display_source_type: + xor ecx,ecx + call display_error_string + display_source_name: + mov esi,[ebx+SourceEntry.name] + test esi,esi + jz unnamed_source + mov ecx,[ebx+SourceEntry.name_length] + cmp ecx,-1 + je display_source_symbol + call display_error_string + jmp display_line_number + display_source_symbol: + xchg ebx,esi + call show_symbol_name + mov ebx,esi + jmp display_line_number + unnamed_source: + mov esi,_unnamed_source + xor ecx,ecx + call display_error_string + jmp display_line_number + display_memory_source: + mov esi,_memory_source + xor ecx,ecx + call display_error_string + display_line_number: + mov esi,_line_number_prefix + xor ecx,ecx + call display_error_string + mov eax,[ebx+SourceEntry.line_number] + xor edx,edx + call itoa + call display_error_string + mov esi,_line_number_suffix + xor ecx,ecx + call display_error_string + pop ebx + mov esi,[esp] + push ebx + cmp [ebx+SourceEntry.line_number],0 + je skip_line_content + test [trace_mode],TRACE_ERROR_STACK + jnz show_source_line + cmp ebx,[last_source_entry] + je last_source_entry_line_content + cmp ebx,[last_file_source_entry] + je show_source_line + skip_line_content: + mov esi,_space + next_source_entry: + pop ebx + find_next_source_entry: + cmp ebx,[last_source_entry] + je source_context_shown + add ebx,sizeof.SourceEntry + test [trace_mode],TRACE_ERROR_STACK + jnz show_source_entry + test [ebx+SourceEntry.flags],SRCF_PREPROCESSED + jnz find_next_source_entry + show_source_entry: + xor ecx,ecx + call display_error_string + jmp show_source_context + last_source_entry_line_content: + test [esi+Error.flags],ERR_CUSTOM + jnz skip_line_content + show_source_line: + cmp [ebx+SourceEntry.type],SOURCE_CALM + je show_calm_source + mov esi,_line_content_prefix + xor ecx,ecx + call display_error_string + call show_line_content + mov esi,_new_line + jmp next_source_entry + show_calm_source: + mov esi,_calm_source + xor ecx,ecx + call display_error_string + mov esi,_new_line + jmp next_source_entry + source_context_shown: + mov esi,_new_line + xor ecx,ecx + call display_error_string + mov ebx,[esp] + test [ebx+Error.flags],ERR_CUSTOM + jnz display_error_message + cmp [ebx+Error.preprocessed_length],0 + je display_error_message + mov esi,_preprocessed_text_prefix + xor ecx,ecx + call display_error_string + mov esi,[ebx+Error.preprocessed_data] + mov ecx,[ebx+Error.preprocessed_length] + call show_preprocessed_line + mov esi,_new_line + xor ecx,ecx + call display_error_string + display_error_message: + pop ebx + call show_error_message + mov esi,ebx + next_error: + mov esi,[esi+Error.next] + jmp display_error + +show_error_message: +; in: +; ebx - Error +; preserves: ebx + mov esi,_error_prefix + test [ebx+Error.flags],ERR_CUSTOM + jz display_error_prefix + mov esi,_custom_error_prefix + display_error_prefix: + xor ecx,ecx + call display_error_string + mov esi,[ebx+Error.message] + test [ebx+Error.flags],ERR_CUSTOM + jz format_error_message + xor ecx,ecx + call display_error_string + finish_error_message: + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + retn + format_error_message: + mov edx,esi + cut_error_message: + lodsb + test al,al + jz show_error_message_segment + cmp al,'%' + jne cut_error_message + show_error_message_segment: + dec esi + push esi + xchg ecx,esi + sub ecx,edx + mov esi,edx + call display_error_string + pop esi + lodsb + test al,al + jz finish_error_message + lodsb + cmp al,'s' + je insert_string_into_error_message + cmp al,'i' + jne format_error_message + push ebx + mov ebx,[ebx+Error.symbol] + mov ebx,[ebx+SymbolTree_Leaf.branch] + call show_symbol_name + pop ebx + jmp format_error_message + insert_string_into_error_message: + push esi + mov esi,[ebx+Error.symbol] + xor ecx,ecx + call display_error_string + pop esi + jmp format_error_message + +show_symbol_name: +; in: +; ebx - SymbolTree_Foliage, may be null +; preserves: esi + test ebx,ebx + jz symbol_name_shown + mov edi,[identifier_workspace.memory_start] + cmp [ebx+SymbolTree_Foliage.name_kind],NAME_NUMERIC + je next_name_segment + compose_symbol_name: + mov ecx,[ebx+SymbolTree_Foliage.name_length] + mov edx,identifier_workspace + mov al,[ebx+SymbolTree_Foliage.name_kind] + cmp al,NAME_CASESENSITIVE + je name_segment_to_copy + cmp al,NAME_ABSTRACT + je name_segment_copied + cmp al,NAME_NUMERIC + je dot_label_name + mov al,'?' + stosb + name_segment_to_copy: + push ecx + add ecx,2 + call reserve_workspace + pop ecx + mov edx,[ebx+SymbolTree_Foliage.name_data] + copy_name_segment: + jecxz name_segment_copied + dec ecx + mov al,[edx+ecx] + stosb + jmp copy_name_segment + dot_label_name: + push esi + mov esi,[ebx+SymbolTree_Foliage.name_data] + xor eax,eax + read_dot_count: + jecxz dot_count_read + dec ecx + shl eax,8 + mov al,[esi+ecx] + jmp read_dot_count + dot_count_read: + pop esi + push eax + lea ecx,[eax+2] + call reserve_workspace + pop ecx + mov al,'.' + rep stosb + name_segment_copied: + mov edx,[ebx+SymbolTree_Foliage.root] + mov ebx,[edx+SymbolTree_Root.parent_branch] + test [edx+SymbolTree_Root.flags],NAMESPACE_LOCAL or NAMESPACE_CALM + jnz mark_local_symbol_name + test ebx,ebx + jz symbol_name_ready + next_name_segment: + mov al,'.' + stosb + jmp compose_symbol_name + mark_local_symbol_name: + mov al,':' + stosb + test [edx+SymbolTree_Root.flags],NAMESPACE_CALM + jz symbol_name_ready + mov eax,[ebx+SymbolTree_Foliage.name_data] + mov ebx,[eax+SymbolTree_Leaf.branch] + test ebx,ebx + jnz compose_symbol_name + symbol_name_ready: + mov ebx,[identifier_workspace.memory_start] + mov ecx,edi + sub ecx,ebx + jz symbol_name_shown + push esi + mov esi,ebx + reverse_composed_name: + dec edi + cmp ebx,edi + jae show_composed_name + mov al,[ebx] + xchg al,[edi] + mov [ebx],al + inc ebx + jmp reverse_composed_name + show_composed_name: + call display_error_string + pop esi + symbol_name_shown: + retn + +show_line_content: +; in: +; ebx - SourceEntry + cmp [ebx+SourceEntry.type],SOURCE_MACRO + je show_line_from_macro + mov esi,[ebx+SourceEntry.text] + add esi,[ebx+SourceEntry.line_offset] + mov ecx,[ebx+SourceEntry.number_of_attached_lines] + inc ecx + mov [number_of_lines],ecx + show_token: + mov al,[esi] + test al,al + jz line_content_shown + cmp al,0Ah + je line_content_shown + cmp al,1Ah + je show_name_token + cmp al,22h + je show_string_token + cmp al,27h + je show_string_token + cmp al,'\' + jne show_basic_token + cmp byte [esi+1],0Ah + jne show_basic_token + dec [number_of_lines] + jnz show_attached_line + show_basic_token: + mov ecx,1 + call display_error_string + inc esi + jmp show_token + show_name_token: + add esi,1+4 + mov ecx,[esi-4] + call display_error_string + add esi,[esi-4] + add esi,12 + jmp show_token + show_string_token: + mov ebx,esi + inc esi + call show_string_token_content + lea esi,[ebx+1] + lodsd + add esi,eax + jmp show_token + show_string_token_content: + lea edi,[esi+4] + mov ecx,[esi] + show_string_segment: + push ecx edi + mov esi,_single_quote + mov ecx,1 + call display_error_string + pop edi ecx + jecxz show_end_quote + mov edx,ecx + mov al,27h + repne scasb + sub edx,ecx + mov esi,edi + sub esi,edx + push ecx edi + mov ecx,edx + call display_error_string + pop edi ecx + test ecx,ecx + jnz show_string_segment + show_end_quote: + cmp byte [ebx],27h + je string_token_shown + mov esi,_single_quote + mov ecx,1 + call display_error_string + string_token_shown: + retn + show_attached_line: + mov ecx,1 + call display_error_string + lea ebx,[esi+2] + mov esi,_line_segment_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + jmp show_token + show_line_from_macro: + mov edx,[ebx+SourceEntry.text] + mov esi,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + mov eax,[ebx+SourceEntry.line_offset] + add esi,eax + sub ecx,eax + jbe line_content_shown + call show_preprocessed_line + line_content_shown: + retn + +show_preprocessed_line: +; in: +; esi - preprocessed tokens +; ecx = total length of preprocessed tokens + lea eax,[esi+ecx] + mov [preprocessed_text_end],eax + show_preprocessed_token: + cmp esi,[preprocessed_text_end] + jae preprocessed_line_shown + mov al,[esi] + test al,al + jz preprocessed_line_shown + cmp al,1Ah + je show_preprocessed_name_token + cmp al,22h + je show_preprocessed_string_token + cmp al,27h + je show_preprocessed_string_token + cmp al,30h + je show_internal_number + cmp al,40h + je show_context_token + mov ecx,1 + call display_error_string + inc esi + jmp show_preprocessed_token + show_preprocessed_name_token: + inc esi + lodsd + mov ebx,esi + mov esi,eax + lodsd + mov ecx,eax + call display_error_string + mov esi,ebx + jmp show_preprocessed_token + show_preprocessed_string_token: + mov ebx,esi + mov esi,[esi+1] + call show_string_token_content + lea esi,[ebx+1+4] + jmp show_preprocessed_token + show_internal_number: + inc esi + mov edx,esi + push esi + call convert_number_back + lea esi,[edx+4] + mov ecx,[edx] + call display_error_string + pop esi + add esi,[esi] + add esi,4 + jmp show_preprocessed_token + show_context_token: + add esi,1+sizeof.RecognitionContext + jmp show_preprocessed_token + preprocessed_line_shown: + retn + +itoa: +; in: +; edx:eax = unsigned number +; out: +; esi - temporary buffer containing decimal digits +; ecx = length of string (number of digits) + mov edi,temporary_value+4 + stosd + mov eax,edx + stosd + mov edx,temporary_value + mov dword [edx],8 + call convert_number_back + lea esi,[edx+4] + mov ecx,[edx] + retn diff --git a/toolchain/fasm2/source/directives.inc b/toolchain/fasm2/source/directives.inc new file mode 100644 index 0000000..0e21e37 --- /dev/null +++ b/toolchain/fasm2/source/directives.inc @@ -0,0 +1,4852 @@ + +struct DirectiveBlock + type db ? ; DBLOCK_# + subtype db ? ; CTRL_# for DBLOCK_CONTROL + flags db ? ; CTRLF_# for DBLOCK_CONTROL + reserved db ? + reserved2 dw ? + prior_assembly_mode db ? + prior_special_parameters db ? + prior_counter_position dd ? + parameter_namespace dd ? + parameter dd ? ; pointer to first BlockParameter + length_of_data dd ? +ends + +struct BlockParameter + symbol dd ? ; pointer to SymbolTree_Leaf + definition dd ? ; pointer to ValueDefinition + next dd ? ; pointer to another BlockParameter +ends + +struct NamespaceData + prior_namespace dd ? + prior_label dd ? +ends + +struct VirtualBlockData + outer_area dd ? + shift_tracking db ? +ends + +struct ConditionalRepeatData + condition_length dd ? +ends + +struct RepeatData + limit_length dd ? + index_position dd ? +ends + +struct MacroData + nesting_counter dd ? +ends + +struct SymbolSubstitution + symbol_start dd ? + symbol_end dd ? + value_start dd ? + value_end dd ? + leftover_context dd ? +ends + +struct MatchedParameter + pattern dd ? + assembly_position dd ? +ends + +DBLOCK_CLOSED = 0 +DBLOCK_NAMESPACE = 1 +DBLOCK_CONTROL = 2 +DBLOCK_MACRO = 3 +DBLOCK_VIRTUAL = 4 +DBLOCK_CALMINSTRUCTION = 5 +DBLOCK_POSTPONED = 8 +DBLOCK_SUSPENDED = 9 + +CTRL_IF = 0 +CTRL_WHILE = 2 +CTRL_REPEAT = 3 +CTRL_IRP = 4 +CTRL_IRPV = 5 +CTRL_MATCH = 6 +CTRL_RMATCH = 7 +CTRL_POSTPONE = 9 + +CTRLF_INACTIVE = 1 +CTRLF_BREAKABLE = 2 +CTRLF_HAS_REPEAT_DATA = 4 +CTRLF_HAS_WRITABLE_INDEX = 8 +CTRLF_ALLOWS_ELSE = 16 +CTRLF_SUSPENDED = 32 + +add_directive_block: +; in: +; dl = DBLOCK_# +; ecx = length of additional data +; out: edi - new DirectiveBlock +; note: area for additional data is placed below the DirectiveBlock structure +; preserves: ebx, edx, esi + dec ecx + and ecx,(-1) shl 2 + add ecx,1 shl 2 + push esi ecx + mov esi,[source_context] + mov eax,[esi+SourceContext.number_of_entries] + imul eax,sizeof.SourceEntry + add eax,sizeof.SourceContext + add ecx,eax + add ecx,sizeof.DirectiveBlock + mov edi,[directives_stack] + lea eax,[edi+ecx] + cmp eax,[directives_stack_end] + jbe directives_stack_ready + add ecx,[directives_stack_end] + jc out_of_memory + mov eax,[directives_stack_base] + sub ecx,eax + push edx + call grow_stack + pop edx + add ecx,eax + mov [directives_stack_end],ecx + mov edi,eax + xchg eax,[directives_stack_base] + sub edi,eax + add edi,[directives_stack] + mov [directives_stack],edi + directives_stack_ready: + push edx + call clone_source_context + pop edx ecx + add edi,ecx + mov eax,edi + sub eax,[directives_stack] + mov [edi+DirectiveBlock.length_of_data],eax + mov [edi+DirectiveBlock.type],dl + mov al,[assembly_mode] + mov [edi+DirectiveBlock.prior_assembly_mode],al + mov ecx,[parameter_namespace] + mov [edi+DirectiveBlock.parameter_namespace],ecx + mov al,[ecx+SymbolTree_Root.parameters] + mov [edi+DirectiveBlock.prior_special_parameters],al + xor eax,eax + mov [edi+DirectiveBlock.subtype],al + mov [edi+DirectiveBlock.flags],al + mov [edi+DirectiveBlock.parameter],eax + mov eax,[current_counter] + sub eax,[counters_stack_base] + mov [edi+DirectiveBlock.prior_counter_position],eax + lea eax,[edi+sizeof.DirectiveBlock] + mov [directives_stack],eax + pop esi + retn + +find_directive_block: +; in: +; dl = DBLOCK_# +; out: +; cf set when no such block found +; when cf = 0 +; edi - DirectiveBlock of the latest block of this type +; preserves: ebx, edx, esi + mov edi,[directives_stack] + scan_directive_blocks: + cmp edi,[directives_stack_base] + je directive_block_not_found + sub edi,sizeof.DirectiveBlock + cmp dl,[edi+DirectiveBlock.type] + je directive_block_found + find_next_directive_block: + ; in: + ; dl = DBLOCK_# + ; edi - DirectiveBlock + ; out: + ; cf set when no such block found + ; when cf = 0 + ; edi - DirectiveBlock of the next latest block of this type + ; preserves: ebx, edx, esi + mov ecx,[edi+DirectiveBlock.length_of_data] + sub edi,ecx + jmp scan_directive_blocks + directive_block_found: + clc + retn + directive_block_not_found: + stc + retn + +close_control_directive_block: +; in: edi - DirectiveBlock +; preserves: esi + mov al,[edi+DirectiveBlock.prior_assembly_mode] + mov [assembly_mode],al + mov eax,[edi+DirectiveBlock.prior_counter_position] + add eax,[counters_stack_base] + mov [current_counter],eax + mov ecx,[edi+DirectiveBlock.parameter_namespace] + mov al,[edi+DirectiveBlock.prior_special_parameters] + mov [ecx+SymbolTree_Root.parameters],al + close_directive_block: + ; in: edi - DirectiveBlock + ; preserves: esi + mov [edi+DirectiveBlock.type],DBLOCK_CLOSED + mov eax,edi + mov ecx,[eax+DirectiveBlock.length_of_data] + sub eax,ecx + call release_source_context + call remove_block_parameters + lea eax,[edi+sizeof.DirectiveBlock] + cmp eax,[directives_stack] + je remove_directive_block + retn + remove_directive_block: + sub eax,sizeof.DirectiveBlock + mov ecx,[eax+DirectiveBlock.length_of_data] + sub eax,ecx + cmp eax,[directives_stack_base] + je directives_stack_cleared + cmp [eax-sizeof.DirectiveBlock+DirectiveBlock.type],DBLOCK_CLOSED + je remove_directive_block + directives_stack_cleared: + mov [directives_stack],eax + retn + +add_block_parameter: +; in: +; ebx - SymbolTree_Leaf +; edi - DirectiveBlock +; esi - value +; ecx = length of value +; [value_type] = VALTYPE_# +; preserves: ebx, edi + push ecx + or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + call create_value_definition + pop ecx + mov eax,[current_pass] + mov [edx+ValueDefinition.pass],eax + mov [edx+ValueDefinition.value_length],ecx + add ecx,sizeof.BlockParameter + push edi + mov edi,[edx+ValueDefinition.value] + cmp ecx,[edx+ValueDefinition.block_length] + jbe write_parameter_value + push edx + push ecx + cmp [edx+ValueDefinition.block_length],0 + je allocate_memory_for_parameter + xor eax,eax + xchg eax,[edx+ValueDefinition.value] + call mfree + allocate_memory_for_parameter: + pop ecx + call malloc + pop edx + mov [edx+ValueDefinition.value],eax + mov [edx+ValueDefinition.block_length],ecx + mov edi,eax + write_parameter_value: + mov al,[value_type] + mov [edx+ValueDefinition.type],al + mov ecx,[edx+ValueDefinition.value_length] + rep movsb + mov ecx,edi + pop edi + mov [ecx+BlockParameter.symbol],ebx + mov [ecx+BlockParameter.definition],edx + inc [edx+ValueDefinition.reference_count] + mov eax,ecx + xchg eax,[edi+DirectiveBlock.parameter] + mov [ecx+BlockParameter.next],eax + retn + +remove_block_parameters: +; in: edi - DirectiveBlock +; preserves: esi, edi + mov eax,[edi+DirectiveBlock.parameter] + test eax,eax + jz no_block_parameters + push esi edi + mov esi,eax + remove_block_parameter: + mov ebx,[esi+BlockParameter.symbol] + mov edx,[esi+BlockParameter.definition] + dec [edx+ValueDefinition.reference_count] + xor edi,edi + call remove_value_definition + mov esi,[esi+BlockParameter.next] + test esi,esi + jnz remove_block_parameter + pop edi esi + no_block_parameters: + retn + +identify_parameter_symbol: +; in: +; esi = pointer into preprocessed line or current embedded value +; out: +; same as from identify_symbol_in_namespace + or [symbol_definition],1 + mov ebx,[parameter_namespace] + mov dl,SYMCLASS_PARAMETER + call identify_symbol_in_namespace + jc parameter_symbol_identified + cmp edi,[parameter_namespace] + je parameter_symbol_identified + xor ebx,ebx + parameter_symbol_identified: + retn + +cut_argument_value: +; in: +; esi = pointer into preprocessed line or current embedded value +; edi - LineExcerpt to be filled with information about cut piece of line +; [breakpoint_token] = initial byte of symbol that - if encountered - should immediately end the value +; out: +; esi = pointer advanced past the cut piece +; al = initial byte of symbol at pointer, zero when no more symbols there +; preserves: ebx, edi + call move_to_next_symbol + jc cut_plain_value + cmp byte [esi],'<' + je cut_enclosed_value + cut_plain_value: + mov dl,',' + xor dh,dh + call cut_piece_of_line + retn + cut_enclosed_value: + inc esi + mov dl,'>' + mov dh,'<' + call cut_piece_of_line + cmp al,'>' + jne missing_enclosing + inc esi + call move_to_next_symbol + jnc parameter_value_cut + xor al,al + parameter_value_cut: + retn + missing_enclosing: + mov edx,_missing_closing_chevron + call register_error + retn + +extract_argument_value: +; in: +; esi = pointer into preprocessed line (not an embedded value) +; edi - buffer for token sequence, must be large enough to hold all the remaining tokens in line and an additional context token +; [breakpoint_token] = initial byte of symbol that - if encountered - should immediately end the value +; [contextless_processing] = zero to have current context added to the extracted value +; out: +; esi = pointer advanced past the processed piece +; edi - end of the extracted sequence of tokens in provided buffer +; al = initial byte of symbol at pointer, zero when no more symbols there +; preserves: ebx +; note: +; when AMODE_DEFINITION is active, current context is not added to the extracted value + call move_to_next_symbol + jc extract_plain_value + cmp byte [esi],'<' + je extract_enclosed_value + extract_plain_value: + mov dl,',' + xor dh,dh + call extract_piece_of_line + retn + extract_enclosed_value: + inc esi + mov dl,'>' + mov dh,'<' + call extract_piece_of_line + cmp al,'>' + jne missing_enclosing + inc esi + call move_to_next_symbol + jnc parameter_value_extracted + xor al,al + parameter_value_extracted: + retn + +get_macro_definition_symbol: +; in: +; esi = pointer into preprocessed line or current embedded value +; al = initial byte of symbol at esi +; dl = SYMCLASS_# +; out: +; ebx - SymbolTree_Leaf +; esi = pointer advanced past the processed declaration +; [macro_leaf] - SymbolTree_Leaf +; [macro_flags] = VAL_# + mov [macro_flags],VAL_NONRECURSIVE + cmp al,'!' + je unconditional_interceptor + or [symbol_definition],1 + call identify_symbol + jc invalid_macro_symbol + test ebx,ebx + jz invalid_macro_symbol + macro_symbol_identified: + call move_to_next_symbol + jc macro_symbol_ok + cmp al,':' + je recursive_macro + test ecx,ecx + jnz macro_symbol_ok + cmp al,'!' + je unconditional_macro + jmp macro_symbol_ok + unconditional_interceptor: + mov ebx,[interceptor_symbol] + cmp dl,SYMCLASS_STRUCTURE + jne unconditional_macro + mov ebx,[label_interceptor_symbol] + unconditional_macro: + or [macro_flags],VAL_UNCONDITIONAL + inc esi + call move_to_next_symbol + jc macro_symbol_ok + cmp al,':' + jne macro_symbol_ok + recursive_macro: + inc esi + call move_to_next_symbol + and [macro_flags],not VAL_NONRECURSIVE + or [ebx+SymbolTree_Leaf.flags],SYM_CONSTANT + jmp macro_symbol_ok + macro_symbol_ok: + mov [macro_leaf],ebx + mov edx,[ebx+SymbolTree_Leaf.definition] + test edx,edx + jz create_placeholder_value + test [edx+ValueDefinition.flags],VAL_INTERNAL + jnz macro_already_defined + mov eax,[current_pass] + sub eax,[edx+ValueDefinition.pass] + jz macro_already_defined + cmp eax,1 + je macro_symbol_ready + create_placeholder_value: + ; for VAL_UNCONDITIONAL macros this helps to detect when a macro tries to call itself, + ; for regular ones this section interferes with operation of SYM_PREDICTED to sometimes prevent excess passes, + ; when SYM_PREDICTED is needed to behave reliably for an instruction, its symbol + ; should be marked with SYMX_INSTRUCTION_PREDICTED to skip this section + test [ebx+SymbolTree_Leaf.extra_flags],SYMX_INSTRUCTION_PREDICTED + jnz macro_symbol_ready + call create_value_definition + test edx,edx + jz macro_symbol_ready + mov eax,[current_pass] + dec eax + mov [edx+ValueDefinition.pass],eax + mov [edx+ValueDefinition.type],VALTYPE_RESERVED + mov al,[macro_flags] + mov [edx+ValueDefinition.flags],al + test al,VAL_UNCONDITIONAL + jnz macro_symbol_ready + or [edx+ValueDefinition.flags],VAL_IN_USE + test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED + jz macro_symbol_ready + mov edi,ebx + mov ecx,[current_pass] + check_macro_usage: + cmp ecx,[edi+SymbolTree_Leaf.last_use_pass] + je macro_possibly_used_earlier + mov edx,[edi+SymbolTree_Leaf.fallback_neighbour] + test edx,edx + jz look_up_parent_namespace_macro + cmp ecx,[edx+SymbolTree_Leaf.last_use_pass] + je macro_possibly_used_earlier + look_up_parent_namespace_macro: + mov edi,[edi+SymbolTree_Leaf.fallback_parent] + test edi,edi + jnz check_macro_usage + and [ebx+SymbolTree_Leaf.flags],not SYM_PREDICTED + jmp macro_symbol_ready + macro_possibly_used_earlier: + test al,VAL_NONRECURSIVE + jnz macro_symbol_ready + or [next_pass_needed],-1 + macro_symbol_ready: + clc + retn + macro_already_defined: + test [ebx+SymbolTree_Leaf.flags],SYM_CONSTANT + jz macro_symbol_ready + mov edx,_conflicting_definition + call register_error + invalid_macro_symbol: + stc + retn + +; instruction handler +; in: +; esi = pointer into preprocessed line +; ecx = number of whitespace tokens between previous symbol and current position +; edx - ValueDefinition of instruction +; ebx - SymbolTree_Leaf of instruction +; edi - SymbolTree_Root of instruction +; when [SymbolTree_Leaf.class] = SYMCLASS_STRUCTURE: +; [label_leaf] - SymbolTree_Leaf of structure label +; [label_branch] - SymbolTree_Foliage of structure label +; [label_independent] = zero when identifier of structure label is relative to current label +; out: +; when done, handler should jump to instruction_assembled with esi containing a pointer moved past the processed part of line, +; or jump directly to assembly_line when the rest of line should be ignored +; note: +; when esi is equal to [line_end], pointer is at the end of line and there is no data available at this address + +set_namespace: + mov dl,DBLOCK_NAMESPACE + mov ecx,sizeof.NamespaceData + call add_directive_block + mov edx,[current_context.base_namespace] + mov [edi-sizeof.NamespaceData+NamespaceData.prior_namespace],edx + mov eax,[edx+SymbolTree_Root.current_label] + mov [edi-sizeof.NamespaceData+NamespaceData.prior_label],eax + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc missing_argument + test ebx,ebx + jz invalid_identifier + call get_symbol_namespace + mov [current_context.base_namespace],ebx + and [ebx+SymbolTree_Root.current_label],0 + jmp instruction_assembled +end_namespace: + mov dl,DBLOCK_NAMESPACE + call find_directive_block + jc unexpected_instruction + mov edx,[edi-sizeof.NamespaceData+NamespaceData.prior_namespace] + mov eax,[edi-sizeof.NamespaceData+NamespaceData.prior_label] + mov [current_context.base_namespace],edx + mov [edx+SymbolTree_Root.current_label],eax + call close_directive_block + jmp instruction_assembled + +set_base_address: + mov edx,[current_area] + mov ebx,[edx+ValueDefinition.value] + test [ebx+AreaHeader.flags],AREA_VIRTUAL + jnz unexpected_instruction + call get_expression_value + jc invalid_argument + push esi + call convert_terms_to_numeric_value + begin_new_output_area: + call create_output_area + inc [edx+ValueDefinition.reference_count] + xchg edx,[current_area] + dec [edx+ValueDefinition.reference_count] + ; jz internal_error + pop esi + jmp instruction_assembled +begin_new_section: + mov edx,[current_area] + mov ebx,[edx+ValueDefinition.value] + test [ebx+AreaHeader.flags],AREA_VIRTUAL + jnz unexpected_instruction + call get_expression_value + jc invalid_argument + push esi + call convert_terms_to_numeric_value + call trim_output + call create_output_area + mov eax,edx + inc [eax+ValueDefinition.reference_count] + xchg eax,[current_area] + dec [eax+ValueDefinition.reference_count] + ; jz internal_error + pop esi + jmp instruction_assembled +restart_output: + mov edx,[current_area] + mov ebx,[edx+ValueDefinition.value] + test [ebx+AreaHeader.flags],AREA_VIRTUAL + jnz unexpected_instruction + call peek_at_constituent_value + jc restart_output_at_current_address + call get_expression_value + jc invalid_argument + push esi + call convert_terms_to_numeric_value + jmp make_new_initial_output_area + restart_output_at_current_address: + push esi + call get_current_address_value + make_new_initial_output_area: + and [initial_output_area_entry],0 + jmp begin_new_output_area + +define_label: + inc esi + xor ecx,ecx + call move_to_next_symbol + jc define_simple_label + test ecx,ecx + jnz define_simple_label + cmp al,'=' + je define_numeric_constant + cmp al,':' + je define_area_label + define_simple_label: + test [assembly_mode],AMODE_SKIP + jnz assemble_after_label + test [assembly_mode],AMODE_DEFINITION + jnz add_label_to_macro + cmp [interceptor],0 + jne execute_interceptor + mov [argument_start],esi + call get_current_address_value + mov edi,ecx + mov ebx,[label_leaf] + call create_constant_value_definition + test edx,edx + jz assembly_line + mov ecx,edi + call assign_shiftable_value + label_defined: + call update_current_label + mov esi,[argument_start] + assemble_after_label: + mov [line_start],esi + mov eax,[embedded_context] + mov [line_context],eax + jmp assemble_instruction + define_area_label: + inc esi + test [assembly_mode],AMODE_SKIP + jnz assemble_after_label + test [assembly_mode],AMODE_DEFINITION + jnz add_label_to_macro + cmp [interceptor],0 + jne execute_interceptor + mov [argument_start],esi + mov ebx,[label_leaf] + mov edx,[current_area] + call update_value_link + jmp label_defined + assign_shiftable_value: + mov [value_type],VALTYPE_NUMERIC + mov eax,[current_area] + mov eax,[eax+ValueDefinition.value] + test [eax+AreaHeader.flags],AREA_SHIFT_TRACKING_DISABLED + jnz assign_value + or [shift_tracking],-1 + call update_predicted_shift + call assign_value + or [edx+ValueDefinition.flags],VAL_SHIFTABLE + retn + update_current_label: + mov edx,[label_branch] + cmp [label_independent],0 + je current_label_ok + mov edi,[edx+SymbolTree_Foliage.root] + test [edi+SymbolTree_Root.flags],NAMESPACE_LOCAL + jnz current_label_ok + mov edi,[current_context.base_namespace] + mov [edi+SymbolTree_Root.current_label],edx + current_label_ok: + retn + +define_numeric_symbol: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + cmp [interceptor],0 + jne execute_interceptor + inc esi + xor ecx,ecx + call move_to_next_symbol + jc define_numeric_variable + test ecx,ecx + jnz define_numeric_variable + cmp al,':' + jne define_numeric_variable + inc esi + call get_expression_value + jc missing_argument + mov ebx,[label_leaf] + call create_value_definition + jmp define_numeric_value +define_numeric_constant: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + cmp [interceptor],0 + jne execute_interceptor + inc esi + call get_expression_value + jc missing_argument + mov ebx,[label_leaf] + call create_constant_value_definition + jmp define_numeric_value +define_numeric_variable: + call get_expression_value + jc missing_argument + mov ebx,[label_leaf] + call update_value_definition + define_numeric_value: + test edx,edx + jz assembly_line + push esi + push ebx edx + mov eax,[edi+ExpressionTerm.attributes] + cmp al,EXPR_STRING + je define_string_variable + cmp al,EXPR_FLOAT + je define_float_variable + mov [value_type],VALTYPE_NUMERIC + call convert_terms_to_numeric_value + assign_numeric_value: + pop edx ebx + call assign_value + pop esi + jmp instruction_assembled + define_string_variable: + mov [value_type],VALTYPE_STRING + call get_term_value + mov esi,edx + mov ecx,[esi] + add ecx,4 + jmp assign_numeric_value + define_float_variable: + mov [value_type],VALTYPE_FLOAT + call get_term_value + mov esi,edx + mov ecx,sizeof.FloatData + jmp assign_numeric_value + +define_element: + or [symbol_definition],1 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc missing_argument + test ebx,ebx + jz invalid_identifier + mov [label_leaf],ebx + call move_to_next_symbol + jc element_with_no_metadata + cmp al,':' + jne get_element_metadata + inc esi + get_element_metadata: + call get_expression_value + jc invalid_argument + mov ebx,[label_leaf] + call create_constant_value_definition + test edx,edx + jz assembly_line + mov [value_type],VALTYPE_ELEMENT + push esi + push ebx edx + call convert_terms_to_numeric_value + pop edx ebx + call assign_value + pop esi + jmp instruction_assembled + element_with_no_metadata: + mov ebx,[label_leaf] + call create_constant_value_definition + test edx,edx + jz assembly_line + mov [value_type],VALTYPE_ELEMENT + push esi + xor esi,esi + xor ecx,ecx + call assign_value + pop esi + jmp instruction_assembled + +redefine_raw_symbolic_variable: + mov [update_function],update_value_definition + jmp raw_symbolic_variable +define_raw_symbolic_variable: + mov [update_function],create_value_definition + raw_symbolic_variable: + or [symbol_definition],1 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc missing_argument + test ebx,ebx + jz invalid_identifier + mov [label_leaf],ebx + or [raw_value],1 + jmp symbolic_variable +redefine_symbolic_variable: + mov [update_function],update_value_definition + and [raw_value],0 + jmp symbolic_variable +define_symbolic_variable: + mov [update_function],create_value_definition + and [raw_value],0 + symbolic_variable: + mov edi,[assembly_workspace.memory_start] + and [previous_symbol_end],0 + and [contextless_processing],0 + expand_symbols: + cmp [raw_value],0 + jne copy_raw_symbols + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + push edi + call identify_symbol + jc symbols_expanded + test edi,edi + jnz symbol_ready + call skip_literal + xor ebx,ebx + symbol_ready: + pop edi + test ebx,ebx + jz copy_symbol + mov [further_whitespace],ecx + call get_available_value + jc copy_symbol + cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC + jne copy_symbol + and [previous_symbol_end],0 + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + cmp ebx,[label_leaf] + jne replace_symbolic_variable + mov ecx,[edx+ValueDefinition.pass] + cmp ecx,[current_pass] + je replace_symbolic_variable + mov edx,_symbolic_self_reference + call register_error + jmp expand_symbols + replace_symbolic_variable: + mov ecx,[edx+ValueDefinition.value_length] + test ecx,ecx + jz expand_symbols + push esi + mov esi,[edx+ValueDefinition.value] + push ecx + add ecx,1+sizeof.RecognitionContext + add ecx,[further_whitespace] + mov edx,assembly_workspace + call reserve_workspace + mov al,40h + cmp al,[esi] + je copy_symbolic_value + stosb + mov eax,esi + mov esi,current_context + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + mov esi,eax + copy_symbolic_value: + pop ecx + rep movsb + pop esi + mov al,20h + mov ecx,[further_whitespace] + rep stosb + jmp expand_symbols + copy_raw_symbols: + mov eax,esi + mov esi,[line_end] + cmp esi,eax + je symbolic_value_ready + mov [symbol_start],eax + copy_symbol: + mov ebx,esi + xchg [previous_symbol_end],esi + test esi,esi + jz copy_symbol_with_recognition_context + mov ecx,ebx + sub ecx,esi + mov edx,assembly_workspace + call reserve_workspace + and [context_boundary],0 + jmp copy_symbol_tokens + copy_symbol_with_recognition_context: + mov ecx,ebx + sub ecx,[symbol_start] + add ecx,1+sizeof.RecognitionContext + mov edx,assembly_workspace + call reserve_workspace + mov al,40h + stosb + cmp [raw_value],0 + je use_recognition_context + mov esi,[embedded_context] + test esi,esi + jz use_current_context + call store_recognition_context + jmp symbol_context_stored + use_current_context: + call store_current_context + jmp symbol_context_stored + use_recognition_context: + mov esi,recognition_context + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + mov [context_boundary],edi + symbol_context_stored: + mov esi,[symbol_start] + copy_symbol_tokens: + cmp esi,ebx + jae expand_symbols + call store_token + jmp copy_symbol_tokens + symbols_expanded: + pop edi + symbolic_value_ready: + mov ebx,[label_leaf] + call [update_function] + test edx,edx + jz assembly_line + mov [value_type],VALTYPE_SYMBOLIC + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + call assign_value + jmp assembly_line + store_token: + lodsb + cmp al,40h + je make_recognition_context_token + stosb + cmp al,1Ah + je store_token_with_data + cmp al,22h + je store_token_with_data + cmp al,27h + je store_token_with_data + cmp al,30h + je store_internal_token + retn + store_token_with_data: + movsd + retn + store_internal_token: + lodsd + stosd + mov ecx,eax + rep movsb + retn + +restore_variables: + mov al,[edx+ValueDefinition.attribute] + mov [chosen_class],al + restore_symbol_value: + mov dl,[chosen_class] + or [symbol_definition],1 + call identify_symbol + jc missing_argument + test ebx,ebx + jz invalid_identifier + remove_variable_value: + xor edx,edx + xor edi,edi + call remove_value_definition + call move_to_next_symbol + jc assembly_line + cmp al,',' + jne invalid_argument + inc esi + jmp restore_symbol_value +move_variable_values: + mov dl,[edx+ValueDefinition.attribute] + mov [chosen_class],dl + or [symbol_definition],1 + call identify_symbol + jc missing_argument + test ebx,ebx + jz invalid_identifier + mov [label_leaf],ebx + call move_to_next_symbol + jc missing_argument + cmp al,',' + jne invalid_argument + inc esi + mov dl,[chosen_class] + call identify_symbol + jc missing_argument + test ebx,ebx + jz invalid_identifier + xor edx,edx + mov edi,[label_leaf] + call remove_value_definition + jmp instruction_assembled + +label_directive: + or [symbol_definition],1 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc missing_argument + test ebx,ebx + jz invalid_identifier + mov [label_leaf],ebx + mov [label_branch],edx + mov al,[symbol_independent] + mov [label_independent],al + and [metadata_length],0 + call peek_at_constituent_value + jc label_at_current_address + cmp al,1Ah + jne label_with_size + test edx,edx + jz label_with_size + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne label_with_size + cmp [edx+ValueDefinition.value],PREPOSITION_AT + je label_at_specified_address + label_with_size: + cmp al,':' + jne get_label_size + and [current_constituent],0 + get_label_size: + call get_expression_value + jc invalid_argument + push esi + mov edx,auxiliary_workspace + call convert_terms_to_numeric_value_in_workspace + mov [metadata_length],ecx + pop esi + call peek_at_constituent_value + jc label_at_current_address + cmp al,1Ah + jne label_at_current_address + test edx,edx + jz invalid_argument + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne label_at_current_address + cmp [edx+ValueDefinition.value],PREPOSITION_AT + jne invalid_argument + label_at_specified_address: + and [current_constituent],0 + call get_expression_value + jc invalid_argument + push esi + call convert_terms_to_numeric_value + mov edi,ecx + mov ebx,[label_leaf] + call create_constant_value_definition + test edx,edx + jz label_ready + call prepare_label_value + mov [value_type],VALTYPE_NUMERIC + call assign_value + jmp label_ready + label_at_current_address: + push esi + call get_current_address_value + mov edi,ecx + mov ebx,[label_leaf] + call create_constant_value_definition + test edx,edx + jz label_ready + call prepare_label_value + call assign_shiftable_value + label_ready: + pop esi + call update_current_label + jmp instruction_assembled + prepare_label_value: + mov ecx,edi + cmp [metadata_length],0 + je label_metadata_ok + add edi,esi + push edx ecx + mov ecx,[metadata_length] + mov edx,assembly_workspace + call reserve_workspace + mov esi,[auxiliary_workspace.memory_start] + mov ecx,[metadata_length] + pop eax + add eax,ecx + rep movsb + pop edx + mov ecx,eax + mov esi,edi + sub esi,ecx + label_metadata_ok: + retn + +virtual_block: + mov dl,DBLOCK_VIRTUAL + mov ecx,sizeof.VirtualBlockData + call add_directive_block + mov edx,[current_area] + mov [edi-sizeof.VirtualBlockData+VirtualBlockData.outer_area],edx + mov al,[shift_tracking] + mov [edi-sizeof.VirtualBlockData+VirtualBlockData.shift_tracking],al + call peek_at_constituent_value + jc virtual_at_current_address + cmp al,1Ah + jne invalid_argument + test edx,edx + jz invalid_argument + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne continue_virtual_block + mov eax,[edx+ValueDefinition.value] + cmp eax,PREPOSITION_AS + je virtual_at_current_address + cmp eax,PREPOSITION_AT + jne invalid_argument + and [current_constituent],0 + call get_expression_value + jc invalid_argument + push esi + call convert_terms_to_numeric_value + jmp create_virtual_block + virtual_at_current_address: + push esi + call get_current_address_value + create_virtual_block: + lea ebx,[virtual_area] + call create_area + or [ebx+AreaHeader.flags],AREA_VIRTUAL + cmp [shift_tracking],0 + je virtual_block_ready + or [ebx+AreaHeader.flags],AREA_SHIFT_TRACKING_DISABLED + virtual_block_ready: + inc [edx+ValueDefinition.reference_count] + or [edx+ValueDefinition.flags],VAL_IN_USE + mov [current_area],edx + pop esi + call get_constituent_value + jc instruction_assembled + cmp al,1Ah + jne invalid_argument + test edx,edx + jz invalid_argument + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne invalid_argument + cmp [edx+ValueDefinition.value],PREPOSITION_AS + jne invalid_argument + call get_constant_value + cmp al,22h + jne invalid_argument + mov ebx,[auxiliary_output_areas] + mov edi,esi + mov ecx,[edx] + lea esi,[edx+4] + test ecx,ecx + jnz register_auxiliary_file + dec esi + register_auxiliary_file: + mov eax,[current_area] + inc [eax+ValueDefinition.reference_count] + push ecx + call put_into_map + pop ecx + jmp validate_extension + continue_virtual_block: + and [leave_opening_parentheses],0 + mov edi,[expression_workspace.memory_start] + call parse_expression + mov edi,[expression_workspace.memory_start] + call get_area_value + jc invalid_area + mov ecx,[current_pass] + cmp [edx+ValueDefinition.pass],ecx + jne invalid_area + mov eax,[edx+ValueDefinition.value] + test [eax+AreaHeader.flags],AREA_VIRTUAL + jz invalid_area + test [edx+ValueDefinition.flags],VAL_IN_USE + jnz invalid_area + inc [edx+ValueDefinition.reference_count] + or [edx+ValueDefinition.flags],VAL_IN_USE + mov [current_area],edx + jmp instruction_assembled + invalid_area: + mov edx,_invalid_area + call register_error + jmp assembly_line + +end_virtual_block: + mov dl,DBLOCK_VIRTUAL + call find_directive_block + jc unexpected_instruction + mov al,[edi-sizeof.VirtualBlockData+VirtualBlockData.shift_tracking] + mov [shift_tracking],al + mov edx,[edi-sizeof.VirtualBlockData+VirtualBlockData.outer_area] + xchg edx,[current_area] + and [edx+ValueDefinition.flags],not VAL_IN_USE + dec [edx+ValueDefinition.reference_count] + jnz close_virtual_block + mov eax,edx + xchg eax,[retired_definition] + mov [edx+ValueDefinition.previous],eax + close_virtual_block: + call close_directive_block + jmp instruction_assembled + +include_source: + call move_to_next_symbol + jc missing_argument + cmp al,'!' + jne conditional_include + inc esi + jmp get_file_name + conditional_include: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + get_file_name: + call get_constant_value + cmp al,22h + jne invalid_argument + push esi + mov [file_name],edx + call prepare_file_path + mov esi,[assembly_workspace.memory_start] + call read_source + test eax,eax + jnz include_read + mov esi,[local_path] + call read_source + test eax,eax + jnz include_read + mov ebx,esi + mov esi,[include_paths] + try_include_paths: + lodsb + test al,al + jz include_not_found + cmp al,';' + je try_include_paths + lea ebx,[esi-1] + measure_path: + lodsb + test al,al + jz path_measured + cmp al,';' + jne measure_path + path_measured: + dec esi + xchg esi,ebx + mov ecx,ebx + sub ecx,esi + mov edx,[file_name] + add ecx,[edx] + add ecx,2 + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + call reserve_workspace + mov ecx,ebx + sub ecx,esi + rep movsb + mov al,[esi-1] + cmp al,'/' + je path_separator_ok + cmp al,'\' + je path_separator_ok + mov al,'/' + stosb + path_separator_ok: + mov esi,[file_name] + lodsd + mov ecx,eax + rep movsb + xor al,al + stosb + mov esi,[assembly_workspace.memory_start] + push ebx + call read_source + mov ebx,esi + pop esi + test eax,eax + jz try_include_paths + mov esi,ebx + include_read: + mov edx,eax + call create_source_entry + jc include_stack_limit_exceeded + mov [ebx+SourceEntry.type],SOURCE_FILE + mov [ebx+SourceEntry.name],esi + mov [ebx+SourceEntry.text],edx + mov edx,[local_parameter_namespace] + mov eax,[edx+SymbolTree_Root.chain] + test eax,eax + jnz new_parameter_namespace_ok + call create_parameter_namespace + mov [edx+SymbolTree_Root.chain],eax + new_parameter_namespace_ok: + and [eax+SymbolTree_Root.parameters],0 + mov [ebx+SourceEntry.local_namespace],eax + pop esi + call get_constituent_value + jc instruction_assembled + cmp al,',' + jne extra_characters_on_line + cmp [number_of_line_embeddings],0 + jne invalid_argument + jmp assemble_after_label + include_stack_limit_exceeded: + pop esi + mov edx,_stack_limit_exceeded + call register_error + jmp instruction_assembled + include_not_found: + pop esi + mov edx,_source_file_not_found + call register_error + jmp instruction_assembled + prepare_file_path: + mov [local_path],edx + call get_file_source_entry + mov esi,[ebx+SourceEntry.name] + mov ecx,esi + cut_parent_path: + lodsb + test al,al + jz parent_path_cut + cmp al,'/' + je found_path_segment + cmp al,'\' + jne cut_parent_path + found_path_segment: + mov ecx,esi + jmp cut_parent_path + parent_path_cut: + mov esi,[ebx+SourceEntry.name] + sub ecx,esi + mov ebx,ecx + add ecx,[edx] + inc ecx + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + call reserve_workspace + mov ecx,ebx + rep movsb + mov edx,edi + xchg edx,[local_path] + lea esi,[edx+4] + mov ecx,[edx] + mov ebx,edi + rep movsb + xor al,al + stosb + retn + +evaluate_string: + mov edi,[assembly_workspace.memory_start] + mov [string_end],edi + collect_source_string: + call get_constant_value + cmp al,30h + je collect_source_byte + cmp al,22h + jne invalid_argument + mov ebx,edx + mov edi,[string_end] + mov ecx,[ebx] + inc ecx + mov edx,assembly_workspace + call reserve_workspace + xchg esi,ebx + lodsd + mov ecx,eax + rep movsb + mov esi,ebx + source_fragment_collected: + mov [string_end],edi + call get_constituent_value + jc source_string_ready + cmp al,',' + jne invalid_argument + jmp collect_source_string + collect_source_byte: + mov ebx,edx + mov edi,[string_end] + mov ecx,2 + mov edx,assembly_workspace + call reserve_workspace + mov edx,ebx + mov ecx,1 + call fit_value + jc value_out_of_range + inc edi + jmp source_fragment_collected + source_string_ready: + mov edi,[string_end] + xor al,al + stosb + push esi + mov esi,[assembly_workspace.memory_start] + call use_source + mov edx,eax + call create_source_entry + jc include_stack_limit_exceeded + mov [ebx+SourceEntry.type],SOURCE_MEMORY + mov [ebx+SourceEntry.name],esi + mov [ebx+SourceEntry.text],edx + mov eax,[parameter_namespace] + mov [ebx+SourceEntry.local_namespace],eax + pop esi + jmp instruction_assembled + +assert_condition: + call get_condition_value + test al,al + jnz instruction_assembled + mov edx,_assertion_failed + call register_error + jmp instruction_assembled + +conditional_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + xor ecx,ecx + call add_directive_block + mov [edi+DirectiveBlock.subtype],CTRL_IF + or [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE + test [assembly_mode],AMODE_SKIP + jnz skip_conditional_block + evaluate_conditional_block: + call get_condition_value + test al,al + jnz instruction_assembled + or [assembly_mode],AMODE_SKIP + jmp instruction_assembled + ignored_directive: + test [assembly_mode],AMODE_SKIP + jz add_line_to_macro + jmp assembly_line + +else_conditional_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + mov al,[edi+DirectiveBlock.flags] + test al,CTRLF_ALLOWS_ELSE + jz unexpected_instruction + mov ah,[assembly_mode] + push eax + call close_control_directive_block + mov dl,DBLOCK_CONTROL + xor ecx,ecx + call add_directive_block + mov [edi+DirectiveBlock.subtype],CTRL_IF + or [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE + pop eax + test al,CTRLF_INACTIVE + jnz skip_conditional_block + test ah,AMODE_SKIP + jnz evaluate_conditional_block + skip_conditional_block: + or [assembly_mode],AMODE_SKIP + or [edi+DirectiveBlock.flags],CTRLF_INACTIVE + jmp assembly_line + +end_conditional_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + cmp [edi+DirectiveBlock.subtype],CTRL_IF + jne unexpected_instruction + end_control_block: + call close_control_directive_block + jmp instruction_assembled + +conditionally_repeated_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + test [assembly_mode],AMODE_SKIP + jnz inactive_conditionally_repeated_block + mov ecx,[line_end] + sub ecx,esi + add ecx,sizeof.ConditionalRepeatData + cmp [embedded_context],0 + je condition_length_ok + add ecx,1+sizeof.RecognitionContext + condition_length_ok: + mov dl,DBLOCK_CONTROL + call add_directive_block + push esi + mov ecx,[line_end] + sub ecx,esi + sub edi,sizeof.ConditionalRepeatData + mov edx,ecx + sub edi,ecx + rep movsb + mov esi,[embedded_context] + test esi,esi + jz condition_stored + add edx,1+sizeof.RecognitionContext + mov ebx,edi + sub edi,edx + mov al,40h + stosb + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + mov edi,ebx + condition_stored: + mov [edi+ConditionalRepeatData.condition_length],edx + add edi,sizeof.ConditionalRepeatData + pop esi + mov [edi+DirectiveBlock.subtype],CTRL_WHILE + or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + call get_condition_value + test al,al + jz skip_repeated_block + start_repeated_block: + mov ecx,2 + call allocate_counter + mov edi,ebx + mov al,1 + stosb + stosb + mov [current_counter],ebx + mov ecx,[parameter_namespace] + mov [ecx+SymbolTree_Root.parameters],SPECPARM_COUNTER + test esi,esi + jz assembly_line + jmp instruction_assembled + inactive_conditionally_repeated_block: + xor esi,esi + mov dh,CTRL_WHILE + inactive_breakable_block: + mov dl,DBLOCK_CONTROL + xor ecx,ecx + call add_directive_block + mov [edi+DirectiveBlock.subtype],dh + or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + skip_repeated_block: + or [assembly_mode],AMODE_SKIP + mov ecx,1 + call allocate_counter + mov byte [ebx],0 + mov [current_counter],ebx + mov ecx,[parameter_namespace] + mov [ecx+SymbolTree_Root.parameters],0 + test esi,esi + jz assembly_line + jmp instruction_assembled + allocate_counter: + mov ebx,[current_counter] + movzx eax,byte [ebx] + lea ebx,[ebx+1+eax] + add ecx,ebx + cmp ecx,[counters_stack_end] + jbe counter_allocated + mov eax,[counters_stack_base] + sub ecx,eax + sub ebx,eax + call grow_stack + add ecx,eax + mov [counters_stack_end],ecx + mov [counters_stack_base],eax + add ebx,eax + counter_allocated: + retn + +end_conditionally_repeated_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + cmp [edi+DirectiveBlock.subtype],CTRL_WHILE + jne unexpected_instruction + test [assembly_mode],AMODE_SKIP + jnz end_control_block + push esi edi + push [line_end] + push [source_context] + lea esi,[edi-sizeof.ConditionalRepeatData] + mov [line_end],esi + sub esi,[esi+ConditionalRepeatData.condition_length] + sub edi,[edi+DirectiveBlock.length_of_data] + mov [source_context],edi + and [embedded_context],0 + call get_condition_value + pop [source_context] + pop [line_end] + pop edi esi + test al,al + jz end_control_block + repeat_condition_upheld: + mov ebx,[current_counter] + movzx ecx,byte [ebx] + inc ebx + increase_counter: + inc byte [ebx] + jnz counter_increased + inc ebx + loop increase_counter + cmp ebx,[counters_stack_end] + jb counter_length_grown + lea ecx,[ebx+1] + mov eax,[counters_stack_base] + sub ecx,eax + sub ebx,eax + sub [current_counter],eax + call grow_stack + add ecx,eax + mov [counters_stack_end],ecx + mov [counters_stack_base],eax + add [current_counter],eax + add ebx,eax + counter_length_grown: + mov byte [ebx],1 + mov ebx,[current_counter] + inc byte [ebx] + counter_increased: + push esi + test [edi+DirectiveBlock.flags],CTRLF_HAS_REPEAT_DATA + jz index_updated + mov esi,[current_counter] + mov eax,[counters_stack_base] + add eax,[edi-sizeof.RepeatData+RepeatData.index_position] + cmp eax,esi + je index_updated + xchg eax,edi + movzx ecx,byte [esi] + inc ecx + rep movsb + mov edi,eax + index_updated: + mov eax,[source_context] + mov esi,eax + call release_source_context + sub edi,[edi+DirectiveBlock.length_of_data] + xchg esi,edi + call clone_source_context + pop esi + jmp instruction_assembled + +repeated_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + test [assembly_mode],AMODE_SKIP + jnz inactive_repeated_block + call get_numeric_constant_value + test edx,edx + jz invalid_count + mov ecx,[edx] + add edx,4 + test ecx,ecx + jz inactive_repeated_block + mov al,[edx+ecx-1] + test al,al + js count_out_of_range + jnz count_ok + optimize_counter: + test ecx,ecx + jz inactive_repeated_block + dec ecx + mov al,[edx+ecx-1] + test al,al + jz optimize_counter + count_ok: + push esi ecx + mov esi,edx + mov dl,DBLOCK_CONTROL + add ecx,sizeof.RepeatData + call add_directive_block + mov [edi+DirectiveBlock.subtype],CTRL_REPEAT + or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + CTRLF_HAS_REPEAT_DATA + mov [directive_block],edi + pop ecx + sub edi,sizeof.RepeatData + mov [edi+RepeatData.limit_length],ecx + sub edi,ecx + rep movsb + pop esi + mov ecx,2 + call allocate_counter + mov eax,ebx + sub eax,[counters_stack_base] + mov [edi+RepeatData.index_position],eax + mov edi,ebx + mov al,1 + stosb + stosb + mov [current_counter],ebx + mov ecx,[parameter_namespace] + mov [ecx+SymbolTree_Root.parameters],SPECPARM_COUNTER + SPECPARM_LIMIT + define_named_counters: + xor al,al + xchg al,[current_constituent] + test al,al + jz get_counter_name + cmp al,',' + je get_counter_name + cmp al,1Ah + jne invalid_argument + mov esi,[symbol_start] + get_counter_name: + call identify_parameter_symbol + jc instruction_assembled + test ebx,ebx + jz invalid_argument + mov [label_leaf],ebx + call peek_at_constituent_value + jc counter_with_default_base + cmp al,':' + jne counter_with_default_base + and [current_constituent],0 + call get_numeric_constant_value + test edx,edx + jz invalid_counter_base + mov ecx,[edx] + test byte [edx+4+ecx-1],80h + jns counter_base_ok + mov edx,_value_out_of_range + call register_error + jmp counter_with_default_base + invalid_counter_base: + mov edx,_invalid_value + call register_error + counter_with_default_base: + mov edx,singular_value + counter_base_ok: + push esi + mov esi,edx + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + mov ecx,[esi] + add ecx,8 + call reserve_workspace + mov eax,[current_counter] + sub eax,[counters_stack_base] + stosd + lodsd + mov ecx,eax + stosd + rep movsb + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + mov [value_type],VALTYPE_NUMERIC_SEQUENCE + mov ebx,[label_leaf] + mov edi,[directive_block] + call add_block_parameter + pop esi + jmp define_named_counters + invalid_count: + mov edx,_invalid_value + call register_error + jmp inactive_repeated_block + count_out_of_range: + mov edx,_value_out_of_range + call register_error + inactive_repeated_block: + xor esi,esi + mov dh,CTRL_REPEAT + jmp inactive_breakable_block + +end_repeated_block: + mov dh,CTRL_REPEAT + close_repeat: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + cmp dh,[edi+DirectiveBlock.subtype] + jne unexpected_instruction + test [assembly_mode],AMODE_SKIP + jnz end_control_block + mov edx,[current_counter] + movzx ecx,byte [edx] + inc edx + lea ebx,[edi-sizeof.RepeatData] + cmp ecx,[ebx+RepeatData.limit_length] + jne repeat_condition_upheld + sub ebx,ecx + compare_counter_with_limit: + mov al,[ebx] + cmp al,[edx] + jne repeat_condition_upheld + inc ebx + inc edx + loop compare_counter_with_limit + jmp end_control_block + +iterator_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + test [assembly_mode],AMODE_SKIP + jnz inactive_iterator_block + xor eax,eax + mov [breakpoint_token],al + mov [number_of_parameters],eax + mov edi,[expression_workspace.memory_start] + call move_to_next_symbol + jc invalid_iterator + cmp al,'<' + jne iterator_parameter_declaration + inc esi + mov [breakpoint_token],'>' + iterator_parameter_declaration: + push edi + call identify_parameter_symbol + pop edi + jc invalid_iterator + test ebx,ebx + jz invalid_iterator + mov eax,[number_of_parameters] + shl eax,2 + add eax,[assembly_stack_base] + lea ecx,[eax+4] + cmp ecx,[assembly_stack_end] + jbe store_parameter_leaf + mov eax,[assembly_stack_base] + sub ecx,eax + call grow_stack + mov [assembly_stack_base],eax + add ecx,eax + mov [assembly_stack_end],ecx + mov ecx,[number_of_parameters] + shl ecx,2 + add eax,ecx + store_parameter_leaf: + mov [eax],ebx + mov edx,expression_workspace + mov ecx,sizeof.LineExcerpt + call reserve_workspace + mov [edi+LineExcerpt.data_start],esi + mov [edi+LineExcerpt.data_end],esi + inc [number_of_parameters] + call move_to_next_symbol + jc invalid_iterator + cmp al,':' + je parameter_with_default_value + cmp al,'=' + je parameter_with_default_value + cmp al,'*' + jne parameter_declaration_done + and [edi+LineExcerpt.data_start],0 + inc esi + call move_to_next_symbol + jc invalid_iterator + jmp parameter_declaration_done + parameter_with_default_value: + inc esi + call cut_argument_value + parameter_declaration_done: + add edi,sizeof.LineExcerpt + mov ah,[breakpoint_token] + test ah,ah + jz iterator_parameters_declared + inc esi + cmp al,',' + je iterator_parameter_declaration + cmp al,ah + jne invalid_iterator + call move_to_next_symbol + jc invalid_iterator + iterator_parameters_declared: + cmp al,',' + jne invalid_iterator + mov ebx,[number_of_parameters] + mov [number_of_values],ebx + and [number_of_iterations],0 + collect_iterator_values: + inc esi + call move_to_next_symbol + jc initialize_iterator + mov edx,expression_workspace + mov ecx,sizeof.LineExcerpt + call reserve_workspace + call cut_argument_value + add edi,sizeof.LineExcerpt + inc [number_of_values] + cmp ebx,[number_of_parameters] + jne iterator_value_collected + inc [number_of_iterations] + xor ebx,ebx + iterator_value_collected: + inc ebx + cmp al,',' + je collect_iterator_values + initialize_iterator: + cmp [number_of_iterations],0 + je inactive_iterator_block + mov dl,DBLOCK_CONTROL + mov ecx,5+sizeof.RepeatData + call add_directive_block + mov [edi+DirectiveBlock.subtype],CTRL_IRP + or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + CTRLF_HAS_REPEAT_DATA + CTRLF_HAS_WRITABLE_INDEX + mov [directive_block],edi + bsr ecx,[number_of_iterations] + shr ecx,3 + inc ecx + push esi + sub edi,sizeof.RepeatData + mov [edi+RepeatData.limit_length],ecx + sub edi,ecx + mov esi,number_of_iterations + rep movsb + mov ecx,[edi+RepeatData.limit_length] + add ecx,3 + call allocate_counter + mov eax,ebx + sub eax,[counters_stack_base] + mov [edi+RepeatData.index_position],eax + mov ecx,[edi+RepeatData.limit_length] + mov edi,ebx + mov al,1 + stosb + stosb + lea edi,[edi+ecx-1] + mov [current_counter],edi + stosb + stosb + mov ecx,[parameter_namespace] + mov [ecx+SymbolTree_Root.parameters],SPECPARM_COUNTER + SPECPARM_LIMIT + xor eax,eax + create_iterator_sequences: + mov [parameter_index],eax + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + mov ecx,[number_of_iterations] + add ecx,2 + shl ecx,2 + call reserve_workspace + mov eax,[directive_block] + mov eax,[eax-sizeof.RepeatData+RepeatData.index_position] + stosd + mov eax,[number_of_iterations] + add eax,2 + shl eax,2 + stosd + mov [sequence_header_length],eax + mov edx,edi + mov edi,[assembly_workspace.memory_start] + sub edx,edi + mov [sequence_header_cursor],edx + add edi,eax + mov eax,[number_of_parameters] + add eax,[parameter_index] + cmp eax,[number_of_values] + jae copy_default_value + copy_individual_value: + mov [value_index],eax + mov ebx,eax + assert sizeof.LineExcerpt = 1 shl 4 + shl ebx,4 + add ebx,[expression_workspace.memory_start] + mov esi,[ebx+LineExcerpt.data_start] + mov ecx,[ebx+LineExcerpt.data_end] + sub ecx,esi + jnz individual_value_ready + copy_default_value: + mov ebx,[parameter_index] + assert sizeof.LineExcerpt = 1 shl 4 + shl ebx,4 + add ebx,[expression_workspace.memory_start] + mov esi,[ebx+LineExcerpt.data_start] + test esi,esi + jz missing_required_individual_value + mov ecx,[ebx+LineExcerpt.data_end] + sub ecx,esi + individual_value_ready: + mov edx,assembly_workspace + add ecx,2*(1+sizeof.RecognitionContext) + call reserve_workspace + mov ecx,[ebx+LineExcerpt.data_end] + sub ecx,esi + jz next_iterator_value + cmp [ebx+LineExcerpt.recognition_context],0 + je copy_iterator_value + mov al,40h + stosb + mov eax,esi + mov edx,ecx + mov esi,[ebx+LineExcerpt.recognition_context] + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + mov ecx,edx + mov esi,eax + copy_iterator_value: + rep movsb + mov eax,[ebx+LineExcerpt.recognition_context] + or eax,[ebx+LineExcerpt.leftover_context] + jz next_iterator_value + mov al,40h + stosb + xor eax,eax + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep stosd + next_iterator_value: + mov edx,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,edx + add edx,[sequence_header_cursor] + mov [edx],ecx + add [sequence_header_cursor],4 + mov eax,[value_index] + add eax,[number_of_parameters] + cmp eax,[number_of_values] + jb copy_individual_value + mov eax,[sequence_header_length] + sub eax,[sequence_header_cursor] + jne copy_default_value + mov ecx,edi + mov esi,[assembly_workspace.memory_start] + sub ecx,esi + mov eax,[parameter_index] + shl eax,2 + add eax,[assembly_stack_base] + mov ebx,[eax] + mov edi,[directive_block] + mov [value_type],VALTYPE_SYMBOLIC_SEQUENCE + call add_block_parameter + mov eax,[parameter_index] + inc eax + cmp eax,[number_of_parameters] + jb create_iterator_sequences + pop esi + jmp instruction_assembled + missing_required_individual_value: + mov edx,_missing_argument + call register_error + jmp next_iterator_value + invalid_iterator: + mov edx,_invalid_argument + call register_error + inactive_iterator_block: + xor esi,esi + mov dh,CTRL_IRP + jmp inactive_breakable_block + +end_iterator_block: + mov dh,CTRL_IRP + jmp close_repeat + +variable_iterator_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + test [assembly_mode],AMODE_SKIP + jnz skipped_variable_iterator_block + call move_to_next_symbol + jc invalid_iterator + call identify_parameter_symbol + jc invalid_variable_iterator + test ebx,ebx + jz invalid_variable_iterator + mov [label_leaf],ebx + call move_to_next_symbol + jc invalid_variable_iterator + cmp al,',' + jne invalid_variable_iterator + inc esi + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc invalid_variable_identifier + test ebx,ebx + jz invalid_variable_identifier + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + mov edi,[assembly_stack_base] + xor ecx,ecx + mov [number_of_values],ecx + mov edx,[ebx+SymbolTree_Leaf.definition] + collect_variable_values: + test edx,edx + jz variable_values_collected + mov eax,[edx+ValueDefinition.pass] + cmp eax,[current_pass] + jne variable_values_collected + cmp [edx+ValueDefinition.type],VALTYPE_RESERVED + je skip_variable_value + add edi,4 + cmp edi,[assembly_stack_end] + jbe store_variable_value + push ecx edx + mov eax,[assembly_stack_base] + sub edi,eax + mov ecx,edi + call grow_stack + add edi,eax + mov [assembly_stack_base],eax + add eax,ecx + mov [assembly_stack_end],eax + pop edx ecx + store_variable_value: + mov [edi-4],edx + inc [number_of_values] + add ecx,[edx+ValueDefinition.value_length] + add ecx,1+sizeof.RecognitionContext + skip_variable_value: + mov edx,[edx+ValueDefinition.previous] + jmp collect_variable_values + variable_values_collected: + mov eax,[number_of_values] + test eax,eax + jz inactive_variable_iterator_block + add eax,2 + shl eax,2 + add ecx,eax + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + call reserve_workspace + mov dl,DBLOCK_CONTROL + mov ecx,5+sizeof.RepeatData + call add_directive_block + mov [edi+DirectiveBlock.subtype],CTRL_IRPV + or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + CTRLF_HAS_REPEAT_DATA + CTRLF_HAS_WRITABLE_INDEX + mov [directive_block],edi + bsr ecx,[number_of_values] + shr ecx,3 + inc ecx + push esi + sub edi,sizeof.RepeatData + mov [edi+RepeatData.limit_length],ecx + sub edi,ecx + mov esi,number_of_values + rep movsb + mov ecx,[edi+RepeatData.limit_length] + add ecx,3 + call allocate_counter + mov eax,ebx + sub eax,[counters_stack_base] + mov [edi+RepeatData.index_position],eax + mov ecx,[edi+RepeatData.limit_length] + mov edi,ebx + mov al,1 + stosb + stosb + lea edi,[edi+ecx-1] + mov [current_counter],edi + stosb + stosb + mov ecx,[parameter_namespace] + mov [ecx+SymbolTree_Root.parameters],SPECPARM_COUNTER + SPECPARM_LIMIT + mov edi,[assembly_workspace.memory_start] + mov ecx,[number_of_values] + mov edx,ecx + add ecx,2 + shl ecx,2 + mov ebx,edi + add edi,ecx + mov eax,[directive_block] + mov eax,[eax-sizeof.RepeatData+RepeatData.index_position] + mov [ebx],eax + add ebx,4 + mov [ebx],ecx + create_value_sequence: + mov eax,edx + dec eax + shl eax,2 + add eax,[assembly_stack_base] + mov eax,[eax] + push edx + mov cl,[eax+ValueDefinition.type] + cmp cl,VALTYPE_SYMBOLIC + je symbolic_value_in_sequence + cmp cl,VALTYPE_NUMERIC + jne proxy_value_in_sequence + mov esi,[eax+ValueDefinition.value] + mov ecx,[esi] + add esi,4 + test byte [esi+ecx-1],80h + jnz proxy_value_in_sequence + cmp dword [esi+ecx],0 + jne proxy_value_in_sequence + push ecx + add ecx,1+4 + call allocate_value_in_sequence + pop ecx + mov al,30h + stosb + mov eax,ecx + stosd + rep movsb + jmp next_value_in_sequence + allocate_value_in_sequence: + mov eax,[ebx] + add eax,ecx + add ebx,4 + mov [ebx],eax + mov edx,assembly_workspace + sub ebx,[edx+Workspace.memory_start] + call reserve_workspace + add ebx,[assembly_workspace.memory_start] + retn + proxy_value_in_sequence: + mov esi,eax + mov ecx,(1+sizeof.RecognitionContext)*2+1 + call allocate_value_in_sequence + push ebx edi + push esi + xor eax,eax + mov ecx,[proxy_number] + inc [proxy_number] + mov dl,SYMCLASS_EXPRESSION + mov ebx,[current_context.base_namespace] + call get_abstract_symbol + xchg edx,[esp] + call update_value_link + pop edx + pop edi ebx + mov al,40h + stosb + mov eax,[current_context.base_namespace] + mov [edi+RecognitionContext.base_namespace],eax + mov [edi+RecognitionContext.base_label],edx + add edi,sizeof.RecognitionContext + mov al,'.' + stosb + jmp close_symbolic_value_in_sequence + symbolic_value_in_sequence: + mov esi,[eax+ValueDefinition.value] + mov ecx,[eax+ValueDefinition.value_length] + push ecx + add ecx,1+sizeof.RecognitionContext + call allocate_value_in_sequence + pop ecx + rep movsb + close_symbolic_value_in_sequence: + mov al,40h + stosb + xor eax,eax + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep stosd + next_value_in_sequence: + pop edx + dec edx + jnz create_value_sequence + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + mov ebx,[label_leaf] + mov edi,[directive_block] + mov [value_type],VALTYPE_SYMBOLIC_SEQUENCE + call add_block_parameter + pop esi + jmp instruction_assembled + invalid_variable_identifier: + mov edx,_invalid_identifier + call register_error + jmp inactive_variable_iterator_block + invalid_variable_iterator: + mov edx,_invalid_argument + call register_error + skipped_variable_iterator_block: + xor esi,esi + inactive_variable_iterator_block: + mov dh,CTRL_IRPV + jmp inactive_breakable_block + +end_variable_iterator_block: + mov dh,CTRL_IRPV + jmp close_repeat + +set_iterator_index: + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + find_indexable_block: + test [edi+DirectiveBlock.flags],CTRLF_HAS_WRITABLE_INDEX + jnz indexable_block_found + call find_next_directive_block + jc unexpected_instruction + jmp find_indexable_block + indexable_block_found: + ; test [edi+DirectiveBlock.flags],CTRLF_HAS_REPEAT_DATA + ; jnz internal_error + mov [directive_block],edi + call get_numeric_constant_value + test edx,edx + jz invalid_argument + mov ecx,[edx] + add edx,4 + mov al,[edx+ecx-1] + test al,al + js value_out_of_range + jnz index_optimized + optimize_index: + test ecx,ecx + jz value_out_of_range + dec ecx + mov al,[edx+ecx-1] + test al,al + jz optimize_index + index_optimized: + mov edi,[directive_block] + sub edi,sizeof.RepeatData + mov ebx,[edi+RepeatData.limit_length] + cmp ecx,ebx + ja value_out_of_range + jb index_ok + sub edi,ebx + compare_index_with_limit: + mov al,[edx+ebx-1] + cmp al,[edi+ebx-1] + ja value_out_of_range + jb index_ok + dec ebx + jnz compare_index_with_limit + index_ok: + xchg esi,edx + mov edi,[directive_block] + mov edi,[edi-sizeof.RepeatData+RepeatData.index_position] + add edi,[counters_stack_base] + mov al,cl + stosb + rep movsb + mov esi,edx + jmp instruction_assembled + +break_directive: + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + find_block_to_break: + test [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + jnz block_to_break_found + call find_next_directive_block + jc unexpected_instruction + jmp find_block_to_break + block_to_break_found: + or [assembly_mode],AMODE_SKIP + mov dl,DBLOCK_CONTROL + call find_directive_block + break_blocks: + or [edi+DirectiveBlock.flags],CTRLF_INACTIVE + test [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + jnz disable_counter + or [edi+DirectiveBlock.prior_assembly_mode],AMODE_SKIP + call find_next_directive_block + jc unexpected_instruction + jmp break_blocks + disable_counter: + mov edi,[current_counter] + xor al,al + stosb + jmp instruction_assembled + +else_directive: + mov edx,[ebx+SymbolTree_Leaf.branch] + call get_symbol_namespace + and [symbol_definition],0 + mov dl,SYMCLASS_INSTRUCTION + call identify_symbol_in_namespace + jc plain_else + test ebx,ebx + jz invalid_else + mov al,[ebx+SymbolTree_Leaf.class] + cmp al,SYMCLASS_INSTRUCTION + jne invalid_else + call get_available_value + jc invalid_else + jmp prefixed_directive + invalid_else: + mov esi,[symbol_start] + plain_else: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + test [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE + jz unexpected_instruction + and [edi+DirectiveBlock.flags],not CTRLF_ALLOWS_ELSE + call remove_block_parameters + test [edi+DirectiveBlock.flags],CTRLF_INACTIVE + jnz assembly_line + xor [assembly_mode],AMODE_SKIP + jmp instruction_assembled + +end_directive: + mov edx,[ebx+SymbolTree_Leaf.branch] + call get_symbol_namespace + and [symbol_definition],0 + mov dl,SYMCLASS_INSTRUCTION + call identify_symbol_in_namespace + jc missing_prefixed_directive + test ebx,ebx + jz invalid_prefixed_directive + mov al,[ebx+SymbolTree_Leaf.class] + cmp al,SYMCLASS_INSTRUCTION + jne invalid_prefixed_directive + call get_available_value + jc invalid_prefixed_directive + prefixed_directive: + test [edx+ValueDefinition.flags],VAL_UNCONDITIONAL + jnz execute_prefixed_directive + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + execute_prefixed_directive: + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_CALM + je launch_calm + cmp al,VALTYPE_SYMBOLIC + je use_macro + cmp al,VALTYPE_NATIVE_COMMAND + jne invalid_argument + jmp [edx+ValueDefinition.value] + missing_prefixed_directive: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + cmp [interceptor],0 + jne execute_interceptor + jmp missing_argument + invalid_prefixed_directive: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + cmp [interceptor],0 + jne execute_interceptor + jmp invalid_argument + +raw_match_block: + mov bl,CTRL_RMATCH + jmp begin_match_block +match_block: + mov bl,CTRL_MATCH + begin_match_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + cmp bl,CTRL_RMATCH + sete [unprocessed_matching] + mov dl,DBLOCK_CONTROL + xor ecx,ecx + call add_directive_block + mov [directive_block],edi + mov [edi+DirectiveBlock.subtype],bl + or [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE + test [assembly_mode],AMODE_SKIP + jnz skip_conditional_block + evaluate_match: + mov [pattern_start],esi + and [number_of_parameters],0 + get_match_pattern: + call move_to_next_symbol + jc invalid_match + qualify_pattern_element: + cmp al,',' + je match_pattern_ok + cmp al,1Ah + je count_pattern_parameter + cmp al,30h + je invalid_match + cmp al,'=' + jne skip_pattern_symbol + call skip_token + xor ecx,ecx + call move_to_next_symbol + jc invalid_match + test ecx,ecx + jz skip_pattern_symbol + jmp qualify_pattern_element + count_pattern_parameter: + call detect_numeric_symbol + jc invalid_match + inc [number_of_parameters] + add esi,1+4 + jmp get_match_pattern + skip_pattern_symbol: + call skip_token + jmp get_match_pattern + match_pattern_ok: + mov [pattern_end],esi + inc esi + mov [argument_start],esi + mov eax,[embedded_context] + mov [matched_context],eax + mov edi,[expression_workspace.memory_start] + mov ecx,[number_of_parameters] + assert sizeof.MatchedParameter = 1 shl 3 + shl ecx,3 + mov ebx,ecx + mov edx,expression_workspace + call reserve_workspace + add edi,ebx + mov [substitutions_end],edi + cmp [unprocessed_matching],0 + jne substitutions_ready + detect_substitutions: + mov eax,[embedded_context] + mov [stored_context],eax + and [symbol_definition],0 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc substitutions_ready + test edi,edi + jnz check_for_substitution + call skip_literal + xor ebx,ebx + check_for_substitution: + test ebx,ebx + jz detect_substitutions + call get_available_value + jc detect_substitutions + cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC + jne detect_substitutions + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + mov ebx,edx + mov edi,[substitutions_end] + mov edx,expression_workspace + mov ecx,sizeof.SymbolSubstitution + call reserve_workspace + mov eax,[ebx+ValueDefinition.value] + mov [edi+SymbolSubstitution.value_start],eax + add eax,[ebx+ValueDefinition.value_length] + mov [edi+SymbolSubstitution.value_end],eax + mov ebx,esi + mov esi,[symbol_start] + mov [edi+SymbolSubstitution.symbol_start],esi + scan_replaced_symbol: + mov al,[esi] + cmp al,20h + je whitespace_in_replaced_symbol + cmp al,40h + jne actual_replaced_symbol + inc esi + mov [stored_context],esi + add esi,sizeof.RecognitionContext + jmp next_token_in_replaced_symbol + whitespace_in_replaced_symbol: + inc esi + jmp next_token_in_replaced_symbol + actual_replaced_symbol: + call skip_token + mov ecx,esi + mov edx,[stored_context] + next_token_in_replaced_symbol: + cmp esi,ebx + jb scan_replaced_symbol + mov [edi+SymbolSubstitution.symbol_end],ecx + mov [edi+SymbolSubstitution.leftover_context],edx + add edi,sizeof.SymbolSubstitution + mov [substitutions_end],edi + jmp detect_substitutions + substitutions_ready: + mov ebx,[number_of_parameters] + assert sizeof.MatchedParameter = 1 shl 3 + shl ebx,3 + add ebx,[expression_workspace.memory_start] + mov esi,[argument_start] + mov edi,[pattern_start] + xor eax,eax + mov [parameter_index],eax + mov [stored_position],eax + mov [substitution_active],al + match_with_pattern: + call get_pattern_token + cmp ah,1Ah + jne exact_match + wildcard_match: + call get_matched_token + jc no_match + cmp al,20h + jne wildcard_matched + inc esi + jmp wildcard_match + wildcard_matched: + xor eax,eax + mov edx,[expression_workspace.memory_start] + mov ecx,[parameter_index] + jecxz prepare_matched_parameter + dec ecx + assert sizeof.MatchedParameter = 1 shl 3 + shl ecx,3 + add edx,ecx + push edi + mov edi,[assembly_workspace.memory_start] + add edi,[edx+MatchedParameter.assembly_position] + push edx + call close_matched_value + pop edx + mov eax,edi + sub eax,[assembly_workspace.memory_start] + mov [edx+MatchedParameter.assembly_position],eax + pop edi + add edx,sizeof.MatchedParameter + prepare_matched_parameter: + mov [edx+MatchedParameter.pattern],edi + inc [parameter_index] + mov edi,[assembly_workspace.memory_start] + add edi,eax + xor eax,eax + mov [embedded_context],eax + mov [stored_position],eax + mov [whitespace_matching],al + push edx + call copy_matched_token + pop edx + sub edi,[assembly_workspace.memory_start] + mov [edx+MatchedParameter.assembly_position],edi + mov edi,[edx+MatchedParameter.pattern] + add edi,1+4 + call get_pattern_token + cmp ah,1Ah + je wildcard_match + cmp ah,'?' + jne exact_match + inc edi + jmp match_with_pattern + exact_match: + cmp [stored_position],0 + jne match_position_stored + mov [stored_position],esi + mov [stored_substitution],ebx + mov dl,[substitution_active] + mov [stored_substitution_activity],dl + mov ecx,[matched_context] + mov [stored_context],ecx + mov [stored_pattern],edi + or [whitespace_matching],1 + match_position_stored: + cmp ah,',' + je end_of_pattern + cmp ah,20h + je allow_whitespace + cmp ah,'=' + jne match_tokens + inc edi + call get_pattern_token + match_tokens: + call get_matched_token + jc no_match + cmp al,20h + je match_whitespace + and [whitespace_matching],0 + cmpsb + jne token_mismatch + cmp ah,1Ah + je match_name_tokens + cmp ah,22h + je match_string_tokens + cmp ah,27h + je match_string_tokens + cmp ah,30h + jne match_with_pattern + mov ecx,esi + mov edx,edi + lodsd + add esi,eax + mov eax,[edi] + lea edi,[edi+4+eax] + call get_pattern_token + cmp ah,'?' + jne compare_token_contents + inc edi + jmp compare_token_contents + match_string_tokens: + lodsd + mov ecx,eax + mov edx,[edi] + add edi,4 + compare_token_contents: + cmp ecx,edx + je match_with_pattern + push esi edi + mov esi,ecx + mov edi,edx + mov ecx,[esi] + add ecx,4 + repe cmpsb + pop edi esi + jne retract_match + jmp match_with_pattern + match_name_tokens: + lodsd + mov ecx,eax + mov edx,[edi] + add edi,4 + call get_pattern_token + cmp ah,'?' + je case_insensitive_match + cmp ecx,edx + je match_with_pattern + push esi edi + mov esi,ecx + mov edi,edx + lodsd + scasd + jne name_mismatch + mov ecx,eax + mov eax,[esi+ecx] + cmp eax,[edi+ecx] + jne name_mismatch + repe cmpsb + jne name_mismatch + pop edi esi + jmp match_with_pattern + name_mismatch: + pop edi esi + jmp retract_match + case_insensitive_match: + inc edi + cmp ecx,edx + je match_with_pattern + push esi edi + mov esi,ecx + mov edi,edx + lodsd + scasd + jne name_mismatch + mov ecx,eax + mov eax,[esi+ecx+4] + cmp eax,[edi+ecx+4] + jne name_mismatch + xor eax,eax + compare_case_insensitively: + lodsb + mov dl,[characters+eax] + mov al,[edi] + inc edi + cmp dl,[characters+eax] + jne name_mismatch + loop compare_case_insensitively + pop edi esi + jmp match_with_pattern + match_converted_number: + call convert_number_to_match + jmp compare_token_contents + match_with_converted_number: + xchg esi,edi + call convert_number_to_match + xchg esi,edi + jmp compare_token_contents + convert_number_to_match: + mov edx,esi + lodsd + add esi,eax + push ebx esi edi + call convert_number_back + pop edi esi ebx + mov ecx,[edi] + add edi,4 + retn + token_mismatch: + cmp ax,1A30h + je match_converted_number + cmp ax,301Ah + je match_with_converted_number + retract_match: + xor esi,esi + xchg esi,[stored_position] + test esi,esi + jz no_match + mov ebx,[stored_substitution] + mov dl,[stored_substitution_activity] + mov [substitution_active],dl + mov ecx,[stored_context] + mov [matched_context],ecx + mov edi,[stored_pattern] + and [whitespace_matching],0 + mov edx,[parameter_index] + sub edx,1 + jc no_match + assert sizeof.MatchedParameter = 1 shl 3 + shl edx,3 + add edx,[expression_workspace.memory_start] + push edi + mov edi,[assembly_workspace.memory_start] + add edi,[edx+MatchedParameter.assembly_position] + push edx + copy_whitespace: + call get_matched_token + jc no_match + cmp al,20h + jne copy_additional_symbol + call copy_matched_token + jmp copy_whitespace + copy_additional_symbol: + call copy_matched_token + pop edx + sub edi,[assembly_workspace.memory_start] + mov [edx+MatchedParameter.assembly_position],edi + pop edi + jmp match_with_pattern + match_whitespace: + cmp al,ah + je required_whitespace + cmp [whitespace_matching],0 + je retract_match + inc esi + jmp match_tokens + required_whitespace: + inc esi + allow_whitespace: + inc edi + or [whitespace_matching],1 + jmp match_with_pattern + end_of_pattern: + call get_matched_token + jc pattern_matched + cmp al,20h + jne retract_match + call skip_token + jmp end_of_pattern + pattern_matched: + mov ebx,[parameter_index] + sub ebx,1 + jc matching_done + assert sizeof.MatchedParameter = 1 shl 3 + shl ebx,3 + add ebx,[expression_workspace.memory_start] + mov edi,[assembly_workspace.memory_start] + add edi,[ebx+MatchedParameter.assembly_position] + call close_matched_value + sub edi,[assembly_workspace.memory_start] + mov [ebx+MatchedParameter.assembly_position],edi + matching_done: + cmp [number_of_parameters],0 + je assembly_line + mov [symbol_class],SYMCLASS_PARAMETER + and [name_volatile],0 + and [name_token],0 + or [symbol_required],1 + or [symbol_expected],1 + mov [value_type],VALTYPE_SYMBOLIC + xor eax,eax + mov [value_index],eax + define_matched_parameters: + mov [parameter_index],eax + assert sizeof.MatchedParameter = 1 shl 3 + shl eax,3 + add eax,[expression_workspace.memory_start] + mov edi,[eax+MatchedParameter.pattern] + mov esi,[edi+1] + lodsd + mov ecx,eax + add edi,1+4 + call get_pattern_token + mov edx,[esi+ecx] + mov al,NAME_CASESENSITIVE + cmp ah,'?' + jne matched_name_kind_ok + mov edx,[esi+ecx+4] + mov al,NAME_CASEINSENSITIVE + matched_name_kind_ok: + mov [name_kind],al + mov ebx,[parameter_namespace] + call scan_namespace + mov eax,[parameter_index] + assert sizeof.MatchedParameter = 1 shl 3 + shl eax,3 + add eax,[expression_workspace.memory_start] + mov ecx,[eax+MatchedParameter.assembly_position] + mov esi,ecx + xchg esi,[value_index] + sub ecx,esi + add esi,[assembly_workspace.memory_start] + mov edi,[directive_block] + call add_block_parameter + mov eax,[parameter_index] + inc eax + cmp eax,[number_of_parameters] + jb define_matched_parameters + jmp assembly_line + no_match: + or [assembly_mode],AMODE_SKIP + jmp assembly_line + invalid_match: + mov edx,_invalid_argument + call register_error + or [assembly_mode],AMODE_SKIP + jmp assembly_line + get_pattern_token: + mov ah,[edi] + cmp ah,40h + je skip_pattern_context + retn + skip_pattern_context: + add edi,1+sizeof.RecognitionContext + jmp get_pattern_token + get_matched_token: + cmp ebx,[substitutions_end] + je token_in_line + cmp [substitution_active],0 + jne token_in_substitution + cmp esi,[ebx+SymbolSubstitution.symbol_start] + je substitution_encountered + token_in_line: + cmp esi,[line_end] + je no_more_matched_tokens + check_for_matched_token: + mov al,[esi] + cmp al,40h + je matched_context_change + clc + retn + no_more_matched_tokens: + stc + retn + matched_context_change: + inc esi + cmp [unprocessed_matching],0 + jne matched_context_change_done + mov [matched_context],esi + matched_context_change_done: + add esi,sizeof.RecognitionContext + jmp get_matched_token + substitution_encountered: + mov esi,[ebx+SymbolSubstitution.value_start] + and [matched_context],0 + or [substitution_active],1 + token_in_substitution: + cmp esi,[ebx+SymbolSubstitution.value_end] + jb check_for_matched_token + mov esi,[ebx+SymbolSubstitution.symbol_end] + mov ecx,[ebx+SymbolSubstitution.leftover_context] + mov [matched_context],ecx + add ebx,sizeof.SymbolSubstitution + and [substitution_active],0 + jmp get_matched_token + skip_token: + inc esi + cmp al,1Ah + je skip_token_with_data + cmp al,22h + je skip_token_with_data + cmp al,27h + je skip_token_with_data + cmp al,30h + je skip_internal_token + cmp al,40h + je skip_context_token + retn + skip_token_with_data: + add esi,4 + retn + skip_internal_token: + lodsd + add esi,eax + retn + skip_context_token: + add esi,sizeof.RecognitionContext + retn + copy_matched_token: + mov edx,[matched_context] + cmp edx,[embedded_context] + je matched_context_ok + test edx,edx + jz copy_matched_context + mov eax,[edx] + test eax,eax + jnz copy_matched_context + mov [matched_context],eax + cmp eax,[embedded_context] + je matched_context_ok + mov edx,eax + copy_matched_context: + mov [embedded_context],edx + mov ecx,1+sizeof.RecognitionContext + mov edx,assembly_workspace + call reserve_workspace + mov al,40h + stosb + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + mov edx,[matched_context] + test edx,edx + jz clear_matched_context + xchg esi,edx + rep movsd + mov esi,edx + jmp matched_context_ok + clear_matched_context: + xor eax,eax + rep stosd + matched_context_ok: + mov ecx,1+4 + mov edx,assembly_workspace + call reserve_workspace + lodsb + stosb + cmp al,1Ah + je copy_token_with_data + cmp al,22h + je copy_token_with_data + cmp al,27h + je copy_token_with_data + cmp al,30h + je copy_internal_token + retn + copy_token_with_data: + movsd + retn + copy_internal_token: + mov ecx,[esi] + add ecx,4 + mov edx,assembly_workspace + call reserve_workspace + lodsd + stosd + mov ecx,eax + rep movsb + retn + close_matched_value: + mov eax,[embedded_context] + test eax,eax + jz matched_value_closed + mov ecx,1+sizeof.RecognitionContext + mov edx,assembly_workspace + call reserve_workspace + mov al,40h + stosb + xor eax,eax + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep stosd + matched_value_closed: + retn + +else_raw_match_block: + mov bl,CTRL_RMATCH + jmp begin_else_match_block +else_match_block: + mov bl,CTRL_MATCH + begin_else_match_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + mov al,[edi+DirectiveBlock.flags] + test al,CTRLF_ALLOWS_ELSE + jz unexpected_instruction + mov ah,[assembly_mode] + push eax ebx + call close_control_directive_block + mov dl,DBLOCK_CONTROL + xor ecx,ecx + call add_directive_block + mov [directive_block],edi + pop ebx eax + cmp bl,CTRL_RMATCH + sete [unprocessed_matching] + mov [edi+DirectiveBlock.subtype],bl + or [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE + test al,CTRLF_INACTIVE + jnz skip_conditional_block + test ah,AMODE_SKIP + jnz evaluate_match + jmp skip_conditional_block + +end_raw_match_block: + mov bl,CTRL_RMATCH + jmp close_match_block +end_match_block: + mov bl,CTRL_MATCH + close_match_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + call find_directive_block + jc unexpected_instruction + cmp [edi+DirectiveBlock.subtype],bl + jne unexpected_instruction + call close_control_directive_block + jmp instruction_assembled + +postponed_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + xor ecx,ecx + call add_directive_block + mov [edi+DirectiveBlock.subtype],CTRL_POSTPONE + mov [directive_block],edi + or [assembly_mode],AMODE_SKIP + call get_constituent_value + jc instruction_assembled + cmp al,'?' + jne invalid_argument + mov edi,[directive_block] + or [edi+DirectiveBlock.flags],CTRLF_SUSPENDED + jmp instruction_assembled + +end_postponed_block: + test [assembly_mode],AMODE_DEFINITION + jnz ignored_directive + mov dl,DBLOCK_CONTROL + call find_directive_block + jc end_postponed_execution + cmp [edi+DirectiveBlock.subtype],CTRL_POSTPONE + jne unexpected_instruction + mov al,[edi+DirectiveBlock.prior_assembly_mode] + mov [assembly_mode],al + test al,AMODE_SKIP + jz keep_postponed_block + call close_directive_block + jmp instruction_assembled + keep_postponed_block: + test [edi+DirectiveBlock.flags],CTRLF_SUSPENDED + jnz keep_suspended_block + mov [edi+DirectiveBlock.type],DBLOCK_POSTPONED + jmp instruction_assembled + keep_suspended_block: + mov [edi+DirectiveBlock.type],DBLOCK_SUSPENDED + jmp instruction_assembled + end_postponed_execution: + test [assembly_mode],AMODE_POSTPONED + jz unexpected_instruction + mov eax,[source_context] + mov esi,eax + call release_source_context + and [esi+SourceContext.number_of_entries],0 + jmp pass_done + +define_struc: + mov bl,SYMCLASS_STRUCTURE + jmp begin_macro_definition +define_macro: + mov bl,SYMCLASS_INSTRUCTION + begin_macro_definition: + test [assembly_mode],AMODE_DEFINITION + jnz nested_macro_definition + mov dl,DBLOCK_MACRO + mov ecx,sizeof.MacroData + call add_directive_block + mov [edi+DirectiveBlock.subtype],bl + mov [edi-sizeof.MacroData+MacroData.nesting_counter],1 + xor eax,eax + mov [macro_end_position],eax + mov [macro_definition_active],al + or [assembly_mode],AMODE_DEFINITION + test [assembly_mode],AMODE_SKIP + jnz assembly_line + xor ecx,ecx + call move_to_next_symbol + jc invalid_macro_definition + cmp al,'(' + je macro_with_label_parameter + read_macro_name: + mov dl,bl + call get_macro_definition_symbol + jc invalid_identifier + mov [argument_start],esi + mov eax,[embedded_context] + mov [macro_parameters_context],eax + xor ecx,ecx + call move_to_next_symbol + jc macro_parameters_correct + check_macro_parameters: + cmp al,'&' + jne macro_parameter_prefix_ok + inc esi + call move_to_next_symbol + jc invalid_macro_definition + macro_parameter_prefix_ok: + cmp al,'#' + jne check_parameter_name + call check_concatenation + jnc check_macro_parameters + invalid_macro_definition: + mov edx,_invalid_argument + call register_error + jmp assembly_line + check_parameter_name: + cmp al,'?' + je parameter_starting_question_mark + cmp al,1Ah + jne invalid_macro_definition + call detect_numeric_symbol + jc invalid_macro_definition + parameter_name_token: + inc esi + lodsd + parameter_name_present: + xor ecx,ecx + call move_to_next_symbol + jc macro_parameters_correct + cmp al,'?' + je check_parameter_name_modifier + cmp al,'#' + jne check_parameter_modifiers + call check_concatenation + jnc check_parameter_name_concatenation + call move_to_next_symbol + jc macro_parameters_correct + jmp check_parameter_modifiers + parameter_starting_question_mark: + inc esi + parameter_name_freeform: + call move_to_next_symbol + jc macro_parameters_correct + cmp al,1Ah + je parameter_name_token + cmp al,'#' + je parameter_name_freeform_concatenation + cmp al,30h + jne invalid_macro_definition + parameter_number_token: + inc esi + lodsd + add esi,eax + jmp parameter_name_present + parameter_name_freeform_concatenation: + call check_concatenation + jc invalid_macro_definition + jmp parameter_name_freeform + check_parameter_name_concatenation: + cmp al,1Ah + je parameter_name_token + cmp al,30h + je parameter_number_token + cmp al,'?' + jne check_parameter_modifiers + check_parameter_name_modifier: + inc esi + call move_to_next_symbol + jc macro_parameters_correct + check_parameter_modifiers: + cmp al,':' + je check_default_value + cmp al,'=' + je check_default_value + cmp al,'*' + jne check_next_parameter + inc esi + call move_to_next_symbol + jnc check_next_parameter + jmp macro_parameters_correct + check_default_value: + mov edi,[expression_workspace.memory_start] + inc esi + call move_to_next_symbol + jc check_plain_default_value + cmp al,'<' + je check_enclosed_default_value + check_plain_default_value: + mov dl,',' + xor dh,dh + mov [breakpoint_token],'&' + call cut_piece_of_line + jmp check_next_parameter + check_enclosed_default_value: + inc esi + mov dl,'>' + mov dh,'<' + mov [breakpoint_token],0 + call cut_piece_of_line + cmp al,'>' + jne invalid_macro_definition + inc esi + call move_to_next_symbol + jc macro_parameters_correct + check_next_parameter: + test al,al + jz macro_parameters_correct + inc esi + cmp al,',' + jne check_final_parameter_modifiers + call move_to_next_symbol + jc invalid_macro_definition + jmp check_macro_parameters + check_final_parameter_modifiers: + cmp al,'&' + jne invalid_macro_definition + call move_to_next_symbol + jnc invalid_macro_definition + macro_parameters_correct: + or [macro_definition_active],1 + cmp [macro_parameters_context],0 + je store_macro_header + xor esi,esi + mov ecx,1+sizeof.RecognitionContext + call append_to_macro + mov al,40h + stosb + mov esi,[macro_parameters_context] + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + store_macro_header: + mov esi,[argument_start] + mov ecx,[line_end] + sub ecx,esi + call append_to_macro + call add_line_break_to_macro + jmp instruction_assembled + nested_macro_definition: + mov dl,DBLOCK_MACRO + call find_directive_block + ; jc internal_error + cmp bl,[edi+DirectiveBlock.subtype] + jne add_nested_macro_block + inc [edi-sizeof.MacroData+MacroData.nesting_counter] + jmp add_line_to_macro + add_nested_macro_block: + mov ecx,sizeof.MacroData + call add_directive_block + mov [edi+DirectiveBlock.subtype],bl + mov [edi-sizeof.MacroData+MacroData.nesting_counter],1 + jmp add_line_to_macro + macro_with_label_parameter: + cmp bl,SYMCLASS_STRUCTURE + jne invalid_macro_definition + mov [argument_start],esi + inc esi + xor ecx,ecx + call move_to_next_symbol + jc invalid_macro_definition + cmp al,'&' + jne check_label_parameter_initial_concatenation + inc esi + call move_to_next_symbol + jc invalid_macro_definition + check_label_parameter_initial_concatenation: + cmp al,'#' + jne check_label_parameter_name + call check_concatenation + jnc check_label_parameter_initial_concatenation + jmp invalid_macro_definition + check_label_parameter_name: + cmp al,1Ah + jne invalid_macro_definition + call detect_numeric_symbol + jc invalid_macro_definition + label_parameter_name_present: + inc esi + lodsd + xor ecx,ecx + call move_to_next_symbol + jc invalid_macro_definition + cmp al,'?' + je check_label_parameter_name_modifier + cmp al,'#' + jne label_parameter_name_end + call check_concatenation + jnc check_label_parameter_name_concatenation + call move_to_next_symbol + jc invalid_macro_definition + jmp label_parameter_name_end + check_label_parameter_name_concatenation: + cmp al,1Ah + je label_parameter_name_present + cmp al,'?' + jne label_parameter_name_end + check_label_parameter_name_modifier: + inc esi + call move_to_next_symbol + jc invalid_macro_definition + label_parameter_name_end: + inc esi + cmp al,')' + jne invalid_macro_definition + push esi + or [macro_definition_active],1 + mov ecx,esi + mov esi,[argument_start] + sub ecx,esi + call append_to_macro + and [macro_definition_active],0 + pop esi + xor ecx,ecx + call move_to_next_symbol + jc invalid_macro_definition + jmp read_macro_name + +end_struc: + mov bl,SYMCLASS_STRUCTURE + jmp close_macro_block +end_macro: + mov bl,SYMCLASS_INSTRUCTION + close_macro_block: + mov dl,DBLOCK_MACRO + call find_directive_block + jc unexpected_instruction + cmp bl,[edi+DirectiveBlock.subtype] + je close_macro_definition + ; handle improper nesting, for partial backward-compatibility: + cmp bl,SYMCLASS_INSTRUCTION + jne add_line_to_macro + call close_directive_block + mov dl,DBLOCK_MACRO + call find_directive_block + jc unexpected_instruction + ; cmp [edi+DirectiveBlock.subtype],SYMCLASS_INSTRUCTION + ; jne internal_error + close_macro_definition: + dec [edi-sizeof.MacroData+MacroData.nesting_counter] + jnz add_line_to_macro + mov al,[assembly_mode] + and al,not (AMODE_SKIP or AMODE_DEFINITION) + or al,[edi+DirectiveBlock.prior_assembly_mode] + mov [assembly_mode],al + call close_directive_block + mov al,[assembly_mode] + test al,AMODE_DEFINITION + jne add_line_to_macro + test al,AMODE_SKIP + jnz assembly_line + push esi + cmp [macro_definition_active],0 + je macro_definition_done + mov ebx,[macro_leaf] + call create_value_definition + test edx,edx + jz macro_definition_done + mov [value],eax + mov [value_length],ecx + mov esi,[macro_buffer] + mov ecx,[macro_end_position] + mov [value_type],VALTYPE_SYMBOLIC + call assign_value + mov al,[macro_flags] + or [edx+ValueDefinition.flags],al + macro_definition_done: + pop esi + jmp instruction_assembled + +escape_directive: + mov dl,DBLOCK_MACRO + call find_directive_block + jc unexpected_instruction + cmp [edi-sizeof.MacroData+MacroData.nesting_counter],1 + ja add_line_to_macro + test [edi+DirectiveBlock.prior_assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + cmp [embedded_context],0 + je escape_context_ok + push esi + xor esi,esi + mov ecx,1+sizeof.RecognitionContext + call append_to_macro + mov al,40h + stosb + mov esi,[embedded_context] + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + pop esi + escape_context_ok: + mov ecx,[line_end] + sub ecx,esi + call append_to_macro + call add_line_break_to_macro + jmp assembly_line +add_line_to_macro: + mov esi,[line_start] + mov ecx,[line_end] + sub ecx,esi + call append_to_macro + call add_line_break_to_macro + jmp assembly_line + append_to_macro: + cmp [macro_definition_active],0 + je macro_appended + mov edi,[macro_buffer] + mov eax,[macro_end_position] + add edi,eax + add eax,ecx + mov [macro_end_position],eax + cmp eax,[macro_buffer_length] + jbe macro_block_ready + push ecx + mov ecx,eax + mov eax,[macro_buffer] + sub edi,eax + call realloc + add edi,eax + mov [macro_buffer],eax + mov [macro_buffer_length],ecx + pop ecx + macro_block_ready: + test esi,esi + jz macro_appended + rep movsb + macro_appended: + retn +add_label_to_macro: + mov ecx,esi + xchg esi,[line_start] + sub ecx,esi + call append_to_macro + mov esi,[line_start] + cmp esi,[line_end] + jne assemble_instruction + call add_line_break_to_macro + jmp assemble_instruction +add_line_break_to_macro: + mov eax,[macro_buffer] + mov ecx,[macro_end_position] + cmp ecx,[macro_buffer_length] + jb macro_line_break + add ecx,100h + call realloc + mov [macro_buffer],eax + mov [macro_buffer_length],ecx + mov ecx,[macro_end_position] + macro_line_break: + lea edi,[eax+ecx] + xor al,al + stosb + inc [macro_end_position] + retn + +use_macro: + and [label_branch],0 +use_struc: + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + mov [instruction_value],edx + mov eax,[ebx+SymbolTree_Leaf.branch] + mov [instruction_branch],eax + xor ecx,ecx + call embed_symbolic_value + measure_macro_header: + lodsb + test al,al + jz macro_header_measured + cmp al,1Ah + je measure_token_with_data + cmp al,22h + je measure_token_with_data + cmp al,27h + je measure_token_with_data + cmp al,30h + je measure_internal_token + cmp al,40h + jne measure_macro_header + add esi,sizeof.RecognitionContext + jmp measure_macro_header + measure_token_with_data: + add esi,4 + jmp measure_macro_header + measure_internal_token: + lodsd + add esi,eax + jmp measure_macro_header + macro_header_measured: + mov [instruction_body],esi + dec esi + mov [line_end],esi + mov eax,ebx + mov ecx,[parameter_namespace] + call get_local_anchor + call get_local_namespace + mov [new_local_namespace],ebx + mov eax,[parameter_namespace] + mov [ebx+SymbolTree_Root.chain],eax + mov edx,[instruction_value] + local_namespace_ready: + mov esi,[edx+ValueDefinition.value] + or [symbol_definition],1 + mov ebx,[new_local_namespace] + mov eax,[label_branch] + mov [ebx+SymbolTree_Root.current_label],eax + cmp [label_independent],0 + je struc_label_ok + or [ebx+SymbolTree_Root.flags],NAMESPACE_LABEL_FORWARDING + struc_label_ok: + cmp byte [esi],'(' + jne prepare_macro_parameters + inc esi + call move_to_next_symbol + jc invalid_argument + test [assembly_mode],AMODE_DEFINITION + setnz dl + cmp al,'&' + sete al + jne struc_label_prefix_ok + inc esi + struc_label_prefix_ok: + or al,dl + mov [contextless_processing],al + mov ebx,[new_local_namespace] + mov dl,SYMCLASS_PARAMETER + call identify_symbol_in_namespace + jc invalid_argument + test ebx,ebx + jz invalid_argument + cmp edi,[new_local_namespace] + jne invalid_argument + push esi + push [line_end] + push [embedded_context] + mov eax,[line_context] + mov [embedded_context],eax + mov esi,[line_start] + mov ecx,[label_instruction_start] + mov [line_end],ecx + sub ecx,esi + add ecx,(1+sizeof.RecognitionContext)*2 + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + call reserve_workspace + xor edx,edx + mov [breakpoint_token],dl + call extract_piece_of_line + call finish_extracted_parameter + pop [embedded_context] + pop [line_end] + or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + call update_value_definition + mov [value_type],VALTYPE_SYMBOLIC + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + call assign_value + pop esi + call move_to_next_symbol + jc invalid_argument + cmp al,')' + jne invalid_argument + inc esi + prepare_macro_parameters: + mov edi,[expression_workspace.memory_start] + add edi,sizeof.LineExcerpt + xor eax,eax + mov [macro_greedy],al + mov [number_of_parameters],eax + macro_parameter_declaration: + call move_to_next_symbol + jc macro_parameters_declared + cmp al,'&' + sete al + mov [contextless_processing],al + jne identify_macro_parameter_name + inc esi + identify_macro_parameter_name: + mov ebx,[new_local_namespace] + mov dl,SYMCLASS_PARAMETER + push edi + call identify_symbol_in_namespace + mov eax,edi + pop edi + jc macro_parameters_declared + test ebx,ebx + jz invalid_argument + cmp eax,[new_local_namespace] + jne invalid_argument + mov eax,[number_of_parameters] + shl eax,3 + add eax,[assembly_stack_base] + lea ecx,[eax+8] + cmp ecx,[assembly_stack_end] + jbe store_macro_parameter_leaf + mov eax,[assembly_stack_base] + sub ecx,eax + call grow_stack + mov [assembly_stack_base],eax + add ecx,eax + mov [assembly_stack_end],ecx + mov ecx,[number_of_parameters] + shl ecx,3 + add eax,ecx + store_macro_parameter_leaf: + mov [eax],ebx + mov cl,[contextless_processing] + mov [eax+4],cl + mov edx,expression_workspace + mov ecx,sizeof.LineExcerpt + call reserve_workspace + mov [edi+LineExcerpt.data_start],esi + mov [edi+LineExcerpt.data_end],esi + inc [number_of_parameters] + call move_to_next_symbol + jc macro_parameters_declared + cmp al,':' + je macro_parameter_with_default_value + cmp al,'=' + je macro_parameter_with_default_value + cmp al,'*' + jne next_parameter_declaration + and [edi+LineExcerpt.data_start],0 + inc esi + call move_to_next_symbol + jnc next_parameter_declaration + xor al,al + jmp next_parameter_declaration + macro_parameter_with_default_value: + inc esi + call move_to_next_symbol + jc get_plain_default_value + cmp al,'<' + je get_enclosed_default_value + get_plain_default_value: + mov dl,',' + xor dh,dh + mov [breakpoint_token],'&' + call cut_piece_of_line + jmp next_parameter_declaration + get_enclosed_default_value: + inc esi + mov dl,'>' + mov dh,'<' + mov [breakpoint_token],0 + call cut_piece_of_line + cmp al,'>' + jne invalid_argument + inc esi + call move_to_next_symbol + jc macro_parameters_declared + next_parameter_declaration: + test al,al + jz macro_parameters_declared + inc esi + add edi,sizeof.LineExcerpt + cmp al,',' + je macro_parameter_declaration + cmp al,'&' + jne invalid_argument + or [macro_greedy],1 + call move_to_next_symbol + jnc invalid_argument + macro_parameters_declared: + call warp_to_next_symbol + ; cmp [number_of_line_embeddings],0 + ; jne internal_error + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + mov ecx,[line_end] + sub ecx,esi + add ecx,(1+sizeof.RecognitionContext)*2 + call reserve_workspace + xor eax,eax + mov [breakpoint_token],al + mov [parameter_index],eax + macro_parameter_definition: + mov eax,[number_of_parameters] + sub eax,[parameter_index] + jz macro_parameters_ready + jmp get_macro_parameter + macro_parameter_after_comma: + mov eax,[number_of_parameters] + sub eax,[parameter_index] + jz macro_parameters_ready + inc esi + get_macro_parameter: + mov edi,[assembly_workspace.memory_start] + mov ecx,[parameter_index] + shl ecx,3 + add ecx,[assembly_stack_base] + mov ebx,[ecx] + test [assembly_mode],AMODE_DEFINITION + setnz dl + or dl,[ecx+4] + mov [contextless_processing],dl + cmp [macro_greedy],0 + je standard_parameter_value + cmp eax,1 + ja standard_parameter_value + xor edx,edx + call extract_piece_of_line + jmp parameter_value_ready + standard_parameter_value: + call extract_argument_value + parameter_value_ready: + or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + call update_value_definition + mov [value_type],VALTYPE_SYMBOLIC + cmp edi,[assembly_workspace.memory_start] + je empty_parameter_value + call finish_extracted_parameter + push esi + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + assign_parameter_value: + call assign_value + pop esi + parameter_value_assigned: + inc [parameter_index] + call move_to_next_symbol + jc macro_parameter_definition + cmp al,',' + je macro_parameter_after_comma + macro_parameters_ready: + mov edx,[instruction_value] + mov ecx,[instruction_body] + sub ecx,[edx+ValueDefinition.value] + push ecx + call create_source_entry + pop eax + jc stack_limit_exceeded + mov [ebx+SourceEntry.type],SOURCE_MACRO + mov [ebx+SourceEntry.text],edx + mov [ebx+SourceEntry.offset],eax + or [edx+ValueDefinition.flags],VAL_IN_USE + inc [edx+ValueDefinition.reference_count] + mov eax,[new_local_namespace] + mov [local_namespace],eax + and [eax+SymbolTree_Root.parameters],0 + mov [ebx+SourceEntry.local_namespace],eax + mov ecx,[instruction_branch] + test ecx,ecx + jz instruction_assembled + mov [ebx+SourceEntry.name],ecx + or [ebx+SourceEntry.name_length],-1 + jmp instruction_assembled + stack_limit_exceeded: + mov edx,_stack_limit_exceeded + call register_error + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jz assembly_line + jmp add_line_to_macro + empty_parameter_value: + mov edi,[parameter_index] + inc edi + assert sizeof.LineExcerpt = 1 shl 4 + shl edi,4 + add edi,[expression_workspace.memory_start] + mov eax,[edi+LineExcerpt.data_start] + test eax,eax + jz missing_argument + mov ecx,[edi+LineExcerpt.data_end] + sub ecx,eax + push esi + mov esi,eax + test ecx,ecx + jz assign_parameter_value + push ebx edx + mov ebx,edi + mov edi,[assembly_workspace.memory_start] + add ecx,2*(1+sizeof.RecognitionContext) + mov edx,assembly_workspace + call reserve_workspace + mov al,40h + cmp [ebx+LineExcerpt.recognition_context],0 + je parameter_with_current_context + stosb + mov eax,esi + mov esi,[ebx+LineExcerpt.recognition_context] + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep movsd + mov [context_boundary],edi + mov esi,eax + jmp copy_parameter_contents + parameter_with_current_context: + cmp [contextless_processing],0 + jne copy_parameter_contents + stosb + call store_current_context + copy_parameter_contents: + call store_token + cmp esi,[ebx+LineExcerpt.data_end] + jne copy_parameter_contents + call store_context_reset_token + pop edx ebx + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + jmp assign_parameter_value + finish_extracted_parameter: + test [assembly_mode],AMODE_DEFINITION + jz store_context_reset_token + cmp [embedded_context],0 + jne store_context_reset_token + retn + store_context_reset_token: + cmp edi,[context_boundary] + je context_reset_in_reused_token + mov al,40h + stosb + store_context_reset: + xor eax,eax + assert sizeof.RecognitionContext and 11b = 0 + mov ecx,sizeof.RecognitionContext shr 2 + rep stosd + retn + context_reset_in_reused_token: + sub edi,sizeof.RecognitionContext + jmp store_context_reset + +local_directive: + test [assembly_mode],AMODE_SKIP + jnz assembly_line + test [assembly_mode],AMODE_DEFINITION + jnz add_line_to_macro + mov ebx,[local_namespace] + test ebx,ebx + jz unexpected_instruction + or [symbol_definition],1 + mov dl,SYMCLASS_PARAMETER + call identify_symbol_in_namespace + jc missing_argument + test ebx,ebx + jz invalid_argument + cmp edi,[local_namespace] + jne invalid_argument + or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + call update_value_definition + mov eax,[current_pass] + mov [edx+ValueDefinition.pass],eax + mov [edx+ValueDefinition.type],VALTYPE_NATIVE_COMMAND + mov eax,local_symbol_name + xchg eax,[edx+ValueDefinition.value] + cmp [edx+ValueDefinition.block_length],0 + je next_local_declaration + and [edx+ValueDefinition.block_length],0 + call mfree + next_local_declaration: + call move_to_next_symbol + jc assembly_line + cmp al,',' + jne invalid_argument + inc esi + jmp local_directive +outscope_directive: + test [assembly_mode],AMODE_SKIP + jnz assemble_prefixed_instruction + mov ebx,[source_context] + mov eax,[ebx+SourceContext.number_of_entries] + dec eax + imul eax,sizeof.SourceEntry + lea ebx,[ebx+sizeof.SourceContext+eax] + test [assembly_mode],AMODE_DEFINITION + jnz define_outscope + mov ecx,[ebx+SourceEntry.local_namespace] + test [ecx+SymbolTree_Root.flags],NAMESPACE_UNATTACHED + jnz unexpected_instruction + mov eax,[ecx+SymbolTree_Root.chain] + test eax,eax + jz unexpected_instruction + outscope_namespace_ok: + mov [parameter_namespace],eax + test [eax+SymbolTree_Root.flags],NAMESPACE_UNATTACHED + jz outscope_local_namespace_ok + xor eax,eax + outscope_local_namespace_ok: + mov [local_namespace],eax + assemble_prefixed_instruction: + mov [line_start],esi + mov eax,[embedded_context] + mov [line_context],eax + jmp assemble_instruction + define_outscope: + cmp [ebx+SourceEntry.type],SOURCE_MACRO + je assemble_prefixed_instruction + jmp ignored_directive + +define_data: + and [label_leaf],0 +define_labeled_data: + movzx eax,[edx+ValueDefinition.attribute] + mov [data_unit_length],eax + test eax,eax + jnz data_unit_length_ok + call get_numeric_constant_value + test edx,edx + jz invalid_argument + mov ecx,4 + mov edi,data_unit_length + call fit_value + jc value_out_of_range + js value_out_of_range + cmp [data_unit_length],0 + je value_out_of_range + call get_constituent_value + jc missing_argument + cmp al,':' + je data_unit_length_ok + cmp al,',' + jne invalid_argument + data_unit_length_ok: + cmp [label_leaf],0 + je data_definition + call define_data_label + data_definition: + call peek_at_constituent_value + jc missing_argument + cmp al,'?' + je single_uninitialized_unit + call get_constant_value + cmp al,30h + je numeric_data + cmp al,2Eh + je float_data + cmp al,22h + jne invalid_argument + call output_string + data_outputted: + call get_constituent_value + jc instruction_assembled + cmp al,',' + jne invalid_argument + jmp data_definition + float_data: + push esi + push edx + mov ecx,[data_unit_length] + call initialize_output + pop esi + mov ecx,[data_unit_length] + call fit_float + pop esi + jmp data_outputted + numeric_data: + call keep_value + call peek_at_constituent_value + jc single_data_unit + cmp al,1Ah + jne single_data_unit + test edx,edx + jz single_data_unit + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne single_data_unit + cmp [edx+ValueDefinition.value],PREPOSITION_DUP + je duplication_operator + single_data_unit: + mov ecx,[data_unit_length] + call initialize_output + call get_kept_value + mov ecx,[data_unit_length] + call fit_value + jc value_out_of_range + jmp data_outputted + single_uninitialized_unit: + and [current_constituent],0 + mov ecx,[data_unit_length] + call uninitialized_output + jmp data_outputted + duplication_operator: + call get_kept_value + mov edi,number_of_iterations + mov ecx,4 + call fit_value + jc value_out_of_range + js value_out_of_range + xor eax,eax + mov [current_constituent],al + mov [initial_parentheses],eax + call peek_at_constituent_value + jc invalid_argument + cmp al,'?' + je reserve_through_duplication + mov edi,[expression_workspace.memory_start] + mov [expression_sequence_end],edi + or [leave_opening_parentheses],1 + parse_duplicated_expression: + call parse_expression + add [initial_parentheses],ecx + jecxz duplicated_value_parsed + mov eax,[expression_workspace.memory_start] + mov eax,[eax] + test eax,eax + jnz duplicated_value_parsed + call get_constituent_value + jc invalid_argument + cmp al,'?' + jne invalid_argument + mov edi,[expression_workspace.memory_start] + or eax,-1 + stosd + duplicated_value_parsed: + mov [expression_sequence_end],edi + and [leave_opening_parentheses],0 + cmp [initial_parentheses],1 + jb duplicated_data_parsed + ja invalid_argument + call get_constituent_value + jc missing_closing_parenthesis + cmp al,')' + je duplicated_data_parsed + cmp al,',' + jne invalid_argument + mov edi,[expression_sequence_end] + call peek_at_constituent_value + jc invalid_argument + mov edi,[expression_sequence_end] + cmp al,'?' + jne parse_duplicated_expression + and [current_constituent],0 + mov ecx,4 + mov edx,expression_workspace + call reserve_workspace + or eax,-1 + stosd + jmp duplicated_value_parsed + duplicated_data_parsed: + cmp [number_of_iterations],0 + je data_outputted + duplicated_data: + mov eax,[expression_workspace.memory_start] + mov [expression_sequence_cursor],eax + generate_duplicate: + mov eax,[expression_sequence_cursor] + cmp eax,[expression_sequence_end] + je duplicate_outputted + cmp dword [eax],-1 + je duplicated_uninitialized_unit + push esi + mov esi,eax + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + mov [expression_sequence_cursor],esi + pop esi + jc duplicate_outputted + call pop_terms + jc invalid_argument + call get_calculated_constant_value + cmp al,30h + je duplicated_data_unit + cmp al,2Eh + je duplicated_data_unit + cmp al,22h + jne invalid_argument + call output_string + jmp generate_duplicate + duplicated_data_unit: + push eax edx + mov ecx,[data_unit_length] + call initialize_output + pop edx eax + mov ecx,[data_unit_length] + cmp al,2Eh + je duplicated_float + call fit_value + jc value_out_of_range + jmp generate_duplicate + duplicated_float: + push esi + mov esi,edx + call fit_float + pop esi + jmp generate_duplicate + duplicated_uninitialized_unit: + add eax,4 + mov [expression_sequence_cursor],eax + mov ecx,[data_unit_length] + call uninitialized_output + jmp generate_duplicate + duplicate_outputted: + dec [number_of_iterations] + jnz duplicated_data + jmp data_outputted + reserve_through_duplication: + and [current_constituent],0 + mov eax,[number_of_iterations] + mul [data_unit_length] + test edx,edx + jnz duplication_overflow + mov ecx,eax + call uninitialized_output + jmp data_outputted + duplication_overflow: + mov edx,_area_overflow + call register_error + jmp data_outputted + output_string: + push esi + mov esi,edx + mov ecx,[esi] + call initialize_output + lodsd + mov ecx,eax + rep movsb + pop esi + mov ecx,[data_unit_length] + xor edx,edx + div ecx + test edx,edx + jz string_outputted + sub ecx,edx + push ecx + call initialize_output + pop ecx + xor al,al + rep stosb + string_outputted: + retn + define_data_label: + push esi + call get_current_address_value + lea edi,[esi+ecx] + mov ecx,4+4+4 + mov edx,assembly_workspace + call reserve_workspace + mov edx,[data_unit_length] + bsr eax,edx + inc al + shr al,3 + inc al + stosd + mov [edi],edx + add edi,eax + xor eax,eax + stosd + mov ebx,[label_leaf] + call create_constant_value_definition + test edx,edx + jz data_label_defined + mov ecx,edi + sub ecx,esi + call assign_shiftable_value + data_label_defined: + call update_current_label + pop esi + retn + +reserve_labeled_data: + movzx eax,[edx+ValueDefinition.attribute] + mov [data_unit_length],eax + call define_data_label + jmp data_reservation +reserve_data: + movzx eax,[edx+ValueDefinition.attribute] + mov [data_unit_length],eax + data_reservation: + call get_numeric_constant_value + test edx,edx + jz invalid_argument + mov ecx,4 + mov edi,[assembly_workspace.memory_start] + call fit_value + jc reservation_out_of_range + js reservation_out_of_range + mov eax,[edi] + mul [data_unit_length] + test edx,edx + jnz reservation_overflow + mov ecx,eax + call uninitialized_output + jmp instruction_assembled + reservation_out_of_range: + mov edx,_value_out_of_range + call register_error + jmp instruction_assembled + reservation_overflow: + mov edx,_area_overflow + call register_error + jmp instruction_assembled + +include_labeled_data: + mov [data_unit_length],1 + call define_data_label +include_data: + xor eax,eax + mov [data_offset],eax + mov [data_offset+4],eax + call get_constant_value + cmp al,22h + jne invalid_argument + push esi + call prepare_file_path + pop esi + call get_constituent_value + jc include_all_available_data + cmp al,':' + jne get_data_length + call get_numeric_constant_value + test edx,edx + jz invalid_argument + mov edi,file_offset + mov ecx,8 + call fit_value + jc value_out_of_range + js value_out_of_range + call get_constituent_value + jc include_all_available_data + get_data_length: + cmp al,',' + jne invalid_argument + call get_numeric_constant_value + test edx,edx + jz invalid_argument + mov edi,data_length + mov ecx,4 + call fit_value + jc value_out_of_range + js value_out_of_range + push esi + mov ecx,[data_length] + call initialize_output + mov esi,[assembly_workspace.memory_start] + call get_file_data + test ebx,ebx + jnz read_from_file + mov esi,[local_path] + call get_file_data + test ebx,ebx + jz data_file_not_found + read_from_file: + call read_file_data + jc file_data_not_read + pop esi + jmp instruction_assembled + data_file_not_found: + mov ebx,esi + mov edx,_source_file_not_found + call register_error + pop esi + jmp instruction_assembled + include_all_available_data: + push esi + mov esi,[assembly_workspace.memory_start] + call get_file_data + test ebx,ebx + jnz measure_available_data + mov esi,[local_path] + call get_file_data + test ebx,ebx + jz data_file_not_found + measure_available_data: + mov ecx,dword [ebx+FileData.length] + mov edx,dword [ebx+FileData.length+4] + sub ecx,dword [file_offset] + sbb edx,dword [file_offset+4] + jc file_data_not_read + jnz out_of_memory + mov [data_length],ecx + push ebx + call initialize_output + pop ebx + call read_file_data + jc file_data_not_read + pop esi + jmp instruction_assembled + file_data_not_read: + mov ebx,esi + mov edx,_error_reading_file + call register_error + pop esi + jmp instruction_assembled + +load_value: + or [symbol_definition],1 + mov dl,SYMCLASS_EXPRESSION + call identify_symbol + jc missing_argument + test ebx,ebx + jz invalid_identifier + mov [label_leaf],ebx + mov [size_specified],0 + call peek_at_constituent_value + jc load_syntax_error + cmp al,':' + je size_after_separator + cmp al,1Ah + jne get_load_size + test edx,edx + jz get_load_size + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne get_load_size + cmp [edx+ValueDefinition.value],PREPOSITION_FROM + jne load_syntax_error + and [current_constituent],0 + jmp get_source_address + size_after_separator: + and [current_constituent],0 + get_load_size: + call get_numeric_constant_value + test edx,edx + jz load_syntax_error + or [size_specified],1 + mov edi,value_length + mov ecx,4 + call fit_value + jc value_out_of_range + js value_out_of_range + call get_constituent_value + jc load_syntax_error + cmp al,1Ah + jne load_syntax_error + test edx,edx + jz load_syntax_error + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne load_syntax_error + cmp [edx+ValueDefinition.value],PREPOSITION_FROM + jne load_syntax_error + get_source_address: + call peek_at_constituent_value + jc invalid_argument + cmp al,':' + je load_from_output_offset + mov eax,[current_area] + mov [data_area],eax + and [data_area_symbol],0 + and [leave_opening_parentheses],0 + mov edi,[expression_workspace.memory_start] + call parse_expression + call peek_at_constituent_value + jc source_address_parsed + cmp al,':' + jne source_address_parsed + and [current_constituent],0 + mov edi,[expression_workspace.memory_start] + call get_area_value + jc invalid_area + mov [data_area],edx + mov [data_area_symbol],ebx + mov edi,[expression_workspace.memory_start] + call parse_expression + source_address_parsed: + call calculate_relative_address + jc invalid_argument + mov edi,data_offset + mov ecx,4 + call fit_value + jc data_out_of_area + js data_out_of_area + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + mov eax,[value_length] + stosd + mov ecx,eax + call reserve_workspace + mov edx,[data_area] + call load_from_area + jc loaded_no_value + value_loaded: + mov ebx,[label_leaf] + call update_value_definition + test edx,edx + jz instruction_assembled + push esi + mov esi,[assembly_workspace.memory_start] + mov ecx,[esi] + add ecx,4 + mov [value_type],VALTYPE_STRING + call assign_value + pop esi + jmp instruction_assembled + load_syntax_error: + mov edx,_invalid_argument + jmp error_while_loading + data_out_of_area: + mov edx,_address_out_of_range + error_while_loading: + call register_error + loaded_no_value: + mov edi,[assembly_workspace.memory_start] + xor eax,eax + stosd + jmp value_loaded + calculate_relative_address: + push esi + mov esi,[expression_workspace.memory_start] + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + jc invalid_relative_address + mov ebx,edi + mov edi,[expression_workspace.memory_start] + mov esi,edi + mov eax,EXPR_SYMBOL_VALUE + stosd + mov edx,[data_area] + mov eax,[data_area_symbol] + test eax,eax + jnz data_area_symbol_ok + mov eax,[void_symbol] + mov [eax+SymbolTree_Leaf.definition],edx + data_area_symbol_ok: + stosd + mov eax,edx + stosd + mov eax,EXPR_OPERATOR + stosd + mov eax,extract_first_term_metadata + stosd + mov eax,EXPR_OPERATOR + stosd + mov eax,calculate_sub + stosd + xor eax,eax + stosd + mov edi,ebx + call calculate_parsed_expression + jc invalid_relative_address + call pop_terms + jc invalid_relative_address + cmp [size_specified],0 + jne addressed_length_ok + and [value_length],0 + mov edx,[edi+ExpressionTerm.metadata] + test edx,edx + jz addressed_length_ok + cmp dword [edx],0 + jne addressed_length_ok + add edx,4 + mov esi,edi + mov ecx,4 + mov edi,value_length + call fit_value + jc invalid_relative_address + js invalid_relative_address + mov ecx,[edx] + cmp dword [edx+4+ecx],0 + jne invalid_relative_address + mov edi,esi + addressed_length_ok: + pop esi + mov eax,edi + check_for_uncanceled_terms: + add eax,sizeof.ExpressionTerm + cmp [eax+ExpressionTerm.attributes],0 + je relative_address_ok + cmp [eax+ExpressionTerm.metadata],0 + je check_for_uncanceled_terms + mov edx,_address_out_of_range + call register_error + relative_address_ok: + call get_term_value + clc + retn + invalid_relative_address: + pop esi + stc + retn + load_from_output_offset: + call read_output_offset + jc value_out_of_range + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + mov eax,[value_length] + stosd + mov ecx,eax + call reserve_workspace + push esi + call read_from_output + pop esi + cmp [value_length],0 + jne data_out_of_area + jmp value_loaded + read_output_offset: + and [current_constituent],0 + call get_numeric_constant_value + test edx,edx + jz output_offset_out_of_range + push edi + mov edi,file_offset + mov ecx,8 + call fit_value + pop edi + jc output_offset_out_of_range + js output_offset_out_of_range + cmp [size_specified],0 + jne output_offset_ok + and [value_length],0 + mov edx,[edi+ExpressionTerm.metadata] + test edx,edx + jz output_offset_ok + cmp dword [edx],0 + jne output_offset_ok + add edx,4 + mov ecx,4 + mov edi,value_length + call fit_value + jc output_offset_out_of_range + js output_offset_out_of_range + output_offset_ok: + clc + retn + output_offset_out_of_range: + stc + retn + +store_value: + mov [size_specified],0 + call get_constant_value + cmp al,22h + je store_string_value + cmp al,30h + jne invalid_argument + call keep_value + call peek_at_constituent_value + jc invalid_argument + cmp al,':' + je size_after_value + cmp al,1Ah + jne size_before_value + test edx,edx + jz invalid_argument + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + je get_destination_address + size_before_value: + or [size_specified],1 + call get_kept_value + mov edi,value_length + mov ecx,4 + call fit_value + jc value_out_of_range + js value_out_of_range + call get_constant_value + cmp al,22h + je value_after_size_ok + cmp al,30h + jne invalid_argument + value_after_size_ok: + call keep_value + jmp value_with_size_ready + store_string_value: + mov eax,[edx] + mov [value_length],eax + call keep_value + call peek_at_constituent_value + jc invalid_argument + cmp al,':' + jne check_symbol_after_value_with_size + size_after_value: + and [current_constituent],0 + call get_constant_value + cmp al,30h + jne invalid_argument + or [size_specified],1 + mov edi,value_length + mov ecx,4 + call fit_value + jc value_out_of_range + js value_out_of_range + value_with_size_ready: + call peek_at_constituent_value + jc invalid_argument + check_symbol_after_value_with_size: + cmp al,1Ah + jne invalid_argument + test edx,edx + jz invalid_argument + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne invalid_argument + get_destination_address: + cmp [edx+ValueDefinition.value],PREPOSITION_AT + jne invalid_argument + and [current_constituent],0 + call peek_at_constituent_value + jc invalid_argument + cmp al,':' + je store_at_output_offset + mov eax,[current_area] + mov [data_area],eax + and [data_area_symbol],0 + and [leave_opening_parentheses],0 + mov edi,[expression_workspace.memory_start] + call parse_expression + call peek_at_constituent_value + jc destination_address_parsed + cmp al,':' + jne destination_address_parsed + and [current_constituent],0 + mov edi,[expression_workspace.memory_start] + call get_area_value + jc invalid_area + mov ecx,[current_pass] + cmp [edx+ValueDefinition.pass],ecx + jne invalid_area + mov [data_area],edx + mov [data_area_symbol],ebx + mov edi,[expression_workspace.memory_start] + call parse_expression + destination_address_parsed: + call calculate_relative_address + jc invalid_argument + mov edi,data_offset + mov ecx,4 + call fit_value + jc store_out_of_area + js store_out_of_area + call prepare_area_to_write + call get_kept_value + call fit_value + jc value_out_of_range + jmp instruction_assembled + store_out_of_area: + mov edx,_address_out_of_range + call register_error + jmp instruction_assembled + store_at_output_offset: + call read_output_offset + jc value_out_of_range + mov ecx,[value_length] + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + call reserve_workspace + call get_kept_value + mov ecx,[value_length] + call fit_value + jc value_out_of_range + push esi + mov esi,[assembly_workspace.memory_start] + call rewrite_output + pop esi + cmp [value_length],0 + jne store_out_of_area + jmp instruction_assembled + +display_data: + call get_constant_value + cmp al,30h + je display_character_data + cmp al,22h + jne invalid_argument + call display_string_data + display_next_value: + call get_constituent_value + jc assembly_line + cmp al,',' + jne invalid_argument + jmp display_data + display_character_data: + call display_single_byte_data + jmp display_next_value + +format_directive: + mov edx,[ebx+SymbolTree_Leaf.branch] + call get_symbol_namespace + and [symbol_definition],0 + mov dl,SYMCLASS_INSTRUCTION + call identify_symbol_in_namespace + jc invalid_argument + test ebx,ebx + jz invalid_argument + mov al,[ebx+SymbolTree_Leaf.class] + cmp al,SYMCLASS_INSTRUCTION + jne invalid_argument + call get_available_value + jc invalid_argument + jmp prefixed_directive +format_binary: + call get_constituent_value + jc instruction_assembled + cmp al,1Ah + jne invalid_argument + test edx,edx + jz invalid_argument + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION + jne invalid_argument + cmp [edx+ValueDefinition.value],PREPOSITION_AS + jne invalid_argument + cmp [output_extension],0 + jne repeated_declaration + call get_constant_value + cmp al,22h + jne invalid_argument + mov edi,esi + mov ecx,[edx] + lea esi,[edx+4] + mov [output_extension_length],ecx + mov ebx,[auxiliary_output_areas] + call get_from_map + jnc extension_stored + xor eax,eax + mov ecx,[output_extension_length] + call put_into_map + extension_stored: + mov [output_extension],esi + validate_extension: + mov ebx,characters + scan_extension: + test ecx,ecx + jz extension_valid + lodsb + xlatb + test al,al + jz invalid_argument + dec ecx + jmp scan_extension + extension_valid: + mov esi,edi + jmp instruction_assembled + +custom_error: + mov edi,[assembly_workspace.memory_start] + add edi,4 + create_custom_error_message: + push edi + call get_constant_value + pop edi + cmp al,30h + je attach_byte_to_error_message + cmp al,22h + jne invalid_argument + mov ebx,edx + mov ecx,[edx] + mov edx,assembly_workspace + call reserve_workspace + mov edx,esi + lea esi,[ebx+4] + mov ecx,[ebx] + rep movsb + mov esi,edx + jmp collect_next_part_of_message + attach_byte_to_error_message: + mov ebx,edx + mov ecx,1 + mov edx,assembly_workspace + call reserve_workspace + mov edx,ebx + mov ecx,1 + call fit_value + jc value_out_of_range + inc edi + collect_next_part_of_message: + push edi + call get_constituent_value + pop edi + jc custom_error_message_ready + cmp al,',' + jne invalid_argument + jmp create_custom_error_message + custom_error_message_ready: + mov edx,[assembly_workspace.memory_start] + sub edi,edx + sub edi,4 + mov [edx],edi + call register_volatile_error + test edx,edx + jz instruction_assembled + or [edx+Error.flags],ERR_CUSTOM + jmp instruction_assembled + +choose_to_remove_comments: + and [preprocessing_mode],not PMODE_RETAIN_COMMENTS + jmp instruction_assembled +choose_to_retain_comments: + or [preprocessing_mode],PMODE_RETAIN_COMMENTS + jmp instruction_assembled +choose_to_combine_lines: + and [preprocessing_mode],not PMODE_ISOLATE_LINES + jmp instruction_assembled +choose_to_isolate_lines: + or [preprocessing_mode],PMODE_ISOLATE_LINES + jmp instruction_assembled + +missing_argument: + mov edx,_missing_argument + call register_error + jmp assembly_line + +invalid_argument: + mov edx,_invalid_argument + call register_error + jmp assembly_line + +invalid_identifier: + mov edx,_invalid_identifier + call register_error + jmp assembly_line + +value_out_of_range: + mov edx,_value_out_of_range + call register_error + jmp assembly_line + +missing_closing_parenthesis: + mov edx,_missing_closing_parenthesis + call register_error + jmp assembly_line + +unexpected_instruction: + mov edx,_unexpected_instruction + call register_error + jmp assembly_line + +repeated_declaration: + mov edx,_repeated_declaration + call register_error + jmp assembly_line diff --git a/toolchain/fasm2/source/dos/fasmg.asm b/toolchain/fasm2/source/dos/fasmg.asm new file mode 100644 index 0000000..2b56d3b --- /dev/null +++ b/toolchain/fasm2/source/dos/fasmg.asm @@ -0,0 +1,643 @@ + +include 'macro/struct.inc' + +include '../version.inc' + +BUFFER_SIZE = 4000h +STACK_SIZE = 4000h + + format MZ + heap 0 + stack stack_segment:stack_top-stack_bottom + entry loader:startup + + use i386 + +segment loader use16 + + startup: + + mov ax,1687h + int 2Fh + or ax,ax ; DPMI installed? + jnz short no_dpmi + test bl,1 ; 32-bit programs supported? + jz short no_dpmi + mov word [cs:mode_switch],di + mov word [cs:mode_switch+2],es + mov bx,si ; allocate memory for DPMI data + mov ah,48h + int 21h + jnc switch_to_protected_mode + init_failed: + call startup_error + db 'DPMI initialization failed.',0Dh,0Ah,0 + no_dpmi: + call startup_error + db '32-bit DPMI services are not available.',0Dh,0Ah,0 + startup_error: + pop si + push cs + pop ds + show_message: + lodsb + test al,al + jz message_shown + mov dl,al + mov ah,2 + int 21h + jmp show_message + message_shown: + mov ax,4CFFh + int 21h + switch_to_protected_mode: + mov es,ax + mov ds,[ds:2Ch] + mov ax,1 + call far [cs:mode_switch] ; switch to protected mode + jc init_failed + mov cx,1 + xor ax,ax + int 31h ; allocate descriptor for code + jc init_failed + mov si,ax + xor ax,ax + int 31h ; allocate descriptor for data + jc init_failed + mov di,ax + mov dx,cs + lar cx,dx + shr cx,8 + or cx,0C000h + mov bx,si + mov ax,9 + int 31h ; set code descriptor access rights + jc init_failed + mov dx,ds + lar cx,dx + shr cx,8 + or cx,0C000h + mov bx,di + int 31h ; set data descriptor access rights + jc init_failed + mov ecx,main + shl ecx,4 + mov dx,cx + shr ecx,16 + mov ax,7 + int 31h ; set data descriptor base address + jc init_failed + mov bx,si + int 31h ; set code descriptor base address + jc init_failed + mov cx,0FFFFh + mov dx,0FFFFh + mov ax,8 ; set segment limit to 4 GB + int 31h + jc init_failed + mov bx,di + int 31h + jc init_failed + mov ax,ds + mov ds,di + mov [main_selector],di + mov [psp_selector],es + mov gs,ax ; environment selector in GS + cli + mov ss,di + mov esp,stack_top + sti + mov es,di + mov cx,1 + xor ax,ax + int 31h ; allocate descriptor for BIOS data segment + jc init_failed + mov bx,ax + mov ax,gs + lar cx,ax + shr cx,8 + mov ax,9 + int 31h ; set descriptor access rights + jc init_failed + xor cx,cx + mov dx,400h + mov ax,7 + int 31h ; set base address of BIOS data segment + jc init_failed + xor cx,cx + mov dx,0FFh + mov ax,8 + int 31h ; set limit of BIOS data segment + jc init_failed + mov fs,bx ; BIOS data selector in FS + push si + push start + retf + + mode_switch dd ? + +segment main use32 + + start: + + call system_init + + call get_arguments + mov bl,al + cmp [no_logo],0 + jne logo_ok + mov esi,_logo + xor ecx,ecx + call display_string + logo_ok: + test bl,bl + jnz display_usage_information + + xor al,al + mov ecx,[verbosity_level] + jecxz init + or al,TRACE_ERROR_STACK + dec ecx + jz init + or al,TRACE_DISPLAY + init: + + call assembly_init + + mov eax,[fs:6Ch] + mov [timer],eax + + assemble: + mov esi,[initial_commands] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,_code_cannot_be_generated + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + jmp assembly_failed + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + cmp [no_logo],0 + jne summary_done + mov eax,[current_pass] + xor edx,edx + call itoa + call display_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_string + mov eax,[fs:6Ch] + sub eax,[timer] + mov ecx,36000 + mul ecx + shrd eax,edx,16 + shr edx,16 + mov ecx,10 + div ecx + mov [timer],edx + or edx,eax + jz display_output_length + xor edx,edx + call itoa + call display_string + mov esi,_message_suffix + mov ecx,1 + call display_string + mov eax,[timer] + xor edx,edx + call itoa + call display_string + mov esi,_seconds + xor ecx,ecx + call display_string + display_output_length: + call get_output_length + push eax edx + call itoa + call display_string + pop edx eax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_string + mov esi,_new_line + xor ecx,ecx + call display_string + summary_done: + + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + call assembly_shutdown + call system_shutdown + + mov ax,4C00h + int 21h + + assembly_failed: + + call show_errors + + call assembly_shutdown + call system_shutdown + + mov ax,4C02h + int 21h + + write_failed: + mov ebx,_write_failed + jmp fatal_error + + out_of_memory: + mov ebx,_out_of_memory + jmp fatal_error + + fatal_error: + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + call assembly_shutdown + call system_shutdown + + mov ax,4C03h + int 21h + + display_usage_information: + + mov esi,_usage + xor ecx,ecx + call display_string + + call system_shutdown + + mov ax,4C01h + int 21h + + get_arguments: + push ds + mov ds,[psp_selector] + mov esi,81h + mov edi,command_line + mov ecx,7Fh + move_command_line: + lodsb + cmp al,0Dh + je command_line_moved + stosb + loop move_command_line + command_line_moved: + pop ds + xor eax,eax + stosb + mov [initial_commands],eax + mov [source_path],eax + mov [output_path],eax + mov [no_logo],al + mov [verbosity_level],eax + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1 + mov [maximum_depth_of_stack],10000 + mov esi,command_line + mov edi,parameters + get_argument: + xor ah,ah + read_character: + lodsb + test al,al + jz no_more_arguments + cmp al,22h + je switch_quote + cmp ax,20h + je end_argument + stosb + jmp read_character + end_argument: + xor al,al + stosb + find_next_argument: + mov al,[esi] + test al,al + jz no_more_arguments + cmp al,20h + jne next_argument_found + inc esi + jmp find_next_argument + switch_quote: + xor ah,1 + jmp read_character + next_argument_found: + cmp al,'-' + je get_option + cmp al,'/' + je get_option + cmp [source_path],0 + je get_source_path + cmp [output_path],0 + je get_output_path + error_in_arguments: + or al,-1 + retn + get_source_path: + mov [source_path],edi + jmp get_argument + get_output_path: + mov [output_path],edi + jmp get_argument + no_more_arguments: + cmp [source_path],0 + je error_in_arguments + xor al,al + stosb + retn + get_option: + inc esi + lodsb + cmp al,'e' + je set_errors_limit + cmp al,'E' + je set_errors_limit + cmp al,'i' + je insert_initial_command + cmp al,'I' + je insert_initial_command + cmp al,'p' + je set_passes_limit + cmp al,'P' + je set_passes_limit + cmp al,'r' + je set_recursion_limit + cmp al,'R' + je set_recursion_limit + cmp al,'v' + je set_verbose_mode + cmp al,'V' + je set_verbose_mode + cmp al,'n' + je set_no_logo + cmp al,'N' + jne error_in_arguments + set_no_logo: + or [no_logo],-1 + mov al,[esi] + cmp al,20h + je find_next_argument + test al,al + jnz error_in_arguments + jmp find_next_argument + set_verbose_mode: + call get_option_value + jc error_in_arguments + cmp edx,2 + ja error_in_arguments + mov [verbosity_level],edx + jmp find_next_argument + set_errors_limit: + call get_option_value + jc error_in_arguments + test edx,edx + jz error_in_arguments + mov [maximum_number_of_errors],edx + jmp find_next_argument + set_recursion_limit: + call get_option_value + jc error_in_arguments + test edx,edx + jz error_in_arguments + mov [maximum_depth_of_stack],edx + jmp find_next_argument + set_passes_limit: + call get_option_value + jc error_in_arguments + test edx,edx + jz error_in_arguments + mov [maximum_number_of_passes],edx + jmp find_next_argument + get_option_value: + xor eax,eax + mov edx,eax + find_option_value: + cmp byte [esi],20h + jne get_option_digit + inc esi + jmp find_option_value + get_option_digit: + lodsb + cmp al,20h + je option_value_ok + test al,al + jz option_value_ok + sub al,30h + jc invalid_option_value + cmp al,9 + ja invalid_option_value + imul edx,10 + jo invalid_option_value + add edx,eax + jc invalid_option_value + jmp get_option_digit + option_value_ok: + dec esi + clc + ret + invalid_option_value: + stc + ret + insert_initial_command: + push edi + find_command_segment: + cmp byte [esi],20h + jne command_segment_found + inc esi + jmp find_command_segment + command_segment_found: + xor ah,ah + cmp byte [esi],22h + jne measure_command_segment + inc esi + inc ah + measure_command_segment: + mov ebx,esi + scan_command_segment: + mov ecx,esi + mov al,[esi] + test al,al + jz command_segment_measured + cmp ax,20h + je command_segment_measured + cmp ax,22h + je command_segment_measured + inc esi + cmp al,22h + jne scan_command_segment + command_segment_measured: + sub ecx,ebx + mov edi,[initial_commands] + lea eax,[ecx+2] + test edi,edi + jz allocate_initial_commands_buffer + mov edx,[initial_commands_length] + add edi,edx + add eax,edx + cmp eax,[initial_commands_maximum_length] + ja grow_initial_commands_buffer + copy_initial_command: + xchg esi,ebx + rep movsb + mov esi,ebx + sub edi,[initial_commands] + mov [initial_commands_length],edi + mov al,[esi] + test al,al + jz initial_command_ready + cmp al,20h + jne command_segment_found + initial_command_ready: + mov edi,[initial_commands] + add edi,[initial_commands_length] + mov ax,0Ah + stosw + inc [initial_commands_length] + pop edi + jmp find_next_argument + allocate_initial_commands_buffer: + push ecx + mov ecx,eax + call malloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + pop ecx + jmp copy_initial_command + grow_initial_commands_buffer: + push ecx + mov ecx,eax + mov eax,[initial_commands] + call realloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + add edi,[initial_commands_length] + pop ecx + jmp copy_initial_command + + include 'system.inc' + + include '../malloc.inc' + include '../assembler.inc' + include '../symbols.inc' + include '../expressions.inc' + include '../conditions.inc' + include '../floats.inc' + include '../directives.inc' + include '../calm.inc' + include '../errors.inc' + include '../map.inc' + include '../reader.inc' + include '../output.inc' + include '../console.inc' + + _logo db 'flat assembler version g.',VERSION,13,10,0 + + _usage db 'Usage: fasmg source [output]',13,10 + db 'Optional settings:',13,10 + db ' -e limit Set the maximum number of displayed errors (default 1)',13,10 + db ' -p limit Set the maximum allowed number of passes (default 100)',13,10 + db ' -r limit Set the maximum depth of the stack (default 10000)',13,10 + db ' -v flag Enable or disable showing all lines from the stack (default 0)',13,10 + db ' -i command Insert instruction at the beginning of source',13,10 + db ' -n Do not show logo nor summary',13,10 + db 0 + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'failed to write the output file',0 + _out_of_memory db 'not enough memory to complete the assembly',0 + _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 + + include '../tables.inc' + include '../messages.inc' + + align 4 + + include '../variables.inc' + + psp_selector dw ? + main_selector dw ? + + malloc_freelist dd ? + + source_path dd ? + output_path dd ? + maximum_number_of_passes dd ? + + initial_commands dd ? + initial_commands_length dd ? + initial_commands_maximum_length dd ? + + timestamp dq ? + + timer dd ? + verbosity_level dd ? + no_logo db ? + + command_line db 80h dup ? + parameters db 80h dup ? + +segment buffer_segment + + buffer = (buffer_segment-main) shl 4 + + db BUFFER_SIZE dup ? + +segment stack_segment + + stack_bottom = (stack_segment-main) shl 4 + + db STACK_SIZE dup ? + + stack_top = stack_bottom + $ diff --git a/toolchain/fasm2/source/dos/system.inc b/toolchain/fasm2/source/dos/system.inc new file mode 100644 index 0000000..12d9374 --- /dev/null +++ b/toolchain/fasm2/source/dos/system.inc @@ -0,0 +1,415 @@ + +LINE_FEED equ 13,10 + +system_init: + cld + mov [malloc_freelist],0 + mov ah,2Ah + int 21h + push dx cx + movzx ecx,cx + mov eax,ecx + sub eax,1970 + mov ebx,365 + mul ebx + mov ebp,eax + mov eax,ecx + sub eax,1969 + shr eax,2 + add ebp,eax + mov eax,ecx + sub eax,1901 + mov ebx,100 + div ebx + sub ebp,eax + mov eax,ecx + xor edx,edx + sub eax,1601 + mov ebx,400 + div ebx + add ebp,eax + movzx ecx,byte [esp+3] + mov eax,ecx + dec eax + mov ebx,30 + mul ebx + add ebp,eax + cmp ecx,8 + jbe months_correction + mov eax,ecx + sub eax,7 + shr eax,1 + add ebp,eax + mov ecx,8 + months_correction: + mov eax,ecx + shr eax,1 + add ebp,eax + cmp ecx,2 + pop cx + jbe day_correction_ok + sub ebp,2 + test ecx,11b + jnz day_correction_ok + xor edx,edx + mov eax,ecx + mov ebx,100 + div ebx + or edx,edx + jnz day_correction + mov eax,ecx + mov ebx,400 + div ebx + or edx,edx + jnz day_correction_ok + day_correction: + inc ebp + day_correction_ok: + pop dx + movzx eax,dl + dec eax + add eax,ebp + mov ebx,24 + mul ebx + push eax + mov ah,2Ch + int 21h + pop eax + push dx + movzx ebx,ch + add eax,ebx + mov ebx,60 + mul ebx + movzx ebx,cl + add eax,ebx + mov ebx,60 + mul ebx + pop bx + movzx ebx,bh + add eax,ebx + adc edx,0 + mov dword [timestamp],eax + mov dword [timestamp+4],edx + retn + +system_shutdown: + ; call mcheck + retn + +dos_int: + push 0 + push 0 + push 0 + pushw buffer_segment + pushw buffer_segment + stc + pushfw + push eax + push ecx + push edx + push ebx + push 0 + push ebp + push esi + push edi + mov ax,300h + mov bx,21h + xor cx,cx + mov edi,esp + push es ss + pop es + int 31h + pop es + mov edi,[esp] + mov esi,[esp+4] + mov ebp,[esp+8] + mov ebx,[esp+10h] + mov edx,[esp+14h] + mov ecx,[esp+18h] + mov ah,[esp+20h] + sahf + mov eax,[esp+1Ch] + lea esp,[esp+32h] + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push esi edi + call adapt_path + mov ax,716Ch + mov bx,100000b + mov dx,1 + xor cx,cx + xor si,si + call dos_int + jnc open_done + cmp ax,7100h + je old_open + stc + jmp open_done + old_open: + mov ax,3D00h + xor dx,dx + call dos_int + open_done: + mov bx,ax + pop edi esi + retn + adapt_path: + mov esi,edx + mov edi,buffer + copy_path: + lodsb + cmp al,'/' + jne path_char_ok + mov al,'\' + path_char_ok: + stosb + cmp edi,buffer+BUFFER_SIZE + jae out_of_memory + test al,al + jnz copy_path + retn + +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push esi edi + call adapt_path + mov ax,716Ch + mov bx,100001b + mov dx,10010b + xor cx,cx + xor si,si + xor di,di + call dos_int + jnc create_done + cmp ax,7100h + je old_create + stc + jmp create_done + old_create: + mov ah,3Ch + xor cx,cx + xor dx,dx + call dos_int + create_done: + mov bx,ax + pop edi esi + retn + +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push esi edi ebp + mov ebp,ecx + mov esi,edx + write_loop: + mov ecx,BUFFER_SIZE + sub ebp,BUFFER_SIZE + jnc do_write + add ebp,BUFFER_SIZE + mov ecx,ebp + xor ebp,ebp + do_write: + push ecx + mov edi,buffer + rep movsb + pop ecx + mov ah,40h + xor dx,dx + call dos_int + or ebp,ebp + jnz write_loop + pop ebp edi esi + ret + +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push esi edi ebp + mov ebp,ecx + mov edi,edx + read_loop: + mov ecx,BUFFER_SIZE + sub ebp,BUFFER_SIZE + jnc do_read + add ebp,BUFFER_SIZE + mov ecx,ebp + xor ebp,ebp + do_read: + push ecx + mov ah,3Fh + xor dx,dx + call dos_int + cmp ax,cx + jne read_eof + mov esi,buffer + pop ecx + rep movsb + or ebp,ebp + jnz read_loop + read_done: + pop ebp edi esi + ret + read_eof: + pop ecx + stc + jmp read_done + +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + mov ah,3Eh + int 21h + ret + +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + mov dx,ax + xchg ecx,eax + shr ecx,16 + mov ah,42h + int 21h + pushf + shl edx,16 + popf + mov dx,ax + mov eax,edx + xor edx,edx + ret + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx + mov ebx,1 + jmp write_string +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx + mov ebx,2 + write_string: + test ecx,ecx + jnz string_length_ok + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + string_length_ok: + mov edx,esi + call write + pop ebx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push ebx esi edi + mov ebx,esi + xor esi,esi + compare_variable_names: + mov edx,ebx + compare_name_character: + lods byte [gs:esi] + mov ah,[edx] + inc edx + cmp al,'=' + je end_of_variable_name + test ah,ah + jz next_variable + sub ah,al + jz compare_name_character + cmp ah,20h + jne next_variable + cmp al,41h + jb next_variable + cmp al,5Ah + jna compare_name_character + next_variable: + lods byte [gs:esi] + test al,al + jnz next_variable + cmp byte [gs:esi],0 + jne compare_variable_names + mov ah,al + end_of_variable_name: + test ah,ah + jnz next_variable + add ecx,edi + mov edx,esi + copy_variable_value: + lods byte [gs:esi] + cmp edi,ecx + jae variable_value_next_character + stosb + variable_value_next_character: + or al,al + jnz copy_variable_value + lea eax,[esi-1] + sub eax,edx + pop edi esi ebx + ret + +VALLOC_MIN = 40000h + +valloc: +; in: ecx = requested minimum size +; out: eax - allocated block, ecx = allocated size, zero if failed +; preserves: ebx, esi, edi + cmp ecx,VALLOC_MIN + jbe valloc_size_minimum + dec ecx + and ecx,(-1) shl 12 + add ecx,1 shl 12 + jmp valloc_size_ready + valloc_size_minimum: + mov ecx,VALLOC_MIN + valloc_size_ready: + push ebx esi edi + push ecx + mov ebx,ecx + shr ebx,16 + mov ax,501h + int 31h + movzx eax,cx + pop ecx + jc valloc_failed + shl ebx,16 + or eax,ebx + mov edx,main + shl edx,4 + sub eax,edx + pop edi esi ebx + ret + valloc_failed: + xor ecx,ecx + pop edi esi ebx + retn diff --git a/toolchain/fasm2/source/errors.inc b/toolchain/fasm2/source/errors.inc new file mode 100644 index 0000000..daafd17 --- /dev/null +++ b/toolchain/fasm2/source/errors.inc @@ -0,0 +1,177 @@ + +struct Error + flags dd ? ; ERR_# + message dd ? + symbol dd ? + preprocessed_data dd ? + preprocessed_length dd ? + next dd ? ; pointer to another Error + ; source SourceContext +ends + +ERR_CUSTOM = 1 + +register_volatile_error: +; in: +; edx - 32-bit length followed by string data +; ebx - data for message formatting (only relevant for non-custom messages that contain % character) +; out: +; edx - Error +; preserves: eax, ebx, ecx, esi, edi + cmp [next_pass_needed],0 + jne error_ignored + push eax ebx ecx esi edi + or [message_volatile],1 + jmp get_error_line +register_delayed_error: +; in: +; edx - error message +; esi - SourceContext +; ebx - data for message formatting (only relevant for non-custom messages that contain % character) +; out: +; edx - Error +; preserves: eax, ebx, ecx, esi, edi + cmp [next_pass_needed],0 + jne error_ignored + push eax ebx ecx esi edi + and [message_volatile],0 + and [error_line_start],0 + and [error_line_end],0 + jmp add_error +register_error: +; in: +; edx - error message +; ebx - data for message formatting (only relevant for non-custom messages that contain % character) +; out: +; edx - Error, null when error was not registered +; preserves: eax, ebx, ecx, esi, edi + cmp [next_pass_needed],0 + jne error_ignored + push eax ebx ecx esi edi + and [message_volatile],0 + get_error_line: + mov eax,[line_start] + mov [error_line_start],eax + mov ecx,[line_end] + cmp [number_of_line_embeddings],0 + je error_line_end_ok + mov eax,[line_embeddings] + mov ecx,[eax+LineEmbedding.previous_end] + error_line_end_ok: + mov [error_line_end],ecx + xor esi,esi + add_error: + mov [error_symbol],ebx + lea ebx,[first_error] + xor ecx,ecx + find_last_error: + mov eax,[ebx] + test eax,eax + jz last_error_found + lea ebx,[eax+Error.next] + inc ecx + cmp ecx,[maximum_number_of_errors] + jb find_last_error + pop edi esi ecx ebx eax + xor edx,edx + retn + last_error_found: + cmp [message_volatile],0 + jne prepare_volatile_error + test esi,esi + jnz prepare_error + mov esi,[source_context] + prepare_error: + mov ecx,[esi+SourceContext.number_of_entries] + imul ecx,sizeof.SourceEntry + add ecx,sizeof.SourceContext + cmp [esi+ecx-sizeof.SourceEntry+SourceEntry.type],SOURCE_CALM + jne error_source_context_ready + mov eax,[calm_instruction_number] + mov [esi+ecx-sizeof.SourceEntry+SourceEntry.line_number],eax + and [error_line_start],0 + and [error_line_end],0 + error_source_context_ready: + add ecx,sizeof.Error + add ecx,[error_line_end] + sub ecx,[error_line_start] + mov edi,edx + call malloc + mov [ebx],eax + mov [eax+Error.message],edi + mov ecx,[error_symbol] + mov [eax+Error.symbol],ecx + xor ecx,ecx + mov [eax+Error.flags],ecx + mov [eax+Error.next],ecx + lea edi,[eax+sizeof.Error] + push eax + call clone_source_context + pop edx + store_preprocessed_data: + mov [edx+Error.preprocessed_data],edi + mov esi,[error_line_start] + mov ecx,[error_line_end] + sub ecx,esi + mov [edx+Error.preprocessed_length],ecx + rep movsb + pop edi esi ecx ebx eax + retn + error_ignored: + xor edx,edx + retn + prepare_volatile_error: + mov esi,edx + mov eax,[source_context] + mov ecx,[eax+SourceContext.number_of_entries] + imul ecx,sizeof.SourceEntry + add ecx,sizeof.SourceContext + cmp [eax+ecx-sizeof.SourceEntry+SourceEntry.type],SOURCE_CALM + jne volatile_error_source_context_ready + mov edx,[calm_instruction_number] + mov [eax+ecx-sizeof.SourceEntry+SourceEntry.line_number],edx + and [error_line_start],0 + and [error_line_end],0 + volatile_error_source_context_ready: + add ecx,sizeof.Error + add ecx,[error_line_end] + sub ecx,[error_line_start] + mov edi,ecx + add ecx,[esi] + inc ecx + call malloc + add edi,eax + mov [ebx],eax + mov edx,eax + mov [edx+Error.message],edi + xor eax,eax + mov [edx+Error.next],eax + mov [edx+Error.flags],eax + lodsd + mov ecx,eax + rep movsb + xor al,al + stosb + mov esi,[source_context] + lea edi,[edx+sizeof.Error] + push edx + call clone_source_context + pop edx + jmp store_preprocessed_data + +discard_errors: + mov eax,[first_error] + test eax,eax + jnz discard_error + retn + discard_error: + add eax,sizeof.Error + call release_source_context + sub eax,sizeof.Error + mov ebx,[eax+Error.next] + call mfree + mov eax,ebx + test eax,eax + jnz discard_error + mov [first_error],eax + retn \ No newline at end of file diff --git a/toolchain/fasm2/source/expressions.inc b/toolchain/fasm2/source/expressions.inc new file mode 100644 index 0000000..9f87a69 --- /dev/null +++ b/toolchain/fasm2/source/expressions.inc @@ -0,0 +1,4252 @@ + +struct ExpressionTerm + attributes dd ? ; EXPR_# in low byte, plus any EXPRF_# + metadata dd ? + value dd ? +ends + +EXPR_NUMBER = 30h +EXPR_STRING = 22h +EXPR_FLOAT = 2Eh + +EXPR_SYMBOL_VALUE = 10h +EXPR_OPERATOR = 20h +EXPR_SYMBOL = 40h + +EXPR_POLYNOMIAL = 31h + +EXPR_MISSING_ARGUMENT = 29h +EXPR_MISSING_PARENTHESIS = 28h + +EXPRF_VALUE_IN_WORKSPACE = 100h +EXPRF_CALM_LITERAL = 200h + +EXPRF_OPERATOR_UNARY = 1000h + +convert_number: +; in: +; edx - 32-bit length followed by a string of that length +; out: +; cf set when number has no known prefix or suffix but is not a plain decimal number +; when cf = 0: +; edx - 32-bit length followed by binary data of that length, null when string did not represent a valid number +; when cf = 1: +; edx preserved +; preserves: esi + mov edi,[value_workspace.memory_start] + add edi,[value_position] + mov ecx,[edx] + add edx,4 + cmp byte [edx],'$' + je pascal_hexadecimal_number + cmp ecx,2 + jb check_number_suffix + cmp word [edx],'0x' + je c_hexadecimal_number + check_number_suffix: + movzx eax,byte [edx+ecx-1] + mov al,[characters+eax] + cmp al,'h' + je suffixed_hexadecimal_number + cmp al,'b' + je suffixed_binary_number + cmp al,'o' + je suffixed_octal_number + cmp al,'q' + je suffixed_octal_number + cmp al,'d' + jne decimal_number + or ah,1 + dec ecx + jz invalid_number + decimal_number: + mov ebx,ecx + check_decimal_digits: + mov al,[edx+ebx-1] + cmp al,27h + je check_next_decimal_digit + cmp al,'_' + je check_next_decimal_digit + cmp al,'0' + jb unknown_number + cmp al,'9' + ja unknown_number + check_next_decimal_digit: + dec ebx + jnz check_decimal_digits + push ecx edx + add ecx,12 + mov edx,value_workspace + call reserve_workspace + xor eax,eax + mov dword [edi+4],eax + add eax,4 + mov dword [edi],eax + pop edx ebx + convert_decimal_number: + mov al,[edx] + cmp al,27h + je skip_decimal_digit + cmp al,'_' + je skip_decimal_digit + sub al,'0' + mov ecx,[edi] + xor ecx,ecx + add_decimal_digit: + add ecx,4 + movzx eax,al + add [edi+ecx],eax + setc al + sets ah + cmp ecx,[edi] + jb add_decimal_digit + or ah,al + jz decimal_digit_added + xor ah,ah + add ecx,4 + mov [edi+ecx],eax + mov [edi],ecx + decimal_digit_added: + dec ebx + jz decimal_number_converted + next_decimal_digit: + inc edx + push ebx edx + mov ebx,10 + xor ecx,ecx + xor edx,edx + multiply_decimal_number: + add ecx,4 + mov eax,[edi+ecx] + mov [edi+ecx],edx + mul ebx + add [edi+ecx],eax + cmp ecx,[edi] + jb multiply_decimal_number + test edx,edx + jz decimal_number_multiplied + add ecx,4 + mov [edi+ecx],edx + mov [edi],ecx + decimal_number_multiplied: + pop edx ebx + xor eax,eax + jmp convert_decimal_number + skip_decimal_digit: + inc edx + dec ebx + jnz convert_decimal_number + decimal_number_converted: + lea edx,[edi+4] + mov ecx,[edi] + dec ecx + optimize_number: + movsx eax,byte [edx+ecx-1] + cmp ah,[edx+ecx] + jne number_optimized + loop optimize_number + cmp byte [edx],0 + je number_finished + number_optimized: + inc ecx + number_finished: + sub edx,4 + mov [edx],ecx + lea edi,[edx+4+ecx] + sub edi,[value_workspace.memory_start] + mov [value_position],edi + ; clc + retn + c_hexadecimal_number: + sub ecx,3 + jc invalid_number + add edx,2 + jmp hexadecimal_number + pascal_hexadecimal_number: + inc edx + suffixed_hexadecimal_number: + sub ecx,2 + jc invalid_number + hexadecimal_number: + push edx ecx + shr ecx,1 + add ecx,6 + mov edx,value_workspace + call reserve_workspace + pop ebx edx + push edi + xor eax,eax + stosd + mov [edi],al + xor cl,cl + hexadecimal_digit: + movzx eax,byte [edx+ebx] + cmp al,27h + je skip_hexadecimal_digit + cmp al,'_' + je skip_hexadecimal_digit + mov al,[characters+eax] + sub al,'0' + jc invalid_digit + cmp al,10 + jb hexadecimal_digit_ok + sub al,'a'-'0' + jc invalid_digit + add al,10 + cmp al,16 + jae invalid_digit + hexadecimal_digit_ok: + shl al,cl + or [edi],al + sub ebx,1 + jc number_converted + xor cl,4 + jnz hexadecimal_digit + inc edi + mov [edi],cl + jmp hexadecimal_digit + skip_hexadecimal_digit: + sub ebx,1 + jnc hexadecimal_digit + number_converted: + pop edx + inc edi + and byte [edi],0 + add edx,4 + mov ecx,edi + sub ecx,edx + jmp optimize_number + suffixed_binary_number: + sub ecx,2 + jc invalid_number + push edx ecx + shr ecx,3 + add ecx,6 + mov edx,value_workspace + call reserve_workspace + pop ebx edx + push edi + xor eax,eax + stosd + mov [edi],al + xor cl,cl + binary_digit: + mov al,[edx+ebx] + cmp al,27h + je skip_binary_digit + cmp al,'_' + je skip_binary_digit + sub al,'0' + jc invalid_digit + cmp al,2 + jae invalid_digit + shl al,cl + or [edi],al + sub ebx,1 + jc number_converted + inc cl + and cl,111b + jnz binary_digit + inc edi + mov [edi],cl + jmp binary_digit + skip_binary_digit: + sub ebx,1 + jnc binary_digit + jmp number_converted + suffixed_octal_number: + sub ecx,2 + jc invalid_number + push edx ecx + shr ecx,1 + add ecx,6 + mov edx,value_workspace + call reserve_workspace + pop ebx edx + push edi + xor eax,eax + stosd + mov [edi],al + xor cl,cl + octal_digit: + mov al,[edx+ebx] + cmp al,27h + je skip_octal_digit + cmp al,'_' + je skip_octal_digit + sub al,'0' + jc invalid_digit + cmp al,8 + jae invalid_digit + shl eax,cl + or [edi],al + add cl,3 + cmp cl,8 + jb skip_octal_digit + sub cl,8 + inc edi + mov [edi],ah + xor eax,eax + skip_octal_digit: + sub ebx,1 + jnc octal_digit + jmp number_converted + unknown_number: + test ah,ah + jnz invalid_number + sub edx,4 + stc + retn + invalid_digit: + pop edi + invalid_number: + xor edx,edx + mov al,30h + clc + retn + +convert_number_back: +; in: +; edx - 32-bit length followed by binary data of that length +; out: +; edx - 32-bit length followed by a string of that length +; note: +; the number is treated as unsigned +; returned string is in temporary storage and should be copied out of it immediately + mov edi,[value_workspace.memory_start] + add edi,[value_position] + mov ecx,[edx] + add ecx,2 + shl ecx,2 + mov esi,edx + mov edx,value_workspace + call reserve_workspace + lodsd + lea ebx,[edi+4+(eax+1)*4] + mov edx,edi + mov ecx,eax + rep movsb + xchg eax,ecx + stosd + jecxz highest_dword_offset_ok + dec ecx + and ecx,not 11b + highest_dword_offset_ok: + mov esi,edx + mov edi,ebx + push edi + obtain_digit: + xor edx,edx + divide_highest_dwords: + mov eax,[esi+ecx] + call div10 + test eax,eax + jnz more_digits_to_come + sub ecx,4 + jnc divide_highest_dwords + pop ecx + cmp ecx,edi + je store_final_digit + test dl,dl + jz finish_number + store_final_digit: + add dl,'0' + dec edi + mov [edi],dl + finish_number: + sub ecx,edi + sub edi,4 + mov [edi],ecx + mov edx,edi + retn + more_digits_to_come: + mov ebx,ecx + divide_remaining_dwords: + mov [esi+ebx],eax + sub ebx,4 + jc store_digit + mov eax,[esi+ebx] + call div10 + jmp divide_remaining_dwords + store_digit: + add dl,'0' + dec edi + mov [edi],dl + jmp obtain_digit + div10: + ; cmp edx,10 + ; jae internal_error + push ebx ecx + push eax + mov ebx,eax + mov ecx,edx + shld edx,eax,2 + sub ebx,edx + sbb ecx,0 + mov eax,ebx + mov ebx,1999999Ah + mul ebx + mov eax,ecx + imul eax,ebx + add eax,edx + pop edx + imul ecx,eax,10 + sub edx,ecx + cmp edx,10 + jb div10_done + sub edx,10 + inc eax + div10_done: + pop ecx ebx + retn + +fit_value: +; in: +; edx - 32-bit length followed by numeric data +; ecx = number of bytes that the value has to fit into +; edi - buffer for the specified amount of bytes, null when just checking whether value fits in range +; out: +; sf set when value is negative +; cf set if value does not fit into extended range for specified size +; when cf = 0: +; edi - value fit into specified amount of bytes +; preserves: edx, esi, edi +; note: when value is zero, it fits even into zero byte range + mov ebx,ecx + cmp [edx],ecx + jbe term_in_range + xor al,al + cmp [edx+4+ecx],al + je check_redundant_bytes + dec al + cmp [edx+4+ecx],al + jne term_out_of_range + jecxz term_out_of_range + check_redundant_bytes: + inc ecx + cmp ecx,[edx] + je term_in_range + cmp [edx+4+ecx],al + je check_redundant_bytes + term_out_of_range: + mov ecx,[edx] + mov al,[edx+4+ecx-1] + test al,al + stc + retn + term_in_range: + test edi,edi + jz value_fit + mov ecx,[edx] + cmp ecx,ebx + jbe copy_value + mov ecx,ebx + copy_value: + lea eax,[edx+4] + xchg eax,esi + rep movsb + mov esi,eax + mov ecx,[edx] + movsx eax,byte [edx+4+ecx-1] + mov al,ah + mov ecx,ebx + sub ecx,[edx] + jbe value_ready + rep stosb + value_ready: + sub edi,ebx + value_fit: + test al,al + clc + retn + +start_decimal_converter: +; preserves: ebx + mov edx,value_workspace + mov edi,[value_position] + mov [converter_position],edi + add edi,[edx+Workspace.memory_start] + mov ecx,2*sizeof.FloatData + call reserve_workspace + lea ecx,[edi+2*sizeof.FloatData] + sub ecx,[edx+Workspace.memory_start] + mov [value_position],ecx + mov esi,edi + xor eax,eax + assert sizeof.FloatData and 11b = 0 + mov ecx,sizeof.FloatData shr 2 + rep stosd + mov edx,edi + mov ecx,sizeof.FloatData shr 2 + rep stosd + mov [edx+FloatData.exponent],7 + retn + +convert_decimal_digit: +; in: +; al = value of subsequent digit +; ecx = number of zero digits to insert before +; out: +; edi - FloatData holding the value corresponding to digits converted so far +; note: start_decimal_converter should be called before converting the first digit + mov esi,[value_workspace.memory_start] + add esi,[converter_position] + mov edi,esi + shl eax,24 + mov [esi+sizeof.FloatData+FloatData.mantissa],eax + jecxz multiply_by_ten + inc ecx + call multiply_float_by_power_of_ten + jmp add_subsequent_digit + multiply_by_ten: + mov ecx,10 + call multiply_float_by_unsigned_int + add_subsequent_digit: + mov esi,edi + lea ebx,[esi+sizeof.FloatData] + call add_floats + retn + +finish_decimal_conversion: +; out: +; edi - FloatData holding the converted value +; preserves: ebx, ecx, esi, edi +; note: this function should not be called before all the digits of a value have been processed by convert_decimal_digit + mov eax,[converter_position] + mov edi,[value_workspace.memory_start] + add edi,eax + add eax,2*sizeof.FloatData + cmp eax,[value_position] + jne decimal_conversion_finished + sub eax,sizeof.FloatData + mov [value_position],eax + decimal_conversion_finished: + retn + +keep_value: +; in: +; edx - numeric or string data returned by source parsing or expression evaluating functions +; preserves: ebx, esi, edi +; note: +; this function should be used in conjunction with get_kept_value to retain access to data +; while calling other parsing or expression evaluating functions + xor al,al + cmp edx,[value_workspace.memory_end] + jae keep_value_pointer + mov ecx,edx + sub ecx,[value_workspace.memory_start] + jc keep_value_pointer + mov edx,ecx + inc al + keep_value_pointer: + mov [kept_value],edx + mov [kept_value_in_workspace],al + retn + +get_kept_value: +; out: +; edx - numeric or string data previously passed to keep_value +; preserves: eax, ebx, ecx, esi, edi + mov edx,[kept_value] + cmp [kept_value_in_workspace],0 + je kept_value_ok + add edx,[value_workspace.memory_start] + kept_value_ok: + retn + +get_constant_value: +; in: +; esi = pointer into preprocessed line or the last embedded line +; out: +; esi = pointer advanced past the processed part of line +; al = type of value, zero when expression gave no result +; when al = 22h: +; edx - 32-bit length followed by string data +; when al = 30h: +; edx - 32-bit length followed by numeric data +; when al = 2Eh: +; edx - FloatData + call get_expression_value + jc return_empty_type + get_calculated_constant_value: + ; in: + ; edi - list of ExpressionTerm elements as returned by get_expression_value + ; out: + ; same as get_constant_value + ; preserves: esi, edi + call forbid_variable_terms + call get_term_value + mov eax,[edi+ExpressionTerm.attributes] + assert EXPR_STRING = 22h + assert EXPR_NUMBER = 30h + assert EXPR_FLOAT = 2Eh + retn + return_empty_type: + xor al,al + retn + forbid_variable_terms: + mov eax,edi + detect_variable_terms: + add eax,sizeof.ExpressionTerm + cmp [eax+ExpressionTerm.attributes],0 + je expression_terms_ok + cmp [eax+ExpressionTerm.metadata],0 + je detect_variable_terms + mov edx,_misused_variable_term + call register_error + expression_terms_ok: + retn + +get_numeric_constant_value: +; in: +; esi = pointer into preprocessed line or the last embedded line +; out: +; esi = pointer advanced past the processed part of line +; edx - 32-bit length followed by numeric data, null when expression gave no result +; edi - ExpressionTerm, null when expression gave no result + call get_expression_value + jc empty_numeric_constant + call forbid_variable_terms + call get_numeric_term_value + retn + empty_numeric_constant: + xor edx,edx + xor edi,edi + retn + +get_expression_value: +; in: +; esi = pointer into preprocessed line or the last embedded line +; out: +; cf set if expression gave no result +; esi = pointer advanced past the processed part of line +; when cf = 0: +; edi - list of ExpressionTerm elements, the closing element has attributes set to zero + mov edi,[expression_workspace.memory_start] + and [leave_opening_parentheses],0 + call parse_expression + push esi + mov esi,[expression_workspace.memory_start] + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + call pop_terms + pop esi + retn + +convert_terms_to_numeric_value: +; in: +; edi - list of ExpressionTerm elements as returned by get_expression_value +; out: +; esi - value in VALTYPE_NUMERIC format +; ecx = length of value +; note: the returned value is placed in assembly workspace + mov edx,assembly_workspace + convert_terms_to_numeric_value_in_workspace: + ; in: + ; edx - Workspace + ; edi - list of ExpressionTerm elements as returned by get_expression_value + ; out: + ; esi - value in VALTYPE_NUMERIC format (same as [edx+Workspace.memory_start]) + ; ecx = length of value + ; preserves: edx + mov ebx,[edx+Workspace.memory_start] + copy_numeric_term_values: + mov esi,edx + call get_numeric_term_value + xchg esi,edx + xchg ebx,edi + mov ecx,[esi] + add ecx,8 + call reserve_workspace + lodsd + stosd + mov ecx,eax + rep movsb + next_numeric_term: + add ebx,sizeof.ExpressionTerm + cmp [ebx+ExpressionTerm.attributes],0 + je numeric_term_values_copied + mov eax,[ebx+ExpressionTerm.metadata] + test eax,eax + jz next_numeric_term + stosd + xchg ebx,edi + jmp copy_numeric_term_values + numeric_term_values_copied: + xor eax,eax + stosd + mov esi,[edx+Workspace.memory_start] + mov ecx,edi + sub ecx,esi + retn + +update_predicted_shift: +; in: +; edx - ValueDefinition that is going to be updated +; esi - new value in VALTYPE_NUMERIC fomat +; preserves: ebx, ecx, edx, esi + test edx,edx + jz zero_shift + cmp [edx+ValueDefinition.type],VALTYPE_NUMERIC + jne zero_shift + mov eax,[current_pass] + dec eax + cmp eax,[edx+ValueDefinition.pass] + jne zero_shift + call get_low_dword + mov [predicted_shift],eax + mov edi,[edx+ValueDefinition.value] + xchg esi,edi + call get_low_dword + sub [predicted_shift],eax + test byte [predicted_shift+3],11000000b + mov esi,edi + jnp zero_shift + retn + zero_shift: + mov [predicted_shift],0 + retn + get_low_dword: + mov eax,[esi] + cmp eax,1 + jb low_dword_ready + je dword_from_single_byte + cmp eax,3 + jb dword_from_two_bytes + je dword_from_three_bytes + mov eax,[esi+4] + low_dword_ready: + retn + dword_from_single_byte: + movsx eax,byte [esi+4] + retn + dword_from_two_bytes: + movsx eax,word [esi+4] + retn + dword_from_three_bytes: + mov eax,[esi+4-1] + sar eax,8 + retn + +get_area_value: +; in: +; edi - command sequence created by parse_expression +; out: +; cf set if expression does not yield a valid and accessible VALTYPE_AREA value +; when cf = 0: +; ebx - SymbolTree_Leaf +; edx - ValueDefinition +; preserves: esi + mov al,[edi] + cmp al,EXPR_SYMBOL + je check_for_plain_symbol + cmp al,EXPR_SYMBOL_VALUE + jne no_plain_area_symbol + cmp dword [edi+3*4],0 + jne no_plain_area_symbol + mov edx,[edi+2*4] + test edx,edx + jz no_plain_area_symbol + check_area_symbol: + cmp [edx+ValueDefinition.type],VALTYPE_AREA + jne no_plain_area_symbol + mov ebx,[edi+4] + call mark_symbol_as_used + clc + retn + check_for_plain_symbol: + cmp dword [edi+2*4],0 + jne no_plain_area_symbol + mov ebx,[edi+4] + call get_available_value + jnc check_area_symbol + no_plain_area_symbol: + push esi + mov esi,edi + mov edi,[calculation_workspace.memory_start] + call calculate_parsed_expression + jc invalid_area_expression + call pop_terms + jc invalid_area_expression + mov eax,edi + xor esi,esi + extract_variable_term: + add eax,sizeof.ExpressionTerm + cmp [eax+ExpressionTerm.attributes],0 + je variable_term_extracted + cmp [eax+ExpressionTerm.metadata],0 + je extract_variable_term + test esi,esi + jnz invalid_area_expression + mov esi,eax + jmp extract_variable_term + variable_term_extracted: + test esi,esi + jz invalid_area_expression + call get_term_value + xor ecx,ecx + mov edi,ecx + call fit_value + jc invalid_area_expression + mov edi,esi + call get_term_value + mov ecx,1 + mov edi,value + call fit_value + jc invalid_area_expression + cmp byte [value],1 + jne invalid_area_expression + mov ebx,[esi+ExpressionTerm.metadata] + mov edx,[ebx+SymbolTree_Leaf.definition] + test edx,edx + jz invalid_area_expression + cmp [edx+ValueDefinition.type],VALTYPE_AREA + jne invalid_area_expression + pop esi + clc + retn + invalid_area_expression: + pop esi + invalid_area_symbol: + stc + retn + +get_constituent_value: +; same as get_processed_value +; note: after any expression evaluation functions have been used, only this function should be used to retrieve constituents of line + xor al,al + xchg al,[current_constituent] + test al,al + jz get_processed_value + get_constituent_components: + mov ebx,[constituent_symbol] + mov edx,[constituent_value] + mov ecx,[constituent_whitespace] + clc + retn + +peek_at_constituent_value: +; same as get_constituent_value, but returned values are also kept in constituent variables +; note: +; the retrieved value is still going to be available to expression evaluation functions or to the next call of get_constituent_value +; to consume the value it is enough to set [current_constituent] to zero + cmp [current_constituent],0 + jne get_current_constituent + call get_processed_value + jc constituent_value_ok + mov [current_constituent],al + mov [constituent_symbol],ebx + mov [constituent_value],edx + mov [constituent_whitespace],ecx + constituent_value_ok: + retn + get_current_constituent: + mov al,[current_constituent] + jmp get_constituent_components + +parse_expression: +; in: +; esi = pointer into preprocessed line or the last embedded line +; edi = pointer to a place in expression workspace where the parsed command sequence should be stored +; [leave_opening_parentheses] = non-zero when parentheses opened in the beginning of expression that did not get closed should be returned to caller instead of being registered in parsed expression +; out: +; esi = pointer advanced past the processed part of line +; edi = pointer advanced past the created sequence in expression workspace +; ecx = number of parentheses opened in the beginning of expression that did not get closed (zero when [leave_opening_parentheses] was zero) + mov [expression_end],edi + sub edi,[expression_workspace.memory_start] + mov [expression_position],edi + mov eax,[operator_stack_base] + mov [operator_stack],eax + mov [operator_stack_position],eax + mov [operator_argument_expected],1 + get_expression_element: + mov edi,[expression_end] + mov edx,expression_workspace + mov ecx,[operator_stack_position] + sub ecx,[operator_stack_base] + add ecx,16 + call reserve_workspace + mov [expression_end],edi + call peek_at_constituent_value + mov edi,[expression_end] + jc expression_line_end + cmp al,'(' + je open_subexpression + cmp al,')' + je close_subexpression + cmp al,30h + je store_expression_number + cmp al,22h + je store_expression_string + cmp al,2Eh + je store_expression_float + cmp al,1Ah + je expression_symbol + movzx eax,al + shl eax,2 + add eax,[operator_table] + mov edx,[eax] + test edx,edx + jz terminate_expression + xor ebx,ebx + mov ecx,edx + jmp identify_operator + expression_symbol: + test edx,edx + jz store_expression_symbol + mov ecx,edx + identify_operator: + cmp [ecx+ValueDefinition.type],VALTYPE_NATIVE_COMMAND + jne inspect_expression_symbol + test [ecx+ValueDefinition.attribute],OPERATOR_UNARY + setnz al + xor al,[operator_argument_expected] + jz store_expression_operator + mov ecx,[ecx+ValueDefinition.previous] + test ecx,ecx + jnz identify_operator + inspect_expression_symbol: + cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_COMPARATOR + je terminate_expression + store_expression_symbol: + cmp [operator_argument_expected],0 + je terminate_expression + mov eax,EXPR_SYMBOL_VALUE + stosd + mov eax,ebx + stosd + mov eax,edx + stosd + expression_symbol_stored: + mov [expression_end],edi + and [operator_argument_expected],0 + and [current_constituent],0 + jmp get_expression_element + store_expression_number: + cmp [operator_argument_expected],0 + je terminate_expression + mov eax,EXPR_NUMBER + value_pointer_in_expression: + cmp edx,[value_workspace.memory_end] + jae value_pointer_in_expression_ok + mov ebx,edx + sub ebx,[value_workspace.memory_start] + jc value_pointer_in_expression_ok + mov edx,ebx + or eax,EXPRF_VALUE_IN_WORKSPACE + value_pointer_in_expression_ok: + stosd + mov eax,edx + stosd + jmp expression_symbol_stored + store_expression_string: + cmp [operator_argument_expected],0 + je terminate_expression + mov eax,EXPR_STRING + jmp value_pointer_in_expression + store_expression_float: + cmp [operator_argument_expected],0 + je terminate_expression + mov eax,EXPR_FLOAT + jmp value_pointer_in_expression + store_expression_operator: + mov edx,[ecx+ValueDefinition.value] + mov cl,[ecx+ValueDefinition.attribute] + mov ch,cl + and cl,OPERATOR_PRECEDENCE_MASK + mov ebx,[operator_stack_position] + cmp [operator_argument_expected],0 + jne push_operator + establish_operator_precedence: + cmp ebx,[operator_stack] + je push_operator + cmp cl,[ebx-8] + ja push_operator + jb store_pending_operator + test ch,OPERATOR_RIGHT_ASSOCIATIVE + jnz push_operator + store_pending_operator: + sub ebx,8 + xor eax,eax + test byte [ebx+1],OPERATOR_UNARY + setnz al + shl eax,bsf EXPRF_OPERATOR_UNARY + mov al,EXPR_OPERATOR + stosd + mov eax,[ebx+4] + stosd + jmp establish_operator_precedence + push_operator: + call reserve_operator_stack + mov [ebx],ecx + mov [ebx+4],edx + add ebx,8 + mov [operator_stack_position],ebx + mov [expression_end],edi + or [operator_argument_expected],1 + and [current_constituent],0 + jmp get_expression_element + open_subexpression: + cmp [operator_argument_expected],0 + je terminate_expression + mov ebx,[operator_stack_position] + call reserve_operator_stack + mov eax,[operator_stack] + sub eax,[operator_stack_base] + mov [ebx],eax + add ebx,4 + mov [operator_stack],ebx + mov [operator_stack_position],ebx + and [current_constituent],0 + jmp get_expression_element + close_subexpression: + mov eax,[operator_stack] + cmp eax,[operator_stack_base] + je terminate_expression + cmp [operator_argument_expected],0 + je subexpression_closed + mov eax,EXPR_MISSING_ARGUMENT + stosd + subexpression_closed: + call store_remaining_operators + mov [expression_end],edi + sub ebx,4 + mov eax,[ebx] + add eax,[operator_stack_base] + mov [operator_stack],eax + mov [operator_stack_position],ebx + and [current_constituent],0 + jmp get_expression_element + expression_line_end: + and [current_constituent],0 + terminate_expression: + cmp [operator_argument_expected],0 + je close_expression + mov eax,[operator_stack_position] + cmp eax,[operator_stack] + jne expression_terminated_prematurely + mov eax,edi + sub eax,[expression_workspace.memory_start] + cmp eax,[expression_position] + je close_expression + expression_terminated_prematurely: + mov eax,EXPR_MISSING_ARGUMENT + stosd + close_expression: + call store_remaining_operators + xor ecx,ecx + cmp ebx,[operator_stack_base] + jne forcibly_close_subexpressions + expression_parsed: + xor eax,eax + stosd + retn + forcibly_close_subexpressions: + sub ebx,4 + mov eax,[ebx] + add eax,[operator_stack_base] + mov [operator_stack],eax + cmp [leave_opening_parentheses],0 + je internal_parenthesis + cmp eax,ebx + je external_parenthesis + internal_parenthesis: + mov eax,EXPR_MISSING_PARENTHESIS + inc ecx + rep stosd + mov [operator_stack_position],ebx + call store_remaining_operators + cmp ebx,[operator_stack_base] + jne forcibly_close_subexpressions + jmp expression_parsed + external_parenthesis: + inc ecx + cmp ebx,[operator_stack_base] + jne forcibly_close_subexpressions + jmp expression_parsed + reserve_operator_stack: + mov eax,[operator_stack_end] + sub eax,8 + cmp ebx,eax + jbe operator_stack_ready + push edx + mov eax,[operator_stack_base] + sub ebx,eax + sub [operator_stack],eax + mov ecx,[operator_stack_end] + sub ecx,eax + add ecx,8 + call grow_stack + add ebx,eax + add [operator_stack],eax + mov [operator_stack_base],eax + add eax,ecx + mov [operator_stack_end],eax + pop edx + operator_stack_ready: + retn + store_remaining_operators: + mov ebx,[operator_stack_position] + store_operator: + cmp ebx,[operator_stack] + je remaining_operators_stored + sub ebx,8 + xor eax,eax + test byte [ebx+1],OPERATOR_UNARY + setnz al + shl eax,bsf EXPRF_OPERATOR_UNARY + mov al,EXPR_OPERATOR + stosd + mov eax,[ebx+4] + stosd + jmp store_operator + remaining_operators_stored: + retn + +calculate_parsed_expression: +; in: +; esi - command sequence created by parse_expression +; edi - top of the stack in the calculation workspace +; out: +; cf set if expression had structural errors +; esi = pointer moved past the processed sequence +; edi - top of the updated stack +; when cf = 0: +; eax = non-zero if result is considered not yet known for resolving purposes + mov [expression_end],esi + mov eax,edi + sub eax,[calculation_workspace.memory_start] + mov [calculation_position],eax + cmp dword [esi],0 + je invalid_expression + calculation_loop: + mov esi,[expression_end] + lodsd + cmp al,EXPR_OPERATOR + je execute_operator + cmp al,EXPR_NUMBER + je push_literal + cmp al,EXPR_STRING + je push_literal + cmp al,EXPR_FLOAT + je push_literal + cmp al,EXPR_SYMBOL_VALUE + je push_symbol_value + cmp al,EXPR_SYMBOL + je push_symbol_current_value + cmp al,EXPR_POLYNOMIAL + je push_polynomial_literal + test eax,eax + jnz structural_error + ; clc + retn + execute_operator: + lodsd + mov [expression_end],esi + jmp eax + push_literal: + mov ebx,eax + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + lodsd + test ebx,EXPRF_CALM_LITERAL + jnz calm_literal_value + test ebx,EXPRF_VALUE_IN_WORKSPACE + jnz valid_literal_value + test eax,eax + jnz valid_literal_value + jmp invalid_number_in_expression + calm_literal_value: + add eax,[calm_literals] + valid_literal_value: + mov [edi+ExpressionTerm.attributes],ebx + mov [edi+ExpressionTerm.value],eax + xor eax,eax + mov [edi+ExpressionTerm.metadata],eax + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + add edi,2*sizeof.ExpressionTerm + mov [expression_end],esi + jmp calculation_loop + push_polynomial_literal: + ; occurring only in reduced CALM expressions + mov ebx,eax + lodsd + mov [expression_end],esi + test ebx,EXPRF_CALM_LITERAL + jz polynomial_value_ready + add eax,[calm_literals] + polynomial_value_ready: + xor esi,esi + mov ebx,eax + jmp push_polynomial + push_symbol_current_value: + ; occurring only in CALM expressions, entire expression workspace should be free to use + lodsd + test eax,eax + jz invalid_identifier_in_expression + mov ebx,eax + mov [expression_end],esi + call use_available_value + jc undefined_symbol_in_expression + mov al,[edx+ValueDefinition.type] + cmp al,VALTYPE_SYMBOLIC + jne identify_value_to_push + push esi edi + call clear_line_embeddings + xor esi,esi + xor ecx,ecx + call embed_symbolic_value + mov edi,[expression_workspace.memory_start] + and [leave_opening_parentheses],0 + call parse_expression + pop edi + call get_constituent_value + jnc invalid_subexpression + mov esi,[expression_workspace.memory_start] + push [calculation_position] + call calculate_parsed_expression + pop [calculation_position] + jc invalid_subexpression + pop [expression_end] + test eax,eax + jnz unknown_result + jmp calculation_loop + invalid_subexpression: + pop [expression_end] + mov edx,_invalid_expression + call register_error + jmp unknown_result + push_symbol_value: + lodsd + test eax,eax + jz invalid_identifier_in_expression + mov ebx,eax + lodsd + mov edx,eax + call mark_symbol_as_used + mov [expression_end],esi + test edx,edx + jz undefined_symbol_in_expression + mov al,[edx+ValueDefinition.type] + identify_value_to_push: + cmp al,VALTYPE_NUMERIC + je push_numeric_symbol + cmp al,VALTYPE_ELEMENT + je push_element + cmp al,VALTYPE_AREA + je push_area + cmp al,VALTYPE_STRING + je push_string + cmp al,VALTYPE_FLOAT + je push_float + cmp al,VALTYPE_PLAIN + je push_plain_symbol + cmp al,VALTYPE_NATIVE_FUNCTION + jne invalid_symbol_in_expression + jmp [edx+ValueDefinition.value] + push_numeric_symbol: + xor esi,esi + test [edx+ValueDefinition.flags],VAL_SHIFTABLE + jz predicted_shift_ok + mov eax,[edx+ValueDefinition.pass] + cmp eax,[current_pass] + je predicted_shift_ok + mov esi,[predicted_shift] + predicted_shift_ok: + mov ebx,[edx+ValueDefinition.value] + mov eax,ebx + add eax,[edx+ValueDefinition.value_length] + push_polynomial: + push eax edi + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + mov [edi+ExpressionTerm.value],ebx + test esi,esi + jz push_numeric_terms + or [next_pass_needed],1 + mov ecx,temporary_value + mov dword [ecx],4 + mov dword [ecx+4],esi + lea esi,[edi+sizeof.ExpressionTerm] + mov [esi+ExpressionTerm.attributes],EXPR_NUMBER + mov [esi+ExpressionTerm.value],ecx + push ebx + call add_term_values + pop ebx + push_numeric_terms: + add edi,sizeof.ExpressionTerm + mov edx,calculation_workspace + mov ecx,sizeof.ExpressionTerm + call reserve_workspace + mov eax,[ebx] + lea ebx,[ebx+4+eax] + mov eax,[ebx] + test eax,eax + jz numeric_terms_pushed + mov eax,[ebx] + mov [edi+ExpressionTerm.metadata],eax + add ebx,4 + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + mov [edi+ExpressionTerm.value],ebx + jmp push_numeric_terms + numeric_terms_pushed: + pop edx ecx + sub ecx,8 + cmp ebx,ecx + jbe symbol_metadata_ok + xor ebx,ebx + symbol_metadata_ok: + mov [edx+ExpressionTerm.metadata],ebx + xor eax,eax + mov [edi+ExpressionTerm.attributes],eax + add edi,sizeof.ExpressionTerm + jmp calculation_loop + push_plain_symbol: + mov ebx,[edx+ValueDefinition.value] + push_plain_value: + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + mov esi,edi + mov edx,value_workspace + mov edi,[edx+Workspace.memory_start] + add edi,[value_position] + mov ecx,4+4 + call reserve_workspace + xor eax,eax + test ebx,ebx + jz number_length_ok + bsr eax,ebx + inc al + shr al,3 + inc al + number_length_ok: + stosd + mov [edi],ebx + add eax,edi + sub eax,[value_workspace.memory_start] + xchg eax,[value_position] + mov edi,esi + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + mov [edi+ExpressionTerm.value],eax + xor eax,eax + mov [edi+ExpressionTerm.metadata],eax + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + add edi,2*sizeof.ExpressionTerm + jmp calculation_loop + push_string: + mov al,EXPR_STRING + push_value: + mov [term_type],al + mov ebx,[edx+ValueDefinition.value] + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + mov [edi+ExpressionTerm.value],ebx + xor eax,eax + mov [edi+ExpressionTerm.metadata],eax + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + mov al,[term_type] + mov [edi+ExpressionTerm.attributes],eax + add edi,2*sizeof.ExpressionTerm + jmp calculation_loop + push_float: + mov al,EXPR_FLOAT + jmp push_value + push_area: + mov esi,edx + jmp push_variable_term + push_element: + xor esi,esi + push_variable_term: + mov edx,calculation_workspace + mov ecx,3*sizeof.ExpressionTerm + call reserve_workspace + mov eax,EXPR_NUMBER + mov [edi+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.metadata],esi + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.value],zero_value + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.value],singular_value + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.metadata],ebx + and [edi+2*sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + add edi,3*sizeof.ExpressionTerm + jmp calculation_loop + base_address_value: + mov edx,[current_area] + area_address_value: + mov ebx,[edx+ValueDefinition.value] + add ebx,sizeof.AreaHeader + push_numeric_value: + mov edx,calculation_workspace + mov ecx,sizeof.ExpressionTerm + call reserve_workspace + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + mov [edi+ExpressionTerm.value],ebx + and [edi+ExpressionTerm.metadata],0 + jmp push_variable_terms + truncated_address_value: + xor esi,esi + jmp push_current_address + current_address_value: + or esi,-1 + push_current_address: + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + mov eax,[current_area] + mov ebx,[eax+ValueDefinition.value] + mov ecx,[eax+ValueDefinition.value_length] + sub ecx,[ebx+AreaHeader.base_address_length] + sub ecx,sizeof.AreaHeader + and esi,[ebx+AreaHeader.uninitialized_length] + add ecx,esi + add ebx,sizeof.AreaHeader + mov esi,temporary_value + mov dword [esi],4 + mov [esi+4],ecx + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + mov [edi+ExpressionTerm.value],esi + and [edi+ExpressionTerm.metadata],0 + lea esi,[edi+sizeof.ExpressionTerm] + mov [esi+ExpressionTerm.attributes],EXPR_NUMBER + mov [esi+ExpressionTerm.value],ebx + call add_term_values + mov ebx,[esi+ExpressionTerm.value] + push_variable_terms: + mov eax,[ebx] + lea ebx,[ebx+4+eax] + convert_variable_term: + add edi,sizeof.ExpressionTerm + mov edx,calculation_workspace + mov ecx,sizeof.ExpressionTerm + call reserve_workspace + mov eax,[ebx] + test eax,eax + jz variable_terms_converted + mov [edi+ExpressionTerm.metadata],eax + add ebx,4 + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + mov [edi+ExpressionTerm.value],ebx + mov eax,[ebx] + lea ebx,[ebx+4+eax] + jmp convert_variable_term + variable_terms_converted: + mov [edi+ExpressionTerm.attributes],eax + add edi,sizeof.ExpressionTerm + jmp calculation_loop + truncated_position_value: + call prepare_to_push_computed_value + call get_output_length + jmp push_output_position + prepare_to_push_computed_value: + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + mov esi,edi + mov edx,value_workspace + mov edi,[edx+Workspace.memory_start] + add edi,[value_position] + mov ecx,4+8 + call reserve_workspace + retn + current_position_value: + call prepare_to_push_computed_value + call get_output_position + push_output_position: + mov edi,[value_workspace.memory_start] + add edi,[value_position] + push_computed_value: + mov ecx,eax + or ecx,edx + jz computed_value_length_ok + bsr ecx,edx + jnz long_computed_value + bsr ecx,eax + inc cl + shr cl,3 + inc cl + jmp computed_value_length_ok + long_computed_value: + inc cl + shr cl,3 + add cl,1+4 + computed_value_length_ok: + mov [edi],ecx + add edi,4 + stosd + mov eax,edx + stosd + add ecx,edi + sub ecx,[value_workspace.memory_start] + xchg ecx,[value_position] + mov edi,esi + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + mov [edi+ExpressionTerm.value],ecx + xor eax,eax + mov [edi+ExpressionTerm.metadata],eax + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + add edi,2*sizeof.ExpressionTerm + jmp calculation_loop + current_time_value: + call prepare_to_push_computed_value + call get_timestamp + jmp push_computed_value + current_line_number_value: + call prepare_to_push_computed_value + call get_file_source_entry + mov eax,[ebx+SourceEntry.line_number] + xor edx,edx + jmp push_computed_value + current_file_name_value: + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + push edi + call get_file_source_entry + jmp push_file_name_value + main_file_name_value: + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + push edi + mov ebx,[source_context] + lea ebx,[ebx+sizeof.SourceContext] + push_file_name_value: + mov esi,[ebx+SourceEntry.name] + xor ecx,ecx + cmp [ebx+SourceEntry.type],SOURCE_FILE + jne file_name_length_ok + mov ecx,[ebx+SourceEntry.name_length] + test ecx,ecx + jnz file_name_length_ok + mov edi,esi + xor al,al + dec ecx + repne scasb + add ecx,2 + neg ecx + file_name_length_ok: + mov ebx,ecx + add ecx,4 + mov edx,value_workspace + mov edi,[edx+Workspace.memory_start] + add edi,[value_position] + call reserve_workspace + mov eax,ebx + stosd + mov ecx,ebx + rep movsb + mov eax,edi + sub eax,[value_workspace.memory_start] + xchg eax,[value_position] + pop edi + mov [edi+ExpressionTerm.attributes],EXPR_STRING + EXPRF_VALUE_IN_WORKSPACE + mov [edi+ExpressionTerm.value],eax + xor eax,eax + mov [edi+ExpressionTerm.metadata],eax + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + add edi,2*sizeof.ExpressionTerm + jmp calculation_loop + structural_error: + cmp eax,EXPR_MISSING_PARENTHESIS + je expression_missing_parenthesis + invalid_expression: + mov edx,_invalid_expression + call register_error + stc + retn + expression_missing_parenthesis: + mov edx,_missing_closing_parenthesis + call register_error + stc + retn + undefined_symbol_in_expression: + cmp [next_pass_needed],0 + jne unknown_result + mov edx,_undefined_symbol + jmp error_causing_unknown_result + invalid_identifier_in_expression: + mov edx,_invalid_identifier + jmp error_causing_unknown_result + invalid_number_in_expression: + mov edx,_invalid_number + jmp error_causing_unknown_result + invalid_symbol_in_expression: + mov edx,_invalid_symbol_value + error_causing_unknown_result: + call register_error + unknown_result: + mov eax,edi + mov edi,[calculation_position] + add edi,[calculation_workspace.memory_start] + cmp edi,eax + jb unknown_result_terms_ready + mov edi,eax + mov edx,calculation_workspace + mov ecx,2*sizeof.ExpressionTerm + call reserve_workspace + xor eax,eax + mov [edi+ExpressionTerm.metadata],eax + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + unknown_result_terms_ready: + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + mov [edi+ExpressionTerm.value],zero_value + add edi,2*sizeof.ExpressionTerm + mov esi,[expression_end] + skip_expression: + lodsd + cmp al,EXPR_OPERATOR + je skip_dword + cmp al,EXPR_NUMBER + je skip_dword + cmp al,EXPR_STRING + je skip_dword + cmp al,EXPR_FLOAT + je skip_dword + cmp al,EXPR_SYMBOL + je skip_dword + cmp al,EXPR_SYMBOL_VALUE + je skip_two_dwords + cmp al,EXPR_POLYNOMIAL + je skip_dword + test eax,eax + jnz invalid_expression + inc eax + ; clc + retn + skip_two_dwords: + add esi,4 + skip_dword: + add esi,4 + jmp skip_expression + +pop_terms: +; in: +; edi = top of the stack +; out: +; edi = new top of the stack, at the same time a pointer to the first term of retrieved linear polynomial +; cf set when there were no more entries on the stack +; preserves: eax, ebx, ecx, edx, esi + cmp edi,[calculation_workspace.memory_start] + je nothing_to_pop + sub edi,sizeof.ExpressionTerm + find_first_term: + cmp edi,[calculation_workspace.memory_start] + je first_term_found + cmp [edi-sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + je first_term_found + sub edi,sizeof.ExpressionTerm + jmp find_first_term + first_term_found: + clc + retn + nothing_to_pop: + and [edi+ExpressionTerm.metadata],0 + and [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + mov [edi+ExpressionTerm.value],zero_value + stc + retn + +calculate_to_number: + call pop_terms + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je single_term_result + make_terms_numeric: + mov eax,[edi+ExpressionTerm.attributes] + test eax,eax + jz all_terms_numeric + call get_numeric_term_value + add edi,sizeof.ExpressionTerm + jmp make_terms_numeric + all_terms_numeric: + add edi,sizeof.ExpressionTerm + jmp calculation_loop + +calculate_to_string: + call pop_terms + call get_string_term_value + jmp single_term_result + +calculate_to_float: + call pop_terms + call get_float_term_value + jmp single_term_result + +extract_integer_part: + call pop_terms + call truncate_term_value + jmp single_term_result + +calculate_neg: + call pop_terms + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je negate_float_term + call negate_term_value + add edi,sizeof.ExpressionTerm + negate_element_terms: + cmp [edi+ExpressionTerm.attributes],0 + je all_terms_negated + cmp [edi+ExpressionTerm.metadata],0 + je negate_next_term + call negate_term_value + negate_next_term: + add edi,sizeof.ExpressionTerm + jmp negate_element_terms + all_terms_negated: + add edi,sizeof.ExpressionTerm + jmp calculation_loop + negate_float_term: + call prepare_altered_float_term + xor [ebx+FloatData.attributes],FLOAT_NEGATIVE + single_term_result: + add edi,sizeof.ExpressionTerm + mov eax,edi + call check_for_excess_terms + jnc single_term_result_ok + mov edx,_misused_variable_term + call register_error + single_term_result_ok: + and [edi+ExpressionTerm.attributes],0 + add edi,sizeof.ExpressionTerm + jmp calculation_loop + check_for_excess_terms: + cmp [eax+ExpressionTerm.attributes],0 + je no_excess_terms + cmp [eax+ExpressionTerm.metadata],0 + jne excess_terms + add eax,sizeof.ExpressionTerm + jne check_for_excess_terms + no_excess_terms: + clc + retn + excess_terms: + stc + retn + prepare_altered_float_term: + mov ebx,edi + mov edx,value_workspace + mov edi,[edx+Workspace.memory_start] + add edi,[value_position] + mov ecx,sizeof.FloatData + call reserve_workspace + xchg edi,ebx + call get_term_value + xchg edi,ebx + mov esi,edx + assert sizeof.FloatData and 11b = 0 + mov ecx,sizeof.FloatData shr 2 + rep movsd + mov eax,edi + sub eax,[value_workspace.memory_start] + xchg eax,[value_position] + sub edi,sizeof.FloatData + xchg edi,ebx + mov [edi+ExpressionTerm.value],eax + or [edi+ExpressionTerm.attributes],EXPRF_VALUE_IN_WORKSPACE + retn + +calculate_add: + call pop_terms + mov esi,edi + call pop_terms + cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT + je add_float_terms + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je add_float_terms + cmp [edi+ExpressionTerm.metadata],0 + jne add_constant_terms + mov eax,[esi+ExpressionTerm.metadata] + mov [edi+ExpressionTerm.metadata],eax + add_constant_terms: + call add_term_values + add esi,sizeof.ExpressionTerm + add_variable_terms: + cmp [esi+ExpressionTerm.attributes],0 + je all_terms_added + mov eax,[esi+ExpressionTerm.metadata] + test eax,eax + jz add_next_term + push edi + find_element_to_add_to: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je attach_new_element + cmp eax,[edi+ExpressionTerm.metadata] + jne find_element_to_add_to + push esi + call add_term_values + jnz variable_term_added + and [edi+ExpressionTerm.metadata],0 + variable_term_added: + pop esi edi + add_next_term: + add esi,sizeof.ExpressionTerm + jmp add_variable_terms + attach_new_element: + assert sizeof.ExpressionTerm and 11b = 0 + mov ecx,sizeof.ExpressionTerm shr 2 + rep movsd + and [edi+ExpressionTerm.attributes],0 + pop edi + jmp add_variable_terms + all_terms_added: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + jne all_terms_added + add edi,sizeof.ExpressionTerm + jmp calculation_loop + add_float_terms: + mov eax,add_floats + operation_on_float_terms: + push esi edi eax + mov ebx,edi + mov edx,value_workspace + mov edi,[edx+Workspace.memory_start] + add edi,[value_position] + mov ecx,sizeof.FloatData + call reserve_workspace + lea ecx,[edi+sizeof.FloatData] + sub ecx,[edx+Workspace.memory_start] + mov [value_position],ecx + xchg edi,ebx + call get_float_term_value + xchg edi,esi + call get_float_term_value + mov edi,esi + mov esi,edx + call get_term_value + mov edi,ebx + mov ebx,edx + pop eax + call eax + mov ebx,edi + sub ebx,[value_workspace.memory_start] + test [edi+FloatData.attributes],FLOAT_INFINITE or FLOAT_INDETERMINATE or FLOAT_UNDERFLOW + jz operation_on_float_terms_ok + mov edx,_indeterminate_result + call register_error + xor eax,eax + mov [edi+FloatData.attributes],eax + add edi,FloatData.mantissa + mov ecx,MANTISSA_SEGMENTS + rep stosd + operation_on_float_terms_ok: + pop edi esi + mov [edi+ExpressionTerm.value],ebx + mov [edi+ExpressionTerm.attributes],EXPR_FLOAT + EXPRF_VALUE_IN_WORKSPACE + and [edi+ExpressionTerm.metadata],0 + finish_calculation_on_single_terms: + add edi,sizeof.ExpressionTerm + mov eax,edi + call check_for_excess_terms + jc single_terms_violation + lea eax,[esi+sizeof.ExpressionTerm] + call check_for_excess_terms + jnc single_terms_ok + single_terms_violation: + mov edx,_misused_variable_term + call register_error + single_terms_ok: + and [edi+ExpressionTerm.attributes],0 + add edi,sizeof.ExpressionTerm + jmp calculation_loop + +calculate_sub: + call pop_terms + mov esi,edi + call pop_terms + cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT + je subtract_float_terms + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je subtract_float_terms + cmp [edi+ExpressionTerm.metadata],0 + jne subtract_constant_terms + mov eax,[esi+ExpressionTerm.metadata] + mov [edi+ExpressionTerm.metadata],eax + subtract_constant_terms: + call subtract_term_values + add esi,sizeof.ExpressionTerm + subtract_variable_terms: + cmp [esi+ExpressionTerm.attributes],0 + je all_terms_subtracted + mov eax,[esi+ExpressionTerm.metadata] + test eax,eax + jz subtract_next_term + push edi + find_element_to_subtract_from: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je attach_negated_element + cmp eax,[edi+ExpressionTerm.metadata] + jne find_element_to_subtract_from + push esi + call subtract_term_values + jnz variable_term_subtracted + and [edi+ExpressionTerm.metadata],0 + variable_term_subtracted: + pop esi edi + subtract_next_term: + add esi,sizeof.ExpressionTerm + jmp subtract_variable_terms + attach_negated_element: + assert sizeof.ExpressionTerm and 11b = 0 + mov ecx,sizeof.ExpressionTerm shr 2 + rep movsd + sub edi,sizeof.ExpressionTerm + call negate_term_value + add edi,sizeof.ExpressionTerm + and [edi+ExpressionTerm.attributes],0 + pop edi + jmp subtract_variable_terms + all_terms_subtracted: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + jne all_terms_subtracted + add edi,sizeof.ExpressionTerm + jmp calculation_loop + subtract_float_terms: + mov eax,subtract_floats + jmp operation_on_float_terms + +calculate_mul: + call pop_terms + mov esi,edi + call pop_terms + cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT + je multiply_float_terms + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je multiply_float_terms + cmp [esi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + jne multiply_by_destination + multiply_terms: + call multiply_term_values + jnz multiply_next_term + and [edi+ExpressionTerm.metadata],0 + multiply_next_term: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je terms_multiplied + jmp multiply_terms + terms_multiplied: + add edi,sizeof.ExpressionTerm + jmp calculation_loop + multiply_by_destination: + and [esi+ExpressionTerm.metadata],0 + cmp [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + je duplicate_destination_constant_term + mov edx,_nonlinear_polynomial + call register_error + duplicate_destination_constant_term: + mov eax,[edi+ExpressionTerm.attributes] + mov edx,[edi+ExpressionTerm.value] + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.value],edx + multiply_source_terms: + mov eax,[esi+ExpressionTerm.metadata] + mov [edi+ExpressionTerm.metadata],eax + call multiply_term_values + jnz multiply_next_source_term + and [edi+ExpressionTerm.metadata],0 + multiply_next_source_term: + add esi,sizeof.ExpressionTerm + add edi,sizeof.ExpressionTerm + cmp [esi+ExpressionTerm.attributes],0 + je source_terms_multiplied + cmp [esi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + je multiply_source_terms + jmp duplicate_destination_constant_term + source_terms_multiplied: + and [edi+ExpressionTerm.attributes],0 + jmp terms_multiplied + multiply_float_terms: + mov eax,multiply_floats + jmp operation_on_float_terms + +calculate_div: + call pop_terms + mov eax,edi + call check_for_excess_terms + jnc divisor_ok + mov edx,_misused_variable_term + call register_error + divisor_ok: + mov esi,edi + call pop_terms + cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT + je divide_float_terms + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je divide_float_terms + and [edi+ExpressionTerm.metadata],0 + mov eax,[esi+ExpressionTerm.attributes] + mov edx,[esi+ExpressionTerm.value] + mov [esi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + mov [esi+sizeof.ExpressionTerm+ExpressionTerm.value],edx + call divide_term_values + divide_variable_term: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je division_done + cmp [edi+ExpressionTerm.metadata],0 + je divide_variable_term + mov eax,[esi+sizeof.ExpressionTerm+ExpressionTerm.attributes] + mov edx,[esi+sizeof.ExpressionTerm+ExpressionTerm.value] + mov [esi+ExpressionTerm.attributes],eax + mov [esi+ExpressionTerm.value],edx + call divide_term_values + jz divide_variable_term + mov edx,_subdivided_variable_term + call register_error + jmp divide_variable_term + division_done: + add edi,sizeof.ExpressionTerm + jmp calculation_loop + divide_float_terms: + mov eax,divide_floats + jmp operation_on_float_terms + +calculate_mod: + call pop_terms + mov esi,edi + call pop_terms + call divide_term_values + and [esi+ExpressionTerm.metadata],0 + assert sizeof.ExpressionTerm and 11b = 0 + mov ecx,sizeof.ExpressionTerm shr 2 + rep movsd + mov eax,edi + call check_for_excess_terms + jc mod_variable_term + mov eax,esi + call check_for_excess_terms + jnc mod_terms_ok + mod_variable_term: + mov edx,_misused_variable_term + call register_error + mod_terms_ok: + and [edi+ExpressionTerm.attributes],0 + add edi,sizeof.ExpressionTerm + jmp calculation_loop + +calculate_not: + call pop_terms + call invert_term_value_bits + jmp single_term_result + +calculate_xor: + call pop_terms + mov esi,edi + call pop_terms + call bitwise_add_term_values + finish_bitwise_calculation: + cmp [edi+ExpressionTerm.metadata],0 + jne finish_calculation_on_single_terms + mov eax,[esi+ExpressionTerm.metadata] + mov [edi+ExpressionTerm.metadata],eax + jmp finish_calculation_on_single_terms + +calculate_and: + call pop_terms + mov esi,edi + call pop_terms + call bitwise_multiply_term_values + jmp finish_bitwise_calculation + +calculate_or: + call pop_terms + mov esi,edi + call pop_terms + call bitwise_inclusive_or_of_term_values + jmp finish_bitwise_calculation + +calculate_shl: + call pop_terms + call get_numeric_term_value + mov ecx,5 + call fit_value + js negative_shift_left + jc huge_shift_left + shift_left: + mov esi,edi + check_shift_left_argument: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je shift_left_argument_ok + cmp [edi+ExpressionTerm.metadata],0 + je check_shift_left_argument + mov edx,_misused_variable_term + call register_error + shift_left_argument_ok: + mov edi,esi + call pop_terms + and [edi+ExpressionTerm.metadata],0 + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je shift_floating_point_left + shift_term_left: + mov eax,[esi] + mov dl,[esi+4] + call shift_term_value_left + shift_variable_term_left: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je shift_done + cmp [edi+ExpressionTerm.metadata],0 + je shift_variable_term_left + jmp shift_term_left + shift_done: + add edi,sizeof.ExpressionTerm + jmp calculation_loop + negative_shift_left: + jc huge_shift_right + not byte [edi+4] + neg dword [edi] + jc shift_right + inc byte [edi+4] + jnz shift_right + huge_shift_right: + or eax,-1 + mov [edi],eax + mov [edi+4],al + jmp shift_right + shift_floating_point_left: + push esi + call prepare_altered_float_term + pop esi + xchg esi,ebx + call get_float_unnormalization + jc single_term_result + mov eax,[esi+FloatData.exponent] + cdq + add eax,[ebx] + movzx ebx,byte [ebx+4] + adc ebx,edx + mov [esi+FloatData.exponent],eax + cdq + cmp ebx,edx + jne floating_point_over_boundary + test ecx,ecx + jz single_term_result + push edi + mov edi,esi + and [mantissa_tail],0 + call normalize_float + pop edi + jmp single_term_result + floating_point_over_boundary: + jecxz floating_point_out_of_range + test ebx,ebx + jnz floating_point_out_of_range + mov ecx,7FFFFFFFh + sub eax,ecx + mov [esi+FloatData.exponent],ecx + push eax edi + mov edi,esi + and [mantissa_tail],0 + call normalize_float + pop edi ecx + mov eax,[esi+FloatData.exponent] + cdq + add eax,ecx + js floating_point_out_of_range + adc edx,0 + jnz floating_point_out_of_range + mov [esi+FloatData.exponent],eax + jmp single_term_result + floating_point_out_of_range: + mov edx,_value_out_of_range + call register_error + jmp single_term_result + +calculate_shr: + call pop_terms + call get_numeric_term_value + mov ecx,5 + call fit_value + js negative_shift_right + jc huge_shift_right + shift_right: + mov esi,edi + check_shift_right_argument: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je shift_right_argument_ok + cmp [edi+ExpressionTerm.metadata],0 + je check_shift_right_argument + mov edx,_misused_variable_term + call register_error + shift_right_argument_ok: + mov edi,esi + call pop_terms + and [edi+ExpressionTerm.metadata],0 + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + je shift_floating_point_right + shift_term_right: + mov eax,[esi] + mov dl,[esi+4] + call shift_term_value_right + shift_variable_term_right: + add edi,sizeof.ExpressionTerm + cmp [edi+ExpressionTerm.attributes],0 + je shift_done + cmp [edi+ExpressionTerm.metadata],0 + je shift_variable_term_right + call get_term_value + mov ecx,[esi] + mov bl,cl + mov al,[esi+4] + shrd ecx,eax,3 + shr al,3 + jnz not_exact_shift + cmp ecx,[edx] + jae not_exact_shift + xchg edi,edx + add edi,4 + xor al,al + repe scasb + xchg edi,edx + jne not_exact_shift + mov cl,bl + and cl,8-1 + jz shift_term_right + mov al,1 + shl al,cl + dec al + test [edx],al + jz shift_term_right + not_exact_shift: + mov edx,_subdivided_variable_term + call register_error + jmp shift_variable_term_right + negative_shift_right: + jc huge_shift_left + not byte [edi+4] + neg dword [edi] + jc shift_left + inc byte [edi+4] + jnz shift_left + huge_shift_left: + or eax,-1 + mov [edi],eax + mov [edi+4],al + jmp shift_left + shift_floating_point_right: + push esi + call prepare_altered_float_term + pop esi + xchg esi,ebx + call get_float_unnormalization + jc single_term_result + mov eax,[esi+FloatData.exponent] + cdq + sub eax,[ebx] + movzx ecx,byte [ebx+4] + sbb edx,ecx + mov ecx,edx + mov [esi+FloatData.exponent],eax + cdq + cmp ecx,edx + je single_term_result + cmp ecx,-1 + jne floating_point_out_of_range + mov [esi+FloatData.exponent],-80000000h + mov ecx,eax + neg ecx + push edi + mov edi,esi + and [mantissa_tail],0 + call unnormalize_float + pop edi + mov [esi+FloatData.exponent],-80000000h + call get_float_unnormalization + jc floating_point_out_of_range + jmp single_term_result + +calculate_bsf: + call pop_terms + mov esi,edi + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov ecx,10 + mov edx,value_workspace + call reserve_workspace + call find_first_set_bit_in_term_value + jz bit_scan_result_undefined + movzx edx,dl + bit_scan_result_ready: + mov ebx,edi + and dword [edi],0 + add edi,4 + stosd + mov ax,dx + stosw + mov ecx,6 + optimize_result_value: + cmp [edi-1],dh + jne result_value_ready + movsx eax,byte [edi-2] + cmp ah,dh + jne result_value_ready + dec edi + loop optimize_result_value + result_value_ready: + mov [ebx],ecx + sub edi,[value_workspace.memory_start] + mov [value_position],edi + sub ebx,[value_workspace.memory_start] + mov edi,esi + mov [edi+ExpressionTerm.value],ebx + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + and [edi+ExpressionTerm.metadata],0 + jmp single_term_result + +calculate_bsr: + call pop_terms + mov esi,edi + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov ecx,10 + mov edx,value_workspace + call reserve_workspace + cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT + je extract_float_exponent + call find_last_set_bit_in_term_value + jc bit_scan_result_undefined + movzx edx,dl + jmp bit_scan_result_ready + bit_scan_result_undefined: + mov edi,esi + mov edx,_indeterminate_result + call register_error + mov [edi+ExpressionTerm.value],zero_value + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + and [edi+ExpressionTerm.metadata],0 + jmp single_term_result + extract_float_exponent: + mov edi,esi + mov [destination_term],edi + call get_term_value + mov esi,edx + call get_float_unnormalization + jc exponent_indeterminate + mov eax,[esi+FloatData.exponent] + cdq + sub eax,ecx + sbb edx,0 + exponent_extracted: + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov esi,[destination_term] + jmp bit_scan_result_ready + exponent_indeterminate: + mov edx,_indeterminate_result + call register_error + xor eax,eax + xor edx,edx + jmp exponent_extracted + +calculate_bswap: + call pop_terms + call get_numeric_term_value + mov ecx,4 + call fit_value + js bswap_argument_out_of_range + jc bswap_argument_out_of_range + mov esi,edi + mov eax,edi + call check_for_excess_terms + jnc bswap_argument_ok + mov edx,_misused_variable_term + call register_error + bswap_argument_ok: + call pop_terms + and [edi+ExpressionTerm.metadata],0 + mov ebx,[esi] + call reverse_term_value_bytes + jmp single_term_result + bswap_argument_out_of_range: + mov edx,_value_out_of_range + call register_error + call pop_terms + jmp single_term_result + +calculate_bappend: + call pop_terms + mov [source_term],edi + call pop_terms + mov [destination_term],edi + call get_string_term_value + mov ecx,[edx] + mov edi,[source_term] + call get_string_term_value + add ecx,[edx] + add ecx,4 + mov edi,[value_position] + mov edx,value_workspace + add edi,[edx+Workspace.memory_start] + call reserve_workspace + push edi + mov edi,[destination_term] + call get_term_value + mov [edi+ExpressionTerm.attributes],EXPR_STRING + EXPRF_VALUE_IN_WORKSPACE + mov eax,[value_position] + mov [edi+ExpressionTerm.value],eax + pop edi + mov esi,edx + mov ecx,[esi] + movsd + rep movsb + push edi + mov edi,[source_term] + call get_term_value + pop edi + mov esi,edx + lodsd + mov ecx,eax + rep movsb + mov edx,[value_workspace.memory_start] + sub edi,edx + xchg [value_position],edi + add edi,edx + add [edi],eax + mov esi,[source_term] + mov edi,[destination_term] + jmp finish_calculation_on_single_terms + +count_bytes: + call pop_terms + call get_string_term_value + mov esi,edi + add esi,sizeof.ExpressionTerm + mov eax,esi + call check_for_excess_terms + mov ebx,[edx] + jnc push_plain_value + mov edx,_misused_variable_term + call register_error + jmp push_plain_value + +count_elements: + call pop_terms + mov edx,[edi+ExpressionTerm.metadata] + xor ebx,ebx + mov edx,edi + count_variable_terms: + add edx,sizeof.ExpressionTerm + cmp [edx+ExpressionTerm.attributes],0 + je push_plain_value + cmp [edx+ExpressionTerm.metadata],0 + je count_variable_terms + inc ebx + jmp count_variable_terms + +extract_element_reverse: + xor eax,eax +extract_element: + call get_indexed_term + jc replace_with_zero + jecxz replace_with_constant_unit + mov ebx,[ebx+ExpressionTerm.metadata] + jmp push_element + get_indexed_term: + call pop_terms + mov esi,edi + call pop_terms + mov ebx,edi + test eax,eax + jnz process_term_indexing + xchg ebx,esi + process_term_indexing: + mov edx,esi + check_term_index: + add edx,sizeof.ExpressionTerm + cmp [edx+ExpressionTerm.attributes],0 + je term_index_ok + cmp [edx+ExpressionTerm.metadata],0 + je check_term_index + mov edx,_misused_variable_term + call register_error + term_index_ok: + push ebx + xchg edi,esi + call get_numeric_term_value + mov ecx,4 + call fit_value + xchg esi,edi + pop ebx + js no_such_term + jc no_such_term + xor ecx,ecx + find_indexed_term: + cmp ecx,[esi] + je term_found + find_next_term: + add ebx,sizeof.ExpressionTerm + cmp [ebx+ExpressionTerm.attributes],0 + je no_such_term + cmp [ebx+ExpressionTerm.metadata],0 + je find_next_term + inc ecx + jmp find_indexed_term + term_found: + clc + retn + no_such_term: + stc + retn + replace_with_constant_unit: + mov edx,singular_value + jmp replace_with_simple_number + replace_with_zero: + mov edx,zero_value + replace_with_simple_number: + mov eax,EXPR_NUMBER + replace_with_simple_constant: + mov [edi+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.value],edx + xor eax,eax + mov [edi+ExpressionTerm.metadata],eax + mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax + add edi,2*sizeof.ExpressionTerm + jmp calculation_loop + +extract_scale_reverse: + xor eax,eax +extract_scale: + call get_indexed_term + jc replace_with_zero + mov eax,[ebx+ExpressionTerm.attributes] + mov edx,[ebx+ExpressionTerm.value] + mov [edi+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.value],edx + and [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 + add edi,2*sizeof.ExpressionTerm + jmp calculation_loop + +extract_metadata_reverse: + xor eax,eax +extract_metadata: + call get_indexed_term + jc replace_with_zero + extract_term_metadata: + mov ebx,[ebx+ExpressionTerm.metadata] + test ebx,ebx + jz replace_with_zero + test ecx,ecx + jz extract_label_metadata + mov edx,[ebx+SymbolTree_Leaf.definition] + test edx,edx + jz replace_with_zero + cmp [edx+ValueDefinition.type],VALTYPE_AREA + je area_address_value + cmp [edx+ValueDefinition.type],VALTYPE_ELEMENT + jne replace_with_zero + mov ecx,[edx+ValueDefinition.value_length] + jecxz replace_with_zero + jmp push_numeric_symbol +extract_size: + call pop_terms + mov ebx,[edi+ExpressionTerm.metadata] + test ebx,ebx + jz replace_with_zero + extract_label_metadata: + cmp dword [ebx],0 + jne extract_area_size + add ebx,4 + jmp push_numeric_value + extract_area_size: + call prepare_to_push_computed_value + xor edx,edx + mov eax,[ebx+ValueDefinition.value_length] + mov edi,[ebx+ValueDefinition.value] + sub eax,sizeof.AreaHeader + sub eax,[edi+AreaHeader.base_address_length] + add eax,[edi+AreaHeader.uninitialized_length] + adc edx,0 + jmp push_output_position +extract_first_term_metadata: + call pop_terms + lea ebx,[edi+sizeof.ExpressionTerm] + mov ecx,1 + jmp extract_term_metadata + +get_term_value: +; in: edi - ExpressionTerm +; out: edx - 32-bit length followed by data +; preserves: eax, ebx, ecx, esi, edi + mov edx,[edi+ExpressionTerm.value] + test [edi+ExpressionTerm.attributes],EXPRF_VALUE_IN_WORKSPACE + jz value_pointer_ready + add edx,[value_workspace.memory_start] + value_pointer_ready: + retn + +get_numeric_term_value: +; in: edi - ExpressionTerm +; out: edx - 32-bit length followed by numeric data +; preserves: ebx, esi, edi +; note: +; term is converted to numeric and the value workspace may be modified in process +; other pointers to term values may become invalidated + mov eax,[edi+ExpressionTerm.attributes] + mov edx,[edi+ExpressionTerm.value] + test eax,EXPRF_VALUE_IN_WORKSPACE + jz convert_to_numeric + add edx,[value_workspace.memory_start] + convert_to_numeric: + cmp al,EXPR_FLOAT + je wrong_numeric_type + cmp al,EXPR_NUMBER + je value_pointer_ready + mov eax,[edx] + test byte [edx+4+eax-1],80h + jnz extend_to_unsigned_value + mov byte [edi+ExpressionTerm.attributes],EXPR_NUMBER + retn + wrong_numeric_type: + mov edx,_invalid_value + call register_error + mov edx,zero_value + mov [edi+ExpressionTerm.value],edx + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + retn + extend_to_unsigned_value: + push esi edi + mov esi,edi + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov ecx,[edx] + add ecx,5 + mov edx,value_workspace + call reserve_workspace + jnc pointer_for_unsigned_value_ready + mov edi,[value_position] + add edi,[value_workspace.memory_start] + pointer_for_unsigned_value_ready: + mov eax,EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + xchg eax,[esi+ExpressionTerm.attributes] + mov edx,[value_position] + xchg edx,[esi+ExpressionTerm.value] + mov esi,edx + test eax,EXPRF_VALUE_IN_WORKSPACE + jz make_unsigned_value + add esi,[value_workspace.memory_start] + make_unsigned_value: + mov edx,edi + lodsd + stosd + mov ecx,eax + rep movsb + xor al,al + stosb + sub edi,[value_workspace.memory_start] + mov [value_position],edi + inc dword [edx] + pop edi esi + retn + +get_string_term_value: +; in: edi - ExpressionTerm +; out: edx - 32-bit length followed by string data +; preserves: ebx, ecx, esi, edi + mov eax,[edi+ExpressionTerm.attributes] + cmp al,EXPR_STRING + je string_value_available + mov byte [edi+ExpressionTerm.attributes],EXPR_STRING + cmp al,EXPR_NUMBER + je string_value_available + mov edx,_invalid_value + call register_error + mov edx,zero_value + mov [edi+ExpressionTerm.value],edx + mov [edi+ExpressionTerm.attributes],EXPR_STRING + retn + string_value_available: + mov edx,[edi+ExpressionTerm.value] + test eax,EXPRF_VALUE_IN_WORKSPACE + jz string_value_pointer_ready + add edx,[value_workspace.memory_start] + string_value_pointer_ready: + retn + +get_float_term_value: +; in: edi - ExpressionTerm +; out: edx - FloatData +; preserves: ebx, esi, edi +; note: +; term is converted to float and the value workspace may be modified in process +; other pointers to term values may become invalidated + mov eax,[edi+ExpressionTerm.attributes] + mov edx,[edi+ExpressionTerm.value] + test eax,EXPRF_VALUE_IN_WORKSPACE + jz convert_to_float + add edx,[value_workspace.memory_start] + convert_to_float: + cmp al,EXPR_FLOAT + je value_pointer_ready + cmp al,EXPR_STRING + je convert_positive_to_float + mov eax,[edx] + test byte [edx+4+eax-1],80h + jnz convert_negative_to_float + convert_positive_to_float: + push ebx esi + mov ebx,edi + mov edx,value_workspace + mov edi,[edx+Workspace.memory_start] + add edi,[value_position] + mov ecx,sizeof.FloatData + call reserve_workspace + xchg edi,ebx + call get_term_value + mov esi,edx + lea eax,[ebx+sizeof.FloatData] + sub eax,[value_workspace.memory_start] + xchg eax,[value_position] + mov [edi+ExpressionTerm.value],eax + mov [edi+ExpressionTerm.attributes],EXPR_FLOAT + EXPRF_VALUE_IN_WORKSPACE + push edi + mov edi,ebx + call number_to_float + mov edx,edi + pop edi esi ebx + retn + convert_negative_to_float: + push ebx + call negate_term_value + pop ebx + call convert_positive_to_float + or [edx+FloatData.attributes],FLOAT_NEGATIVE + retn + +negate_term_value: +; in: +; edi - ExpressionTerm +; out: +; zf set if result is zero +; preserves: esi, edi + push esi + mov [destination_term],edi + call get_numeric_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov ecx,[esi] + add ecx,5 + mov edx,value_workspace + call reserve_workspace + jnc pointers_ready_for_negation + mov edi,[destination_term] + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + pointers_ready_for_negation: + mov edx,[esi] + and edx,not 11b + mov eax,1 + xor ecx,ecx + add esi,4 + add edi,4 + negate_dwords: + cmp ecx,edx + je dwords_negated + mov ebx,[esi+ecx] + not ebx + add eax,ebx + mov [edi+ecx],eax + setc al + movzx eax,al + add ecx,4 + jmp negate_dwords + dwords_negated: + mov edx,[esi-4] + negate_bytes: + cmp ecx,edx + je bytes_negated + mov bl,[esi+ecx] + not bl + add al,bl + mov [edi+ecx],al + setc al + inc ecx + jmp negate_bytes + bytes_negated: + movsx ebx,byte [esi+ecx-1] + not bh + add al,bh + mov [edi+ecx],al + pop esi + value_calculated: + jecxz check_for_zero + optimize_value: + movsx edx,byte [edi+ecx-1] + cmp dh,[edi+ecx] + jne value_optimized + loop optimize_value + check_for_zero: + cmp byte [edi],0 + je finish_value + value_optimized: + inc ecx + finish_value: + sub edi,4 + mov [edi],ecx + value_finished: + mov edx,edi + sub edx,[value_workspace.memory_start] + lea eax,[edx+4+ecx] + mov [value_position],eax + mov edi,[destination_term] + mov [edi+ExpressionTerm.value],edx + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + test ecx,ecx + retn + +add_term_values: +; in: +; esi - source ExpressionTerm +; edi - destination ExpressionTerm +; out: +; zf set if result is zero +; preserves: esi, edi + call prepare_pointers_for_summation + mov edx,[ebx] + cmp edx,[esi] + jb shorter_addend_selected + mov edx,[esi] + xchg ebx,esi + shorter_addend_selected: + and edx,not 11b + add ebx,4 + add esi,4 + add edi,4 + xor al,al + xor ecx,ecx + add_dwords: + cmp ecx,edx + je dwords_added + neg al + mov eax,[esi+ecx] + adc eax,[ebx+ecx] + mov [edi+ecx],eax + setc al + add ecx,4 + jmp add_dwords + dwords_added: + mov edx,[ebx-4] + add_bytes: + cmp ecx,edx + je bytes_added + neg al + mov al,[esi+ecx] + adc al,[ebx+ecx] + mov [edi+ecx],al + setc al + inc ecx + jmp add_bytes + bytes_added: + movsx ebx,byte [ebx+ecx-1] + sar ebx,8 + mov edx,[esi-4] + sub edx,ecx + and edx,not 11b + add edx,ecx + carry_dwords: + cmp ecx,edx + je dwords_carried + neg al + mov eax,[esi+ecx] + adc eax,ebx + mov [edi+ecx],eax + setc al + add ecx,4 + jmp carry_dwords + dwords_carried: + mov edx,[esi-4] + carry_bytes: + cmp ecx,edx + je bytes_carried + neg al + mov al,[esi+ecx] + adc al,bl + mov [edi+ecx],al + setc al + inc ecx + jmp carry_bytes + bytes_carried: + movsx edx,byte [esi+ecx-1] + neg al + mov al,dh + adc al,bl + mov [edi+ecx],al + mov esi,[source_term] + jmp value_calculated + prepare_pointers_for_summation: + mov [source_term],esi + mov [destination_term],edi + call get_numeric_term_value + mov ebx,[edx] + mov edi,esi + call get_numeric_term_value + mov ecx,[edx] + cmp ecx,ebx + jae sum_length_estimated + mov ecx,ebx + sum_length_estimated: + add ecx,5 + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov edx,value_workspace + call reserve_workspace + mov edi,[destination_term] + call get_term_value + mov ebx,edx + mov edi,esi + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + retn + +subtract_term_values: +; in: +; esi - source ExpressionTerm +; edi - destination ExpressionTerm +; out: +; zf set if result is zero +; preserves: esi, edi + call prepare_pointers_for_summation + mov edx,[esi] + cmp edx,[ebx] + jb shorter_length_selected + mov edx,[ebx] + shorter_length_selected: + push edx + and edx,not 11b + add ebx,4 + add esi,4 + add edi,4 + xor al,al + xor ecx,ecx + subtract_dwords: + cmp ecx,edx + je dwords_subtracted + neg al + mov eax,[ebx+ecx] + sbb eax,[esi+ecx] + mov [edi+ecx],eax + setc al + add ecx,4 + jmp subtract_dwords + dwords_subtracted: + pop edx + subtract_bytes: + cmp ecx,edx + je bytes_subtracted + neg al + mov al,[ebx+ecx] + sbb al,[esi+ecx] + mov [edi+ecx],al + setc al + inc ecx + jmp subtract_bytes + bytes_subtracted: + cmp ecx,[ebx-4] + je minuend_ended + xchg esi,ebx + movsx ebx,byte [ebx+ecx-1] + sar ebx,8 + mov edx,[esi-4] + sub edx,ecx + and edx,not 11b + add edx,ecx + borrow_dwords: + cmp ecx,edx + je dwords_borrowed + neg al + mov eax,[esi+ecx] + sbb eax,ebx + mov [edi+ecx],eax + setc al + add ecx,4 + jmp borrow_dwords + dwords_borrowed: + mov edx,[esi-4] + borrow_bytes: + cmp ecx,edx + je bytes_borrowed + neg al + mov al,[esi+ecx] + sbb al,bl + mov [edi+ecx],al + setc al + inc ecx + jmp borrow_bytes + bytes_borrowed: + movsx edx,byte [esi+ecx-1] + neg al + mov al,dh + sbb al,bl + mov [edi+ecx],al + mov esi,[source_term] + jmp value_calculated + minuend_ended: + movsx ebx,byte [ebx+ecx-1] + sar ebx,8 + mov edx,[esi-4] + sub edx,ecx + and edx,not 11b + add edx,ecx + subtract_supernumerary_dwords: + cmp ecx,edx + je supernumerary_dwords_subtracted + neg al + mov eax,ebx + sbb eax,[esi+ecx] + mov [edi+ecx],eax + setc al + add ecx,4 + jmp subtract_supernumerary_dwords + supernumerary_dwords_subtracted: + mov edx,[esi-4] + subtract_supernumerary_bytes: + cmp ecx,edx + je supernumerary_bytes_subtracted + neg al + mov al,bl + sbb al,[esi+ecx] + mov [edi+ecx],al + setc al + inc ecx + jmp subtract_supernumerary_bytes + supernumerary_bytes_subtracted: + movsx edx,byte [esi+ecx-1] + neg al + mov al,bl + sbb al,dh + mov [edi+ecx],al + mov esi,[source_term] + jmp value_calculated + +multiply_term_values: +; in: +; esi - source ExpressionTerm +; edi - destination ExpressionTerm +; out: +; zf set if result is zero +; preserves: esi, edi + mov [source_term],esi + mov [destination_term],edi + call get_numeric_term_value + mov edi,multiplier + mov ecx,4 + call fit_value + jnc multiply_by_dword + mov edi,esi + call get_numeric_term_value + mov esi,[destination_term] + mov edi,multiplier + mov ecx,4 + call fit_value + jnc multiply_by_dword + mov edi,[source_term] + call get_term_value + mov ebx,[edx] + mov edi,[destination_term] + call get_term_value + mov eax,[edx] + mov ecx,ebx + add ecx,eax + cmp ebx,eax + jae split_length_selected + xchg ebx,eax + split_length_selected: + shr ebx,1 + add ecx,18 + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov edx,value_workspace + call reserve_workspace + mov eax,edi + mov edi,[source_term] + push edi + call get_term_value + mov edi,eax + mov esi,edx + call split_value + mov eax,edi + mov edi,[destination_term] + push edi + call get_term_value + mov edi,eax + mov esi,edx + call split_value + sub edi,[value_workspace.memory_start] + mov edx,edi + mov edi,[free_temporary_terms] + add [free_temporary_terms],6*sizeof.ExpressionTerm + mov eax,EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + xchg edx,[value_position] + push edx + mov esi,[value_workspace.memory_start] + mov ecx,4 + create_temporary_terms: + mov [edi+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.value],edx + add edx,[esi+edx] + add edx,4 + add edi,sizeof.ExpressionTerm + loop create_temporary_terms + mov ecx,2 + duplicate_temporary_terms: + mov [edi+ExpressionTerm.attributes],eax + mov edx,[edi-4*sizeof.ExpressionTerm+ExpressionTerm.value] + mov [edi+ExpressionTerm.value],edx + add edi,sizeof.ExpressionTerm + loop duplicate_temporary_terms + push ebx + sub edi,6*sizeof.ExpressionTerm + lea esi,[edi+2*sizeof.ExpressionTerm] + call multiply_term_values + add esi,sizeof.ExpressionTerm + add edi,sizeof.ExpressionTerm + call multiply_term_values + add edi,sizeof.ExpressionTerm + call add_term_values + add esi,2*sizeof.ExpressionTerm + add edi,2*sizeof.ExpressionTerm + call add_term_values + mov esi,edi + sub edi,2*sizeof.ExpressionTerm + call multiply_term_values + add edi,sizeof.ExpressionTerm + mov eax,[esi-3*sizeof.ExpressionTerm+ExpressionTerm.attributes] + mov edx,[esi-3*sizeof.ExpressionTerm+ExpressionTerm.value] + mov [esi+ExpressionTerm.attributes],eax + mov [esi+ExpressionTerm.value],edx + mov eax,[edi-3*sizeof.ExpressionTerm+ExpressionTerm.attributes] + mov edx,[edi-3*sizeof.ExpressionTerm+ExpressionTerm.value] + mov [edi+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.value],edx + call add_term_values + sub edi,sizeof.ExpressionTerm + sub esi,sizeof.ExpressionTerm + call subtract_term_values + mov eax,[esp] + xor dl,dl + shld edx,eax,3 + shl eax,3 + call shift_term_value_left + mov esi,edi + sub edi,2*sizeof.ExpressionTerm + call add_term_values + mov esi,edi + add edi,sizeof.ExpressionTerm + pop eax + xor dl,dl + shld edx,eax,4 + shl eax,4 + call shift_term_value_left + pop [value_position] + mov eax,[edi+ExpressionTerm.attributes] + mov edx,[edi+ExpressionTerm.value] + pop edi + mov [edi+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.value],edx + call add_term_values + mov [free_temporary_terms],esi + pop esi + test edi,edi + retn + split_value: + cmp ebx,[esi] + jae too_small_to_split + mov eax,ebx + inc eax + stosd + mov ecx,ebx + lodsd + rep movsb + mov ecx,eax + xor al,al + stosb + sub ecx,ebx + mov eax,ecx + stosd + rep movsb + retn + too_small_to_split: + lodsd + mov ecx,eax + stosd + rep movsb + xor eax,eax + stosd + retn + multiply_by_dword: + sets al + mov [multiplier_sign],al + movzx eax,al + or eax,[multiplier] + jz zero_product + mov ebx,esi + mov edi,esi + call get_numeric_term_value + mov esi,edx + mov ecx,[esi] + add ecx,16 + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov edx,value_workspace + call reserve_workspace + jnc pointers_ready_for_multiplication_by_dword + mov edi,ebx + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + pointers_ready_for_multiplication_by_dword: + mov eax,[esi] + and eax,not 11b + mov [edi],eax + add esi,4 + add edi,4 + xor ebx,ebx + xor ecx,ecx + multiply_dwords_by_dword: + cmp ecx,[edi-4] + je dwords_multiplied_by_dword + mov eax,[esi+ecx] + mul [multiplier] + add eax,ebx + adc edx,0 + mov ebx,edx + mov [edi+ecx],eax + add ecx,4 + jmp multiply_dwords_by_dword + dwords_multiplied_by_dword: + mov edx,[esi-4] + and edx,11b + jz only_sign_in_last_dword + cmp edx,2 + jb single_byte_in_last_dword + je two_bytes_in_last_dword + movsx eax,byte [esi+ecx+2] + shl eax,16 + mov ax,[esi+ecx] + jmp last_dword_ready + two_bytes_in_last_dword: + movsx eax,word [esi+ecx] + jmp last_dword_ready + single_byte_in_last_dword: + movsx eax,byte [esi+ecx] + jmp last_dword_ready + only_sign_in_last_dword: + movsx eax,byte [esi+ecx-1] + sar eax,8 + last_dword_ready: + mov [edi-4],eax + mul [multiplier] + add eax,ebx + adc edx,0 + mov [edi+ecx],eax + xor eax,eax + mov ebx,[esi-4] + test byte [esi+ebx-1],80h + jz product_extension + sub edx,[multiplier] + sbb eax,0 + product_extension: + mov [edi+ecx+4],edx + add ecx,8 + mov [edi+ecx],eax + cmp [multiplier_sign],0 + je product_ready + mov edx,[esi-4] + and edx,not 11b + xor ecx,ecx + xor al,al + adjust_product: + cmp ecx,edx + je finish_product_adjustment + neg al + mov eax,[esi+ecx] + sbb [edi+ecx+4],eax + setc al + add ecx,4 + jmp adjust_product + finish_product_adjustment: + neg al + mov eax,[edi-4] + cdq + sbb [edi+ecx+4],eax + sbb [edi+ecx+8],edx + add ecx,8 + product_ready: + mov esi,[source_term] + jmp value_calculated + zero_product: + ; zf already set + mov esi,[source_term] + mov edi,[destination_term] + mov [edi+ExpressionTerm.value],zero_value + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + retn + +divide_term_values: +; in: +; esi - divisor ExpressionTerm, to be replaced with remainder +; edi - dividend ExpressionTerm, to be replaced with quotient +; out: +; zf set if remainder is zero +; preserves: esi, edi + mov [source_term],esi + mov [destination_term],edi + call get_numeric_term_value + mov eax,[edx] + test byte [edx+4+eax-1],80h + jnz negative_dividend + xchg edi,esi + call get_numeric_term_value + mov eax,[edx] + test byte [edx+4+eax-1],80h + jnz negative_divisor + mov edi,divisor + mov ecx,4 + call fit_value + jnc divide_by_dword + xor eax,eax + mov ebx,[edx] + find_divisor_length: + mov al,[edx+4+ebx-1] + test al,al + jnz divisor_length_ok + dec ebx + jmp find_divisor_length + divisor_length_ok: + bsr ecx,eax + inc cl + mov [long_divisor_length],ebx + mov [high_bits_count],cl + mov ebx,[edx+4+ebx-5] + shrd ebx,eax,cl + inc ebx + mov [divisor],ebx + mov eax,[source_term] + mov [long_divisor_term],eax + mov eax,[destination_term] + mov [long_dividend_term],eax + mov edi,[free_temporary_terms] + add [free_temporary_terms],4*sizeof.ExpressionTerm + mov [division_temporary_terms],edi + xor eax,eax + mov [edi+ExpressionTerm.attributes],eax + compare_dividend_with_divisor: + mov esi,edx + mov edi,[long_dividend_term] + call get_term_value + xor eax,eax + mov ebx,[edx] + find_dividend_length: + mov al,[edx+4+ebx-1] + test al,al + jnz dividend_length_ok + dec ebx + jmp find_dividend_length + dividend_length_ok: + cmp ebx,[long_divisor_length] + ja long_division + jb dividend_to_remainder + bsr ecx,eax + inc cl + cmp cl,[high_bits_count] + ja long_division + jb dividend_to_remainder + compare_with_divisor_bytes: + mov al,[edx+4+ebx-1] + cmp al,[esi+4+ebx-1] + ja subtract_divisor + jb dividend_to_remainder + dec ebx + jnz compare_with_divisor_bytes + mov esi,[long_divisor_term] + mov edi,[long_dividend_term] + mov eax,EXPR_NUMBER + mov [esi+ExpressionTerm.attributes],eax + mov [esi+ExpressionTerm.value],zero_value + mov [edi+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.value],singular_value + jmp accomodate_quotient + dividend_to_remainder: + mov esi,[division_temporary_terms] + mov [free_temporary_terms],esi + mov eax,[esi+ExpressionTerm.attributes] + mov edx,[esi+ExpressionTerm.value] + test eax,eax + jnz quotient_ready + mov eax,EXPR_NUMBER + mov edx,zero_value + quotient_ready: + mov esi,[long_divisor_term] + mov edi,[long_dividend_term] + xchg eax,[edi+ExpressionTerm.attributes] + xchg edx,[edi+ExpressionTerm.value] + mov [esi+ExpressionTerm.attributes],eax + mov [esi+ExpressionTerm.value],edx + jmp test_remainder + subtract_divisor: + mov esi,[long_divisor_term] + mov edi,[long_dividend_term] + call subtract_term_values + mov eax,EXPR_NUMBER + mov edx,singular_value + xchg eax,[edi+ExpressionTerm.attributes] + xchg edx,[edi+ExpressionTerm.value] + mov [esi+ExpressionTerm.attributes],eax + mov [esi+ExpressionTerm.value],edx + accomodate_quotient: + mov esi,[division_temporary_terms] + mov [free_temporary_terms],esi + cmp [esi+ExpressionTerm.attributes],0 + je quotient_complete + call add_term_values + quotient_complete: + mov esi,[long_divisor_term] + test_remainder: + cmp dword [esi],0 + retn + long_division: + mov edi,[division_temporary_terms] + add edi,sizeof.ExpressionTerm + mov esi,[long_dividend_term] + mov eax,[esi+ExpressionTerm.attributes] + mov edx,[esi+ExpressionTerm.value] + mov [edi+ExpressionTerm.attributes],eax + mov [edi+ExpressionTerm.value],edx + mov ecx,8 + cmp [divisor],0 + je shift_dividend_right + add cl,32 + shift_dividend_right: + xor edx,edx + mov eax,[long_divisor_length] + shld edx,eax,3 + shl eax,3 + sub cl,[high_bits_count] + sub eax,ecx + sbb edx,0 + call shift_term_value_right + cmp [divisor],0 + je quotient_approximation_ready + mov esi,edi + mov [destination_term],esi + add edi,sizeof.ExpressionTerm + mov [source_term],edi + call divide_by_dword + quotient_approximation_ready: + mov esi,[division_temporary_terms] + cmp [esi+ExpressionTerm.attributes],0 + jne accumulate_quotient + mov eax,[edi+ExpressionTerm.attributes] + mov edx,[edi+ExpressionTerm.value] + mov [esi+ExpressionTerm.attributes],eax + mov [esi+ExpressionTerm.value],edx + jmp calculate_remainder + accumulate_quotient: + xchg esi,edi + call add_term_values + mov edi,esi + calculate_remainder: + mov esi,[long_divisor_term] + call multiply_term_values + mov esi,edi + mov edi,[long_dividend_term] + call subtract_term_values + mov edi,[long_divisor_term] + call get_term_value + jmp compare_dividend_with_divisor + negative_divisor: + call negate_term_value + xchg edi,esi + call divide_term_values + pushf + call negate_term_value + popf + retn + negative_dividend: + call negate_term_value + xchg edi,esi + call get_numeric_term_value + mov eax,[edx] + test byte [edx+4+eax-1],80h + jnz negative_dividend_and_divisor + xchg edi,esi + call divide_term_values + call negate_term_value + jmp negative_remainder + negative_dividend_and_divisor: + call negate_term_value + xchg edi,esi + call divide_term_values + negative_remainder: + xchg edi,esi + call negate_term_value + xchg edi,esi + retn + divide_by_dword: + cmp [divisor],0 + je division_by_zero + mov ebx,esi + mov edi,esi + call get_term_value + mov esi,edx + mov ecx,[esi] + add ecx,4+9 + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov edx,value_workspace + call reserve_workspace + jnc pointers_ready_for_division_by_dword + mov edi,ebx + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + pointers_ready_for_division_by_dword: + mov eax,[esi] + add esi,4 + add edi,4 + mov ecx,eax + and ecx,not 11b + xor edx,edx + and eax,11b + jz first_dword_for_division_ready + cmp eax,2 + jb single_byte_in_first_dword + je two_bytes_in_first_dword + mov dl,[esi+ecx+2] + shl edx,16 + two_bytes_in_first_dword: + mov dh,[esi+ecx+1] + single_byte_in_first_dword: + mov dl,[esi+ecx] + first_dword_for_division_ready: + mov eax,edx + xor edx,edx + div [divisor] + mov [edi+ecx],eax + divide_dwords: + sub ecx,4 + jc dwords_divided + mov eax,[esi+ecx] + div [divisor] + mov [edi+ecx],eax + jmp divide_dwords + dwords_divided: + mov ecx,[esi-4] + and ecx,not 11b + add ecx,4 + call optimize_positive_value + lea ebx,[edi-4] + mov [ebx],ecx + lea edi,[edi+ecx+4] + mov ecx,5 + mov [edi],edx + mov [edi+4],ch + call optimize_positive_value + lea eax,[edi-4] + mov [eax],ecx + sub ebx,[value_workspace.memory_start] + mov edi,[destination_term] + mov [edi+ExpressionTerm.value],ebx + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + sub eax,[value_workspace.memory_start] + mov esi,[source_term] + mov [esi+ExpressionTerm.value],eax + mov [esi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + add eax,4 + add eax,ecx + mov [value_position],eax + test ecx,ecx + retn + optimize_positive_value: + mov al,[edi+ecx-1] + test al,al + js zero_extension_needed + jnz positive_value_optimized + dec ecx + jnz optimize_positive_value + positive_value_optimized: + retn + zero_extension_needed: + inc ecx + retn + division_by_zero: + mov edx,_indeterminate_result + call register_error + xor eax,eax + jmp zero_product + +invert_term_value_bits: +; in: +; edi - ExpressionTerm +; out: +; zf set if result is zero +; preserves: esi, edi + mov [destination_term],edi + call get_numeric_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov ecx,[esi] + add ecx,4 + mov edx,value_workspace + call reserve_workspace + jnc pointers_ready_for_bit_inversion + mov edi,[destination_term] + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + pointers_ready_for_bit_inversion: + mov edx,[esi] + xor ecx,ecx + test edx,edx + jz invert_zero + and edx,not 11b + add esi,4 + add edi,4 + invert_bits_in_dwords: + cmp ecx,edx + je bits_in_dwords_inverted + mov eax,[esi+ecx] + not eax + mov [edi+ecx],eax + add ecx,4 + jmp invert_bits_in_dwords + bits_in_dwords_inverted: + mov edx,[esi-4] + invert_bits_in_bytes: + cmp ecx,edx + je bits_in_bytes_inverted + mov al,[esi+ecx] + not al + mov [edi+ecx],al + inc ecx + jmp invert_bits_in_bytes + bits_in_bytes_inverted: + sub edi,4 + mov [edi],ecx + jmp value_finished + invert_zero: + inc ecx + mov [edi],ecx + neg cl + mov [edi+4],cl + jmp value_finished + +bitwise_add_term_values: +; in: +; esi - source ExpressionTerm +; edi - destination ExpressionTerm +; out: +; zf set if result is zero +; preserves: esi, edi + call set_up_bitwise_operation + jc zero_product + bitwise_add_dwords: + cmp ecx,edx + je dwords_added_bitwise + mov eax,[esi+ecx] + xor eax,[ebx+ecx] + mov [edi+ecx],eax + add ecx,4 + jmp bitwise_add_dwords + dwords_added_bitwise: + mov edx,[ebx-4] + bitwise_add_bytes: + cmp ecx,edx + je bytes_added_bitwise + mov al,[esi+ecx] + xor al,[ebx+ecx] + mov [edi+ecx],al + inc ecx + jmp bitwise_add_bytes + bytes_added_bitwise: + movsx ebx,byte [ebx+ecx-1] + sar ebx,8 + mov edx,[esi-4] + sub edx,ecx + and edx,not 11b + add edx,ecx + bitwise_add_supernumerary_dwords: + cmp ecx,edx + je supernumerary_dwords_added_bitwise + mov eax,[esi+ecx] + xor eax,ebx + mov [edi+ecx],eax + add ecx,4 + jmp bitwise_add_supernumerary_dwords + supernumerary_dwords_added_bitwise: + mov edx,[esi-4] + bitwise_add_supernumerary_bytes: + cmp ecx,edx + je supernumerary_bytes_added_bitwise + mov al,[esi+ecx] + xor al,bl + mov [edi+ecx],al + inc ecx + jmp bitwise_add_supernumerary_bytes + supernumerary_bytes_added_bitwise: + dec ecx + mov esi,[source_term] + jmp value_calculated + set_up_bitwise_operation: + mov [source_term],esi + mov [destination_term],edi + call get_numeric_term_value + mov ebx,[edx] + mov edi,esi + call get_numeric_term_value + mov ecx,[edx] + mov eax,ecx + or eax,ebx + jz bitwise_zero_with_zero + cmp ecx,ebx + jae bitwise_result_length_estimated + mov ecx,ebx + bitwise_result_length_estimated: + add ecx,4 + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov edx,value_workspace + call reserve_workspace + mov edi,[destination_term] + call get_term_value + mov ebx,edx + mov edi,esi + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov edx,[ebx] + cmp edx,[esi] + jb shorter_value_selected + mov edx,[esi] + xchg ebx,esi + shorter_value_selected: + and edx,not 11b + add ebx,4 + add esi,4 + add edi,4 + xor al,al + xor ecx,ecx + retn + bitwise_zero_with_zero: + stc + retn + +bitwise_multiply_term_values: +; in: +; esi - source ExpressionTerm +; edi - destination ExpressionTerm +; out: +; zf set if result is zero +; preserves: esi, edi + call set_up_bitwise_operation + jc zero_product + bitwise_multiply_dwords: + cmp ecx,edx + je dwords_multiplied_bitwise + mov eax,[esi+ecx] + and eax,[ebx+ecx] + mov [edi+ecx],eax + add ecx,4 + jmp bitwise_multiply_dwords + dwords_multiplied_bitwise: + mov edx,[ebx-4] + bitwise_multiply_bytes: + cmp ecx,edx + je bytes_multiplied_bitwise + mov al,[esi+ecx] + and al,[ebx+ecx] + mov [edi+ecx],al + inc ecx + jmp bitwise_multiply_bytes + bytes_multiplied_bitwise: + movsx ebx,byte [ebx+ecx-1] + sar ebx,8 + mov edx,[esi-4] + sub edx,ecx + and edx,not 11b + add edx,ecx + bitwise_multiply_supernumerary_dwords: + cmp ecx,edx + je supernumerary_dwords_multiplied_bitwise + mov eax,[esi+ecx] + and eax,ebx + mov [edi+ecx],eax + add ecx,4 + jmp bitwise_multiply_supernumerary_dwords + supernumerary_dwords_multiplied_bitwise: + mov edx,[esi-4] + bitwise_multiply_supernumerary_bytes: + cmp ecx,edx + je supernumerary_bytes_multiplied_bitwise + mov al,[esi+ecx] + and al,bl + mov [edi+ecx],al + inc ecx + jmp bitwise_multiply_supernumerary_bytes + supernumerary_bytes_multiplied_bitwise: + dec ecx + mov esi,[source_term] + jmp value_calculated + +bitwise_inclusive_or_of_term_values: +; in: +; esi - source ExpressionTerm +; edi - destination ExpressionTerm +; out: +; zf set if result is zero +; preserves: esi, edi + call set_up_bitwise_operation + jc zero_product + inclusive_or_of_dwords: + cmp ecx,edx + je performed_inclusive_or_of_dwords + mov eax,[esi+ecx] + or eax,[ebx+ecx] + mov [edi+ecx],eax + add ecx,4 + jmp inclusive_or_of_dwords + performed_inclusive_or_of_dwords: + mov edx,[ebx-4] + inclusive_or_of_bytes: + cmp ecx,edx + je performed_inclusive_or_of_bytes + mov al,[esi+ecx] + or al,[ebx+ecx] + mov [edi+ecx],al + inc ecx + jmp inclusive_or_of_bytes + performed_inclusive_or_of_bytes: + movsx ebx,byte [ebx+ecx-1] + sar ebx,8 + mov edx,[esi-4] + sub edx,ecx + and edx,not 11b + add edx,ecx + inclusive_or_of_supernumerary_dwords: + cmp ecx,edx + je performed_inclusive_or_of_supernumerary_dwords + mov eax,[esi+ecx] + or eax,ebx + mov [edi+ecx],eax + add ecx,4 + jmp inclusive_or_of_supernumerary_dwords + performed_inclusive_or_of_supernumerary_dwords: + mov edx,[esi-4] + inclusive_or_of_supernumerary_bytes: + cmp ecx,edx + je performed_inclusive_or_of_supernumerary_bytes + mov al,[esi+ecx] + or al,bl + mov [edi+ecx],al + inc ecx + jmp inclusive_or_of_supernumerary_bytes + performed_inclusive_or_of_supernumerary_bytes: + dec ecx + mov esi,[source_term] + jmp value_calculated + +shift_term_value_left: +; in: +; edi - ExpressionTerm +; dl:eax = number of bits +; out: +; zf set if result is zero +; preserves: esi, edi + mov ebx,eax + and al,8-1 + mov [bit_shift],al + shrd ebx,edx,3 + shr dl,3 + mov [shift_overflow],dl + mov [destination_term],edi + call get_numeric_term_value + mov eax,[edx] + check_for_shifted_zero: + test eax,eax + jz shift_left_ok + cmp byte [edx+4+eax-1],0 + jne reserve_memory_for_shift_left + dec eax + jmp check_for_shifted_zero + reserve_memory_for_shift_left: + cmp [shift_overflow],0 + jne out_of_memory + push esi + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov ecx,[esi] + add ecx,ebx + jc out_of_memory + add ecx,5 + jc out_of_memory + mov edx,value_workspace + call reserve_workspace + jnc pointers_ready_for_shift_left + mov edi,[destination_term] + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + pointers_ready_for_shift_left: + add edi,4 + mov ecx,ebx + push ecx + xor al,al + rep stosb + mov cl,[bit_shift] + mov edx,[esi] + add esi,4 + xor ebx,ebx + shift_bytes_left: + cmp ebx,edx + je bytes_shifted_left + mov ah,[esi+ebx] + shl eax,cl + mov [edi+ebx],ah + mov al,[esi+ebx] + inc ebx + jmp shift_bytes_left + bytes_shifted_left: + movsx eax,byte [esi+ebx-1] + shl eax,cl + mov [edi+ebx],ah + pop ecx + sub edi,ecx + add ecx,ebx + pop esi + jmp value_calculated + shift_left_ok: + retn + +shift_term_value_right: +; in: +; edi - ExpressionTerm +; dl:eax = number of bits +; out: +; zf set if result is zero +; preserves: esi, edi + push esi + mov ebx,eax + and al,8-1 + mov [bit_shift],al + shrd ebx,edx,3 + shr dl,3 + jz byte_shift_ok + or ebx,-1 + byte_shift_ok: + mov [destination_term],edi + call get_numeric_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov ecx,[esi] + sub ecx,ebx + jnc size_of_shift_result_estimated + xor ecx,ecx + size_of_shift_result_estimated: + add ecx,5 + mov edx,value_workspace + call reserve_workspace + jnc pointers_ready_for_shift_right + mov edi,[destination_term] + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + pointers_ready_for_shift_right: + add edi,4 + mov cl,[bit_shift] + mov edx,[esi] + sub edx,ebx + jbe value_dissipated + lea esi,[esi+4+ebx] + xor ebx,ebx + shift_bytes_right: + inc ebx + cmp ebx,edx + je bytes_shifted_right + mov ax,[esi+ebx-1] + shr ax,cl + mov [edi+ebx-1],al + jmp shift_bytes_right + bytes_shifted_right: + dec ebx + movsx eax,byte [esi+ebx] + shr eax,cl + mov [edi+ebx],al + mov ecx,ebx + pop esi + jmp value_calculated + value_dissipated: + mov edx,[esi] + movsx eax,byte [esi+4+edx-1] + mov [edi],ah + xor ecx,ecx + pop esi + jmp value_calculated + +find_first_set_bit_in_term_value: +; in: +; esi - ExpressionTerm +; out: +; zf set when value is zero +; when zf = 0: +; dl:eax = index of first set bit +; preserves: esi, edi + xchg edi,esi + call get_numeric_term_value + xchg edi,esi + mov ebx,edx + mov edx,[ebx] + and edx,not 11b + xor ecx,ecx + add ebx,4 + find_first_set_bit_in_dwords: + cmp ecx,edx + je no_set_bit_found_in_dwords + bsf eax,[ebx+ecx] + jnz first_set_bit_found + add ecx,4 + jmp find_first_set_bit_in_dwords + no_set_bit_found_in_dwords: + mov edx,[ebx-4] + find_first_set_bit_in_bytes: + cmp ecx,edx + je no_set_bit_found + movzx eax,byte [ebx+ecx] + bsf eax,eax + jnz first_set_bit_found + inc ecx + jmp find_first_set_bit_in_bytes + no_set_bit_found: + retn + first_set_bit_found: + xor dl,dl + shld edx,ecx,3 + shl ecx,3 + add eax,ecx + adc dl,0 + inc dh + retn + +find_last_set_bit_in_term_value: +; in: +; esi - ExpressionTerm +; out: +; cf set when value is zero or negative +; when cf = 0: +; dl:eax = index of last set bit +; preserves: esi, edi + xchg edi,esi + call get_numeric_term_value + xchg edi,esi + mov ebx,edx + mov edx,[ebx] + add ebx,4 + test byte [ebx+edx-1],80h + jnz last_set_bit_unreachable + mov ecx,edx + and edx,11b + find_last_set_bit_in_dwords: + cmp ecx,edx + je find_last_set_bit_in_bytes + sub ecx,4 + bsr eax,[ebx+ecx] + jnz last_set_bit_found + jmp find_last_set_bit_in_dwords + find_last_set_bit_in_bytes: + jecxz last_set_bit_unreachable + dec ecx + movzx eax,byte [ebx+ecx] + bsr eax,eax + jnz last_set_bit_found + jmp find_last_set_bit_in_bytes + last_set_bit_unreachable: + stc + retn + last_set_bit_found: + xor dl,dl + shld edx,ecx,3 + shl ecx,3 + add eax,ecx + adc dl,0 + ; clc + retn + +truncate_term_value: +; in: +; edi - ExpressionTerm +; preserves: edi + cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT + jne get_numeric_term_value + mov [destination_term],edi + call get_term_value + mov ecx,[edx+FloatData.exponent] + cmp ecx,0 + jl no_integer_part + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + shr ecx,5 + lea ecx,[4+(ecx+1)*4] + mov edx,value_workspace + call reserve_workspace + jnc pointers_ready_for_truncation + mov edi,[destination_term] + call get_term_value + mov esi,edx + mov edi,[value_position] + add edi,[value_workspace.memory_start] + pointers_ready_for_truncation: + add edi,4 + mov ecx,32*MANTISSA_SEGMENTS + sub ecx,[esi+FloatData.exponent] + jbe integer_precision_loss + dec ecx + mov edx,ecx + and ecx,11111b + shr edx,5 + neg edx + add edx,MANTISSA_SEGMENTS + mov ebx,[esi+FloatData.mantissa+(edx-1)*4] + extract_integer_bits: + mov eax,ebx + dec edx + jz extract_highest_integer_bits + mov ebx,[esi+FloatData.mantissa+(edx-1)*4] + shrd eax,ebx,cl + stosd + jmp extract_integer_bits + extract_highest_integer_bits: + shr eax,cl + stosd + integer_part_ready: + and byte [edi],0 + dec ecx + sar ecx,3 + neg ecx + add ecx,edi + mov edi,[destination_term] + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE + mov edx,[value_position] + mov [edi+ExpressionTerm.value],edx + sub ecx,[value_workspace.memory_start] + mov [value_position],ecx + sub ecx,edx + sub ecx,4 + add edx,[value_workspace.memory_start] + mov [edx],ecx + test [esi+FloatData.attributes],FLOAT_NEGATIVE + jnz negate_term_value + retn + integer_precision_loss: + neg ecx + inc ecx + mov edx,ecx + shr ecx,5 + xor eax,eax + rep stosd + mov ecx,edx + and ecx,11111b + mov edx,MANTISSA_SEGMENTS-1 + mov eax,[esi+FloatData.mantissa+edx*4] + shl eax,cl + stosd + extract_significant_bits: + mov eax,[esi+FloatData.mantissa+(edx-1)*4] + mov ebx,[esi+FloatData.mantissa+edx*4] + shld eax,ebx,cl + stosd + dec edx + jnz extract_significant_bits + mov eax,[esi+FloatData.mantissa+edx*4] + neg ecx + and ecx,11111b + jnz extract_highest_integer_bits + xor eax,eax + jmp integer_part_ready + no_integer_part: + mov [edi+ExpressionTerm.value],zero_value + mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + retn + +reverse_term_value_bytes: +; in: +; edi - ExpressionTerm +; ebx = number of bytes +; preserves: esi, edi + push esi + mov [destination_term],edi + call get_numeric_term_value + mov edi,[value_position] + add edi,[value_workspace.memory_start] + mov ecx,ebx + add ecx,4 + mov edx,value_workspace + call reserve_workspace + mov edi,[destination_term] + call get_term_value + mov [edi+ExpressionTerm.attributes],EXPR_STRING + EXPRF_VALUE_IN_WORKSPACE + mov esi,[value_position] + mov [edi+ExpressionTerm.value],esi + lea eax,[esi+4+ebx] + mov [value_position],eax + add esi,[value_workspace.memory_start] + mov [esi],ebx + xor ecx,ecx + test ebx,ebx + jz reversed_bytes_ready + store_reversed_bytes: + cmp ecx,[edx] + jae extend_reversed_bytes + mov al,[edx+4+ecx] + mov [esi+4+ebx-1],al + inc ecx + dec ebx + jnz store_reversed_bytes + reversed_bytes_ready: + cmp ecx,[edx] + jae reversed_bytes_ok + mov al,[edx+4+ecx] + cbw + mov al,ah + lea edi,[edx+4+ecx] + neg ecx + add ecx,[edx] + repe scasb + je reversed_bytes_ok + mov edx,_value_out_of_range + call register_error + jmp reversed_bytes_ok + extend_reversed_bytes: + mov al,[edx+4+ecx-1] + cbw + mov al,ah + lea edi,[esi+4] + mov ecx,ebx + rep stosb + reversed_bytes_ok: + mov edi,[destination_term] + pop esi + retn diff --git a/toolchain/fasm2/source/floats.inc b/toolchain/fasm2/source/floats.inc new file mode 100644 index 0000000..c114e0d --- /dev/null +++ b/toolchain/fasm2/source/floats.inc @@ -0,0 +1,1182 @@ + +struct FloatData + attributes dd ? ; FLOAT_# + exponent dd ? + mantissa rd MANTISSA_SEGMENTS +ends + +MANTISSA_SEGMENTS = 4 + +FLOAT_NEGATIVE = 1 +FLOAT_INFINITE = 2 +FLOAT_INDETERMINATE = 4 +FLOAT_UNDERFLOW = 8 + +number_to_float: +; in: +; esi - 32-bit length followed by binary data of that length +; edi - FloatData +; preserves: edi +; note: the number is treated as unsigned + xor eax,eax + mov [edi+FloatData.attributes],eax + lodsd + mov ecx,eax + cmp eax,10000000h + ja unsigned_too_large + shl eax,3 + dec eax + mov [edi+FloatData.exponent],eax + mov edx,MANTISSA_SEGMENTS*4 + cmp ecx,edx + ja unsigned_precision_loss + xor eax,eax + mov [mantissa_tail],eax + zero_appended_segments: + sub edx,4 + jc converted_mantissa_ready + cmp ecx,edx + ja appended_segments_zeroed + mov [edi+FloatData.mantissa+edx],eax + jmp zero_appended_segments + appended_segments_zeroed: + sub ecx,edx + jz copy_significant_dwords + read_lowest_bytes: + lodsb + ror eax,8 + loop read_lowest_bytes + mov [edi+FloatData.mantissa+edx],eax + sub edx,4 + jc converted_mantissa_ready + copy_significant_dwords: + lodsd + mov [edi+FloatData.mantissa+edx],eax + sub edx,4 + jnc copy_significant_dwords + converted_mantissa_ready: + mov esi,edi + call normalize_float + call round_float + retn + unsigned_precision_loss: + sub ecx,edx + add esi,ecx + mov eax,[esi-4] + sub ecx,4 + jz unsigned_tail_ready + jc unsigned_short_tail + xor dl,dl + lea ebx,[esi-4] + unsigned_tail_contraction: + dec ebx + or dl,[ebx] + loop unsigned_tail_contraction + setnz dl + and dl,1 + or al,dl + jmp unsigned_tail_ready + unsigned_short_tail: + neg cl + shl cl,3 + shr eax,cl + shl eax,cl + unsigned_tail_ready: + mov [mantissa_tail],eax + mov edx,(MANTISSA_SEGMENTS-1)*4 + jmp copy_significant_dwords + unsigned_too_large: + or [edi+FloatData.attributes],FLOAT_INFINITE + retn + +get_float_exponent: +; in: +; esi - FloatData +; out: +; zf set when value is zero +; eax = exponent of normalized value +; preserves: ebx, ecx, esi, edi +; note: +; when value cannot be normalized, smallest possible exponent is returned +; float attributes are ignored + xor eax,eax + find_exponent: + inc eax + bsr edx,[esi+FloatData.mantissa+(eax-1)*4] + jnz exponent_found + cmp eax,MANTISSA_SEGMENTS + jne find_exponent + xor edx,edx + minimal_exponent: + mov eax,-80000000h + test edx,edx + retn + exponent_found: + assert MANTISSA_SEGMENTS shl 5 <= 1 shl 32 + inc edx + shl eax,5 + sub edx,eax + mov eax,[esi+FloatData.exponent] + add eax,edx + jo minimal_exponent + test esi,esi + retn + +get_float_unnormalization: +; in: +; esi - FloatData +; out: +; cf set when value is zero +; when cf = 0: +; ecx = number of leading zeroes in mantissa +; preserves: ebx, edx, esi, edi + xor ecx,ecx + find_highest_set_bit: + inc ecx + bsr eax,[esi+FloatData.mantissa+(ecx-1)*4] + jnz highest_set_bit_found + cmp ecx,MANTISSA_SEGMENTS + jne find_highest_set_bit + stc + retn + highest_set_bit_found: + assert MANTISSA_SEGMENTS shl 5 <= 1 shl 32 + inc eax + shl ecx,5 + sub ecx,eax + ; clc + retn + +normalize_float: +; in: +; esi - source FloatData +; edi - destination FloatData +; [mantissa_tail] = additional bits of source mantissa, lowest bit indicating that there are set bits far down +; out: +; [mantissa_tail] = additional bits of destination mantissa, lowest bit indicating that there are set bits far down +; preserves: esi, edi +; note: float attributes are ignored + xor edx,edx + find_highest_bit: + bsr ecx,[esi+FloatData.mantissa+edx*4] + jnz highest_bit_found + inc edx + cmp edx,MANTISSA_SEGMENTS + jne find_highest_bit + bsr ecx,[mantissa_tail] + jnz highest_bit_found + call copy_float_data + mov [edi+FloatData.exponent],-80000000h + retn + copy_float_data: + cmp esi,edi + je float_data_ready + assert sizeof.FloatData and 11b = 0 + mov ecx,sizeof.FloatData shr 2 + rep movsd + sub esi,sizeof.FloatData + sub edi,sizeof.FloatData + float_data_ready: + retn + highest_bit_found: + not ecx + add ecx,32 + mov eax,edx + shl eax,5 + add eax,ecx + neg eax + jz copy_float_data + add eax,[esi+FloatData.exponent] + jo copy_float_data + mov [edi+FloatData.exponent],eax + add edi,FloatData.mantissa + shift_mantissa_up: + push edx + xor eax,eax + cmp edx,MANTISSA_SEGMENTS-1 + ja shift_mantissa_tail_up + mov eax,[esi+FloatData.mantissa+edx*4] + je shift_mantissa_tail_up + shift_mantissa_segment_up: + inc edx + mov ebx,[esi+FloatData.mantissa+edx*4] + shld eax,ebx,cl + stosd + mov eax,ebx + cmp edx,MANTISSA_SEGMENTS-1 + jne shift_mantissa_segment_up + shift_mantissa_tail_up: + mov ebx,[mantissa_tail] + and ebx,not 1 + shld eax,ebx,cl + stosd + mov eax,ebx + shl eax,cl + pop ecx + jecxz mantissa_normalized + stosd + dec ecx + xor eax,eax + rep stosd + mantissa_normalized: + and [mantissa_tail],1 + or [mantissa_tail],eax + sub edi,FloatData.mantissa + MANTISSA_SEGMENTS*4 + mov eax,[esi+FloatData.attributes] + mov [edi+FloatData.attributes],eax + retn + +unnormalize_float: +; in: +; esi - source FloatData +; edi - destination FloatData +; ecx = target exponent +; [mantissa_tail] = additional bits of source mantissa, lowest bit indicating that there are set bits far down +; out: +; [mantissa_tail] = additional bits of destination mantissa, lowest bit indicating that there are set bits far down +; preserves: esi, edi +; note: +; when target exponent is smaller than the actual one, the overflowing bits are ignored +; float attributes are ignored + mov eax,[esi+FloatData.exponent] + mov [edi+FloatData.exponent],ecx + sub ecx,eax + jz copy_float_data + js contrary_unnormalization + mov ebx,ecx + shr ebx,5 + and cl,11111b + add edi,FloatData.mantissa + (MANTISSA_SEGMENTS-1)*4 + std + mov edx,MANTISSA_SEGMENTS + sub edx,ebx + push ebx + mov ebx,edx + mov edx,MANTISSA_SEGMENTS + mov eax,[mantissa_tail] + collect_far_mantissa: + cmp edx,ebx + je far_mantissa_collected + or [mantissa_tail],eax + mov eax,[esi+FloatData.mantissa+(edx-1)*4] + dec edx + jz unnormalization_underflow + jmp collect_far_mantissa + far_mantissa_collected: + mov ebx,[esi+FloatData.mantissa+(edx-1)*4] + shrd eax,ebx,cl + xchg eax,[mantissa_tail] + test eax,eax + setnz al + and eax,1 + or [mantissa_tail],eax + dec edx + jz shift_first_mantissa_segment_down + shift_mantissa_segment_down: + mov eax,ebx + mov ebx,[esi+FloatData.mantissa+(edx-1)*4] + shrd eax,ebx,cl + stosd + dec edx + jnz shift_mantissa_segment_down + shift_first_mantissa_segment_down: + mov eax,[esi+FloatData.mantissa] + shr eax,cl + stosd + pop ecx + zero_higher_mantissa_segments: + xor eax,eax + rep stosd + sub edi,FloatData.mantissa-4 + cld + mov eax,[esi+FloatData.attributes] + mov [edi+FloatData.attributes],eax + retn + unnormalization_underflow: + cmp edx,ebx + je only_mantissa_tail + or [mantissa_tail],eax + xor eax,eax + only_mantissa_tail: + shr eax,cl + xchg eax,[mantissa_tail] + test eax,eax + setnz al + and eax,1 + or [mantissa_tail],eax + pop ebx + mov ecx,MANTISSA_SEGMENTS + jmp zero_higher_mantissa_segments + contrary_unnormalization: + add edi,FloatData.mantissa + neg ecx + mov edx,ecx + shr edx,5 + cmp edx,MANTISSA_SEGMENTS + ja unnormalization_overflow + and cl,11111b + jmp shift_mantissa_up + unnormalization_overflow: + mov ecx,MANTISSA_SEGMENTS + xor eax,eax + rep stosd + sub edi,FloatData.mantissa + MANTISSA_SEGMENTS*4 + retn + +round_float: +; in: +; edi - FloatData +; [mantissa_tail] = additional bits of mantissa, lowest bit indicating that there are set bits far down +; preserves: ebx, esi, edi + test [mantissa_tail],1 shl 31 + jz rounding_done + test [mantissa_tail],not (1 shl 31) + jnz round_up + test [edi+FloatData.mantissa+(MANTISSA_SEGMENTS-1)*4],1 + jz rounding_done + round_up: + mov edx,MANTISSA_SEGMENTS + increment_mantissa: + inc [edi+FloatData.mantissa+(edx-1)*4] + jnz rounding_done + dec edx + jnz increment_mantissa + or [edi+FloatData.mantissa],80000000h + add [edi+FloatData.exponent],1 + jo float_overflow + rounding_done: + retn + float_overflow: + or [edi+FloatData.attributes],FLOAT_INFINITE + retn + +add_floats: +; in: +; ebx - FloatData with first addend +; esi - FloatData with second addend +; edi - FloatData where sum should be stored +; preserves: edi + test [ebx+FloatData.attributes],FLOAT_NEGATIVE + setnz [first_sign] + test [esi+FloatData.attributes],FLOAT_NEGATIVE + setnz [second_sign] + float_summator: + call get_float_exponent + mov ecx,eax + xchg esi,ebx + call get_float_exponent + cmp eax,ecx + jge significant_mantissa_selected + xchg esi,ebx + mov al,[first_sign] + xchg al,[second_sign] + mov [first_sign],al + significant_mantissa_selected: + push edi + mov eax,[esi+FloatData.mantissa] + test eax,eax + js align_second_mantissa + push ebx + mov edi,[temporary_floats] + and [mantissa_tail],0 + call normalize_float + mov esi,edi + pop ebx + align_second_mantissa: + push esi + and [mantissa_tail],0 + mov ecx,[esi+FloatData.exponent] + mov esi,ebx + mov edi,[temporary_floats] + add edi,sizeof.FloatData + call unnormalize_float + mov ebx,edi + pop esi + pop edi + mov eax,[esi+FloatData.attributes] + or eax,[ebx+FloatData.attributes] + and eax,FLOAT_INFINITE or FLOAT_INDETERMINATE + mov [edi+FloatData.attributes],eax + mov ecx,[esi+FloatData.exponent] + mov [edi+FloatData.exponent],ecx + mov al,[first_sign] + xor al,[second_sign] + jnz opposite_mantissa + mov ecx,MANTISSA_SEGMENTS + clc + add_mantissa_segments: + mov eax,[esi+FloatData.mantissa+(ecx-1)*4] + adc eax,[ebx+FloatData.mantissa+(ecx-1)*4] + mov [edi+FloatData.mantissa+(ecx-1)*4],eax + loop add_mantissa_segments + jnc sum_value_ready + mov ecx,[edi+FloatData.exponent] + add ecx,1 + jo float_overflow + mov esi,edi + call unnormalize_float + or [edi+FloatData.mantissa],80000000h + jmp sum_value_ready + opposite_mantissa: + xor ecx,ecx + compare_mantissa_segments: + mov eax,[esi+FloatData.mantissa+ecx*4] + cmp eax,[ebx+FloatData.mantissa+ecx*4] + ja keep_mantissa_sources + jb switch_mantissa_sources + inc ecx + cmp ecx,MANTISSA_SEGMENTS + jne compare_mantissa_segments + switch_mantissa_sources: + xchg esi,ebx + mov al,[first_sign] + xchg al,[second_sign] + mov [first_sign],al + clc + jmp mantissa_subtraction_ready + keep_mantissa_sources: + neg [mantissa_tail] + mantissa_subtraction_ready: + mov ecx,MANTISSA_SEGMENTS + subtract_mantissa_segments: + mov eax,[esi+FloatData.mantissa+(ecx-1)*4] + sbb eax,[ebx+FloatData.mantissa+(ecx-1)*4] + mov [edi+FloatData.mantissa+(ecx-1)*4],eax + loop subtract_mantissa_segments + mov esi,edi + call normalize_float + sum_value_ready: + xor eax,eax + cmp [first_sign],0 + je round_float + or [edi+FloatData.attributes],FLOAT_NEGATIVE + jmp round_float + +subtract_floats: +; in: +; ebx - FloatData with minuend +; esi - FloatData with subtrahend +; edi - FloatData where difference should be stored +; preserves: edi + test [ebx+FloatData.attributes],FLOAT_NEGATIVE + setnz [first_sign] + test [esi+FloatData.attributes],FLOAT_NEGATIVE + setz [second_sign] + jmp float_summator + +multiply_float_by_unsigned_int: +; in: +; esi - source FloatData +; ecx = unsigned multiplier +; edi - FloatData where multipled value should be stored +; preserves: edi + mov [multiplier],ecx + cmp esi,edi + je multiply_mantissa + mov eax,[esi+FloatData.attributes] + mov edx,[esi+FloatData.exponent] + mov [edi+FloatData.attributes],eax + mov [edi+FloatData.exponent],edx + multiply_mantissa: + xor edx,edx + mov [mantissa_tail],edx + mov ecx,MANTISSA_SEGMENTS + multiply_mantissa_segments: + mov ebx,edx + mov eax,[esi+FloatData.mantissa+(ecx-1)*4] + mul [multiplier] + add eax,ebx + mov [edi+FloatData.mantissa+(ecx-1)*4],eax + loop multiply_mantissa_segments + mov esi,edi + bsr ecx,edx + jz normalize_float + inc ecx + mov eax,ecx + neg cl + add cl,32 + shl edx,cl + push edx + mov ecx,eax + add ecx,[esi+FloatData.exponent] + jo float_overflow + call unnormalize_float + pop eax + or [edi+FloatData.mantissa],eax + jmp round_float + +multiply_floats: +; in: +; ebx - FloatData with first factor +; esi - FloatData with second factor +; edi - FloatData where product should be stored +; preserves: edi + test [esi+FloatData.attributes],FLOAT_INFINITE or FLOAT_INDETERMINATE + jnz first_factor_not_zero + call get_float_exponent + jz multiply_zero_float + first_factor_not_zero: + xchg esi,ebx + test [esi+FloatData.attributes],FLOAT_INFINITE or FLOAT_INDETERMINATE + jnz second_factor_not_zero + call get_float_exponent + jz multiply_zero_float + second_factor_not_zero: + mov eax,[ebx+FloatData.attributes] + mov edx,[esi+FloatData.attributes] + xor eax,edx + and edx,FLOAT_INFINITE or FLOAT_INDETERMINATE + or eax,edx + mov [edi+FloatData.attributes],eax + mov eax,[ebx+FloatData.exponent] + add eax,[esi+FloatData.exponent] + jo exponent_overflow + inc eax + jo exponent_overflow + mov [edi+FloatData.exponent],eax + push edi + mov edi,accumulator + xor eax,eax + mov ecx,3 + rep stosd + mov [mantissa_tail],eax + mov ecx,MANTISSA_SEGMENTS-1 + mov edi,ecx + multiply_low_segments: + or [mantissa_tail],eax + mov eax,[ebx+FloatData.mantissa+ecx*4] + mul [esi+FloatData.mantissa+edi*4] + add [accumulator],eax + adc [accumulator+4],edx + adc [accumulator+8],0 + dec ecx + inc edi + cmp edi,MANTISSA_SEGMENTS + jb multiply_low_segments + dec edi + xchg ecx,edi + xor eax,eax + xchg eax,[accumulator+8] + xchg eax,[accumulator+4] + xchg eax,[accumulator] + cmp edi,0 + jge multiply_low_segments + xchg eax,[mantissa_tail] + test eax,eax + setnz al + and eax,1 + or [mantissa_tail],eax + dec ecx + inc edi + multiply_high_segments: + mov eax,[ebx+FloatData.mantissa+ecx*4] + mul [esi+FloatData.mantissa+edi*4] + add [accumulator],eax + adc [accumulator+4],edx + adc [accumulator+8],0 + dec ecx + inc edi + cmp ecx,0 + jge multiply_high_segments + inc ecx + xchg ecx,edi + xor eax,eax + xchg eax,[accumulator+8] + xchg eax,[accumulator+4] + xchg eax,[accumulator] + mov edx,[esp] + mov [edx+FloatData.mantissa+ecx*4],eax + sub ecx,2 + ja multiply_high_segments + mov eax,[ebx+FloatData.mantissa] + mul [esi+FloatData.mantissa] + add eax,[accumulator] + adc edx,[accumulator+4] + pop edi + mov [edi+FloatData.mantissa+4],eax + mov [edi+FloatData.mantissa],edx + mov esi,edi + call normalize_float + jmp round_float + multiply_zero_float: + mov eax,[ebx+FloatData.attributes] + test eax,FLOAT_INFINITE or FLOAT_INDETERMINATE + jnz indeterminate_product + mov edx,[esi+FloatData.attributes] + and edx,FLOAT_NEGATIVE + xor eax,edx + mov [edi+FloatData.attributes],eax + xor eax,eax + zero_float_result: + mov [edi+FloatData.exponent],eax + xor eax,eax + add edi,FloatData.mantissa + mov ecx,MANTISSA_SEGMENTS + rep stosd + sub edi,FloatData.mantissa + MANTISSA_SEGMENTS*4 + retn + indeterminate_product: + or [edi+FloatData.attributes],FLOAT_INDETERMINATE + retn + exponent_overflow: + js float_overflow + mov [edi+FloatData.attributes],FLOAT_UNDERFLOW + jmp zero_float_result + +multiply_float_by_power_of_ten: +; in: +; esi - FloatData with number to multiply +; ecx = signed number representing exponent +; edi - FloatData for the result +; preserves: edi + call get_float_exponent + jz copy_float_data + cmp ecx,0 + je copy_float_data + jl negative_power_of_ten + mov [exponent],ecx + mov ebx,edi + mov edi,[temporary_floats] + xor eax,eax + mov [edi+FloatData.attributes],eax + mov al,3 + mov [edi+FloatData.exponent],eax + add edi,FloatData.mantissa + mov eax,0A0000000h + stosd + xor eax,eax + mov ecx,MANTISSA_SEGMENTS-1 + rep stosd + mov edi,ebx + get_power_bit: + shr [exponent],1 + jnc square_multiplier + mov ebx,[temporary_floats] + call multiply_floats + test [edi+FloatData.attributes],FLOAT_UNDERFLOW + jnz power_exhausted + square_multiplier: + cmp [exponent],0 + je power_exhausted + push edi + mov ebx,[temporary_floats] + mov esi,ebx + mov edi,ebx + call multiply_floats + test [edi+FloatData.attributes],FLOAT_UNDERFLOW + jnz power_of_ten_underflow + pop edi + mov esi,edi + jmp get_power_bit + power_exhausted: + retn + negative_power_of_ten: + neg ecx + mov [exponent],ecx + mov ebx,edi + mov edi,[temporary_floats] + xor eax,eax + mov [edi+FloatData.attributes],eax + or eax,-4 + mov [edi+FloatData.exponent],eax + add edi,FloatData.mantissa + mov eax,0CCCCCCCCh + mov ecx,MANTISSA_SEGMENTS + dec ecx + rep stosd + inc eax + stosd + mov edi,ebx + jmp get_power_bit + power_of_ten_underflow: + pop edi + or [edi+FloatData.attributes],FLOAT_UNDERFLOW + retn + +multiplicative_inverse: +; in: +; esi - source FloatData +; edi - destination FloatData +; preserves: edi + and [mantissa_tail],0 + call normalize_float + mov eax,[edi+FloatData.attributes] + test eax,FLOAT_INFINITE + jnz reverse_of_infinity + mov ecx,[edi+FloatData.exponent] + cmp ecx,-80000000h + je float_overflow + and [edi+FloatData.attributes],0 + or [edi+FloatData.exponent],-1 + push eax ecx edi + mov [iterations],3 + bsr (MANTISSA_SEGMENTS+1) + mov ebx,edi + mov edi,[temporary_floats] + add edi,2*sizeof.FloatData + xor eax,eax + mov [edi+FloatData.attributes],eax + inc eax + mov [edi+FloatData.exponent],eax + add edi,FloatData.mantissa + mov ecx,MANTISSA_SEGMENTS + mov eax,0B4B4B4B4h + rep stosd + assert FloatData.mantissa + MANTISSA_SEGMENTS*4 = sizeof.FloatData + xor eax,eax + mov [edi+FloatData.attributes],eax + mov [edi+FloatData.exponent],eax + add edi,FloatData.mantissa + mov ecx,MANTISSA_SEGMENTS + mov eax,0F0F0F0F0h + rep stosd + sub edi,FloatData.mantissa + MANTISSA_SEGMENTS*4 + mov esi,edi + call multiply_floats + lea ebx,[edi-sizeof.FloatData] + mov esi,edi + mov edi,ebx + newton_raphson_iteration: + call subtract_floats + mov ebx,edi + mov esi,edi + add edi,sizeof.FloatData + call multiply_floats + mov ebx,[esp] + mov esi,edi + call multiply_floats + mov esi,edi + sub edi,sizeof.FloatData + inc [edi+FloatData.exponent] + mov ebx,edi + dec [iterations] + jnz newton_raphson_iteration + pop edi + call subtract_floats + pop ecx eax + not ecx + add [edi+FloatData.exponent],ecx + and [edi+FloatData.attributes],FLOAT_INFINITE or FLOAT_INDETERMINATE + or [edi+FloatData.attributes],eax + retn + reverse_of_infinity: + and eax,FLOAT_NEGATIVE or FLOAT_INDETERMINATE + mov [edi+FloatData.attributes],eax + xor eax,eax + jmp zero_float_result + +divide_floats: +; in: +; ebx - FloatData with dividend +; esi - FloatData with divisor +; edi - FloatData where quotient should be stored +; preserves: edi + push ebx + call multiplicative_inverse + pop ebx + mov esi,edi + call multiply_floats + retn + +fit_float: +; in: +; esi - FloatData +; ecx = number of bytes that the value has to fit into +; edi - buffer for the specified amount of bytes +; preserves: esi, edi + cmp ecx,2 + je half_precision + cmp ecx,4 + je single_precision + cmp ecx,8 + je double_precision + cmp ecx,10 + je extended_precision + cmp ecx,16 + je quadruple_precision + mov edx,_invalid_value + call register_error + retn + float_out_of_range: + mov edx,_value_out_of_range + call register_error + retn + zero_float: + dec ecx + xor al,al + rep stosb + test [esi+FloatData.attributes],FLOAT_NEGATIVE + setnz al + ror al,1 + stosb + retn + half_precision: + call get_float_exponent + jz zero_float + mov ebx,[esi+FloatData.exponent] + sub ebx,eax + add eax,0Fh + js half_precision_denormal + je half_precision_denormal + cmp eax,1Fh + jae float_out_of_range + mov ecx,10 + shl eax,cl + mov [edi],ax + inc ebx + call read_mantissa_bits + or [edi],ax + call get_mantissa_rounding_increment + add [edi],ax + mov dx,1Fh shl 10 + mov ax,dx + and ax,[edi] + cmp ax,dx + je float_out_of_range + half_precision_ok: + test [esi+FloatData.attributes],FLOAT_NEGATIVE + setnz al + shl ax,15 + or [edi],ax + retn + half_precision_denormal: + neg eax + mov ecx,10 + sub ecx,eax + jc float_out_of_range + call read_mantissa_bits + mov [edi],ax + call get_mantissa_rounding_increment + add [edi],ax + jz float_out_of_range + jmp half_precision_ok + single_precision: + call get_float_exponent + jz zero_float + mov ebx,[esi+FloatData.exponent] + sub ebx,eax + add eax,7Fh + js single_precision_denormal + je single_precision_denormal + cmp eax,0FFh + jae float_out_of_range + mov ecx,23 + shl eax,cl + mov [edi],eax + inc ebx + call read_mantissa_bits + or [edi],eax + call get_mantissa_rounding_increment + add [edi],eax + mov edx,0FFh shl 23 + mov eax,edx + and eax,[edi] + cmp eax,edx + je float_out_of_range + single_precision_ok: + test [esi+FloatData.attributes],FLOAT_NEGATIVE + setnz al + shl eax,31 + or [edi],eax + retn + single_precision_denormal: + neg eax + mov ecx,23 + sub ecx,eax + jc float_out_of_range + call read_mantissa_bits + mov [edi],eax + call get_mantissa_rounding_increment + add [edi],eax + jz float_out_of_range + jmp single_precision_ok + double_precision: + call get_float_exponent + jz zero_float + mov ebx,[esi+FloatData.exponent] + sub ebx,eax + add eax,3FFh + js double_precision_denormal + je double_precision_denormal + cmp eax,7FFh + jae float_out_of_range + mov ecx,20 + shl eax,cl + mov [edi+4],eax + inc ebx + call read_mantissa_bits + or [edi+4],eax + mov ecx,32 + call read_mantissa_bits + mov [edi],eax + call get_mantissa_rounding_increment + xor edx,edx + add [edi],eax + adc [edi+4],edx + mov edx,7FFh shl 20 + mov eax,edx + and eax,[edi+4] + cmp eax,edx + je float_out_of_range + double_precision_ok: + test [esi+FloatData.attributes],FLOAT_NEGATIVE + setnz al + shl eax,31 + or [edi+4],eax + retn + double_precision_denormal: + neg eax + mov ecx,52 + sub ecx,eax + jc float_out_of_range + xor eax,eax + cmp ecx,32 + jbe double_precision_denormal_high_segment_ready + sub ecx,32 + call read_mantissa_bits + mov ecx,32 + double_precision_denormal_high_segment_ready: + mov [edi+4],eax + call read_mantissa_bits + mov [edi],eax + call get_mantissa_rounding_increment + xor edx,edx + add [edi],eax + jc double_precision_denormal_carry + jnz double_precision_ok + cmp [edi+4],edx + je float_out_of_range + jmp double_precision_ok + double_precision_denormal_carry: + adc [edi+4],edx + jmp double_precision_ok + extended_precision: + call get_float_exponent + jz zero_float + mov ebx,[esi+FloatData.exponent] + sub ebx,eax + add eax,3FFFh + js extended_precision_denormal + jz extended_precision_denormal + cmp eax,7FFFh + jae float_out_of_range + mov [edi+8],ax + mov ecx,32 + call read_mantissa_bits + mov [edi+4],eax + mov ecx,32 + call read_mantissa_bits + mov [edi],eax + call get_mantissa_rounding_increment + xor edx,edx + add [edi],eax + adc [edi+4],edx + jnc extended_precision_ok + or byte [edi+7],80h + inc word [edi+8] + cmp word [edi+8],7FFFh + je float_out_of_range + extended_precision_ok: + test [esi+FloatData.attributes],FLOAT_NEGATIVE + setnz al + shl ax,15 + or [edi+8],ax + retn + extended_precision_denormal: + and word [edi+8],0 + neg eax + mov ecx,63 + sub ecx,eax + jc float_out_of_range + xor eax,eax + cmp ecx,32 + jbe extended_precision_denormal_high_segment_ready + sub ecx,32 + call read_mantissa_bits + mov ecx,32 + extended_precision_denormal_high_segment_ready: + mov [edi+4],eax + call read_mantissa_bits + mov [edi],eax + call get_mantissa_rounding_increment + xor edx,edx + add [edi],eax + jc extended_precision_denormal_carry + jnz extended_precision_ok + cmp [edi+4],edx + je float_out_of_range + jmp extended_precision_ok + extended_precision_denormal_carry: + adc [edi+4],edx + jns extended_precision_ok + inc byte [edi+8] + jmp extended_precision_ok + quadruple_precision: + call get_float_exponent + jz zero_float + mov ebx,[esi+FloatData.exponent] + sub ebx,eax + add eax,3FFFh + js quadruple_precision_denormal + je quadruple_precision_denormal + cmp eax,7FFFh + jae float_out_of_range + mov ecx,16 + shl eax,cl + mov [edi+12],eax + inc ebx + call read_mantissa_bits + or [edi+12],eax + mov ecx,32 + call read_mantissa_bits + mov [edi+8],eax + mov ecx,32 + call read_mantissa_bits + mov [edi+4],eax + mov ecx,32 + call read_mantissa_bits + mov [edi],eax + call get_mantissa_rounding_increment + xor edx,edx + add [edi],eax + adc [edi+4],edx + adc [edi+8],edx + adc [edi+12],edx + mov edx,7FFFh shl 16 + mov eax,edx + and eax,[edi+12] + cmp eax,edx + je float_out_of_range + quadruple_precision_ok: + test [esi+FloatData.attributes],FLOAT_NEGATIVE + setnz al + shl eax,31 + or [edi+12],eax + retn + quadruple_precision_denormal: + neg eax + mov ecx,112 + sub ecx,eax + jc float_out_of_range + xor eax,eax + sub ecx,96 + jbe quadruple_precision_denormal_first_segment_ready + call read_mantissa_bits + xor ecx,ecx + quadruple_precision_denormal_first_segment_ready: + mov [edi+12],eax + add ecx,96 + xor eax,eax + sub ecx,64 + jbe quadruple_precision_denormal_second_segment_ready + call read_mantissa_bits + xor ecx,ecx + quadruple_precision_denormal_second_segment_ready: + mov [edi+8],eax + add ecx,64 + xor eax,eax + sub ecx,32 + jbe quadruple_precision_denormal_third_segment_ready + call read_mantissa_bits + xor ecx,ecx + quadruple_precision_denormal_third_segment_ready: + mov [edi+4],eax + add ecx,32 + call read_mantissa_bits + mov [edi],eax + call get_mantissa_rounding_increment + xor edx,edx + add [edi],eax + jc quadruple_precision_denormal_carry + jnz quadruple_precision_ok + or edx,[edi+4] + or edx,[edi+8] + or edx,[edi+12] + jz float_out_of_range + jmp quadruple_precision_ok + quadruple_precision_denormal_carry: + adc [edi+4],edx + adc [edi+8],edx + adc [edi+12],edx + jmp quadruple_precision_ok + read_mantissa_bits: + add ebx,ecx + mov edx,ebx + dec edx + mov al,dl + shr edx,5 + and al,11111b + inc al + mov ch,cl + cmp edx,MANTISSA_SEGMENTS + ja out_of_mantissa_bits + je read_from_mantissa_border + mov cl,32 + sub cl,al + cmp al,ch + jae read_from_single_mantissa_segment + mov eax,[esi+FloatData.mantissa+edx*4] + mov edx,[esi+FloatData.mantissa+(edx-1)*4] + shrd eax,edx,cl + jmp cut_out_mantissa_bits + read_from_single_mantissa_segment: + mov eax,[esi+FloatData.mantissa+edx*4] + shr eax,cl + cut_out_mantissa_bits: + mov cl,ch + cmp cl,32 + je mantissa_bits_ok + mov edx,1 + shl edx,cl + dec edx + and eax,edx + mantissa_bits_ok: + retn + read_from_mantissa_border: + cmp al,32 + jae out_of_mantissa_bits + mov cl,al + mov eax,[esi+FloatData.mantissa+(edx-1)*4] + shl eax,cl + jmp cut_out_mantissa_bits + out_of_mantissa_bits: + xor eax,eax + retn + get_mantissa_rounding_increment: + mov al,bl + shr ebx,5 + and al,11111b + mov cl,31 + sub cl,al + cmp ebx,MANTISSA_SEGMENTS + jae no_rounding_increment + mov edx,1 + shl edx,cl + mov eax,[esi+FloatData.mantissa+ebx*4] + test eax,edx + jz no_rounding_increment + dec edx + and eax,edx + jnz rounding_increment_needed + mov edx,ebx + check_whole_mantissa: + inc edx + cmp edx,MANTISSA_SEGMENTS + jae rounding_tied + cmp dword [esi+FloatData.mantissa+edx*4],0 + je check_whole_mantissa + rounding_increment_needed: + mov eax,1 + retn + rounding_tied: + inc cl + cmp cl,32 + jb test_mantissa_parity + dec ebx + test_mantissa_parity: + mov eax,[esi+FloatData.mantissa+ebx*4] + shr eax,cl + test eax,1 + jnz rounding_increment_needed + no_rounding_increment: + xor eax,eax + retn diff --git a/toolchain/fasm2/source/ide/blocks.inc b/toolchain/fasm2/source/ide/blocks.inc new file mode 100644 index 0000000..fee4f96 --- /dev/null +++ b/toolchain/fasm2/source/ide/blocks.inc @@ -0,0 +1,536 @@ + +; flat editor core +; Copyright (c) 1999-2015, Tomasz Grysztar. +; All rights reserved. + +insert_block: + test [editor_mode],FEMODE_VERTICALSEL + jz block_to_insert_ok + push esi + or edx,-1 + xor ecx,ecx + count_line_characters: + lodsb + cmp al,9 + je cannot_insert + cmp al,0Dh + je count_next_line + or al,al + jz at_end_of_line + inc ecx + jmp count_line_characters + at_end_of_line: + dec esi + jmp check_block_width + count_next_line: + lodsb + cmp al,0Ah + je check_block_width + dec esi + check_block_width: + cmp edx,-1 + je line_to_insert_ok + cmp edx,ecx + je line_to_insert_ok + cannot_insert: + pop esi + stc + retn + line_to_insert_ok: + mov edx,ecx + xor ecx,ecx + cmp byte [esi],0 + jne count_line_characters + pop esi + block_to_insert_ok: + mov eax,[caret_line] + mov ecx,[caret_line_number] + mov edx,[caret_position] + mov [selection_line],eax + mov [selection_line_number],ecx + mov [selection_position],edx + mov ebx,esi + get_line_to_insert: + lodsb + or al,al + jz insert_full_line + cmp al,0Dh + je insert_full_line + cmp al,0Ah + je insert_full_line + cmp al,9 + jne get_line_to_insert + push esi + dec esi + mov ecx,esi + sub ecx,ebx + mov esi,ebx + push ecx + call insert_into_line + pop ecx + add [caret_position],ecx + mov ecx,[caret_position] + and ecx,not 111b + sub ecx,[caret_position] + add ecx,8 + xor esi,esi + push ecx + call insert_into_line + pop ecx + add [caret_position],ecx + pop esi + mov ebx,esi + jmp get_line_to_insert + insert_full_line: + dec esi + push esi + mov ecx,esi + sub ecx,ebx + mov esi,ebx + push ecx + call insert_into_line + pop ecx + add [caret_position],ecx + pop esi + lodsb + or al,al + jz last_line_inserted + cmp al,0Ah + je lf_first + lodsb + cmp al,0Ah + je next_line_to_insert + dec esi + jmp next_line_to_insert + lf_first: + lodsb + cmp al,0Dh + je next_line_to_insert + dec esi + next_line_to_insert: + mov ebx,[selection_position] + test [editor_mode],FEMODE_VERTICALSEL + jnz insert_in_next_line + test [editor_mode],FEMODE_OVERWRITE + jz insert_new_line + push esi + call clear_rest_of_line + pop esi + xor ebx,ebx + insert_in_next_line: + push esi ebx + mov esi,[caret_line] + call check_line_length + pop ebx + call go_to_next_line + pop esi + mov ebx,esi + jmp get_line_to_insert + last_line_inserted: + mov esi,[caret_line] + call check_line_length + clc + retn + insert_new_line: + push esi + push [caret_line] + push [caret_line_number] + xor ebx,ebx + call break_line + pop [caret_line_number] + pop ebx esi + push [caret_line] + mov [caret_line],ebx + go_to_end_of_first_line: + test byte [ebx],1 + jz insert_full_lines + mov ebx,[ebx] + dec ebx + jmp go_to_end_of_first_line + insert_full_lines: + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov [ebx],eax + mov ebx,eax + mov eax,[caret_line] + mov [ebx+4],eax + mov [caret_line],ebx + inc [caret_line_number] + inc [lines_count] + call set_line + jc full_lines_inserted + jmp insert_full_lines + full_lines_inserted: + pop edi + mov eax,[caret_line] + mov [edi+4],eax + mov [ebx],edi + call cut_line_break + mov esi,[caret_line] + call check_line_length + clc + retn + set_line: + mov edi,ebx + add edi,SEGMENT_HEADER_LENGTH + mov ecx,SEGMENT_DATA_LENGTH + mov [caret_position],0 + push ebx + copy_line: + lodsb + or al,al + jz last_line_set + cmp al,0Ah + je copy_lf + cmp al,0Dh + je copy_cr + cmp al,9 + je copy_tab + set_character: + stosb + loop copy_line + extra_segment: + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov edi,eax + or eax,1 + mov [ebx],eax + or ebx,1 + mov [edi+4],ebx + mov ebx,edi + add edi,SEGMENT_HEADER_LENGTH + mov ecx,SEGMENT_DATA_LENGTH + add [caret_position],ecx + jmp copy_line + copy_tab: + mov al,20h + mov edx,SEGMENT_DATA_LENGTH + sub edx,ecx + add edx,[caret_position] + and edx,111b + cmp edx,111b + je set_character + dec esi + jmp set_character + copy_lf: + cmp byte [esi],0Dh + jne copy_new_line + inc esi + jmp copy_new_line + copy_cr: + cmp byte [esi],0Ah + jne copy_new_line + inc esi + copy_new_line: + pop edx + call finish_line + clc + retn + last_line_set: + pop edx + call finish_line + stc + retn + finish_line: + mov eax,SEGMENT_DATA_LENGTH + sub eax,ecx + add eax,[caret_position] + mov [caret_position],eax + mov [edx+8],eax + call register_length + mov al,20h + rep stosb + retn + +delete_block: + test [editor_mode],FEMODE_VERTICALSEL + jnz delete_vertical_block + mov eax,[caret_line_number] + cmp eax,[selection_line_number] + je delete_vertical_block + mov esi,[caret_line] + mov ecx,[caret_line_number] + mov edx,[caret_position] + cmp ecx,[selection_line_number] + jbe position_for_deleting_ok + xchg esi,[selection_line] + xchg ecx,[selection_line_number] + xchg edx,[selection_position] + mov [caret_line],esi + mov [caret_line_number],ecx + mov [caret_position],edx + position_for_deleting_ok: + test [editor_mode],FEMODE_OVERWRITE + jnz clear_block + call get_caret_segment + cmp edx,SEGMENT_DATA_LENGTH + jb first_line_of_block + call attach_empty_segments + first_line_of_block: + mov ecx,[caret_position] + sub ecx,edx + skip_rest_of_first_line: + add ecx,SEGMENT_DATA_LENGTH + mov eax,[esi] + btr eax,0 + jnc end_of_first_line + mov esi,eax + jmp skip_rest_of_first_line + end_of_first_line: + call store_segment_for_undo + mov edi,esi + mov esi,eax + remove_middle_lines: + cmp esi,[selection_line] + je middle_lines_removed + call store_freed_segment_for_undo + mov ebx,[esi] + call cancel_line + mov esi,ebx + btr esi,0 + jnc remove_middle_lines + remove_middle_line_segments: + call store_freed_segment_for_undo + mov esi,[esi] + btr esi,0 + jc remove_middle_line_segments + jmp remove_middle_lines + middle_lines_removed: + call store_segment_for_undo + mov eax,esi + or eax,1 + mov [edi],eax + mov eax,edi + or eax,1 + mov [esi+4],eax + call cancel_line + add ecx,[selection_position] + sub ecx,[caret_position] + call delete_from_line + mov esi,[caret_line] + find_following_line: + mov esi,[esi] + btr esi,0 + jc find_following_line + or esi,esi + jz following_line_ok + call store_segment_for_undo + mov eax,[caret_line] + mov [esi+4],eax + following_line_ok: + mov esi,[caret_line] + call check_line_length + block_deleted: + retn + clear_block: + push [caret_line] + push [caret_position] + clear_lines: + call clear_rest_of_line + mov [caret_line],esi + mov [caret_position],0 + cmp esi,[selection_line] + jne clear_lines + mov ecx,[selection_position] + call clear_in_line + pop [caret_position] + pop [caret_line] + retn + delete_vertical_block: + push [caret_line] + push [caret_line_number] + mov eax,[caret_position] + cmp eax,[selection_position] + jbe delete_vertical_block_line + xchg eax,[selection_position] + mov [caret_position],eax + delete_vertical_block_line: + mov ecx,[selection_position] + sub ecx,[caret_position] + call delete_from_line + mov esi,[caret_line] + call check_line_length + mov esi,[caret_line] + mov eax,[caret_line_number] + cmp eax,[selection_line_number] + je vertical_block_deleted + ja delete_in_previous_line + delete_in_next_line: + mov esi,[esi] + btr esi,0 + jc delete_in_next_line + mov [caret_line],esi + inc [caret_line_number] + jmp delete_vertical_block_line + delete_in_previous_line: + mov esi,[esi+4] + mov [caret_line],esi + dec [caret_line_number] + jmp delete_vertical_block_line + vertical_block_deleted: + pop [caret_line_number] + pop [caret_line] + mov [selection_line],0 + retn + +get_block_length: + test [editor_mode],FEMODE_VERTICALSEL + jnz get_length_of_vertical_block + mov esi,[caret_line] + mov edx,[caret_position] + mov ebx,[selection_line] + mov ecx,[selection_position] + mov eax,[caret_line_number] + cmp eax,[selection_line_number] + je get_length_of_vertical_block + jb get_length_of_standard_block + xchg esi,ebx + xchg ecx,edx + get_length_of_standard_block: + push ecx + mov ecx,[esi+8] + sub ecx,edx + jae add_length_of_line + xor ecx,ecx + add_length_of_line: + add ecx,2 + add [esp],ecx + skip_standard_block_line: + mov esi,[esi] + btr esi,0 + jc skip_standard_block_line + cmp esi,ebx + je length_of_block_ok + mov ecx,[esi+8] + jmp add_length_of_line + length_of_block_ok: + pop ecx + retn + get_length_of_vertical_block: + mov edx,[caret_line_number] + sub edx,[selection_line_number] + jae vertical_dimension_ok + neg edx + vertical_dimension_ok: + mov eax,[caret_position] + sub eax,[selection_position] + jae horizontal_dimension_ok + neg eax + horizontal_dimension_ok: + mov ecx,eax + add eax,2 + mul edx + add ecx,eax + retn + +copy_block: + test [editor_mode],FEMODE_VERTICALSEL + jnz copy_vertical_block + mov esi,[caret_line] + mov edx,[caret_position] + mov ebx,[selection_line] + mov ecx,[selection_position] + mov eax,[caret_line_number] + cmp eax,[selection_line_number] + je copy_vertical_block + jb copy_standard_block + xchg esi,ebx + xchg ecx,edx + copy_standard_block: + push ecx + push ebx + mov ecx,[esi+8] + sub ecx,edx + jb after_line_end + call copy_from_line + jmp block_line_copied + after_line_end: + mov esi,[esi] + btr esi,0 + jc after_line_end + block_line_copied: + pop ebx + copy_next_line: + mov ax,0A0Dh + stosw + cmp esi,ebx + je copy_from_last_line + push ebx + mov ecx,[esi+8] + xor edx,edx + call copy_from_line + pop ebx + jmp copy_next_line + copy_from_last_line: + pop ecx + xor edx,edx + call copy_from_line + xor al,al + stosb + retn + copy_vertical_block: + mov esi,[caret_line] + mov ebx,[selection_line] + mov edx,[caret_position] + mov ecx,[selection_position] + mov eax,[caret_line_number] + cmp eax,[selection_line_number] + jbe vertical_block_starting_line_ok + xchg esi,ebx + vertical_block_starting_line_ok: + cmp edx,ecx + jbe vertical_block_starting_position_ok + xchg edx,ecx + vertical_block_starting_position_ok: + sub ecx,edx + copy_line_from_vertical_block: + mov eax,ebx + sub eax,esi + push eax ebx ecx edx + call copy_from_line + pop edx ecx ebx eax + or eax,eax + jz vertical_block_copied + mov ax,0A0Dh + stosw + jmp copy_line_from_vertical_block + vertical_block_copied: + xor al,al + stosb + retn + copy_from_line: + mov ebx,ecx + find_copying_origin: + cmp edx,SEGMENT_DATA_LENGTH + jb copy_line_segment + mov esi,[esi] + btr esi,0 + jnc line_data_ended + sub edx,SEGMENT_DATA_LENGTH + jmp find_copying_origin + copy_line_segment: + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + cmp ebx,ecx + jae line_segment_length_ok + mov ecx,ebx + line_segment_length_ok: + sub ebx,ecx + mov eax,[esi] + lea esi,[esi+SEGMENT_HEADER_LENGTH+edx] + rep movsb + mov esi,eax + btr esi,0 + jnc line_data_ended + xor edx,edx + jmp copy_line_segment + line_data_ended: + or ebx,ebx + jz line_copy_done + mov ecx,ebx + mov al,20h + rep stosb + line_copy_done: + retn diff --git a/toolchain/fasm2/source/ide/edit.inc b/toolchain/fasm2/source/ide/edit.inc new file mode 100644 index 0000000..1008f04 --- /dev/null +++ b/toolchain/fasm2/source/ide/edit.inc @@ -0,0 +1,1027 @@ + +; flat editor core +; Copyright (c) 1999-2015, Tomasz Grysztar. +; All rights reserved. + +set_text: + push esi + call reset_editor_memory + pop esi + mov ebx,[first_line] + or esi,esi + jz new_text_ok + set_text_line: + call set_line + jc new_text_ok + call allocate_segment + mov [ebx],eax + jc not_enough_memory + mov ebx,eax + mov eax,[caret_line] + mov [ebx+4],eax + mov [caret_line],ebx + inc [lines_count] + inc [caret_line_number] + jmp set_text_line + new_text_ok: + xor eax,eax + mov dword [ebx],eax + inc eax + mov [caret_line_number],eax + mov eax,[first_line] + mov [caret_line],eax + mov [caret_position],0 + retn + +put_character: + call get_caret_segment + inc [caret_position] + put_here: + cmp edx,SEGMENT_DATA_LENGTH + jae put_after_line_end + call store_segment_for_undo + test [editor_mode],FEMODE_OVERWRITE + jnz overwrite + mov ah,[esi+SEGMENT_HEADER_LENGTH+edx] + shl eax,8 + mov al,ah + insert_in_segment: + lea ebx,[esi+SEGMENT_HEADER_LENGTH+edx] + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + shift_data_right: + xchg al,[ebx] + inc ebx + loop shift_data_right + test byte [esi],1 + jnz shift_next_segment_right + cmp al,20h + je put_ok + add_segment: + push eax + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov edi,eax + or eax,1 + xchg eax,[esi] + stosd + mov eax,esi + or eax,1 + stosd + add edi,SEGMENT_HEADER_LENGTH - 8 + pop eax + stosb + mov ecx,SEGMENT_DATA_LENGTH - 1 + mov al,20h + rep stosb + jmp put_ok + shift_next_segment_right: + mov esi,[esi] + dec esi + call store_segment_for_undo + xor edx,edx + jmp insert_in_segment + put_after_line_end: + push eax + call attach_empty_segments + pop eax + mov [esi+SEGMENT_HEADER_LENGTH+edx],al + mov ah,20h + shl eax,8 + put_ok: + test [editor_style],FES_AUTOBRACKETS + jz insert_done + shr eax,8 + xchg ah,al + call recognize_character + jnc insert_done + cmp ah,'(' + je round + cmp ah,'[' + je square + cmp ah,'{' + je brace + insert_done: + retn + round: + mov al,')' + jmp auto_bracket + square: + mov al,']' + jmp auto_bracket + brace: + mov al,'}' + auto_bracket: + mov edx,[caret_position] + mov esi,[caret_line] + call find_segment + jmp put_here + overwrite: + mov [esi+SEGMENT_HEADER_LENGTH+edx],al + retn + attach_empty_segments: + call store_segment_for_undo + attach_segment: + push edx + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + pop edx + mov ebx,esi + mov esi,eax + mov edi,eax + or eax,1 + xchg eax,[ebx] + stosd + mov eax,ebx + or eax,1 + stosd + add edi,SEGMENT_HEADER_LENGTH - 8 + mov ecx,SEGMENT_DATA_LENGTH shr 2 + mov eax,20202020h + rep stosd + sub edx,SEGMENT_DATA_LENGTH + cmp edx,SEGMENT_DATA_LENGTH + jae attach_segment + retn + recognize_character: + cmp al,20h + jb neutral_character + cmp al,30h + jb separator_character + cmp al,3Ah + jb neutral_character + cmp al,40h + jb separator_character + cmp al,5Bh + jb neutral_character + cmp al,5Fh + jb separator_character + cmp al,7Bh + jb neutral_character + cmp al,7Fh + jb separator_character + neutral_character: + clc + retn + separator_character: + stc + retn + +delete_character: + call get_caret_segment + delete_here: + cmp edx,SEGMENT_DATA_LENGTH + jae delete_done + call store_segment_for_undo + test [editor_mode],FEMODE_OVERWRITE + jnz blank + lea ebx,[esi+SEGMENT_LENGTH] + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + mov al,20h + mov edi,[esi] + test edi,1 + jz shift_data_left + mov al,[edi-1+SEGMENT_HEADER_LENGTH] + shift_data_left: + dec ebx + xchg al,[ebx] + loop shift_data_left + lea esi,[edi-1] + xor edx,edx + test edi,1 + jnz delete_here + delete_done: + retn + blank: + mov byte [esi+SEGMENT_HEADER_LENGTH+edx],20h + retn + +tabulate: + test [editor_style],FES_SMARTTABS + jz standard_tab + mov esi,[caret_line] + mov esi,[esi+4] + or esi,esi + jz standard_tab + mov edx,[caret_position] + call find_segment + cmp edx,SEGMENT_DATA_LENGTH + jae standard_tab + push 0 + find_space: + lea edi,[esi+SEGMENT_HEADER_LENGTH+edx] + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + mov ebx,ecx + mov al,20h + repne scasb + jne no_space_in_this_segment + sub ebx,ecx + dec ebx + add edx,ebx + add [esp],ebx + call get_indent + pop ecx + or ebx,ebx + jz standard_tab + add ecx,ebx + jmp insert_tab_spaces + no_space_in_this_segment: + pop ecx + mov esi,[esi] + btr esi,0 + jnc standard_tab + add ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + xor edx,edx + push ecx + jmp find_space + standard_tab: + mov ecx,[caret_position] + and ecx,not 111b + sub ecx,[caret_position] + add ecx,8 + insert_tab_spaces: + xor esi,esi + push ecx + call insert_into_line + pop ecx + add [caret_position],ecx + retn + +carriage_return: + xor ebx,ebx + test [editor_style],FES_AUTOINDENT + jz auto_indent_ok + test [editor_mode],FEMODE_OVERWRITE + jnz auto_indent_ok + call get_caret_segment + call get_indent + add [caret_position],ebx + mov esi,[caret_line] + xor edx,edx + call get_indent + auto_indent_ok: + call break_line + retn + get_indent: + xor ebx,ebx + find_indent_origin: + cmp edx,SEGMENT_DATA_LENGTH + jb find_indent + mov esi,[esi] + btr esi,0 + jnc no_indent + sub edx,SEGMENT_DATA_LENGTH + jmp find_indent_origin + find_indent: + lea edi,[esi+SEGMENT_HEADER_LENGTH+edx] + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + add ebx,ecx + mov al,20h + repe scasb + je segment_indent + sub ebx,ecx + dec ebx + retn + segment_indent: + xor edx,edx + mov esi,[esi] + btr esi,0 + jc find_indent + no_indent: + xor ebx,ebx + retn + +break_line: + test [editor_mode],FEMODE_OVERWRITE + jnz go_to_next_line + push ebx + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov edi,eax + mov eax,[caret_line] + mov [edi+4],eax + mov ebx,[esp] + push edi + add edi,SEGMENT_HEADER_LENGTH + mov ecx,SEGMENT_DATA_LENGTH shr 2 + mov eax,20202020h + rep stosd + call get_caret_segment + call store_segment_for_undo + mov edi,[esp] + cmp edx,SEGMENT_DATA_LENGTH + jae empty_new_line + push esi edx + new_line_segment: + cmp ebx,SEGMENT_DATA_LENGTH + jb new_line_segments_ok + push edi ebx + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov esi,eax + lea edi,[esi+SEGMENT_HEADER_LENGTH] + mov ecx,SEGMENT_DATA_LENGTH shr 2 + mov eax,20202020h + rep stosd + pop ebx edi + sub ebx,SEGMENT_DATA_LENGTH + mov eax,esi + or eax,1 + mov [edi],eax + or edi,1 + mov [esi+4],edi + mov edi,esi + jmp new_line_segment + new_line_segments_ok: + pop edx esi + split_data: + cmp ebx,edx + jbe indent_data + push esi edi + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,ebx + lea esi,[esi+SEGMENT_HEADER_LENGTH+edx] + lea edi,[edi+SEGMENT_HEADER_LENGTH+ebx] + add edx,ecx + mov eax,ecx + rep movsb + mov edi,esi + sub edi,eax + mov ecx,eax + mov al,20h + rep stosb + push edx + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + pop edx edi esi + mov ebx,eax + or eax,1 + mov [edi],eax + or edi,1 + mov [ebx+4],edi + mov edi,ebx + xor ebx,ebx + jmp split_data + indent_data: + push edi + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + mov eax,ecx + lea esi,[esi+SEGMENT_HEADER_LENGTH+edx] + lea edi,[edi+SEGMENT_HEADER_LENGTH+ebx] + rep movsb + add ebx,eax + mov edi,esi + sub edi,eax + mov ecx,eax + mov al,20h + rep stosb + pop edi + mov eax,[esp] + xchg eax,[esi-SEGMENT_LENGTH] + btr eax,0 + jnc finish_new_line + shift_splitted_data: + mov esi,eax + or eax,1 + mov [edi],eax + call store_segment_for_undo + mov eax,edi + or eax,1 + mov [esi+4],eax + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,ebx + lea edi,[edi+SEGMENT_HEADER_LENGTH+ebx] + add esi,SEGMENT_HEADER_LENGTH + mov eax,esi + rep movsb + mov edi,eax + mov ecx,ebx + rep movsb + sub edi,ebx + sub edi,SEGMENT_HEADER_LENGTH + mov eax,[edi] + btr eax,0 + jc shift_splitted_data + finish_new_line: + mov esi,edi + call store_segment_for_undo + mov [edi],eax + pop esi + or eax,eax + jz new_line_pointers_ok + xchg esi,eax + call store_segment_for_undo + xchg esi,eax + mov [eax+4],esi + new_line_pointers_ok: + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,ebx + lea edi,[edi+SEGMENT_HEADER_LENGTH+ebx] + mov al,20h + rep stosb + xchg [caret_line],esi + call check_line_length + mov esi,[caret_line] + mov dword [esi+8],0 + call check_line_length + inc [caret_line_number] + inc [lines_count] + pop [caret_position] + retn + empty_new_line: + pop edi + mov eax,[esi] + mov [esi],edi + mov [edi],eax + or eax,eax + jz empty_line_pointers_ok + mov [eax+4],edi + empty_line_pointers_ok: + mov dword [edi+8],0 + mov [caret_line],edi + inc [caret_line_number] + inc [lines_count] + pop [caret_position] + retn + go_to_next_line: + mov [caret_position],ebx + mov esi,[caret_line] + skip_line_segments: + mov eax,[esi] + btr eax,0 + jnc line_segments_skipped + mov esi,eax + jmp skip_line_segments + line_segments_skipped: + or eax,eax + jz no_next_line + mov [caret_line],eax + next_line_ok: + inc [caret_line_number] + retn + no_next_line: + call store_segment_for_undo + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov [esi],eax + mov edi,eax + xchg eax,[caret_line] + mov [edi+4],eax + xor eax,eax + stosd + add edi,4 + stosd + add edi,SEGMENT_HEADER_LENGTH - 12 + mov ecx,SEGMENT_DATA_LENGTH shr 2 + mov eax,20202020h + rep stosd + inc [lines_count] + jmp next_line_ok + +cut_line_break: + test [editor_mode],FEMODE_OVERWRITE + jnz do_nothing + call get_caret_segment + cmp edx,SEGMENT_DATA_LENGTH + jbe segment_for_deleting_ok + call store_segment_for_undo + add_empty_segment: + push edx esi + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + pop ebx edx + mov esi,eax + mov edi,eax + or eax,1 + xchg eax,[ebx] + stosd + mov eax,ebx + or eax,1 + stosd + add edi,SEGMENT_HEADER_LENGTH - 8 + mov ecx,SEGMENT_DATA_LENGTH shr 2 + mov eax,20202020h + rep stosd + sub edx,SEGMENT_DATA_LENGTH + cmp edx,SEGMENT_DATA_LENGTH + ja add_empty_segment + segment_for_deleting_ok: + call store_segment_for_undo + mov edi,esi + mov esi,[esi] + btr esi,0 + jc append_segment + call cancel_line + append_segment: + or esi,esi + jz fill_rest_with_spaces + call store_segment_for_undo + or byte [edi],1 + lea eax,[edi+1] + mov [esi+4],eax + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + mov eax,ecx + add esi,SEGMENT_HEADER_LENGTH + lea edi,[edi+SEGMENT_HEADER_LENGTH+edx] + rep movsb + mov edi,esi + sub edi,eax + mov ecx,edx + rep movsb + sub esi,SEGMENT_LENGTH + mov edi,esi + mov esi,[esi] + btr esi,0 + jc append_segment + fill_rest_with_spaces: + lea edi,[edi+SEGMENT_HEADER_LENGTH+edx] + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + mov al,20h + rep stosb + or esi,esi + jz delete_done + call store_segment_for_undo + mov eax,[caret_line] + mov [esi+4],eax + do_nothing: + retn + +cancel_line: + dec [lines_count] + mov eax,[esi+8] + call unregister_length + cmp esi,[window_line] + jne window_line_ok + mov eax,[caret_line] + mov [window_line],eax + mov eax,[caret_line_number] + mov [window_line_number],eax + window_line_ok: + cmp esi,[first_line] + jne first_line_ok + mov eax,[caret_line] + mov [first_line],eax + first_line_ok: + retn + +insert_into_line: + or ecx,ecx + jz void_insert + push ecx esi + call get_caret_segment + test [editor_mode],FEMODE_OVERWRITE + jnz overwrite_in_line + cmp edx,SEGMENT_DATA_LENGTH + jae attach_after_line_end + mov eax,[esp+4] + push edx + xor edx,edx + mov ecx,SEGMENT_DATA_LENGTH + div ecx + mov ebx,esi + push esi + or edx,edx + jnz find_last_segment_to_shift + call store_segment_for_undo + mov esi,[esi] + btr esi,0 + jnc following_segments_shifted + call store_segment_for_undo + jmp following_segments_shifted + find_last_segment_to_shift: + test byte [ebx],1 + jz shift_following_segments + mov ebx,[ebx] + dec ebx + jmp find_last_segment_to_shift + shift_following_segments: + push edx + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + pop edx + mov edi,eax + mov esi,[ebx] + mov [edi],esi + mov eax,ebx + or eax,1 + mov [edi+4],eax + lea edi,[edi+SEGMENT_HEADER_LENGTH+edx] + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + mov al,20h + rep stosb + sub edi,SEGMENT_LENGTH + carry_to_next_segment: + mov esi,ebx + call store_segment_for_undo + mov eax,edi + or eax,1 + mov [esi],eax + add esi,SEGMENT_LENGTH + sub esi,edx + mov ecx,edx + add edi,SEGMENT_HEADER_LENGTH + rep movsb + cmp ebx,[esp] + je following_segments_shifted + mov edi,ebx + mov ebx,[edi+4] + btr ebx,0 + push edi + add edi,SEGMENT_LENGTH-1 + mov esi,edi + sub esi,edx + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + std + rep movsb + cld + pop edi + jmp carry_to_next_segment + following_segments_shifted: + pop esi edx + insert_more_segments: + mov edi,esi + mov ecx,[esp+4] + make_inserted_segment: + sub ecx,SEGMENT_DATA_LENGTH + jb fill_inserted_segments + push ecx edx + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + pop edx ecx + mov ebx,[edi] + btr ebx,0 + jnc make_attached_segment + or eax,1 + mov [edi],eax + mov [ebx+4],eax + and eax,not 1 + or ebx,1 + mov [eax],ebx + or edi,1 + mov [eax+4],edi + mov edi,eax + jmp make_inserted_segment + make_attached_segment: + or eax,1 + mov [edi],eax + and eax,not 1 + mov [eax],ebx + or edi,1 + mov [eax+4],edi + mov edi,eax + jmp make_inserted_segment + fill_inserted_segments: + mov eax,SEGMENT_DATA_LENGTH + add ecx,eax + sub eax,edx + sub eax,ecx + jbe all_shifts_done + mov ecx,eax + lea edi,[edi+SEGMENT_LENGTH-1] + push esi + lea esi,[esi+SEGMENT_HEADER_LENGTH+ecx-1] + add esi,edx + std + rep movsb + cld + pop esi + all_shifts_done: + mov edi,esi + pop esi ebx + fill_new_segment: + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + cmp ecx,ebx + jbe length_for_inserting_ok + mov ecx,ebx + length_for_inserting_ok: + sub ebx,ecx + push edi + lea edi,[edi+SEGMENT_HEADER_LENGTH+edx] + or esi,esi + jz insert_blank_string + rep movsb + jmp string_inserted + insert_blank_string: + mov al,20h + rep stosb + string_inserted: + pop edi + mov edi,[edi] + and edi,not 1 + xor edx,edx + or ebx,ebx + jnz fill_new_segment + retn + attach_after_line_end: + call attach_empty_segments + mov ebx,esi + pop esi + or esi,esi + jnz attach_string + pop ecx + retn + attach_string: + mov ecx,[esp] + mov eax,SEGMENT_DATA_LENGTH + sub eax,edx + cmp eax,ecx + jae length_to_attach_ok + mov ecx,eax + length_to_attach_ok: + sub [esp],ecx + lea edi,[ebx+SEGMENT_HEADER_LENGTH+edx] + rep movsb + mov ecx,[esp] + jecxz attach_ok + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov edi,eax + or eax,1 + xchg eax,[ebx] + mov [edi],eax + or ebx,1 + mov [edi+4],ebx + mov ebx,edi + xor edx,edx + jmp attach_string + attach_ok: + pop eax + lea ecx,[ebx+SEGMENT_LENGTH] + sub ecx,edi + mov al,20h + rep stosb + void_insert: + retn + overwrite_in_line: + cmp edx,SEGMENT_DATA_LENGTH + jb position_for_overwrite_ok + call attach_empty_segments + position_for_overwrite_ok: + mov edi,esi + pop esi ebx + overwrite_segment: + xchg esi,edi + call store_segment_for_undo + xchg esi,edi + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + cmp ecx,ebx + jbe length_to_overwrite_ok + mov ecx,ebx + length_to_overwrite_ok: + sub ebx,ecx + push edi + lea edi,[edi+SEGMENT_HEADER_LENGTH+edx] + or esi,esi + jz overwrite_with_blank + rep movsb + jmp overwritten_ok + overwrite_with_blank: + mov al,20h + rep stosb + overwritten_ok: + pop edi + or ebx,ebx + jz overwrite_done + push esi + mov esi,[edi] + btr esi,0 + jc overwrite_existing_segment + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov edx,eax + or edx,1 + mov [edi],edx + mov [eax],esi + or edi,1 + mov [eax+4],edi + mov edi,eax + pop esi + xor edx,edx + cmp ebx,SEGMENT_DATA_LENGTH + jae overwrite_segment + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,ebx + lea edi,[edi+SEGMENT_HEADER_LENGTH+ebx] + mov al,20h + rep stosb + sub edi,SEGMENT_LENGTH + jmp overwrite_segment + overwrite_existing_segment: + call store_segment_for_undo + mov edi,esi + xor edx,edx + pop esi + jmp overwrite_segment + overwrite_done: + retn + +delete_from_line: + or ecx,ecx + jz nothing_to_delete + test [editor_mode],FEMODE_OVERWRITE + jnz clear_in_line + push ecx + add [caret_position],ecx + call get_caret_segment + pop ecx + sub [caret_position],ecx + cmp edx,SEGMENT_DATA_LENGTH + jae clear_rest_of_line + push esi edx + call get_caret_segment + call store_segment_for_undo + mov edi,esi + mov ebx,edx + pop edx esi + shift_over_deleted: + mov ecx,SEGMENT_DATA_LENGTH + mov eax,ecx + sub ecx,ebx + sub eax,edx + cmp eax,ecx + jae size_to_shift_ok + mov ecx,eax + size_to_shift_ok: + push esi edi + lea esi,[esi+SEGMENT_HEADER_LENGTH+edx] + lea edi,[edi+SEGMENT_HEADER_LENGTH+ebx] + add edx,ecx + add ebx,ecx + rep movsb + pop edi + cmp ebx,SEGMENT_DATA_LENGTH + je next_destination_segment + pop esi + cmp edx,SEGMENT_DATA_LENGTH + jne shift_over_deleted + mov esi,[esi] + btr esi,0 + jnc cut_line + xor edx,edx + jmp shift_over_deleted + next_destination_segment: + mov esi,[edi] + btr esi,0 + call store_segment_for_undo + mov edi,esi + pop esi + xor ebx,ebx + jmp shift_over_deleted + cut_line: + mov esi,edi + mov edx,ebx + jmp clear_from_here + clear_in_line: + xor esi,esi + jmp insert_into_line + clear_rest_of_line: + call get_caret_segment + cmp edx,SEGMENT_DATA_LENGTH + jae no_line_tail_to_clear + call store_segment_for_undo + clear_from_here: + lea edi,[esi+SEGMENT_HEADER_LENGTH+edx] + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + mov al,20h + rep stosb + mov ebx,esi + mov esi,[ebx] + remove_following_segments: + btr esi,0 + jnc rest_of_line_cleared + call store_freed_segment_for_undo + mov esi,[esi] + jmp remove_following_segments + rest_of_line_cleared: + mov [ebx],esi + nothing_to_delete: + retn + no_line_tail_to_clear: + mov esi,[esi] + retn + +remove_line: + mov esi,[caret_line] + mov esi,[esi] + or esi,esi + jnz cut_extra_segments + mov edi,[caret_line] + add edi,SEGMENT_HEADER_LENGTH + mov ecx,SEGMENT_DATA_LENGTH + mov al,20h + repe scasb + je line_removed + cut_extra_segments: + btr esi,0 + jnc replace_with_next_line + call store_freed_segment_for_undo + mov esi,[esi] + jmp cut_extra_segments + replace_with_next_line: + or esi,esi + jz clear_current_line + call store_segment_for_undo + mov ebx,esi + xchg esi,[caret_line] + mov eax,[esi+4] + mov [ebx+4],eax + call store_freed_segment_for_undo + call cancel_line + mov esi,[esi+4] + or esi,esi + jz line_removed + find_last_segment_of_previous_line: + mov eax,[esi] + btr eax,0 + jnc link_to_new_next_line + mov esi,eax + jmp find_last_segment_of_previous_line + link_to_new_next_line: + call store_segment_for_undo + mov [esi],ebx + line_removed: + mov [caret_position],0 + mov [selection_line],0 + retn + clear_current_line: + mov esi,[caret_line] + call store_segment_for_undo + mov dword [esi],0 + lea edi,[esi+SEGMENT_HEADER_LENGTH] + mov ecx,SEGMENT_DATA_LENGTH + mov al,20h + rep stosb + jmp line_removed + +duplicate_line: + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov esi,[caret_line] + mov edi,eax + mov [edi+4],esi + mov eax,[esi+8] + mov [edi+8],eax + call register_length + push edi + duplicate_segment: + mov ebx,edi + add edi,SEGMENT_HEADER_LENGTH + add esi,SEGMENT_HEADER_LENGTH + mov ecx,SEGMENT_DATA_LENGTH + rep movsb + sub esi,SEGMENT_LENGTH + mov eax,[esi] + btr eax,0 + jnc all_segments_duplicated + mov esi,eax + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov edi,eax + or eax,1 + mov [ebx],eax + or ebx,1 + mov [edi+4],ebx + jmp duplicate_segment + all_segments_duplicated: + inc [lines_count] + call store_segment_for_undo + mov [ebx],eax + pop ebx + mov [esi],ebx + mov esi,eax + or esi,esi + jz duplicate_done + call store_segment_for_undo + mov [esi+4],ebx + duplicate_done: + retn + +finish_edit: + mov esi,[caret_line] + call check_line_length + retn diff --git a/toolchain/fasm2/source/ide/memory.inc b/toolchain/fasm2/source/ide/memory.inc new file mode 100644 index 0000000..9b04370 --- /dev/null +++ b/toolchain/fasm2/source/ide/memory.inc @@ -0,0 +1,199 @@ + +; flat editor core +; Copyright (c) 1999-2015, Tomasz Grysztar. +; All rights reserved. + +init_editor_memory: + mov ecx,BLOCK_LENGTH + call get_memory + or eax,eax + jz memory_error + mov [editor_memory],eax + mov dword [eax],0 + mov dword [eax+4],0 + mov dword [eax+8],ebx + lea ebx,[eax+SEGMENT_LENGTH] + mov [unallocated_segments],ebx + mov [memory_search_segment],ebx + add eax,BLOCK_LENGTH + mov [unallocated_segments_end],eax + mov [memory_search_block],eax + mov [released_segments],0 + call allocate_segment + mov [first_line],eax + mov [lines_count],1 + mov [peak_line_length],0 + mov [caret_line],eax + mov [caret_line_number],1 + mov [window_line],eax + mov [window_line_number],1 + mov edi,eax + xor eax,eax + mov ecx,SEGMENT_HEADER_LENGTH shr 2 + rep stosd + mov eax,20202020h + mov ecx,SEGMENT_DATA_LENGTH shr 2 + rep stosd + call allocate_segment + jc memory_shortage + mov [lengths_table],eax + mov edi,eax + xor eax,eax + mov ecx,SEGMENT_LENGTH shr 2 + rep stosd + mov [caret_position],eax + mov [window_position],eax + mov [selection_line],eax + mov [undo_data],eax + mov [redo_data],eax + mov [search_data],eax + mov [editor_mode],eax + mov [unmodified_state],eax + clc + retn + memory_error: + stc + retn + +reset_editor_memory: + mov esi,[editor_memory] + lea eax,[esi+SEGMENT_LENGTH] + mov [unallocated_segments],eax + mov [memory_search_segment],eax + lea eax,[esi+BLOCK_LENGTH] + mov [unallocated_segments_end],eax + mov [memory_search_block],eax + mov [released_segments],0 + mov ebx,[esi] + release_blocks: + or ebx,ebx + jz release_done + push dword [ebx] + mov ebx,[ebx+8] + call release_memory + pop ebx + jmp release_blocks + release_done: + mov ebx,[editor_memory] + xor eax,eax + mov [ebx],eax + mov [undo_data],eax + mov [redo_data],eax + mov [search_data],eax + call allocate_segment + jc memory_shortage + mov [first_line],eax + mov [window_line],eax + mov [caret_line],eax + mov edi,eax + xor eax,eax + mov ecx,SEGMENT_HEADER_LENGTH shr 2 + rep stosd + mov eax,20202020h + mov ecx,SEGMENT_DATA_LENGTH shr 2 + rep stosd + xor eax,eax + mov [selection_line],eax + mov [peak_line_length],eax + mov [window_position],eax + inc eax + mov [window_line_number],eax + mov [caret_line_number],eax + mov [lines_count],eax + call allocate_segment + jc memory_shortage + mov [lengths_table],eax + mov edi,eax + xor eax,eax + mov ecx,SEGMENT_LENGTH shr 2 + rep stosd + retn + +release_editor_memory: + mov esi,[editor_memory] + release: + push dword [esi] + mov ebx,[esi+8] + call release_memory + pop esi + or esi,esi + jnz release + mov [editor_memory],0 + retn + +allocate_segment: + mov eax,[unallocated_segments] + cmp eax,[unallocated_segments_end] + je simple_allocation_failed + add [unallocated_segments],SEGMENT_LENGTH + clc + retn + simple_allocation_failed: + push ebx esi + mov ebx,[memory_search_block] + mov esi,[memory_search_segment] + cmp [released_segments],16 + jb add_new_block + find_free_segment: + cmp esi,ebx + je find_in_next_block + cmp dword [esi],-1 + je reuse_segment + add esi,SEGMENT_LENGTH + cmp esi,[memory_search_segment] + jne find_free_segment + add_new_block: + sub ebx,BLOCK_LENGTH + find_last_memory_block: + cmp dword [ebx],0 + je allocate_more_memory + mov ebx,[ebx] + jmp find_last_memory_block + allocate_more_memory: + mov ecx,BLOCK_LENGTH + push ebx + call get_memory + pop esi + or eax,eax + jz allocation_failed + mov [esi],eax + mov dword [eax],0 + mov [eax+4],esi + mov [eax+8],ebx + lea ebx,[eax+BLOCK_LENGTH] + mov [unallocated_segments_end],ebx + add eax,SEGMENT_LENGTH + lea ebx,[eax+SEGMENT_LENGTH] + mov [unallocated_segments],ebx + mov [released_segments],0 + pop esi ebx + clc + retn + allocation_failed: + xor eax,eax + pop esi ebx + stc + retn + reuse_segment: + mov eax,esi + mov [memory_search_block],ebx + add esi,SEGMENT_LENGTH + mov [memory_search_segment],esi + dec [released_segments] + pop esi ebx + clc + retn + find_in_next_block: + sub ebx,BLOCK_LENGTH + mov esi,[ebx] + lea ebx,[esi+BLOCK_LENGTH] + or esi,esi + jnz find_free_segment + mov ebx,[editor_memory] + mov esi,ebx + add ebx,BLOCK_LENGTH + jmp find_free_segment + +memory_shortage: + call undo_changes + jmp not_enough_memory diff --git a/toolchain/fasm2/source/ide/navigate.inc b/toolchain/fasm2/source/ide/navigate.inc new file mode 100644 index 0000000..430e127 --- /dev/null +++ b/toolchain/fasm2/source/ide/navigate.inc @@ -0,0 +1,511 @@ + +; flat editor core +; Copyright (c) 1999-2015, Tomasz Grysztar. +; All rights reserved. + +find_line: + mov esi,[first_line] + mov ecx,1 + mov edx,[window_line_number] + cmp eax,edx + jae forward_from_window + sub edx,eax + cmp edx,eax + jb backward_from_window + jmp find_forward + forward_from_window: + mov esi,[window_line] + mov ecx,edx + find_forward: + cmp ecx,eax + je line_found + cmp dword [esi],0 + je line_found + mov ebx,esi + forward_skip_line: + mov ebx,[ebx] + btr ebx,0 + jc forward_skip_line + or ebx,ebx + jz line_found + mov esi,ebx + inc ecx + jmp find_forward + backward_from_window: + mov esi,[window_line] + mov ecx,[window_line_number] + find_backward: + cmp ecx,eax + je line_found + cmp dword [esi+4],0 + je line_found + mov esi,[esi+4] + dec ecx + jmp find_backward + line_found: + retn + +get_caret_segment: + mov edx,[caret_position] + mov esi,[caret_line] + find_segment: + cmp edx,SEGMENT_DATA_LENGTH + jb segment_found + test byte [esi],1 + jz segment_found + mov esi,[esi] + dec esi + sub edx,SEGMENT_DATA_LENGTH + jmp find_segment + segment_found: + retn + +check_line_length: + xor edx,edx + mov ebx,esi + count_line_segments: + test byte [esi],1 + jz last_line_segment + mov esi,[esi] + dec esi + add edx,SEGMENT_DATA_LENGTH + jmp count_line_segments + last_line_segment: + lea edi,[esi+SEGMENT_LENGTH-1] + mov al,20h + mov ecx,SEGMENT_DATA_LENGTH + std + repe scasb + cld + setne al + movzx eax,al + add ecx,eax + jnz line_segments_ok + or edx,edx + jz line_segments_ok + call store_freed_segment_for_undo + mov eax,[esi] + mov esi,[esi+4] + dec esi + call store_segment_for_undo + mov [esi],eax + sub edx,SEGMENT_DATA_LENGTH + jmp last_line_segment + line_segments_ok: + add ecx,edx + mov edx,ecx + cmp edx,[ebx+8] + je line_length_checked + mov esi,ebx + call store_segment_for_undo + xchg [ebx+8],edx + push edx + mov eax,[ebx+8] + call register_length + pop eax + call unregister_length + line_length_checked: + retn + register_length: + cmp eax,[peak_line_length] + jbe peak_length_ok + mov [peak_line_length],eax + peak_length_ok: + or eax,eax + jz ignore_zero_length + push ebx + call find_lengths_segment + inc dword [ebx+SEGMENT_HEADER_LENGTH+eax*4] + pop ebx + ignore_zero_length: + retn + find_lengths_segment: + mov ebx,[lengths_table] + try_lengths_segment: + cmp eax,SEGMENT_DATA_LENGTH/4 + jb length_entry_ok + sub eax,SEGMENT_DATA_LENGTH/4 + cmp dword [ebx],0 + je add_lengths_segment + mov ebx,[ebx] + jmp try_lengths_segment + add_lengths_segment: + push eax ecx edi + call allocate_segment + jc memory_shortage + call store_allocated_segment_for_undo + mov [ebx],eax + mov edi,eax + xor eax,eax + stosd + mov eax,ebx + stosd + mov eax,[ebx+8] + add eax,SEGMENT_DATA_LENGTH/4 + stosd + add edi,SEGMENT_HEADER_LENGTH-12 + mov ecx,SEGMENT_DATA_LENGTH shr 2 + xor eax,eax + rep stosd + lea ebx,[edi-SEGMENT_LENGTH] + pop edi ecx eax + jmp try_lengths_segment + length_entry_ok: + retn + unregister_length: + or eax,eax + jz ignore_zero_length + push ebx + cmp eax,[peak_line_length] + je unregister_peak_length + call find_lengths_segment + dec dword [ebx+SEGMENT_HEADER_LENGTH+eax*4] + length_unregistered: + pop ebx + retn + unregister_peak_length: + call find_lengths_segment + dec dword [ebx+SEGMENT_HEADER_LENGTH+eax*4] + jnz length_unregistered + find_reduced_peak: + or eax,eax + jz try_earlier_lengths_segment + dec eax + cmp dword [ebx+SEGMENT_HEADER_LENGTH+eax*4],0 + je find_reduced_peak + add eax,[ebx+8] + mov [peak_line_length],eax + jmp length_unregistered + try_earlier_lengths_segment: + mov ebx,[ebx+4] + mov eax,SEGMENT_DATA_LENGTH/4 + or ebx,ebx + jnz find_reduced_peak + mov [peak_line_length],ebx + jmp length_unregistered + +update_window: + mov edx,[window_line_number] + cmp edx,1 + je window_vertical_position_ok + add edx,[window_height] + dec edx + cmp edx,[lines_count] + jle window_vertical_position_ok + sub edx,[lines_count] + window_vertical_correction: + mov esi,[window_line] + mov esi,[esi+4] + or esi,esi + jz window_vertical_position_ok + mov [window_line],esi + dec [window_line_number] + dec edx + jnz window_vertical_correction + window_vertical_position_ok: + mov ecx,[peak_line_length] + cmp ecx,[caret_position] + jae caret_position_ok + mov ecx,[caret_position] + caret_position_ok: + cmp [selection_line],0 + je selection_position_ok + cmp ecx,[selection_position] + jae selection_position_ok + mov ecx,[selection_position] + selection_position_ok: + mov eax,[window_width] + dec eax + cmp ecx,eax + jae edit_space_width_ok + mov ecx,eax + edit_space_width_ok: + mov [maximum_position],ecx + mov edx,[window_position] + or edx,edx + jz window_horizontal_position_ok + add edx,[window_width] + inc ecx + cmp edx,ecx + jbe window_horizontal_position_ok + sub edx,ecx + sub [window_position],edx + jnc window_horizontal_position_ok + mov [window_position],0 + window_horizontal_position_ok: + retn + +let_caret_appear: + mov eax,[caret_position] + cmp eax,[window_position] + jl horizontal_correction + mov ecx,[window_width] + jecxz last_position_ok + dec ecx + last_position_ok: + add ecx,[window_position] + mov eax,[caret_position] + sub eax,ecx + jbe horizontal_ok + add eax,[window_position] + horizontal_correction: + mov [window_position],eax + horizontal_ok: + mov esi,[caret_line] + mov ecx,[caret_line_number] + cmp ecx,[window_line_number] + jl vertical_correction + mov eax,[window_height] + or eax,eax + jz vertical_check + dec eax + vertical_check: + neg eax + add eax,[caret_line_number] + cmp [window_line_number],eax + jge vertical_ok + mov esi,[window_line] + mov ecx,[window_line_number] + vertical_find: + mov esi,[esi] + btr esi,0 + jc vertical_find + inc ecx + cmp ecx,eax + jl vertical_find + vertical_correction: + mov [window_line],esi + mov [window_line_number],ecx + vertical_ok: + retn + +move_line_up: + mov esi,[caret_line] + mov eax,[esi+4] + or eax,eax + jz cannot_move + mov [caret_line],eax + dec [caret_line_number] + clc + retn + cannot_move: + stc + retn + +move_line_down: + mov esi,[caret_line] + find_next_line: + mov eax,[esi] + or eax,eax + jz cannot_move + btr eax,0 + jnc down_ok + mov esi,eax + jmp find_next_line + down_ok: + mov [caret_line],eax + inc [caret_line_number] + clc + retn + +move_page_up: + mov eax,[caret_line_number] + sub eax,[window_height] + ja pgup_caret_ok + mov eax,1 + pgup_caret_ok: + call find_line + mov [caret_line],esi + mov [caret_line_number],ecx + mov eax,[window_line_number] + sub eax,[window_height] + ja pgup_window_ok + mov eax,1 + cmp [window_line_number],eax + je moved_ok + pgup_window_ok: + call find_line + mov [window_line],esi + mov [window_line_number],ecx + retn + +move_page_down: + mov eax,[caret_line_number] + add eax,[window_height] + call find_line + mov [caret_line],esi + mov [caret_line_number],ecx + mov eax,[window_line_number] + mov ecx,[window_height] + add eax,ecx + mov ebx,[lines_count] + sub ebx,ecx + jbe moved_ok + inc ebx + cmp eax,ebx + jb pgdn_window_ok + mov eax,ebx + cmp [window_line_number],eax + je moved_ok + pgdn_window_ok: + call find_line + mov [window_line],esi + mov [window_line_number],ecx + moved_ok: + retn + +move_to_previous_word: + call get_caret_segment + mov ecx,[caret_position] + sub ecx,edx + cmp edx,SEGMENT_DATA_LENGTH + jbe find_word_to_the_left + mov edx,SEGMENT_DATA_LENGTH + find_word_to_the_left: + sub edx,1 + jc word_in_previous_segment + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jnc find_word_start + jmp find_word_to_the_left + word_in_previous_segment: + mov eax,[esi+4] + or eax,eax + jz previous_word_ok + mov esi,eax + btr esi,0 + jnc word_in_previous_line + mov edx,SEGMENT_DATA_LENGTH + sub ecx,edx + jmp find_word_to_the_left + word_in_previous_line: + mov [caret_line],esi + dec [caret_line_number] + mov edx,SEGMENT_DATA_LENGTH + xor ecx,ecx + find_last_segment: + test byte [esi],1 + jz find_word_to_the_left + mov esi,[esi] + dec esi + add ecx,SEGMENT_DATA_LENGTH + jmp find_last_segment + find_word_start: + sub edx,1 + jc word_on_segment_edge + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jc previous_word_ok + jmp find_word_start + word_on_segment_edge: + mov esi,[esi+4] + btr esi,0 + jnc previous_word_ok + mov edx,SEGMENT_DATA_LENGTH + sub ecx,edx + jmp find_word_start + previous_word_ok: + add ecx,edx + inc ecx + mov [caret_position],ecx + retn + +move_to_next_word: + mov ecx,[caret_position] + sub ecx,edx + find_word_end: + cmp edx,SEGMENT_DATA_LENGTH + jae word_wraps_segment_edge + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jc find_word_to_the_right + add edx,1 + jmp find_word_end + word_wraps_segment_edge: + mov esi,[esi] + or esi,esi + jz move_to_line_end + btr esi,0 + jnc word_in_next_line + add ecx,SEGMENT_DATA_LENGTH + sub edx,SEGMENT_DATA_LENGTH + jmp find_word_end + find_word_to_the_right: + cmp edx,SEGMENT_DATA_LENGTH + jae word_in_next_segment + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jnc next_word_ok + add edx,1 + jmp find_word_to_the_right + word_in_next_segment: + mov esi,[esi] + or esi,esi + jz move_to_line_end + btr esi,0 + jnc word_in_next_line + add ecx,SEGMENT_DATA_LENGTH + sub edx,SEGMENT_DATA_LENGTH + jmp find_word_to_the_right + word_in_next_line: + mov [caret_line],esi + inc [caret_line_number] + xor ecx,ecx + xor edx,edx + jmp find_word_to_the_right + next_word_ok: + add ecx,edx + mov [caret_position],ecx + retn + move_to_line_end: + mov esi,[caret_line] + mov eax,[esi+8] + mov [caret_position],eax + retn + +get_word_at_caret: + call get_caret_segment + mov ebx,[caret_position] + sub ebx,edx + find_left_edge: + or edx,edx + jz left_edge_in_previous_segment + cmp edx,SEGMENT_DATA_LENGTH + ja left_edge_ok + mov al,[esi+SEGMENT_HEADER_LENGTH+edx-1] + call recognize_character + jc left_edge_ok + dec edx + jmp find_left_edge + left_edge_in_previous_segment: + mov esi,[esi+4] + btr esi,0 + jnc left_edge_ok + mov edx,SEGMENT_DATA_LENGTH + sub ebx,edx + jmp find_left_edge + left_edge_ok: + add ebx,edx + call get_caret_segment + mov ecx,[caret_position] + sub ecx,edx + find_right_edge: + cmp edx,SEGMENT_DATA_LENGTH + jae right_edge_in_next_segment + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jc right_edge_ok + inc edx + jmp find_right_edge + right_edge_in_next_segment: + mov esi,[esi] + btr esi,0 + jnc right_edge_ok + xor edx,edx + add ecx,SEGMENT_DATA_LENGTH + jmp find_right_edge + right_edge_ok: + add ecx,edx + sub ecx,ebx + mov edx,ebx + retn diff --git a/toolchain/fasm2/source/ide/search.inc b/toolchain/fasm2/source/ide/search.inc new file mode 100644 index 0000000..6173a6f --- /dev/null +++ b/toolchain/fasm2/source/ide/search.inc @@ -0,0 +1,529 @@ + +; flat editor core +; Copyright (c) 1999-2015, Tomasz Grysztar. +; All rights reserved. + +find_first: + mov [search_flags],eax + call release_search_data + or esi,esi + jz nothing_to_search_for + mov edi,esi + xor al,al + xor ecx,ecx + sub ecx,edi + repne scasb + lea ebx,[edi-1] + sub ebx,esi + jz nothing_to_search_for + lea ecx,[(256+ebx)*4+ebx] + push ebx + call get_memory + or eax,eax + jz not_enough_memory + mov [search_data],eax + mov [search_handle],ebx + pop ebx + mov edi,eax + lea ecx,[256+ebx] + mov eax,ebx + rep stosd + mov ecx,ebx + mov ebx,[search_data] + mov edx,ecx + test [search_flags],FEFIND_BACKWARD + jnz text_for_backward_search + test [search_flags],FEFIND_CASESENSITIVE + jnz copy_search_text + push ebx + mov ebx,upper_case_table + convert_search_text: + lodsb + xlatb + stosb + loop convert_search_text + pop ebx + jmp make_character_shifts_table + copy_search_text: + rep movsb + jmp make_character_shifts_table + text_for_backward_search: + add edi,ecx + mov edx,ecx + push ebx + mov ebx,upper_case_table + reverse_search_text: + lodsb + test [search_flags],FEFIND_CASESENSITIVE + jnz reverse_store_character + xlatb + reverse_store_character: + dec edi + mov [edi],al + dec ecx + jnz reverse_search_text + pop ebx + add edi,edx + xor ecx,ecx + make_character_shifts_table: + cmp edx,ecx + je character_shifts_table_ok + dec edi + jecxz character_shift_ok + mov al,[edi] + cmp [ebx+eax*4],edx + jne character_shift_ok + mov [ebx+eax*4],ecx + character_shift_ok: + inc ecx + jmp make_character_shifts_table + character_shifts_table_ok: + lea edi,[ebx+(256+ecx)*4] + push edi + lea edi,[edi+ecx-2] + movzx eax,byte [edi+1] + mov edx,[ebx+eax*4] + mov [ebx+256*4],edx + cmp ecx,1 + je suffix_match_shifts_table_done + mov ecx,2 + mov esi,edi + sub esi,edx + make_suffix_match_shifts_table: + cmp esi,[esp] + jb store_suffix_match_shift + mov al,[esi] + cmp al,[edi] + je store_suffix_match_shift + find_suffix_match: + dec esi + inc edx + cmp esi,[esp] + jb match_part_of_suffix + push ecx esi edi + repe cmpsb + pop edi esi ecx + jne find_suffix_match + jmp store_suffix_match_shift + match_part_of_suffix: + mov eax,[esp] + push ecx esi edi + xchg eax,esi + sub eax,esi + add ecx,eax + repe cmpsb + pop edi esi ecx + jne suffix_match_shifts_table_done + store_suffix_match_shift: + mov [ebx+256*4+(ecx-1)*4],edx + dec esi + dec edi + inc ecx + cmp ecx,[ebx] + jbe make_suffix_match_shifts_table + suffix_match_shifts_table_done: + pop eax + +find_next: + mov edi,[search_data] + or edi,edi + jz nothing_to_search_for + push [caret_line] + push [caret_line_number] + push [caret_position] + push [selection_position] + test [search_flags],FEFIND_BACKWARD + jnz search_backward + test [search_flags],FEFIND_INWHOLETEXT + jz search_for_text + mov eax,[first_line] + mov [caret_line],eax + xor eax,eax + mov [caret_position],eax + inc eax + mov [caret_line_number],eax + search_for_text: + mov ecx,[edi] + dec ecx + add ecx,[caret_position] + mov esi,[caret_line] + cmp ecx,[peak_line_length] + jae text_not_in_this_line + mov [caret_position],ecx + call get_caret_segment + mov edi,[search_data] + mov eax,[edi] + lea ebx,[edi+(256+eax)*4] + mov ah,[ebx+eax-1] + mov ebx,upper_case_table + search_in_line: + cmp edx,SEGMENT_DATA_LENGTH + jae text_not_in_this_line + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + test [search_flags],FEFIND_CASESENSITIVE + jnz compare_last_character + xlatb + compare_last_character: + cmp al,ah + je partial_match + mismatch_shift: + movzx ecx,al + mov ecx,[edi+ecx*4] + shift_search_position: + add edx,ecx + add ecx,[caret_position] + cmp ecx,[peak_line_length] + jae text_not_in_this_line + mov [caret_position],ecx + check_search_position: + cmp edx,SEGMENT_DATA_LENGTH + jb search_in_line + mov ecx,[esi] + btr ecx,0 + jnc search_in_line + sub edx,SEGMENT_DATA_LENGTH + mov esi,ecx + jmp check_search_position + partial_match: + mov ecx,[edi] + dec ecx + jz text_found + push edi + lea edi,[edi+(256+ecx+1)*4] + lea edi,[edi+ecx] + compare_text: + sub edx,1 + jc compare_in_previous_segment + dec edi + mov al,20h + cmp edx,SEGMENT_DATA_LENGTH + jae compare_character + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + test [search_flags],FEFIND_CASESENSITIVE + jnz compare_character + xlatb + compare_character: + cmp al,[edi] + loope compare_text + pop edi + je text_found + neg ecx + add ecx,[edi] + dec ecx + add edx,ecx + mov ecx,[edi+(256+ecx-1)*4] + jmp shift_search_position + compare_in_previous_segment: + mov esi,[esi+4] + and esi,not 1 + mov edx,SEGMENT_DATA_LENGTH + jmp compare_text + text_not_in_this_line: + mov esi,[esi] + or esi,esi + jz text_not_found + btr esi,0 + jc text_not_in_this_line + search_in_next_line: + mov [caret_line],esi + inc [caret_line_number] + mov [caret_position],0 + mov edi,[search_data] + jmp search_for_text + text_found: + mov eax,[caret_position] + inc eax + mov [selection_position],eax + sub eax,[edi] + mov [caret_position],eax + jz left_text_edge_ok + test [search_flags],FEFIND_WHOLEWORDS + jz left_text_edge_ok + mov edi,[search_data] + mov ecx,[edi] + mov al,[edi+(256+ecx)*4] + call recognize_character + jc left_text_edge_ok + dec [caret_position] + call get_caret_segment + inc [caret_position] + cmp edx,SEGMENT_DATA_LENGTH + jae left_text_edge_ok + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jnc found_not_acceptable + left_text_edge_ok: + mov eax,[caret_position] + xchg eax,[selection_position] + mov [caret_position],eax + mov edi,[search_data] + mov ecx,[edi] + lea edi,[edi+(256+ecx)*4] + mov al,[edi+ecx-1] + cmp al,20h + je right_text_edge_blank + test [search_flags],FEFIND_WHOLEWORDS + jz right_text_edge_ok + call recognize_character + jc right_text_edge_ok + call get_caret_segment + cmp edx,SEGMENT_DATA_LENGTH + jae right_text_edge_ok + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jc right_text_edge_ok + mov eax,[selection_position] + mov [caret_position],eax + found_not_acceptable: + mov edi,[search_data] + mov ecx,[edi] + mov eax,[edi+(256+ecx-1)*4] + add [caret_position],eax + jmp search_for_text + right_text_edge_blank: + call get_caret_segment + check_for_blank_end: + mov ecx,SEGMENT_DATA_LENGTH + sub ecx,edx + jz blank_end_next_segment + push edi + mov al,20h + lea edi,[esi+SEGMENT_HEADER_LENGTH+edx] + repe scasb + pop edi + jne right_text_edge_ok + blank_end_next_segment: + mov esi,[esi] + or esi,esi + jz text_not_found + btr esi,0 + jnc search_in_next_line + xor edx,edx + jmp check_for_blank_end + right_text_edge_ok: + mov eax,[caret_line] + mov ecx,[caret_line_number] + mov [selection_line],eax + mov [selection_line_number],ecx + and [search_flags],not FEFIND_INWHOLETEXT + add esp,16 + clc + retn + text_not_found: + pop [selection_position] + pop [caret_position] + pop [caret_line_number] + pop [caret_line] + nothing_to_search_for: + stc + retn + search_backward: + test [search_flags],FEFIND_INWHOLETEXT + jz backward_search_for_text + or eax,-1 + call find_line + mov [caret_line],esi + mov [caret_line_number],ecx + call move_to_line_end + backward_search_for_text: + mov ecx,[caret_position] + sub ecx,1 + jc backward_text_not_in_this_line + mov [caret_position],ecx + mov edi,[search_data] + mov eax,[edi] + mov al,[edi+(256+eax)*4] + cmp al,20h + jne backward_search_starting_position_ok + mov esi,[caret_line] + mov ecx,[esi+8] + mov edi,[search_data] + mov eax,[edi] + sub ecx,eax + jc backward_text_not_in_this_line + cmp ecx,[caret_position] + jae backward_search_starting_position_ok + mov [caret_position],ecx + backward_search_starting_position_ok: + call get_caret_segment + mov edi,[search_data] + mov eax,[edi] + lea ebx,[edi+(256+eax)*4] + mov ah,[ebx+eax-1] + mov ebx,upper_case_table + cmp edx,SEGMENT_DATA_LENGTH + jb backward_search_in_line + mov ecx,edx + sub ecx,SEGMENT_DATA_LENGTH-1 + sub edx,ecx + sub [caret_position],ecx + backward_search_in_line: + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + test [search_flags],FEFIND_CASESENSITIVE + jnz compare_first_character + xlatb + compare_first_character: + cmp al,ah + je backward_partial_match + backward_mismatch_shift: + movzx ecx,al + mov ecx,[edi+ecx*4] + shift_backward_search_position: + sub edx,ecx + sub [caret_position],ecx + jc backward_text_not_in_this_line + check_backward_search_position: + cmp edx,0 + jge backward_search_in_line + mov esi,[esi+4] + and esi,not 1 + add edx,SEGMENT_DATA_LENGTH + jmp check_backward_search_position + backward_partial_match: + mov ecx,[edi] + dec ecx + jz backward_text_found + push edi + lea edi,[edi+(256+ecx+1)*4] + lea edi,[edi+ecx] + backward_compare_text: + inc edx + cmp edx,SEGMENT_DATA_LENGTH + jae compare_in_next_segment + dec edi + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + test [search_flags],FEFIND_CASESENSITIVE + jnz backward_compare_character + xlatb + backward_compare_character: + cmp al,[edi] + loope backward_compare_text + pop edi + je backward_text_found + neg ecx + add ecx,[edi] + dec ecx + sub edx,ecx + mov ecx,[edi+(256+ecx)*4] + jmp shift_backward_search_position + compare_in_next_segment: + sub edx,SEGMENT_DATA_LENGTH + mov esi,[esi] + btr esi,0 + jnc compare_blank_space + dec edx + jmp backward_compare_text + compare_blank_space: + pop edi + cmp ecx,[edi] + jbe backward_text_found + backward_text_not_in_this_line: + mov esi,[caret_line] + mov esi,[esi+4] + or esi,esi + jz text_not_found + mov [caret_line],esi + dec [caret_line_number] + mov ecx,[peak_line_length] + mov [caret_position],ecx + jmp backward_search_for_text + backward_text_found: + test [search_flags],FEFIND_WHOLEWORDS + jz backward_left_text_edge_ok + cmp [caret_position],0 + je backward_left_text_edge_ok + mov edi,[search_data] + mov ecx,[edi] + lea edi,[edi+(256+ecx)*4] + mov al,[edi+ecx-1] + call recognize_character + jc backward_left_text_edge_ok + dec [caret_position] + call get_caret_segment + inc [caret_position] + cmp edx,SEGMENT_DATA_LENGTH + jae backward_left_text_edge_ok + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jnc backward_found_not_acceptable + backward_left_text_edge_ok: + mov eax,[caret_position] + mov [selection_position],eax + mov edi,[search_data] + mov ecx,[edi] + add eax,ecx + mov [caret_position],eax + test [search_flags],FEFIND_WHOLEWORDS + jz backward_right_text_edge_ok + mov al,[edi+(256+ecx)*4] + call recognize_character + jc backward_right_text_edge_ok + call get_caret_segment + cmp edx,SEGMENT_DATA_LENGTH + jae backward_right_text_edge_ok + mov al,[esi+SEGMENT_HEADER_LENGTH+edx] + call recognize_character + jc backward_right_text_edge_ok + mov eax,[selection_position] + mov [caret_position],eax + backward_found_not_acceptable: + mov edi,[search_data] + mov ecx,[edi] + mov eax,[edi+(256+ecx-1)*4] + sub [caret_position],eax + jbe backward_text_not_in_this_line + jmp backward_search_for_text + backward_right_text_edge_ok: + mov eax,[caret_position] + xchg eax,[selection_position] + mov [caret_position],eax + mov eax,[caret_line] + mov ecx,[caret_line_number] + mov [selection_line],eax + mov [selection_line_number],ecx + and [search_flags],not FEFIND_INWHOLETEXT + add esp,16 + clc + retn + +get_search_text_length: + mov ecx,[search_data] + test ecx,ecx + jz no_search_text + mov ecx,[ecx] + clc + retn +get_search_text: + mov esi,[search_data] + test esi,esi + jz no_search_text + mov ecx,[esi] + lea esi,[esi+(256+ecx)*4] + test [search_flags],FEFIND_BACKWARD + jnz copy_inverted_text + rep movsb + xor al,al + stosb + clc + retn + copy_inverted_text: + mov al,[esi+ecx-1] + stosb + loop copy_inverted_text + xor al,al + stosb + clc + retn + no_search_text: + stc + retn + +release_search_data: + mov edi,[search_data] + test edi,edi + jz search_data_released + mov ebx,[search_handle] + call release_memory + mov [search_data],0 + search_data_released: + retn diff --git a/toolchain/fasm2/source/ide/undo.inc b/toolchain/fasm2/source/ide/undo.inc new file mode 100644 index 0000000..65e2790 --- /dev/null +++ b/toolchain/fasm2/source/ide/undo.inc @@ -0,0 +1,339 @@ + +; flat editor core +; Copyright (c) 1999-2015, Tomasz Grysztar. +; All rights reserved. + +store_status_for_undo: + pusha + test [editor_mode],FEMODE_NOUNDO + jnz undo_disabled + call clear_redo_data + call allocate_segment + jc not_enough_memory + mov dword [eax],0 + mov edi,eax + xchg eax,[undo_data] + push eax edi + call allocate_segment + pop edi + jnc store_editor_status + xor eax,eax + stosd + jmp not_enough_memory + store_editor_status: + mov dword [eax],0 + mov dword [eax+4],0 + stosd + pop eax + stosd + lea esi,[editor_status] + mov ecx,editor_status_size shr 2 + rep movsd + mov esi,[lengths_table] + store_lengths_table: + call store_segment_for_undo + mov esi,[esi] + or esi,esi + jnz store_lengths_table + popa + store_status_for_undo_ok: + retn + undo_disabled: + call clear_redo_data + call clear_undo_data + or [unmodified_state],-1 + popa + retn + +store_segment_for_undo: + pusha + or esi,esi + jz segment_for_undo_done + call clear_redo_data + mov esi,[undo_data] + or esi,esi + jz segment_for_undo_done + mov ebx,[esi] + mov eax,[esp+4] + call prepare_slot_for_undo_storage + jc segment_for_undo_done + push edi + call allocate_segment + pop edi + mov ebx,eax + stosd + mov eax,[esp+4] + stosd + jc memory_shortage + mov esi,eax + mov edi,ebx + mov ecx,SEGMENT_LENGTH shr 2 + rep movsd + segment_for_undo_done: + popa + store_segment_for_undo_ok: + retn + prepare_slot_for_undo_storage: + mov esi,[undo_data] + mov esi,[esi] + mov ecx,[esi+4] + lea edi,[esi+8] + repne scasd + jne get_free_slot + stc + retn + get_free_slot: + mov ecx,[esi+4] + lea edi,[esi+8+ecx*8] + inc ecx + cmp ecx,SEGMENT_DATA_LENGTH/8 + jbe slot_ok + push esi + call allocate_segment + jc memory_shortage + mov esi,eax + mov ebx,[undo_data] + mov [ebx],esi + pop dword [esi] + mov ecx,1 + lea edi,[esi+8] + slot_ok: + mov [esi+4],ecx + clc + retn + +store_allocated_segment_for_undo: + pusha + call clear_redo_data + mov eax,[esp+1Ch] + xor edx,edx + mov [eax],edx + mov esi,[undo_data] + or esi,esi + jz segment_for_undo_done + call prepare_slot_for_undo_storage + jc segment_for_undo_done + xor eax,eax + stosd + mov eax,[esp+1Ch] + stosd + popa + retn + +store_freed_segment_for_undo: + pusha + call clear_redo_data + mov esi,[undo_data] + or esi,esi + jz segment_for_undo_done + call prepare_slot_for_undo_storage + jc segment_for_undo_done + mov eax,[esp+4] + stosd + xor eax,eax + stosd + popa + retn + +undo_changes: + mov esi,[undo_data] + or esi,esi + jz undo_ok + mov ebx,[esi] + mov eax,[redo_data] + xchg eax,[esi+4] + mov [undo_data],eax + mov [redo_data],esi + add esi,8 + lea edi,[editor_status] + mov ecx,editor_status_size shr 2 + call exchange_data + xor edx,edx + segments_block: + or ebx,ebx + jz undo_finished + mov esi,ebx + xchg ebx,edx + xchg ebx,[esi] + add esi,4 + lodsd + mov ecx,eax + jecxz undo_finished + lea esi,[esi+ecx*8] + restore_segments: + sub esi,8 + push esi ecx + mov edi,[esi+4] + mov esi,[esi] + or edi,edi + jz restore_next + or esi,esi + jz restore_next + mov ecx,SEGMENT_LENGTH shr 2 + call exchange_data + restore_next: + pop ecx esi + loop restore_segments + jmp segments_block + undo_finished: + mov esi,[redo_data] + mov [esi],edx + undo_ok: + retn + exchange_data: + mov eax,[esi] + xchg eax,[edi] + mov [esi],eax + add esi,4 + add edi,4 + loop exchange_data + retn + +redo_changes: + mov esi,[redo_data] + or esi,esi + jz redo_ok + mov ebx,[esi] + mov eax,[undo_data] + xchg eax,[esi+4] + mov [redo_data],eax + mov [undo_data],esi + add esi,8 + lea edi,[editor_status] + mov ecx,editor_status_size shr 2 + call exchange_data + xor edx,edx + redo_segments_block: + or ebx,ebx + jz redo_finished + mov esi,ebx + xchg ebx,edx + xchg ebx,[esi] + add esi,4 + lodsd + mov ecx,eax + jecxz redo_finished + redo_segments: + push esi ecx + mov edi,[esi+4] + mov esi,[esi] + or edi,edi + jz redo_next + or esi,esi + jz redo_next + mov ecx,SEGMENT_LENGTH shr 2 + call exchange_data + redo_next: + pop ecx esi + add esi,8 + loop redo_segments + jmp redo_segments_block + redo_finished: + mov esi,[undo_data] + mov [esi],edx + redo_ok: + retn + +clear_redo_data: + mov esi,[redo_data] + or esi,esi + jz redo_data_ok + clear_redo_block: + or ebx,-1 + xchg ebx,[esi] + inc [released_segments] + mov eax,[esi+4] + mov [redo_data],eax + clear_redo_segments: + or ebx,ebx + jz next_redo_block + mov esi,ebx + or ebx,-1 + xchg ebx,[esi] + inc [released_segments] + add esi,4 + lodsd + mov ecx,eax + jecxz next_redo_block + release_redo_segments: + push esi ecx + mov edi,[esi+4] + mov esi,[esi] + or edi,edi + jz release_next_segment + or eax,-1 + or esi,esi + jnz release_data + xchg eax,[edi] + jmp data_released + release_data: + xchg eax,[esi] + data_released: + cmp eax,-1 + je release_next_segment + inc [released_segments] + release_next_segment: + pop ecx esi + add esi,8 + loop release_redo_segments + jmp clear_redo_segments + next_redo_block: + mov esi,[redo_data] + or esi,esi + je redo_data_ok + cmp esi,[unmodified_state] + jne clear_redo_block + mov [unmodified_state],-1 + jmp clear_redo_block + redo_data_ok: + retn + +clear_undo_data: + mov esi,[undo_data] + push esi + clear_undo_block: + or esi,esi + jz undo_data_ok + or ebx,-1 + xchg ebx,[esi] + inc [released_segments] + add esi,4 + lodsd + mov [undo_data],eax + clear_undo_segments: + or ebx,ebx + jz next_undo_block + mov esi,ebx + or ebx,-1 + xchg ebx,[esi] + inc [released_segments] + add esi,4 + lodsd + mov ecx,eax + jecxz next_undo_block + lea esi,[esi+ecx*8] + release_segments: + sub esi,8 + mov edx,[esi] + or edx,edx + jz release_next + or eax,-1 + xchg [edx],eax + cmp eax,-1 + je release_next + inc [released_segments] + release_next: + loop release_segments + next_undo_block: + mov esi,[undo_data] + cmp esi,[unmodified_state] + jne clear_undo_block + or [unmodified_state],-1 + jmp clear_undo_block + undo_data_ok: + pop esi + cmp esi,[unmodified_state] + jne unmodified_ok + mov [unmodified_state],0 + unmodified_ok: + retn diff --git a/toolchain/fasm2/source/ide/variable.inc b/toolchain/fasm2/source/ide/variable.inc new file mode 100644 index 0000000..88661d9 --- /dev/null +++ b/toolchain/fasm2/source/ide/variable.inc @@ -0,0 +1,40 @@ + +; flat editor core +; Copyright (c) 1999-2015, Tomasz Grysztar. +; All rights reserved. + +editor_memory dd ? + +label editor_status + +first_line dd ? +lines_count dd ? +peak_line_length dd ? +maximum_position dd ? +window_line dd ? +window_position dd ? +window_line_number dd ? +caret_line dd ? +caret_position dd ? +caret_line_number dd ? +selection_line dd ? +selection_position dd ? +selection_line_number dd ? +editor_mode dd ? + +editor_status_size = $ - editor_status + +window_width dd ? +window_height dd ? +unallocated_segments dd ? +unallocated_segments_end dd ? +released_segments dd ? +memory_search_block dd ? +memory_search_segment dd ? +lengths_table dd ? +undo_data dd ? +redo_data dd ? +search_data dd ? +search_flags dd ? +search_handle dd ? +unmodified_state dd ? diff --git a/toolchain/fasm2/source/ide/version.inc b/toolchain/fasm2/source/ide/version.inc new file mode 100644 index 0000000..3afe63d --- /dev/null +++ b/toolchain/fasm2/source/ide/version.inc @@ -0,0 +1,39 @@ + +; flat editor version 3.12 +; Copyright (c) 1999-2015, Tomasz Grysztar. +; All rights reserved. +; +; This programs is free for commercial and non-commercial use as long as +; the following conditions are adhered to. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are +; met: +; +; 1. Redistributions of source code must retain the above copyright notice, +; this list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; +; The licence and distribution terms for any publically available +; version or derivative of this code cannot be changed. i.e. this code +; cannot simply be copied and put under another distribution licence +; (including the GNU Public Licence). + +FEDIT_VERSION_STRING equ "3.12" + +FEDIT_VERSION_MAJOR = 3 +FEDIT_VERSION_MINOR = 12 diff --git a/toolchain/fasm2/source/ide/windows/fasmg.inc b/toolchain/fasm2/source/ide/windows/fasmg.inc new file mode 100644 index 0000000..df70471 --- /dev/null +++ b/toolchain/fasm2/source/ide/windows/fasmg.inc @@ -0,0 +1,504 @@ + +; flat assembler g interface for Windows IDE +; Copyright (c) 2014-2024, Tomasz Grysztar. +; All rights reserved. + +flat_assembler: + + mov esi,[esp+4] + mov [source_path],esi + + mov [maximum_number_of_errors],MAX_ERRORS + + xor al,al + call assembly_init + + mov eax,[maximum_number_of_passes] + shl eax,16 + invoke PostMessage,[hwnd_progress],PBM_SETRANGE,0,eax + invoke PostMessage,[hwnd_progress],PBM_SETPOS,0,0 + invoke GetTickCount + mov [timer],eax + + assemble: + mov esi,source_header + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov ebx,[current_pass] + invoke PostMessage,[hwnd_progress],PBM_SETPOS,ebx,0 + cmp ebx,[maximum_number_of_passes] + jb assemble + + call show_display_data + cmp [first_error],0 + jne assembly_failed + + call assembly_shutdown + mov esi,_code_cannot_be_generated + jmp fatal_error + + assembly_done: + call show_display_data + cmp [first_error],0 + jne assembly_failed + + mov [executable_path],0 + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + mov eax,[current_pass] + xor edx,edx + call itoa + call display_error_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_error_string + invoke GetTickCount + sub eax,[timer] + xor edx,edx + add eax,50 + mov ecx,1000 + div ecx + mov ebx,eax + mov eax,edx + xor edx,edx + mov ecx,100 + div ecx + mov [timer],eax + xchg eax,ebx + or ebx,eax + jz display_output_length + xor edx,edx + call itoa + call display_error_string + mov esi,_message_suffix + mov ecx,1 + call display_error_string + mov eax,[timer] + xor edx,edx + call itoa + call display_error_string + mov esi,_seconds + xor ecx,ecx + call display_error_string + display_output_length: + call get_output_length + push eax edx + call itoa + call display_error_string + pop edx eax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_error_string + mov esi,_new_line + xor ecx,ecx + call display_error_string + summary_done: + + call assembly_shutdown + xor eax,eax + jmp shutdown + + assembly_failed: + + mov ebx,[first_error] + collect_error: + call show_error_message + xor esi,esi + mov ecx,1 + call display_error_string + mov esi,[ebx+Error.preprocessed_data] + mov ecx,[ebx+Error.preprocessed_length] + push ebx + call show_preprocessed_line + pop ebx + xor esi,esi + mov ecx,1 + call display_error_string + mov eax,[ebx+sizeof.Error+SourceContext.number_of_entries] + test eax,eax + jz display_error_message + lea esi,[ebx+sizeof.Error+sizeof.SourceContext] + dec eax + imul eax,sizeof.SourceEntry + lea edi,[esi+eax] + push esi edi + lea esi,[edi+SourceEntry.type] + mov ecx,1 + call display_error_string + pop edi esi + find_file_source: + cmp [edi+SourceEntry.type],SOURCE_FILE + jne try_next_source_entry + cmp [edi+SourceEntry.line_number],0 + jne file_source_found + try_next_source_entry: + cmp edi,esi + je no_file_source + sub edi,sizeof.SourceEntry + jmp find_file_source + file_source_found: + lea esi,[edi+SourceEntry.line_number] + mov ecx,4 + push edi + call display_error_string + pop edi + mov esi,[edi+SourceEntry.name] + call display_error_string + jmp error_collected + no_file_source: + xor esi,esi + mov ecx,4 + call display_error_string + error_collected: + xor esi,esi + mov ecx,1 + call display_error_string + mov ebx,[ebx+Error.next] + test ebx,ebx + jnz collect_error + + call assembly_shutdown + mov eax,2 + jmp shutdown + + write_failed: + call assembly_shutdown + mov esi,_write_failed + jmp fatal_error + out_of_memory: + call assembly_shutdown + mov esi,_out_of_memory + fatal_error: + xor ecx,ecx + call display_error_string + mov eax,1 + +shutdown: + push eax + invoke PostMessage,[hwnd_compiler],WM_COMMAND,IDOK,0 + call [ExitThread] + +LINE_FEED equ 13,10 + +system_init: + invoke HeapCreate,0,20000h,0 + mov [memory],eax + test eax,eax + jz out_of_memory + invoke GetSystemTime,systemtime + invoke SystemTimeToFileTime,systemtime,filetime + mov ebx,[filetime.dwLowDateTime] + mov eax,[filetime.dwHighDateTime] + sub ebx,116444736000000000 and 0FFFFFFFFh + sbb eax,116444736000000000 shr 32 + xor edx,edx + mov ecx,10000000 + div ecx + mov dword [timestamp+4],eax + mov eax,ebx + div ecx + mov dword [timestamp],eax + retn + +system_shutdown: + cmp [memory],0 + je memory_released + invoke HeapDestroy,[memory] + memory_released: + retn + +malloc: +malloc_fixed: +malloc_growable: +; in: ecx = requested size +; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi +; note: +; use of malloc_fixed hints that block will be kept as is until the end of assembly +; use of malloc_growable hints that block is likely to be resized + invoke HeapAlloc,[memory],0,ecx + test eax,eax + jz out_of_memory + memory_allocated: + push eax + invoke HeapSize,[memory],0,eax + mov ecx,eax + pop eax + cmp ecx,-1 + je out_of_memory + retn +realloc: +; in: eax - memory block, ecx = requested size +; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi + invoke HeapReAlloc,[memory],0,eax,ecx + test eax,eax + jnz memory_allocated + jmp out_of_memory +mfree: +; in: eax - memory block +; out: cf set on error +; preserves: ebx, esi, edi +; note: eax may have value 0 or -1, it should be treated as invalid input then + test eax,eax + jz interface_error + cmp eax,-1 + je interface_error + invoke HeapFree,[memory],0,eax + test eax,eax + jz interface_error + clc + retn + interface_error: + stc + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + mov ebx,edx + invoke WaitForSingleObject,[mutex],-1 + invoke CreateFile,ebx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0 + cmp eax,-1 + je release_mutex + mov ebx,eax + clc + retn +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + cmp [executable_path],0 + jne path_catching_done + push esi edi + mov esi,edx + mov edi,executable_path + catch_path: + lodsb + stosb + test al,al + jnz catch_path + pop edi esi + path_catching_done: + mov ebx,edx + invoke WaitForSingleObject,[mutex],-1 + invoke CreateFile,ebx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0 + cmp eax,-1 + je release_mutex + mov ebx,eax + clc + retn +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ecx + invoke WriteFile,ebx,edx,ecx,systmp,0 + pop ecx + test eax,eax + jz interface_error + cmp ecx,[systmp] + jne interface_error + clc + retn +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ecx + invoke ReadFile,ebx,edx,ecx,systmp,0 + pop ecx + test eax,eax + jz interface_error + cmp ecx,[systmp] + jne interface_error + clc + retn +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + invoke CloseHandle,ebx + release_mutex: + invoke ReleaseMutex,[mutex] ; this relies on the fact that engine never opens more than one file at once + stc + retn +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + movzx ecx,cl + mov [systmp],edx + invoke SetFilePointer,ebx,eax,systmp,ecx + cmp eax,-1 + jne lseek_ok + invoke GetLastError + test eax,eax + jnz interface_error + not eax + lseek_ok: + mov edx,[systmp] + clc + retn + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx + mov ebx,stdout + jmp write_string +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx esi + mov ebx,stderr + write_string: + test ecx,ecx + jnz write_string_to_buffer + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_buffer: + mov edi,[ebx] + push ecx + invoke HeapSize,[hheap],0,dword [ebx] + mov edx,eax + sub eax,4 + sub eax,[edi] + mov ecx,[esp] + sub ecx,eax + jb string_buffer_ready ; do not fit tight, leave room for terminating zero + add edx,ecx + inc edx + invoke HeapReAlloc,[hheap],0,dword [ebx],edx + test eax,eax + jz shutdown + mov [ebx],eax + mov edi,eax + string_buffer_ready: + pop ecx + mov eax,[edi] + add [edi],ecx + lea edi,[edi+4+eax] + xor al,al + test esi,esi + jz zero_string + rep movsb + stosb + pop esi ebx + retn + zero_string: + rep stosb + pop esi ebx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push ecx + invoke GetEnvironmentVariable,esi,string_buffer,1000h + invoke GetPrivateProfileString,_section_environment,esi,string_buffer,string_buffer,1000h,ini_path + mov ecx,[esp] + push esi edi + mov esi,string_buffer + copy_env_val: + lodsb + jecxz next_env_char + mov [edi],al + dec ecx + next_env_char: + inc edi + test al,al + jnz copy_env_val + mov eax,edi + pop edi esi ecx + sub eax,edi + retn + + include '../../assembler.inc' + include '../../symbols.inc' + include '../../expressions.inc' + include '../../conditions.inc' + include '../../floats.inc' + include '../../directives.inc' + include '../../calm.inc' + include '../../errors.inc' + include '../../map.inc' + include '../../reader.inc' + include '../../output.inc' + include '../../console.inc' + +section '.rdata' data readable + + include '../../tables.inc' + include '../../messages.inc' + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'Failed to write the output file.',0 + _out_of_memory db 'Not enough memory to complete the assembly.',0 + _code_cannot_be_generated db 'Could not generate code within the allowed number of passes.',0 + + version_string db VERSION,0 + +section '.bss' readable writeable + + include '../../variables.inc' + + source_string dd ? + source_path dd ? + output_path dd ? + + maximum_number_of_passes dd ? + + timestamp dq ? + systemtime SYSTEMTIME + filetime FILETIME + + memory dd ? + systmp dd ? + + timer dd ? + + stdout dd ? + stderr dd ? diff --git a/toolchain/fasm2/source/ide/windows/fasmgw.asm b/toolchain/fasm2/source/ide/windows/fasmgw.asm new file mode 100644 index 0000000..9e13464 --- /dev/null +++ b/toolchain/fasm2/source/ide/windows/fasmgw.asm @@ -0,0 +1,3811 @@ + +; flat assembler g IDE for Windows +; Copyright (c) 1999-2024, Tomasz Grysztar. +; All rights reserved. + +format PE GUI 4.0 large NX +entry start +stack 20000h + +include 'win32ax.inc' +include 'fedit.ash' + +include '..\..\version.inc' + +struct EDITITEM + header TC_ITEMHEADER + hwnd dd ? + pszpath dd ? +ends + +FM_NEW = WM_USER + 0 +FM_OPEN = WM_USER + 1 +FM_SAVE = WM_USER + 2 +FM_COMPILE = WM_USER + 3 +FM_SELECT = WM_USER + 4 +FM_ASSIGN = WM_USER + 5 +FM_GETSELECTED = WM_USER + 6 +FM_GETASSIGNED = WM_USER + 7 +FM_GETHANDLE = WM_USER + 8 +FM_OPENREADONLY = WM_USER + 11h +FM_SAVEMODIFIED = WM_USER + 12h + +struct HH_AKLINK + cbStruct dd ? + fReserved dd ? + pszKeywords dd ? + pszUrl dd ? + pszMsgText dd ? + pszMsgTitle dd ? + pszWindow dd ? + fIndexOnFail dd ? +ends + +HH_DISPLAY_TOPIC = 0 +HH_KEYWORD_LOOKUP = 0Dh + +CP_ARGUMENTS = 0 +CP_DIRECTORY = 1 + +MAX_ERRORS = 1000 + +EXPRESSION_MAX_LENGTH = 1000 + +section '.data' data readable writeable + + HtmlHelp dd 0 + + SetGestureConfig dd 0 + GetGestureInfo dd 0 + CloseGestureInfoHandle dd 0 + + wheel_scroll_lines dd 3 + + _caption db 'flat assembler 2 (g.',VERSION,')',0 + _class db 'FASMGW',0 + _fedit_class db 'FEDIT',0 + _listbox_class db 'LISTBOX',0 + _tabctrl_class db 'SysTabControl32',0 + _htmlhelp_library db 'HHCTRL.OCX',0 + _htmlhelp_api db 'HtmlHelpA',0 + _user_library db 'USER32.DLL',0 + _setgestureconfig_api db 'SetGestureConfig',0 + _getgestureinfo_api db 'GetGestureInfo',0 + _closegestureinfohandle_api db 'CloseGestureInfoHandle',0 + + _memory_error db 'Not enough memory to complete this operation.',0 + _loading_error db 'Could not load file %s.',0 + _saving_question db 'File was modified. Save it now?',0 + _not_found db 'Text %s not found.',0 + _not_found_after db 'Text %s not found after current position.',0 + _not_found_before db 'Text %s not found before current position.',0 + _replace_prompt db 'Replace this occurence?',0 + _replaces_made db '%d replaces made.',0 + _untitled db 'Untitled',0 + _font_face db 'Courier New',0 + _row_column db 9,'%d,' + _value db '%d' + _null db 0 + _line_number db '%s [%d]',0 + _color db '%d,%d,%d',0 + _modified_status db 9,'Modified',0 + _readonly_status db 9,'Read-only',0 + _pick_help db 'Pick help file',0 + _find db 'Find',0 + _replace db 'Replace',0 + _calm db 'CALM',0 + + _asm_extension db 'asm',0 + + _section_environment db 'Environment',0 + _key_environment_include db 'Include',0 + _section_compiler db 'Compiler',0 + _key_compiler_header db 'SourceHeader',0 + _key_compiler_priority db 'Priority',0 + _key_compiler_max_passes db 'MaxPasses',0 + _key_compiler_max_recursion db 'MaxRecursion',0 + _section_options db 'Options',0 + _key_options_securesel db 'SecureSelection',0 + _key_options_autobrackets db 'AutoBrackets',0 + _key_options_autoindent db 'AutoIndent',0 + _key_options_smarttabs db 'SmartTabs',0 + _key_options_optimalfill db 'OptimalFill',0 + _key_options_revivedeadkeys db 'ReviveDeadKeys',0 + _key_options_consolecaret db 'ConsoleCaret',0 + _key_options_timescroll db 'TimeScroll',0 + _key_options_oneinstanceonly db 'OneInstanceOnly',0 + _section_colors db 'Colors',0 + _key_color_text db 'Text',0 + _key_color_background db 'Background',0 + _key_color_seltext db 'SelectionText',0 + _key_color_selbackground db 'SelectionBackground',0 + _key_color_symbols db 'Symbols',0 + _key_color_numbers db 'Numbers',0 + _key_color_strings db 'Strings',0 + _key_color_comments db 'Comments',0 + _section_font db 'Font',0 + _key_font_face db 'Face',0 + _key_font_height db 'Height',0 + _key_font_width db 'Width',0 + _key_font_weight db 'Weight',0 + _key_font_italic db 'Italic',0 + _key_font_charset db 'CharSet',0 + _section_window db 'Window',0 + _key_window_top db 'Top',0 + _key_window_left db 'Left',0 + _key_window_right db 'Right',0 + _key_window_bottom db 'Bottom',0 + _key_window_maximized db 'Maximized',0 + _section_help db 'Help',0 + _key_help_path db 'Path',0 + + _reg_key_desktop db 'Control Panel\Desktop',0 + _reg_value_wheelscrolllines db 'WheelScrollLines',0 + + _appearance_settings db 'Font',0 + db 'Text color',0 + db 'Background color',0 + db 'Selection text color',0 + db 'Selection background color',0 + db 'Symbols color',0 + db 'Numbers color',0 + db 'Strings color',0 + db 'Comments color',0 + db 0 + _priority_settings db 'Idle',0 + db 'Low',0 + db 'Normal',0 + db 'High',0 + db 'Realtime',0 + db 0 + + fedit_style dd FES_AUTOINDENT+FES_SMARTTABS+FES_CONSOLECARET + + editor_colors rd 4 + asm_syntax_colors dd 0xF03030,0x009000,0x0000B0,0x808080 + + preview_text db 0Dh,0Ah + db ' org 100h',0Dh,0Ah + db 0Dh,0Ah + db ' mov ah,09h ',' ; write',0Dh,0Ah + db ' mov dx,text',0Dh,0Ah + db ' int 21h',0Dh,0Ah + db ' int 20h',0Dh,0Ah + db 0Dh,0Ah + db ' text db "Hello!",24h',0Dh,0Ah + db 0 + preview_selection dd 1,5,1,6 + + asm_filter db 'Assembly files',0,'*.asm;*.inc;*.ash;*.alm',0 + db 'All files',0,'*.*',0 + db 0 + + help_filter db 'Help files',0,'*.hlp;*.chm',0 + db 0 + + default_source_header db "include 'fasm2.inc'",0 + + calculator_string db 'db string ' + expression_buffer db EXPRESSION_MAX_LENGTH dup ? + + align 4 + + hinstance dd ? + hheap dd ? + hkey_main dd ? + hmenu_main dd ? + hmenu_edit dd ? + hmenu_tab dd ? + hacc dd ? + hfont dd ? + hwnd_main dd ? + hwnd_status dd ? + hwnd_tabctrl dd ? + hwnd_history dd ? + hwnd_fedit dd ? + hwnd_compiler dd ? + hwnd_progress dd ? + himl dd ? + hthread dd ? + hfile dd ? + mutex dd ? + + instance_flags dd ? + command_flags dd ? + search_settings dd ? + replaces_count dd ? + compiler_memory dd ? + compiler_priority dd ? + assigned_file dd ? + program_arguments dd ? + + result_address dd ? + result_size dd ? + digits_address dd ? + digits_size dd ? + + param_buffer rd 10h + user_colors rd 10h + name_buffer rb 100h + search_string rb 1000h + replace_string rb 1000h + string_buffer rb 2000h + help_path rb 1000h + ini_path rb 1000h + include_path rb 1000h + source_header rb 1000h + executable_path rb 1000h + path_buffer rb 4000h + + msg MSG + wc WNDCLASS + rc RECT + pt POINT + ei EDITITEM + font LOGFONT + bm BITMAP + tcht TC_HITTESTINFO + wp WINDOWPLACEMENT + fepos FEPOS + ofn OPENFILENAME + cf CHOOSEFONT + cc CHOOSECOLOR + systime SYSTEMTIME + sinfo STARTUPINFO + pinfo PROCESS_INFORMATION + cp COPYDATASTRUCT + + bytes_count dd ? + fedit_font dd ? + + tmp_colors rd 8 + tmp_font LOGFONT + backup_font LOGFONT + + hhkey HH_AKLINK + + upper_case_table rb 100h + + error_pointers rd MAX_ERRORS + +section '.text' code readable executable + +include 'fedit.inc' + + start: + + invoke GetModuleHandle,0 + mov [hinstance],eax + invoke GetProcessHeap + mov [hheap],eax + + invoke GetModuleHandle,_user_library + or eax,eax + jz gesture_api_unavailable + mov ebx,eax + invoke GetProcAddress,ebx,_setgestureconfig_api + or eax,eax + jz gesture_api_unavailable + mov esi,eax + invoke GetProcAddress,ebx,_getgestureinfo_api + or eax,eax + jz gesture_api_unavailable + mov edi,eax + invoke GetProcAddress,ebx,_closegestureinfohandle_api + or eax,eax + jz gesture_api_unavailable + mov [CloseGestureInfoHandle],eax + mov [SetGestureConfig],esi + mov [GetGestureInfo],edi + gesture_api_unavailable: + + invoke GetCommandLine + mov esi,eax + mov edi,ini_path + find_program_path: + lodsb + cmp al,20h + je find_program_path + cmp al,22h + je quoted_program_path + cmp al,0Dh + je program_path_ok + or al,al + jnz get_program_path + dec esi + jmp program_path_ok + get_program_path: + stosb + lodsb + cmp al,20h + je program_path_ok + cmp al,0Dh + je program_path_ok + or al,al + jnz get_program_path + dec esi + jmp program_path_ok + quoted_program_path: + lodsb + cmp al,22h + je program_path_ok + cmp al,0Dh + je program_path_ok + stosb + or al,al + jnz quoted_program_path + dec esi + program_path_ok: + mov [program_arguments],esi + mov ebx,edi + find_program_extension: + cmp ebx,ini_path + je make_ini_extension + dec ebx + mov al,[ebx] + cmp al,'\' + je make_ini_extension + cmp al,'/' + je make_ini_extension + cmp al,'.' + jne find_program_extension + mov edi,ebx + jmp find_program_extension + make_ini_extension: + mov eax,'.ini' + stosd + xor al,al + stosb + invoke GetFullPathName,ini_path,1000h,ini_path,param_buffer + mov esi,ini_path + mov ecx,[param_buffer] + sub ecx,esi + mov edi,include_path + rep movsb + mov eax,'incl' + stosd + mov eax,'ude' + stosd + invoke GetFileAttributes,ini_path + cmp eax,-1 + jne ini_ok + invoke WritePrivateProfileString,_section_environment,_key_environment_include,include_path,ini_path + ini_ok: + + mov [instance_flags],0 + stdcall GetIniBit,ini_path,_section_options,_key_options_oneinstanceonly,instance_flags,1 + cmp [instance_flags],0 + je create_new_window + invoke FindWindow,_class,NULL + or eax,eax + jnz window_already_exists + + create_new_window: + invoke LoadCursor,0,IDC_IBEAM + mov [wc.hCursor],eax + mov [wc.style],CS_GLOBALCLASS+CS_DBLCLKS + mov [wc.lpfnWndProc],FlatEditor + mov eax,[hinstance] + mov [wc.hInstance],eax + mov [wc.cbWndExtra],4 + xor eax,eax + mov [wc.hbrBackground],eax + mov [wc.cbClsExtra],eax + mov [wc.lpszMenuName],eax + mov [wc.lpszClassName],_fedit_class + invoke RegisterClass,wc + or eax,eax + jz end_loop + invoke CreateFont,0,0,0,0,0,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_RASTER_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH+FF_DONTCARE,NULL + or eax,eax + jz end_loop + mov [fedit_font],eax + + mov edi,upper_case_table + xor ebx,ebx + mov esi,100h + make_case_table: + invoke CharUpper,ebx + stosb + inc bl + dec esi + jnz make_case_table + mov edi,characters + mov ecx,100h + xor al,al + prepare_characters_table: + stosb + inc al + loop prepare_characters_table + mov esi,characters+'a' + mov edi,characters+'A' + mov ecx,26 + rep movsb + mov edi,characters + mov esi,syntactical_characters + mov ecx,syntactical_characters.count + xor eax,eax + convert_table: + lodsb + mov byte [edi+eax],0 + loop convert_table + + invoke LoadIcon,[hinstance],IDI_MAIN + mov [wc.hIcon],eax + invoke LoadCursor,0,IDC_ARROW + mov [wc.hCursor],eax + mov [wc.style],0 + mov [wc.lpfnWndProc],MainWindow + mov [wc.cbClsExtra],0 + mov [wc.cbWndExtra],0 + mov eax,[hinstance] + mov [wc.hInstance],eax + mov [wc.hbrBackground],COLOR_BTNFACE+1 + mov [wc.lpszMenuName],0 + mov [wc.lpszClassName],_class + invoke RegisterClass,wc + + invoke LoadMenu,[hinstance],IDM_MAIN + mov [hmenu_main],eax + invoke GetSubMenu,eax,1 + mov [hmenu_edit],eax + invoke LoadMenu,[hinstance],IDM_TAB + invoke GetSubMenu,eax,0 + mov [hmenu_tab],eax + invoke LoadAccelerators,[hinstance],IDA_MAIN + mov [hacc],eax + invoke CreateWindowEx,0,_class,_caption,WS_OVERLAPPEDWINDOW+WS_CLIPCHILDREN+WS_CLIPSIBLINGS,64,64,500,500,NULL,[hmenu_main],[hinstance],NULL + or eax,eax + jz end_loop + mov [hwnd_main],eax + mov eax,SW_SHOW + test [wp.flags],WPF_RESTORETOMAXIMIZED + jz show_main_window + mov eax,SW_SHOWMAXIMIZED + show_main_window: + invoke ShowWindow,[hwnd_main],eax + invoke UpdateWindow,[hwnd_main] + msg_loop: + invoke GetMessage,msg,NULL,0,0 + or eax,eax + jz end_loop + invoke TranslateAccelerator,[hwnd_main],[hacc],msg + or eax,eax + jnz msg_loop + cmp [msg.message],WM_KEYDOWN + je msg_dispatch + invoke TranslateMessage,msg + msg_dispatch: + invoke DispatchMessage,msg + jmp msg_loop + + window_already_exists: + mov ebx,eax + invoke GetWindowPlacement,ebx,wp + mov eax,SW_SHOWNORMAL + cmp [wp.showCmd],SW_SHOWMAXIMIZED + jne show_existing_window + mov eax,SW_SHOWMAXIMIZED + show_existing_window: + invoke ShowWindow,ebx,eax + invoke SetForegroundWindow,ebx + invoke GetCurrentDirectory,4000h,path_buffer + inc eax + mov [cp.cbData],eax + mov [cp.lpData],path_buffer + mov [cp.dwData],CP_DIRECTORY + invoke SendMessage,ebx,WM_COPYDATA,NULL,cp + mov edi,[program_arguments] + mov [cp.lpData],edi + or ecx,-1 + xor al,al + repne scasb + neg ecx + mov [cp.cbData],ecx + mov [cp.dwData],CP_ARGUMENTS + invoke SendMessage,ebx,WM_COPYDATA,NULL,cp + end_loop: + invoke ExitProcess,[msg.wParam] + +proc MainWindow hwnd,wmsg,wparam,lparam + push ebx esi edi + cmp [wmsg],WM_CREATE + je wmcreate + cmp [wmsg],WM_COPYDATA + je wmcopydata + cmp [wmsg],WM_GETMINMAXINFO + je wmgetminmaxinfo + cmp [wmsg],WM_SIZE + je wmsize + cmp [wmsg],WM_SETFOCUS + je wmsetfocus + cmp [wmsg],FM_NEW + je fmnew + cmp [wmsg],FM_OPEN + je fmopen + cmp [wmsg],FM_OPENREADONLY + je fmopenreadonly + cmp [wmsg],FM_SAVE + je fmsave + cmp [wmsg],FM_SAVEMODIFIED + je fmsavemodified + cmp [wmsg],FM_COMPILE + je fmcompile + cmp [wmsg],FM_SELECT + je fmselect + cmp [wmsg],FM_ASSIGN + je fmassign + cmp [wmsg],FM_GETSELECTED + je fmgetselected + cmp [wmsg],FM_GETASSIGNED + je fmgetassigned + cmp [wmsg],FM_GETHANDLE + je fmgethandle + cmp [wmsg],WM_INITMENU + je wminitmenu + cmp [wmsg],WM_COMMAND + je wmcommand + cmp [wmsg],WM_NOTIFY + je wmnotify + cmp [wmsg],WM_DROPFILES + je wmdropfiles + cmp [wmsg],WM_CLOSE + je wmclose + cmp [wmsg],WM_DESTROY + je wmdestroy + invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] + jmp finish + wmcreate: + xor eax,eax + mov [search_settings],eax + mov [search_string],al + mov [replace_string],al + mov [compiler_memory],65536 + mov [compiler_priority],THREAD_PRIORITY_NORMAL + mov [assigned_file],-1 + mov [help_path],0 + mov [ofn.lStructSize],sizeof.OPENFILENAME + mov eax,[hwnd] + mov [ofn.hwndOwner],eax + mov eax,[hinstance] + mov [ofn.hInstance],eax + mov [ofn.lpstrCustomFilter],NULL + mov [ofn.nFilterIndex],1 + mov [ofn.nMaxFile],1000h + mov [ofn.lpstrFileTitle],name_buffer + mov [ofn.nMaxFileTitle],100h + mov [ofn.lpstrInitialDir],NULL + mov [ofn.lpstrDefExt],_asm_extension + mov [font.lfHeight],16 + mov [font.lfWidth],0 + mov [font.lfEscapement],0 + mov [font.lfOrientation],0 + mov [font.lfWeight],0 + mov [font.lfItalic],FALSE + mov [font.lfUnderline],FALSE + mov [font.lfStrikeOut],FALSE + mov [font.lfCharSet],DEFAULT_CHARSET + mov [font.lfOutPrecision],OUT_RASTER_PRECIS + mov [font.lfClipPrecision],CLIP_DEFAULT_PRECIS + mov [font.lfQuality],DEFAULT_QUALITY + mov [font.lfPitchAndFamily],FIXED_PITCH+FF_DONTCARE + mov edi,font.lfFaceName + mov esi,_font_face + copy_font_face: + lodsb + stosb + or al,al + jnz copy_font_face + invoke GetSysColor,COLOR_WINDOWTEXT + mov [editor_colors],eax + invoke GetSysColor,COLOR_WINDOW + mov [editor_colors+4],eax + invoke GetSysColor,COLOR_HIGHLIGHTTEXT + mov [editor_colors+8],eax + invoke GetSysColor,COLOR_HIGHLIGHT + mov [editor_colors+12],eax + mov esi,editor_colors + mov edi,user_colors + mov ecx,8 + rep movsd + mov [wp.length],sizeof.WINDOWPLACEMENT + invoke GetWindowPlacement,[hwnd],wp + invoke RegOpenKeyEx,HKEY_CURRENT_USER,_reg_key_desktop,0,KEY_READ,param_buffer + test eax,eax + jnz wheel_setting_ok + mov [bytes_count],100h + invoke RegQueryValueEx,[param_buffer],_reg_value_wheelscrolllines,0,param_buffer+4,string_buffer,bytes_count + test eax,eax + jnz no_valid_wheel_setting + cmp [param_buffer+4],REG_SZ + jne no_valid_wheel_setting + mov esi,string_buffer + cmp byte [esi],0 + je no_valid_wheel_setting + call atoi + jc no_valid_wheel_setting + mov [wheel_scroll_lines],eax + no_valid_wheel_setting: + invoke RegCloseKey,[param_buffer] + wheel_setting_ok: + invoke GetPrivateProfileString,_section_compiler,_key_compiler_header,default_source_header,source_header,1000h,ini_path + stdcall GetIniInteger,ini_path,_section_compiler,_key_compiler_priority,compiler_priority + mov eax,100 + mov [maximum_number_of_passes],eax + mov [param_buffer],eax + stdcall GetIniInteger,ini_path,_section_compiler,_key_compiler_max_passes,param_buffer + mov eax,[param_buffer] + test eax,eax + jz passes_limit_ok + mov [maximum_number_of_passes],eax + passes_limit_ok: + mov eax,10000 + mov [maximum_depth_of_stack],eax + mov [param_buffer],eax + stdcall GetIniInteger,ini_path,_section_compiler,_key_compiler_max_recursion,param_buffer + mov eax,[param_buffer] + test eax,eax + jz recursion_limit_ok + mov [maximum_depth_of_stack],eax + recursion_limit_ok: + stdcall GetIniBit,ini_path,_section_options,_key_options_securesel,fedit_style,FES_SECURESEL + stdcall GetIniBit,ini_path,_section_options,_key_options_autobrackets,fedit_style,FES_AUTOBRACKETS + stdcall GetIniBit,ini_path,_section_options,_key_options_autoindent,fedit_style,FES_AUTOINDENT + stdcall GetIniBit,ini_path,_section_options,_key_options_smarttabs,fedit_style,FES_SMARTTABS + stdcall GetIniBit,ini_path,_section_options,_key_options_optimalfill,fedit_style,FES_OPTIMALFILL + stdcall GetIniBit,ini_path,_section_options,_key_options_revivedeadkeys,fedit_style,FES_REVIVEDEADKEYS + stdcall GetIniBit,ini_path,_section_options,_key_options_consolecaret,fedit_style,FES_CONSOLECARET + stdcall GetIniBit,ini_path,_section_options,_key_options_timescroll,fedit_style,FES_TIMESCROLL + stdcall GetIniColor,ini_path,_section_colors,_key_color_text,editor_colors + stdcall GetIniColor,ini_path,_section_colors,_key_color_background,editor_colors+4 + stdcall GetIniColor,ini_path,_section_colors,_key_color_seltext,editor_colors+8 + stdcall GetIniColor,ini_path,_section_colors,_key_color_selbackground,editor_colors+12 + stdcall GetIniColor,ini_path,_section_colors,_key_color_symbols,asm_syntax_colors + stdcall GetIniColor,ini_path,_section_colors,_key_color_numbers,asm_syntax_colors+4 + stdcall GetIniColor,ini_path,_section_colors,_key_color_strings,asm_syntax_colors+8 + stdcall GetIniColor,ini_path,_section_colors,_key_color_comments,asm_syntax_colors+12 + invoke GetPrivateProfileString,_section_font,_key_font_face,font.lfFaceName,font.lfFaceName,32,ini_path + stdcall GetIniInteger,ini_path,_section_font,_key_font_height,font.lfHeight + stdcall GetIniInteger,ini_path,_section_font,_key_font_width,font.lfWidth + stdcall GetIniInteger,ini_path,_section_font,_key_font_weight,font.lfWeight + stdcall GetIniBit,ini_path,_section_font,_key_font_italic,font.lfItalic,1 + stdcall GetIniByte,ini_path,_section_font,_key_font_charset,font.lfCharSet + stdcall GetIniInteger,ini_path,_section_window,_key_window_top,wp.rcNormalPosition.top + stdcall GetIniInteger,ini_path,_section_window,_key_window_left,wp.rcNormalPosition.left + stdcall GetIniInteger,ini_path,_section_window,_key_window_right,wp.rcNormalPosition.right + stdcall GetIniInteger,ini_path,_section_window,_key_window_bottom,wp.rcNormalPosition.bottom + stdcall GetIniBit,ini_path,_section_window,_key_window_maximized,wp.flags,WPF_RESTORETOMAXIMIZED + invoke GetPrivateProfileString,_section_help,_key_help_path,help_path,help_path,1000h,ini_path + mov [wp.showCmd],SW_HIDE + invoke SetWindowPlacement,[hwnd],wp + invoke CreateFontIndirect,font + mov [hfont],eax + invoke CreateStatusWindow,WS_CHILD+WS_VISIBLE+SBS_SIZEGRIP,NULL,[hwnd],0 + or eax,eax + jz failed + mov [hwnd_status],eax + mov [param_buffer],48h + mov [param_buffer+4],90h + mov [param_buffer+8],-1 + invoke SendMessage,eax,SB_SETPARTS,3,param_buffer + invoke CreateWindowEx,0,_listbox_class,NULL,WS_CHILD+LBS_HASSTRINGS,0,0,0,0,[hwnd],NULL,[hinstance],NULL + or eax,eax + jz failed + mov [hwnd_history],eax + invoke CreateWindowEx,0,_tabctrl_class,NULL,WS_VISIBLE+WS_CHILD+TCS_FOCUSNEVER+TCS_BOTTOM,0,0,0,0,[hwnd],NULL,[hinstance],NULL + or eax,eax + jz failed + mov [hwnd_tabctrl],eax + invoke SendMessage,[hwnd_tabctrl],TCM_SETITEMEXTRA,sizeof.EDITITEM-sizeof.TC_ITEMHEADER,0 + invoke SendMessage,[hwnd_status],WM_GETFONT,0,0 + invoke SendMessage,[hwnd_tabctrl],WM_SETFONT,eax,FALSE + invoke LoadBitmap,[hinstance],IDB_ASSIGN + mov ebx,eax + invoke GetObject,ebx,sizeof.BITMAP,bm + invoke ImageList_Create,[bm.bmWidth],[bm.bmHeight],ILC_COLOR4,1,0 + or eax,eax + jz failed + mov [himl],eax + invoke ImageList_Add,[himl],ebx,NULL + invoke DeleteObject,ebx + invoke SendMessage,[hwnd_tabctrl],TCM_SETIMAGELIST,0,[himl] + invoke SendMessage,[hwnd],FM_NEW,_untitled,0 + cmp eax,-1 + je failed + invoke DragAcceptFiles,[hwnd],TRUE + mov esi,[program_arguments] + process_arguments: + xor ebx,ebx + ARG_ASSIGN = 1 + ARG_READONLY = 2 + find_argument: + lodsb + cmp al,20h + je find_argument + cmp al,'+' + je argument_assign + cmp al,'-' + je argument_readonly + xor ecx,ecx + cmp al,22h + je quoted_argument + cmp al,0Dh + je command_line_ok + or al,al + jz command_line_ok + lea edx,[esi-1] + find_argument_end: + inc ecx + lodsb + cmp al,20h + je argument_end + cmp al,0Dh + je argument_end + or al,al + jz argument_end + jmp find_argument_end + argument_assign: + or bl,ARG_ASSIGN + jmp find_argument + argument_readonly: + or bl,ARG_READONLY + jmp find_argument + quoted_argument: + mov edx,esi + find_quoted_argument_end: + lodsb + cmp al,22h + je quoted_argument_end + cmp al,0Dh + je quoted_argument_end + or al,al + jz quoted_argument_end + inc ecx + jmp find_quoted_argument_end + argument_end: + dec esi + quoted_argument_end: + push eax edx esi + mov esi,edx + mov edi,path_buffer + cmp ecx,1000h-1 + jae process_next_argument + rep movsb + xor al,al + stosb + mov ecx,path_buffer+4000h + sub ecx,edi + invoke GetFullPathName,path_buffer,ecx,edi,param_buffer + invoke GetFileTitle,edi,name_buffer,100h + mov eax,FM_OPEN + test bl,ARG_READONLY + jz load_from_argument + mov eax,FM_OPENREADONLY + load_from_argument: + invoke SendMessage,[hwnd],eax,name_buffer,edi + cmp eax,-1 + je loading_error + test bl,ARG_ASSIGN + jz process_next_argument + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + invoke SendMessage,[hwnd],FM_ASSIGN,eax,0 + jmp process_next_argument + loading_error: + cinvoke wsprintf,string_buffer,_loading_error,path_buffer + invoke MessageBox,[hwnd],string_buffer,_caption,MB_ICONERROR+MB_OK + process_next_argument: + pop esi edx eax + jmp process_arguments + command_line_ok: + xor eax,eax + jmp finish + wmcopydata: + mov ebx,[lparam] + virtual at ebx + cmd COPYDATASTRUCT + end virtual + mov eax,[cmd.dwData] + cmp eax,CP_ARGUMENTS + je copy_arguments + cmp eax,CP_DIRECTORY + jne failed + invoke SetCurrentDirectory,[cmd.lpData] + jmp finish + copy_arguments: + mov esi,[cmd.lpData] + jmp process_arguments + wmgetminmaxinfo: + mov ebx,[lparam] + virtual at ebx + mmi MINMAXINFO + end virtual + mov [mmi.ptMinTrackSize.x],240 + mov [mmi.ptMinTrackSize.y],160 + jmp finish + wmsize: + invoke SendMessage,[hwnd_status],WM_SIZE,0,0 + xor eax,eax + mov [rc.left],eax + mov [rc.top],eax + mov [rc.right],eax + mov [rc.bottom],eax + invoke SendMessage,[hwnd_tabctrl],TCM_ADJUSTRECT,TRUE,rc + mov esi,[rc.bottom] + sub esi,[rc.top] + invoke GetWindowRect,[hwnd_status],rc + mov ebx,[rc.bottom] + sub ebx,[rc.top] + invoke GetClientRect,[hwnd],rc + sub [rc.bottom],ebx + sub [rc.bottom],esi + invoke SetWindowPos,[hwnd_tabctrl],[hwnd_fedit],0,[rc.bottom],[rc.right],esi,0 + invoke GetSystemMetrics,SM_CYFIXEDFRAME + shl eax,1 + add [rc.bottom],eax + invoke MoveWindow,[hwnd_fedit],0,0,[rc.right],[rc.bottom],TRUE + jmp finish + wmsetfocus: + invoke SetFocus,[hwnd_fedit] + jmp finish + fmnew: + invoke CreateWindowEx,WS_EX_STATICEDGE,_fedit_class,NULL,WS_CHILD+WS_HSCROLL+WS_VSCROLL+ES_NOHIDESEL,0,0,0,0,[hwnd],NULL,[hinstance],NULL + or eax,eax + jz failed + mov [ei.header.mask],TCIF_TEXT+TCIF_PARAM + mov [ei.hwnd],eax + mov eax,[wparam] + mov [ei.header.pszText],eax + and [ei.pszpath],0 + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEMCOUNT,0,0 + invoke SendMessage,[hwnd_tabctrl],TCM_INSERTITEM,eax,ei + mov ebx,eax + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,eax,0 + invoke SendMessage,[hwnd],FM_SELECT,ebx,0 + invoke SetFocus,[hwnd] + mov eax,ebx + jmp finish + fmopen: + and [command_flags],0 + allocate_path_buffer: + invoke VirtualAlloc,0,1000h,MEM_COMMIT,PAGE_READWRITE + or eax,eax + jz failed + mov edi,eax + mov esi,[lparam] + mov [lparam],edi + copy_path_for_fedit: + lodsb + stosb + or al,al + jnz copy_path_for_fedit + xor ebx,ebx + check_if_already_loaded: + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,ebx,ei + or eax,eax + jz load_file + invoke lstrcmpi,[ei.pszpath],[lparam] + or eax,eax + jz show_already_loaded + inc ebx + jmp check_if_already_loaded + show_already_loaded: + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,ebx,0 + invoke SendMessage,[hwnd],FM_SELECT,ebx,0 + jmp update_fedit_mode + load_file: + invoke CreateFile,[lparam],GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0 + cmp eax,-1 + je open_failed + mov ebx,eax + invoke GetFileSize,ebx,NULL + inc eax + push eax + invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE + or eax,eax + pop ecx + jz load_out_of_memory + dec ecx + push MEM_RELEASE + push 0 + push eax + mov byte [eax+ecx],0 + invoke ReadFile,ebx,eax,ecx,param_buffer,0 + invoke CloseHandle,ebx + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEMCOUNT,0,0 + cmp eax,1 + jne new_fedit + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,0,ei + cmp [ei.pszpath],0 + jne new_fedit + invoke SendMessage,[ei.hwnd],FEM_ISUNMODIFIED,0,0 + or eax,eax + jz new_fedit + mov [ei.header.mask],TCIF_TEXT+TCIF_PARAM + mov eax,[wparam] + mov [ei.header.pszText],eax + mov eax,[lparam] + mov [ei.pszpath],eax + invoke SendMessage,[hwnd_tabctrl],TCM_SETITEM,0,ei + xor ebx,ebx + jmp set_fedit_text + new_fedit: + invoke SendMessage,[hwnd],FM_NEW,[wparam],0 + cmp eax,-1 + jne set_path + add esp,12 + jmp open_failed + set_path: + mov ebx,eax + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,ebx,ei + mov eax,[lparam] + mov [ei.pszpath],eax + invoke SendMessage,[hwnd_tabctrl],TCM_SETITEM,ebx,ei + set_fedit_text: + invoke SendMessage,[hwnd_fedit],WM_SETTEXT,0,dword [esp] + call [VirtualFree] + update_fedit_mode: + invoke SendMessage,[hwnd_fedit],FEM_GETMODE,0,0 + and eax,not FEMODE_READONLY + test [command_flags],1 + jz set_fedit_mode + or eax,FEMODE_READONLY + set_fedit_mode: + invoke SendMessage,[hwnd_fedit],FEM_SETMODE,eax,0 + jmp update_status_bar + load_out_of_memory: + invoke CloseHandle,ebx + open_failed: + invoke VirtualFree,[lparam],0,MEM_RELEASE + jmp failed + fmopenreadonly: + or [command_flags],1 + jmp allocate_path_buffer + fmsavemodified: + or ebx,-1 + jmp save_single_file + fmsave: + xor ebx,ebx + save_single_file: + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,[wparam],ei + or eax,eax + jz failed + cmp [ei.pszpath],0 + je failed + invoke SendMessage,[ei.hwnd],FEM_GETMODE,0,0 + test eax,FEMODE_READONLY + jnz ok + invoke SendMessage,[ei.hwnd],FEM_ISUNMODIFIED,0,0 + and eax,ebx + jnz ok + invoke SendMessage,[ei.hwnd],WM_GETTEXTLENGTH,0,0 + inc eax + mov [wparam],eax + invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE + or eax,eax + jz failed + mov [lparam],eax + invoke CreateFile,[ei.pszpath],GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0 + cmp eax,-1 + je save_failed + mov ebx,eax + invoke SendMessage,[ei.hwnd],WM_GETTEXT,[wparam],[lparam] + invoke WriteFile,ebx,[lparam],eax,param_buffer,0 + test eax,eax + jz save_failed + invoke CloseHandle,ebx + invoke VirtualFree,[lparam],0,MEM_RELEASE + invoke SendMessage,[ei.hwnd],FEM_MARKUNMODIFIED,0,0 + xor ebx,ebx + mov eax,[ei.hwnd] + cmp eax,[hwnd_fedit] + je update_status_bar + xor eax,eax + jmp finish + save_failed: + invoke VirtualFree,[lparam],0,MEM_RELEASE + jmp failed + fmcompile: + mov eax,[assigned_file] + push eax + cmp eax,-1 + jne assigned_ok + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + mov [assigned_file],eax + assigned_ok: + invoke SendMessage,[hwnd_main],FM_SAVEMODIFIED,eax,0 + xor ebx,ebx + or eax,eax + jz save_all + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,[assigned_file],0 + invoke SendMessage,[hwnd_main],FM_SELECT,[assigned_file],0 + invoke SendMessage,[hwnd_main],WM_COMMAND,IDM_SAVEAS,0 + or eax,eax + jz save_all + or eax,-1 + jmp compile_done + save_all: + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,ebx,ei + or eax,eax + jz do_compile + invoke SendMessage,[hwnd_main],FM_SAVEMODIFIED,ebx,0 + inc ebx + jmp save_all + do_compile: + mov eax,[wparam] + mov [output_path],eax + invoke DialogBoxParam,[hinstance],IDD_COMPILE,[hwnd],CompileDialog,[assigned_file] + cmp eax,-1 + je compile_done + push eax + cmp eax,2 + je error_details + or eax,eax + jnz show_summary + cmp [lparam],FALSE + jne show_summary + jmp summary_shown + show_summary: + invoke DialogBoxParam,[hinstance],IDD_SUMMARY,[hwnd],SummaryDialog,eax + jmp summary_shown + error_details: + invoke DialogBoxParam,[hinstance],IDD_ERRORSUMMARY,[hwnd],SummaryDialog,eax + summary_shown: + invoke HeapFree,[hheap],0,[stdout] + invoke HeapFree,[hheap],0,[stderr] + pop eax + compile_done: + pop edx + cmp edx,-1 + jne finish + or [assigned_file],-1 + jmp finish + fmselect: + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,[wparam],ei + invoke GetWindowLong,[hwnd_fedit],GWL_STYLE + and eax,not WS_VISIBLE + invoke SetWindowLong,[hwnd_fedit],GWL_STYLE,eax + mov ebx,[ei.hwnd] + mov [hwnd_fedit],ebx + mov eax,WS_CHILD+WS_HSCROLL+WS_VSCROLL+ES_NOHIDESEL + or eax,[fedit_style] + invoke SetWindowLong,ebx,GWL_STYLE,eax + invoke SendMessage,ebx,WM_SETFONT,[hfont],0 + invoke SendMessage,ebx,FEM_SETTEXTCOLOR,[editor_colors],[editor_colors+4] + invoke SendMessage,ebx,FEM_SETSELCOLOR,[editor_colors+8],[editor_colors+12] + invoke SendMessage,ebx,FEM_SETSYNTAXHIGHLIGHT,asm_syntax_colors,fasm_syntax + invoke SendMessage,ebx,FEM_SETRIGHTCLICKMENU,[hmenu_edit],[hwnd] + invoke SendMessage,[hwnd],WM_SIZE,0,0 + invoke ShowWindow,ebx,SW_SHOW + invoke UpdateWindow,ebx + invoke SetFocus,[hwnd] + jmp finish + fmassign: + mov eax,[wparam] + cmp [assigned_file],-1 + je new_assign + push eax + mov [ei.header.mask],TCIF_IMAGE + mov [ei.header.iImage],-1 + invoke SendMessage,[hwnd_tabctrl],TCM_SETITEM,[assigned_file],ei + pop eax + new_assign: + mov [assigned_file],eax + mov [ei.header.mask],TCIF_IMAGE + mov [ei.header.iImage],0 + invoke SendMessage,[hwnd_tabctrl],TCM_SETITEM,eax,ei + or eax,eax + jnz fmgetassigned + or eax,-1 + mov [assigned_file],eax + jmp finish + fmgetassigned: + mov eax,[assigned_file] + jmp finish + fmgetselected: + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + jmp finish + fmgethandle: + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,[wparam],ei + or eax,eax + jz finish + mov eax,[ei.hwnd] + jmp finish + wminitmenu: + mov esi,[hwnd_fedit] + invoke SendMessage,esi,EM_CANUNDO,0,0 + or eax,eax + setz bl + neg bl + and ebx,MF_GRAYED + or ebx,MF_BYCOMMAND + invoke EnableMenuItem,[wparam],IDM_UNDO,ebx + invoke SendMessage,esi,FEM_CANREDO,0,0 + or eax,eax + setz bl + neg bl + and ebx,MF_GRAYED + or ebx,MF_BYCOMMAND + invoke EnableMenuItem,[wparam],IDM_REDO,ebx + invoke SendMessage,esi,FEM_GETPOS,fepos,0 + mov eax,[fepos.selectionLine] + cmp eax,[fepos.caretLine] + sete bh + mov eax,[fepos.selectionPosition] + cmp eax,[fepos.caretPosition] + sete bl + and bl,bh + neg bl + and ebx,MF_GRAYED + or ebx,MF_BYCOMMAND + invoke EnableMenuItem,[wparam],IDM_CUT,ebx + invoke EnableMenuItem,[wparam],IDM_COPY,ebx + invoke EnableMenuItem,[wparam],IDM_DELETE,ebx + invoke IsClipboardFormatAvailable,CF_TEXT + neg al + not al + and eax,MF_GRAYED + or eax,MF_BYCOMMAND + invoke EnableMenuItem,[wparam],IDM_PASTE,eax + invoke SendMessage,esi,FEM_GETMODE,0,0 + mov ebx,eax + test eax,FEMODE_VERTICALSEL + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_VERTICAL,eax + test ebx,FEMODE_READONLY + setnz bl + and ebx,MF_GRAYED + or ebx,MF_BYCOMMAND + invoke EnableMenuItem,[wparam],IDM_CUT,ebx + invoke EnableMenuItem,[wparam],IDM_PASTE,ebx + invoke EnableMenuItem,[wparam],IDM_DELETE,ebx + invoke EnableMenuItem,[wparam],IDM_REPLACE,ebx + invoke SendMessage,esi,FEM_CANFINDNEXT,0,0 + or eax,eax + setz al + neg al + and eax,MF_GRAYED + or eax,MF_BYCOMMAND + invoke EnableMenuItem,[wparam],IDM_FINDNEXT,eax + test [fedit_style],FES_SECURESEL + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_SECURESEL,eax + test [fedit_style],FES_AUTOBRACKETS + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_AUTOBRACKETS,eax + test [fedit_style],FES_AUTOINDENT + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_AUTOINDENT,eax + test [fedit_style],FES_SMARTTABS + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_SMARTTABS,eax + test [fedit_style],FES_OPTIMALFILL + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_OPTIMALFILL,eax + test [fedit_style],FES_REVIVEDEADKEYS + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_REVIVEDEADKEYS,eax + test [fedit_style],FES_TIMESCROLL + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_TIMESCROLL,eax + mov eax,[instance_flags] + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[wparam],IDM_ONEINSTANCEONLY,eax + cmp [help_path],0 + sete bl + neg bl + and ebx,MF_GRAYED + or ebx,MF_BYCOMMAND + invoke EnableMenuItem,[wparam],IDM_CONTENTS,ebx + invoke EnableMenuItem,[wparam],IDM_KEYWORD,ebx + jmp finish + wmcommand: + mov eax,[wparam] + mov ebx,[lparam] + or ebx,ebx + jz menu_command + cmp ebx,[hwnd_fedit] + jne finish + xor ebx,ebx + shr eax,16 + cmp eax,FEN_SETFOCUS + je update_status_bar + cmp eax,FEN_TEXTCHANGE + je update_status_bar + cmp eax,FEN_POSCHANGE + je update_status_bar + cmp eax,FEN_OUTOFMEMORY + je not_enough_mem + jmp finish + update_status_bar: + invoke SendMessage,[hwnd_fedit],FEM_GETPOS,fepos,0 + cinvoke wsprintf,string_buffer,_row_column,[fepos.caretLine],[fepos.caretPosition] + invoke SendMessage,[hwnd_status],SB_SETTEXT,0,string_buffer + mov esi,_null + invoke SendMessage,[hwnd_fedit],FEM_GETMODE,0,0 + test eax,FEMODE_READONLY + jnz readonly_status + invoke SendMessage,[hwnd_fedit],FEM_ISUNMODIFIED,0,0 + or eax,eax + jnz modified_status_ok + mov esi,_modified_status + jmp modified_status_ok + readonly_status: + mov esi,_readonly_status + modified_status_ok: + invoke SendMessage,[hwnd_status],SB_SETTEXT,1,esi + mov eax,ebx + jmp finish + not_enough_mem: + invoke SendMessage,[hwnd_fedit],FEM_RELEASESEARCH,0,0 + invoke MessageBox,[hwnd],_memory_error,_caption,MB_ICONERROR+MB_OK + mov eax,ebx + jmp finish + menu_command: + and eax,0FFFFh + mov ebx,[hwnd_fedit] + cmp eax,IDM_NEW + je new_file + cmp eax,IDM_OPEN + je open_file + cmp eax,IDM_SAVE + je save_file + cmp eax,IDM_SAVEAS + je save_file_as + cmp eax,IDM_NEXT + je next_file + cmp eax,IDM_PREVIOUS + je previous_file + cmp eax,IDM_OPENFOLDER + je open_folder + cmp eax,IDM_CLOSE + je close_file + cmp eax,IDM_EXIT + je exit + cmp eax,IDM_UNDO + je undo + cmp eax,IDM_REDO + je redo + cmp eax,IDM_DISCARD_UNDO + je discard_undo + cmp eax,IDM_CUT + je cut + cmp eax,IDM_COPY + je copy + cmp eax,IDM_PASTE + je paste + cmp eax,IDM_DELETE + je delete + cmp eax,IDM_SELECTALL + je select_all + cmp eax,IDM_VERTICAL + je vertical + cmp eax,IDM_READONLY + je read_only + cmp eax,IDM_POSITION + je position + cmp eax,IDM_FIND + je find + cmp eax,IDM_FINDNEXT + je findnext + cmp eax,IDM_REPLACE + je replace + cmp eax,IDM_RUN + je run + cmp eax,IDM_COMPILE + je compile + cmp eax,IDM_ASSIGN + je assign + cmp eax,IDM_APPEARANCE + je appearance + cmp eax,IDM_COMPILERSETUP + je compiler_setup + cmp eax,IDM_SECURESEL + je option_securesel + cmp eax,IDM_AUTOBRACKETS + je option_autobrackets + cmp eax,IDM_AUTOINDENT + je option_autoindent + cmp eax,IDM_SMARTTABS + je option_smarttabs + cmp eax,IDM_OPTIMALFILL + je option_optimalfill + cmp eax,IDM_REVIVEDEADKEYS + je option_revivedeadkeys + cmp eax,IDM_TIMESCROLL + je option_timescroll + cmp eax,IDM_ONEINSTANCEONLY + je option_oneinstanceonly + cmp eax,IDM_CALCULATOR + je calculator + cmp eax,IDM_CONTENTS + je contents + cmp eax,IDM_KEYWORD + je keyword + cmp eax,IDM_PICKHELP + je pick_help + cmp eax,IDM_ABOUT + je about + sub eax,IDM_SELECTFILE + jc finish + cmp eax,9 + ja finish + mov ebx,eax + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEMCOUNT,0,0 + cmp ebx,eax + ja finish + dec ebx + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,ebx,0 + invoke SendMessage,[hwnd],FM_SELECT,ebx,0 + jmp finish + new_file: + invoke SendMessage,[hwnd],FM_NEW,_untitled,0 + jmp finish + open_file: + mov [ofn.lpstrFile],path_buffer + mov [path_buffer],0 + mov [ofn.lpstrFilter],asm_filter + mov [ofn.Flags],OFN_EXPLORER+OFN_ALLOWMULTISELECT+OFN_FILEMUSTEXIST + mov [ofn.lpstrFileTitle],name_buffer + mov [ofn.lpstrTitle],NULL + invoke GetOpenFileName,ofn + or eax,eax + jz finish + mov ebx,FM_OPEN + test [ofn.Flags],OFN_READONLY + jz open_chosen_files + mov ebx,FM_OPENREADONLY + open_chosen_files: + test [ofn.Flags],OFN_ALLOWMULTISELECT + jz open_single_file + mov esi,path_buffer + movzx eax,[ofn.nFileOffset] + add esi,eax + mov byte [esi-1],'\' + mov edi,esi + open_multiple_files: + cmp byte [esi],0 + je finish + push edi + move_file_name: + lodsb + stosb + or al,al + jnz move_file_name + pop edi + invoke GetFileTitle,path_buffer,name_buffer,100h + invoke SendMessage,[hwnd],ebx,name_buffer,path_buffer + cmp eax,-1 + jne open_multiple_files + invoke wvsprintf,string_buffer,_loading_error,ofn.lpstrFile + invoke MessageBox,[hwnd],string_buffer,_caption,MB_ICONERROR+MB_OK + jmp open_multiple_files + open_single_file: + invoke SendMessage,[hwnd],ebx,name_buffer,path_buffer + cmp eax,-1 + jne finish + invoke wvsprintf,string_buffer,_loading_error,ofn.lpstrFile + invoke MessageBox,[hwnd],string_buffer,_caption,MB_ICONERROR+MB_OK + jmp finish + save_file: + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + invoke SendMessage,[hwnd],FM_SAVE,eax,0 + or eax,eax + jnz save_file_as + jmp finish + save_file_as: + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + mov ebx,eax + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,ebx,ei + mov eax,[ei.pszpath] + or eax,eax + jnz alloc_ok + invoke VirtualAlloc,0,1000h,MEM_COMMIT,PAGE_READWRITE + mov [ei.pszpath],eax + and byte [eax],0 + alloc_ok: + mov [lparam],eax + mov [ofn.lpstrFile],eax + mov [ofn.lpstrFilter],asm_filter + mov [ofn.Flags],OFN_EXPLORER+OFN_HIDEREADONLY+OFN_OVERWRITEPROMPT + mov [ofn.lpstrTitle],NULL + invoke GetSaveFileName,ofn + or eax,eax + jz save_cancelled + mov eax,[ei.pszpath] + mov [ei.header.pszText],name_buffer + mov [ei.header.mask],TCIF_TEXT+TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_SETITEM,ebx,ei + invoke SendMessage,[hwnd],FM_SAVE,ebx,0 + xor esi,esi + check_if_overwritten: + cmp esi,ebx + je not_overwritten + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,esi,ei + or eax,eax + jz save_ok + invoke lstrcmpi,[ei.pszpath],[lparam] + or eax,eax + jz remove_overwritten + not_overwritten: + inc esi + jmp check_if_overwritten + remove_overwritten: + invoke VirtualFree,[ei.pszpath],0,MEM_RELEASE + invoke SendMessage,[hwnd_tabctrl],TCM_DELETEITEM,esi,0 + cmp [assigned_file],-1 + je save_ok + cmp esi,[assigned_file] + ja save_ok + je assigned_overwritten + dec [assigned_file] + jmp save_ok + assigned_overwritten: + mov [assigned_file],-1 + save_ok: + xor eax,eax + jmp finish + save_cancelled: + mov eax,[ei.pszpath] + cmp byte [eax],0 + jne preserve_save_path + invoke VirtualFree,[ei.pszpath],0,MEM_RELEASE + and [ei.pszpath],0 + preserve_save_path: + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + invoke SendMessage,[hwnd_tabctrl],TCM_SETITEM,eax,ei + jmp finish + next_file: + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEMCOUNT,0,0 + mov ebx,eax + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + inc eax + cmp eax,ebx + jb select_file + xor eax,eax + select_file: + push eax + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,eax,0 + pop eax + invoke SendMessage,[hwnd],FM_SELECT,eax,0 + jmp finish + previous_file: + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + sub eax,1 + jnc select_file + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEMCOUNT,0,0 + dec eax + call select_file + jmp select_file + open_folder: + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,eax,ei + or eax,eax + jz finish + mov eax,[ei.pszpath] + or eax,eax + jz finish + invoke GetFullPathName,eax,1000h,path_buffer,param_buffer + mov edi,[param_buffer] + xor al,al + stosb + invoke ShellExecute,HWND_DESKTOP,NULL,path_buffer,NULL,NULL,SW_SHOWNORMAL + jmp finish + close_file: + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEMCOUNT,0,0 + cmp eax,1 + jbe close_window + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + mov ebx,eax + mov [ei.header.mask],TCIF_PARAM+TCIF_TEXT + mov [ei.header.pszText],name_buffer + mov [ei.header.cchTextMax],100h + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,ebx,ei + mov eax,[ei.hwnd] + mov [wparam],eax + invoke SendMessage,eax,FEM_ISUNMODIFIED,0,0 + or eax,eax + jz close_modified + cmp [ei.pszpath],0 + jne do_close + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEMCOUNT,0,0 + cmp eax,1 + jne do_close + jmp failed + close_modified: + mov eax,MB_ICONQUESTION+MB_YESNOCANCEL + or eax,[lparam] + invoke MessageBox,[hwnd],_saving_question,[ei.header.pszText],eax + cmp eax,IDCANCEL + je failed + cmp eax,IDNO + je do_close + invoke SendMessage,[hwnd],WM_COMMAND,IDM_SAVE,0 + or eax,eax + jnz failed + do_close: + cmp [ei.pszpath],0 + je delete_tab + invoke VirtualFree,[ei.pszpath],0,MEM_RELEASE + delete_tab: + invoke SendMessage,[hwnd_tabctrl],TCM_DELETEITEM,ebx,0 + cmp ebx,[assigned_file] + jg tab_deleted + je assigned_deleted + dec [assigned_file] + jmp tab_deleted + assigned_deleted: + mov [assigned_file],-1 + tab_deleted: + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEMCOUNT,0,0 + dec eax + cmp eax,ebx + jge select_next + sub ebx,1 + jnc select_next + invoke SendMessage,[hwnd],FM_NEW,_untitled,0 + jmp destroy_fedit + select_next: + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,ebx,0 + invoke SendMessage,[hwnd],FM_SELECT,ebx,0 + destroy_fedit: + invoke DestroyWindow,[wparam] + xor eax,eax + jmp finish + exit: + mov [lparam],0 + jmp close_window + undo: + invoke SendMessage,ebx,WM_UNDO,0,0 + jmp finish + redo: + invoke SendMessage,ebx,FEM_REDO,0,0 + jmp finish + cut: + invoke SendMessage,ebx,WM_CUT,0,0 + jmp finish + copy: + invoke SendMessage,ebx,WM_COPY,0,0 + jmp finish + paste: + invoke SendMessage,ebx,WM_PASTE,0,0 + jmp finish + delete: + invoke SendMessage,ebx,WM_CLEAR,0,0 + jmp finish + discard_undo: + invoke SendMessage,ebx,EM_EMPTYUNDOBUFFER,0,0 + jmp finish + select_all: + mov [fepos.selectionLine],1 + mov [fepos.selectionPosition],1 + mov [fepos.caretLine],-1 + mov [fepos.caretPosition],1 + invoke SendMessage,ebx,FEM_SETPOS,fepos,0 + invoke SendMessage,ebx,FEM_GETPOS,fepos,0 + invoke SendMessage,ebx,FEM_GETLINELENGTH,[fepos.caretLine],0 + inc eax + mov [fepos.caretPosition],eax + invoke SendMessage,ebx,FEM_SETPOS,fepos,0 + jmp finish + vertical: + invoke SendMessage,ebx,FEM_GETMODE,0,0 + xor eax,FEMODE_VERTICALSEL + invoke SendMessage,ebx,FEM_SETMODE,eax,0 + jmp finish + read_only: + invoke SendMessage,ebx,FEM_GETMODE,0,0 + xor eax,FEMODE_READONLY + invoke SendMessage,ebx,FEM_SETMODE,eax,0 + xor ebx,ebx + jmp update_status_bar + position: + invoke DialogBoxParam,[hinstance],IDD_POSITION,[hwnd],PositionDialog,0 + jmp finish + find: + invoke DialogBoxParam,[hinstance],IDD_FIND,[hwnd],FindDialog,0 + or eax,eax + jz finish + invoke SendMessage,ebx,FEM_FINDFIRST,[search_settings],search_string + or eax,eax + jnz finish + not_found: + mov [param_buffer],1000h + invoke SendMessage,[hwnd_fedit],FEM_GETSEARCHTEXT,search_string,param_buffer + invoke SendMessage,[hwnd_fedit],FEM_GETSEARCHFLAGS,0,0 + mov esi,_not_found + test eax,FEFIND_INWHOLETEXT + jnz make_not_found_message + mov esi,_not_found_after + test eax,FEFIND_BACKWARD + jz make_not_found_message + mov esi,_not_found_before + make_not_found_message: + cinvoke wsprintf,string_buffer,esi,search_string + invoke SendMessage,[hwnd_fedit],FEM_RELEASESEARCH,0,0 + invoke MessageBox,[hwnd],string_buffer,_find,MB_ICONINFORMATION+MB_OK + jmp finish + findnext: + invoke SendMessage,ebx,FEM_FINDNEXT,0,0 + or eax,eax + jz not_found + jmp finish + replace: + invoke DialogBoxParam,[hinstance],IDD_REPLACE,[hwnd],ReplaceDialog,0 + or eax,eax + jz finish + mov [replaces_count],0 + invoke SendMessage,ebx,FEM_BEGINOPERATION,0,0 + test [command_flags],1 + jz .start_replacing + invoke SendMessage,ebx,FEM_ENDOPERATION,0,0 + .start_replacing: + invoke SendMessage,ebx,FEM_FINDFIRST,[search_settings],search_string + or eax,eax + jz .not_found + invoke SendMessage,ebx,FEM_GETMODE,0,0 + push eax + and eax,not (FEMODE_VERTICALSEL + FEMODE_OVERWRITE) + invoke SendMessage,ebx,FEM_SETMODE,eax,0 + .confirm_replace: + test [command_flags],1 + jz .replace + invoke UpdateWindow,edi + invoke MessageBox,[hwnd],_replace_prompt,_replace,MB_ICONQUESTION+MB_YESNOCANCEL + cmp eax,IDCANCEL + je .replace_finish + cmp eax,IDNO + je .replace_next + .replace: + push ebx edi + invoke SendMessage,ebx,EM_REPLACESEL,FALSE,replace_string + pop edi ebx + inc [replaces_count] + .replace_next: + invoke SendMessage,ebx,FEM_FINDNEXT,0,0 + or eax,eax + jnz .confirm_replace + .replace_finish: + pop eax + invoke SendMessage,ebx,FEM_SETMODE,eax,0 + test [command_flags],1 + jnz .replace_summary + invoke SendMessage,ebx,FEM_ENDOPERATION,0,0 + .replace_summary: + invoke SendMessage,[hwnd_fedit],FEM_RELEASESEARCH,0,0 + cinvoke wsprintf,string_buffer,_replaces_made,[replaces_count] + invoke MessageBox,[hwnd],string_buffer,_find,MB_ICONINFORMATION+MB_OK + jmp finish + .not_found: + invoke SendMessage,ebx,FEM_ENDOPERATION,0,0 + jmp not_found + run: + and [command_flags],0 + invoke SendMessage,[hwnd],FM_COMPILE,0,FALSE + or eax,eax + jnz finish + mov [sinfo.cb],sizeof.STARTUPINFO + mov [sinfo.dwFlags],0 + invoke GetFullPathName,executable_path,1000h,path_buffer,param_buffer + mov edx,[param_buffer] + mov byte [edx-1],0 + invoke CreateProcess,executable_path,NULL,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,path_buffer,sinfo,pinfo + invoke CloseHandle,[pinfo.hThread] + invoke CloseHandle,[pinfo.hProcess] + jmp finish + compile: + invoke SendMessage,[hwnd],FM_COMPILE,0,TRUE + jmp finish + assign: + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + cmp eax,[assigned_file] + jne do_assign + or eax,-1 + do_assign: + invoke SendMessage,[hwnd],FM_ASSIGN,eax,0 + jmp finish + appearance: + invoke DialogBoxParam,[hinstance],IDD_APPEARANCE,[hwnd],AppearanceSetup,0 + or eax,eax + jnz update + jmp finish + compiler_setup: + invoke DialogBoxParam,[hinstance],IDD_COMPILERSETUP,[hwnd],CompilerSetup,0 + jmp finish + option_securesel: + xor [fedit_style],FES_SECURESEL + jmp update + option_autobrackets: + xor [fedit_style],FES_AUTOBRACKETS + jmp update + option_autoindent: + xor [fedit_style],FES_AUTOINDENT + jmp update + option_smarttabs: + xor [fedit_style],FES_SMARTTABS + jmp update + option_optimalfill: + xor [fedit_style],FES_OPTIMALFILL + jmp update + option_revivedeadkeys: + xor [fedit_style],FES_REVIVEDEADKEYS + jmp update + option_timescroll: + xor [fedit_style],FES_TIMESCROLL + jmp update + option_oneinstanceonly: + xor [instance_flags],1 + stdcall WriteIniBit,ini_path,_section_options,_key_options_oneinstanceonly,[instance_flags],1 + jmp finish + calculator: + invoke DialogBoxParam,[hinstance],IDD_CALCULATOR,[hwnd],CalculatorDialog,0 + jmp finish + contents: + call get_help_file_extension + cmp eax,'.hlp' + je winhelp_contents + call check_htmlhelp + jc winhelp_contents + invoke HtmlHelp,[hwnd],help_path,HH_DISPLAY_TOPIC,0 + jmp finish + winhelp_contents: + invoke WinHelp,[hwnd],help_path,HELP_FINDER,0 + jmp finish + get_help_file_extension: + mov esi,help_path + skip_help_path: + lodsb + or al,al + jnz skip_help_path + mov ebx,characters + dec esi + mov ecx,4 + convert_extension: + dec esi + shl eax,8 + mov al,[esi] + xlatb + loop convert_extension + retn + check_htmlhelp: + cmp [HtmlHelp],0 + jne htmlhelp_ok + invoke LoadLibrary,_htmlhelp_library + or eax,eax + jz htmlhelp_unavailable + invoke GetProcAddress,eax,_htmlhelp_api + or eax,eax + jz htmlhelp_unavailable + mov [HtmlHelp],eax + htmlhelp_ok: + clc + retn + htmlhelp_unavailable: + stc + retn + keyword: + invoke SendMessage,[hwnd_fedit],FEM_GETWORDATCARET,1000h,string_buffer + call get_help_file_extension + cmp eax,'.hlp' + je winhelp_keyword + call check_htmlhelp + jc winhelp_keyword + mov [hhkey.cbStruct],sizeof.HH_AKLINK + mov [hhkey.pszKeywords],string_buffer + mov [hhkey.pszUrl],0 + mov [hhkey.fIndexOnFail],TRUE + invoke HtmlHelp,[hwnd],help_path,HH_DISPLAY_TOPIC,0 + invoke HtmlHelp,[hwnd],help_path,HH_KEYWORD_LOOKUP,hhkey + jmp finish + winhelp_keyword: + invoke WinHelp,[hwnd],help_path,HELP_KEY,string_buffer + jmp finish + pick_help: + mov [ofn.lpstrFile],help_path + mov [ofn.lpstrFilter],help_filter + mov [ofn.Flags],OFN_EXPLORER+OFN_FILEMUSTEXIST+OFN_HIDEREADONLY + mov [ofn.lpstrTitle],_pick_help + invoke GetOpenFileName,ofn + jmp finish + about: + invoke DialogBoxParam,[hinstance],IDD_ABOUT,[hwnd],AboutDialog,0 + jmp finish + failed: + or eax,-1 + jmp finish + wmnotify: + mov ebx,[lparam] + virtual at ebx + nmh NMHDR + end virtual + cmp [nmh.code],NM_RCLICK + je rclick + cmp [nmh.code],TCN_SELCHANGING + je selchanging + cmp [nmh.code],TCN_SELCHANGE + jne finish + update: + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + invoke SendMessage,[hwnd],FM_SELECT,eax,0 + jmp finish + selchanging: + xor eax,eax + jmp finish + rclick: + invoke GetCursorPos,pt + invoke GetWindowRect,[hwnd_tabctrl],rc + mov eax,[pt.x] + sub eax,[rc.left] + mov [tcht.pt.x],eax + mov eax,[pt.y] + sub eax,[rc.top] + mov [tcht.pt.y],eax + invoke SendMessage,[hwnd_tabctrl],TCM_HITTEST,0,tcht + cmp eax,-1 + je finish + mov ebx,eax + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,ebx,0 + invoke SendMessage,[hwnd],FM_SELECT,ebx,0 + cmp ebx,[assigned_file] + sete al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[hmenu_tab],IDM_ASSIGN,eax + invoke SendMessage,[hwnd_fedit],FEM_GETMODE,0,0 + test eax,FEMODE_READONLY + setnz al + neg al + and eax,MF_CHECKED + or eax,MF_BYCOMMAND + invoke CheckMenuItem,[hmenu_tab],IDM_READONLY,eax + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,ebx,ei + invoke SendMessage,[hwnd_fedit],FEM_ISUNMODIFIED,0,0 + test eax,eax + setz al + cmp [ei.pszpath],0 + setz ah + or al,ah + neg al + and eax,MF_GRAYED + or eax,MF_BYCOMMAND + invoke EnableMenuItem,[hmenu_tab],IDM_READONLY,eax + invoke TrackPopupMenu,[hmenu_tab],TPM_RIGHTBUTTON,[pt.x],[pt.y],0,[hwnd],0 + jmp finish + wmdropfiles: + invoke DragQueryFile,[wparam],-1,NULL,0 + xor ebx,ebx + drop_files: + cmp ebx,eax + je drag_finish + push eax + invoke DragQueryFile,[wparam],ebx,path_buffer,1000h + push ebx + invoke GetFileTitle,path_buffer,name_buffer,100h + invoke SendMessage,[hwnd],FM_OPEN,name_buffer,path_buffer + cmp eax,-1 + jne drop_ok + cinvoke wsprintf,string_buffer,_loading_error,path_buffer + invoke MessageBox,[hwnd],string_buffer,_caption,MB_ICONERROR+MB_OK + drop_ok: + pop ebx eax + inc ebx + jmp drop_files + drag_finish: + invoke DragFinish,[wparam] + xor eax,eax + jmp finish + wmclose: + mov [lparam],MB_DEFBUTTON2 + close_window: + mov [wparam],0 + check_before_exiting: + mov [ei.header.mask],TCIF_PARAM+TCIF_TEXT + mov [ei.header.pszText],name_buffer + mov [ei.header.cchTextMax],100h + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,[wparam],ei + or eax,eax + jz check_done + mov esi,[ei.pszpath] + invoke SendMessage,[ei.hwnd],FEM_ISUNMODIFIED,0,0 + or eax,eax + jnz check_next + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,[wparam],0 + invoke SendMessage,[hwnd],FM_SELECT,[wparam],0 + mov eax,MB_ICONQUESTION+MB_YESNOCANCEL + or eax,[lparam] + invoke MessageBox,[hwnd],_saving_question,[ei.header.pszText],eax + cmp eax,IDCANCEL + je finish + cmp eax,IDNO + je check_next + invoke SendMessage,[hwnd],WM_COMMAND,IDM_SAVE,0 + or eax,eax + jnz finish + check_next: + inc [wparam] + jmp check_before_exiting + check_done: + mov [wparam],0 + release_paths: + mov [ei.header.mask],TCIF_PARAM+TCIF_TEXT + mov [ei.header.pszText],name_buffer + mov [ei.header.cchTextMax],100h + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,[wparam],ei + or eax,eax + jz quit + mov esi,[ei.pszpath] + or esi,esi + jz release_next_path + invoke VirtualFree,esi,0,MEM_RELEASE + release_next_path: + inc [wparam] + jmp release_paths + quit: + invoke WritePrivateProfileString,_section_compiler,_key_compiler_header,source_header,ini_path + stdcall WriteIniInteger,ini_path,_section_compiler,_key_compiler_max_passes,[maximum_number_of_passes] + stdcall WriteIniInteger,ini_path,_section_compiler,_key_compiler_max_recursion,[maximum_depth_of_stack] + stdcall WriteIniInteger,ini_path,_section_compiler,_key_compiler_priority,[compiler_priority] + stdcall WriteIniBit,ini_path,_section_options,_key_options_securesel,[fedit_style],FES_SECURESEL + stdcall WriteIniBit,ini_path,_section_options,_key_options_autobrackets,[fedit_style],FES_AUTOBRACKETS + stdcall WriteIniBit,ini_path,_section_options,_key_options_autoindent,[fedit_style],FES_AUTOINDENT + stdcall WriteIniBit,ini_path,_section_options,_key_options_smarttabs,[fedit_style],FES_SMARTTABS + stdcall WriteIniBit,ini_path,_section_options,_key_options_optimalfill,[fedit_style],FES_OPTIMALFILL + stdcall WriteIniBit,ini_path,_section_options,_key_options_revivedeadkeys,[fedit_style],FES_REVIVEDEADKEYS + stdcall WriteIniBit,ini_path,_section_options,_key_options_consolecaret,[fedit_style],FES_CONSOLECARET + stdcall WriteIniBit,ini_path,_section_options,_key_options_timescroll,[fedit_style],FES_TIMESCROLL + stdcall WriteIniColor,ini_path,_section_colors,_key_color_text,[editor_colors] + stdcall WriteIniColor,ini_path,_section_colors,_key_color_background,[editor_colors+4] + stdcall WriteIniColor,ini_path,_section_colors,_key_color_seltext,[editor_colors+8] + stdcall WriteIniColor,ini_path,_section_colors,_key_color_selbackground,[editor_colors+12] + stdcall WriteIniColor,ini_path,_section_colors,_key_color_symbols,[asm_syntax_colors] + stdcall WriteIniColor,ini_path,_section_colors,_key_color_numbers,[asm_syntax_colors+4] + stdcall WriteIniColor,ini_path,_section_colors,_key_color_strings,[asm_syntax_colors+8] + stdcall WriteIniColor,ini_path,_section_colors,_key_color_comments,[asm_syntax_colors+12] + invoke WritePrivateProfileString,_section_font,_key_font_face,font.lfFaceName,ini_path + stdcall WriteIniInteger,ini_path,_section_font,_key_font_height,[font.lfHeight] + stdcall WriteIniInteger,ini_path,_section_font,_key_font_width,[font.lfWidth] + stdcall WriteIniInteger,ini_path,_section_font,_key_font_weight,[font.lfWeight] + stdcall WriteIniBit,ini_path,_section_font,_key_font_italic,dword [font.lfItalic],1 + movzx eax,[font.lfCharSet] + stdcall WriteIniInteger,ini_path,_section_font,_key_font_charset,eax + invoke GetWindowPlacement,[hwnd],wp + stdcall WriteIniInteger,ini_path,_section_window,_key_window_top,[wp.rcNormalPosition.top] + stdcall WriteIniInteger,ini_path,_section_window,_key_window_left,[wp.rcNormalPosition.left] + stdcall WriteIniInteger,ini_path,_section_window,_key_window_right,[wp.rcNormalPosition.right] + stdcall WriteIniInteger,ini_path,_section_window,_key_window_bottom,[wp.rcNormalPosition.bottom] + cmp [wp.showCmd],SW_SHOWMAXIMIZED + sete al + stdcall WriteIniBit,ini_path,_section_window,_key_window_maximized,eax,1 + invoke WritePrivateProfileString,_section_help,_key_help_path,help_path,ini_path + invoke DestroyWindow,[hwnd] + jmp finish + wmdestroy: + invoke WinHelp,[hwnd],0,HELP_QUIT,0 + invoke ImageList_Destroy,[himl] + invoke PostQuitMessage,0 + ok: + xor eax,eax + finish: + pop edi esi ebx + ret +endp + +proc WriteIniInteger ini,sec,key,val + cinvoke wsprintf,string_buffer,_value,[val] + invoke WritePrivateProfileString,[sec],[key],string_buffer,[ini] + ret +endp + +proc WriteIniColor ini,sec,key,color + movzx eax,byte [color] + movzx ebx,byte [color+1] + movzx ecx,byte [color+2] + cinvoke wsprintf,string_buffer,_color,eax,ebx,ecx + invoke WritePrivateProfileString,[sec],[key],string_buffer,[ini] + ret +endp + +proc WriteIniBit ini,sec,key,val,mask + mov eax,[val] + test eax,[mask] + setnz al + movzx eax,al + cinvoke wsprintf,string_buffer,_value,eax + invoke WritePrivateProfileString,[sec],[key],string_buffer,[ini] + ret +endp + +proc GetIniInteger ini,sec,key,lpval + mov [string_buffer],0 + invoke GetPrivateProfileString,[sec],[key],string_buffer,string_buffer,1000h,[ini] + mov esi,string_buffer + cmp byte [esi],0 + je .done + call atoi + jc .done + mov ebx,[lpval] + mov [ebx],eax + .done: + ret +endp + +proc atoi + lodsb + cmp al,20h + je atoi + cmp al,9 + je atoi + mov bl,al + xor eax,eax + xor edx,edx + cmp bl,'-' + je atoi_digit + cmp bl,'+' + je atoi_digit + dec esi + atoi_digit: + mov dl,[esi] + sub dl,30h + jc atoi_done + cmp dl,9 + ja atoi_done + mov ecx,eax + shl ecx,1 + jc atoi_overflow + shl ecx,1 + jc atoi_overflow + add eax,ecx + shl eax,1 + jc atoi_overflow + js atoi_overflow + add eax,edx + jc atoi_overflow + inc esi + jmp atoi_digit + atoi_overflow: + stc + ret + atoi_done: + cmp bl,'-' + jne atoi_sign_ok + neg eax + atoi_sign_ok: + clc + ret +endp + +proc GetIniColor ini,sec,key,lpcolor + mov [string_buffer],0 + invoke GetPrivateProfileString,[sec],[key],string_buffer,string_buffer,1000h,[ini] + mov esi,string_buffer + cmp byte [esi],0 + je .done + call atoi + jc .done + cmp eax,0FFh + ja .done + mov edi,eax + call .find + jne .done + call atoi + jc .done + cmp eax,0FFh + ja .done + shl eax,8 + or edi,eax + call .find + jne .done + call atoi + jc .done + cmp eax,0FFh + ja .done + shl eax,16 + or edi,eax + mov ebx,[lpcolor] + mov [ebx],edi + .done: + ret + .find: + lodsb + cmp al,20h + je .find + cmp al,9 + je .find + cmp al,',' + retn +endp + +proc GetIniByte ini,sec,key,lpval + mov [string_buffer],0 + invoke GetPrivateProfileString,[sec],[key],string_buffer,string_buffer,1000h,[ini] + mov esi,string_buffer + cmp byte [esi],0 + je .done + call atoi + jc .done + cmp eax,100h + jae .done + mov ebx,[lpval] + mov [ebx],al + .done: + ret +endp + +proc GetIniBit ini,sec,key,lpval,mask + mov [string_buffer],0 + invoke GetPrivateProfileString,[sec],[key],string_buffer,string_buffer,1000h,[ini] + mov esi,string_buffer + xor eax,eax + .find: + lodsb + cmp al,20h + je .find + cmp al,9 + je .find + sub al,30h + jc .done + cmp al,1 + ja .done + neg eax + mov ebx,[lpval] + mov edx,[mask] + not edx + and [ebx],edx + and eax,[mask] + or [ebx],eax + .done: + ret +endp + +proc fasm_syntax lpLine,uChars,lpColors + push ebx esi edi + mov esi,[lpLine] + mov edi,[lpColors] + mov ebx,characters + mov ecx,[uChars] + xor edx,edx + .scan_syntax: + lodsb + .check_character: + cmp al,20h + je .syntax_space + cmp al,3Bh + je .syntax_comment + mov ah,al + xlatb + or al,al + jz .syntax_symbol + or edx,edx + jnz .syntax_neutral + cmp ah,27h + je .syntax_string + cmp ah,22h + je .syntax_string + cmp ah,24h + je .syntax_pascal_hex + cmp ah,39h + ja .syntax_neutral + cmp ah,30h + jae .syntax_number + .syntax_neutral: + or edx,-1 + inc edi + loop .scan_syntax + jmp .done + .syntax_space: + xor edx,edx + inc edi + loop .scan_syntax + jmp .done + .syntax_symbol: + mov al,1 + stosb + xor edx,edx + loop .scan_syntax + jmp .done + .syntax_pascal_hex: + cmp ecx,1 + je .syntax_neutral + mov al,[esi] + mov ah,al + xlatb + or al,al + jz .syntax_neutral + cmp ah,24h + jne .syntax_number + cmp ecx,2 + je .syntax_neutral + mov al,[esi+1] + xlatb + or al,al + jz .syntax_neutral + .syntax_number: + mov al,2 + stosb + loop .number_character + jmp .done + .number_character: + lodsb + mov ah,al + xlatb + xchg al,ah + or ah,ah + jz .check_character + cmp al,20h + je .check_character + cmp al,3Bh + je .check_character + mov al,2 + stosb + loop .number_character + jmp .done + .syntax_string: + mov al,3 + stosb + dec ecx + jz .done + lodsb + cmp al,ah + jne .syntax_string + mov al,3 + stosb + dec ecx + jz .done + lodsb + cmp al,ah + je .syntax_string + xor edx,edx + jmp .check_character + .process_comment: + lodsb + cmp al,20h + jne .syntax_comment + inc edi + loop .process_comment + jmp .done + .syntax_comment: + mov al,4 + stosb + loop .process_comment + .done: + pop edi esi ebx + ret +endp + +proc PositionDialog hwnd_dlg,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_INITDIALOG + je .initdialog + cmp [msg],WM_COMMAND + je .command + cmp [msg],WM_CLOSE + je .close + xor eax,eax + jmp .finish + .initdialog: + invoke SendMessage,[hwnd_fedit],FEM_GETPOS,fepos,0 + cinvoke wsprintf,string_buffer,_value,[fepos.caretLine] + invoke SetDlgItemText,[hwnd_dlg],ID_ROW,string_buffer + cinvoke wsprintf,string_buffer,_value,[fepos.caretPosition] + invoke SetDlgItemText,[hwnd_dlg],ID_COLUMN,string_buffer + jmp .processed + .command: + cmp [wparam],IDCANCEL + je .close + cmp [wparam],IDOK + jne .processed + invoke GetDlgItemInt,[hwnd_dlg],ID_ROW,param_buffer,FALSE + mov [fepos.caretLine],eax + mov [fepos.selectionLine],eax + invoke GetDlgItemInt,[hwnd_dlg],ID_COLUMN,param_buffer,FALSE + mov [fepos.caretPosition],eax + mov [fepos.selectionPosition],eax + invoke IsDlgButtonChecked,[hwnd_dlg],ID_SELECT + or eax,eax + jz .position + mov [fepos.selectionLine],0 + mov [fepos.selectionPosition],0 + .position: + invoke SendMessage,[hwnd_fedit],FEM_SETPOS,fepos,0 + invoke EndDialog,[hwnd_dlg],TRUE + jmp .processed + .close: + invoke EndDialog,[hwnd_dlg],FALSE + .processed: + mov eax,1 + .finish: + pop edi esi ebx + ret +endp + +proc GetStringsFromHistory hwnd_combobox + push ebx esi + invoke SendMessage,[hwnd_history],LB_GETCOUNT,0,0 + mov esi,eax + xor ebx,ebx + .get_string: + cmp ebx,esi + je .finish + invoke SendMessage,[hwnd_history],LB_GETTEXT,ebx,string_buffer + invoke SendMessage,[hwnd_combobox],CB_ADDSTRING,0,string_buffer + inc ebx + jmp .get_string + .finish: + pop esi ebx + ret +endp + +proc AddStringToHistory lpstr + mov eax,[lpstr] + cmp byte [eax],0 + je .finish + invoke SendMessage,[hwnd_history],LB_FINDSTRINGEXACT,-1,[lpstr] + cmp eax,LB_ERR + je .insert + invoke SendMessage,[hwnd_history],LB_DELETESTRING,eax,0 + .insert: + invoke SendMessage,[hwnd_history],LB_INSERTSTRING,0,[lpstr] + cmp eax,LB_ERRSPACE + jne .finish + invoke SendMessage,[hwnd_history],LB_GETCOUNT,0,0 + sub eax,1 + jc .finish + invoke SendMessage,[hwnd_history],LB_DELETESTRING,eax,0 + jmp .insert + .finish: + ret +endp + +proc FindDialog hwnd_dlg,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_INITDIALOG + je .initdialog + cmp [msg],WM_COMMAND + je .command + cmp [msg],WM_CLOSE + je .close + xor eax,eax + jmp .finish + .initdialog: + invoke SendMessage,[hwnd_fedit],FEM_GETWORDATCARET,1000h,search_string + invoke SetDlgItemText,[hwnd_dlg],ID_TEXT,search_string + invoke GetDlgItem,[hwnd_dlg],ID_TEXT + stdcall GetStringsFromHistory,eax + xor eax,eax + test [search_settings],FEFIND_CASESENSITIVE + setnz al + invoke CheckDlgButton,[hwnd_dlg],ID_CASESENSITIVE,eax + xor eax,eax + test [search_settings],FEFIND_WHOLEWORDS + setnz al + invoke CheckDlgButton,[hwnd_dlg],ID_WHOLEWORDS,eax + xor eax,eax + test [search_settings],FEFIND_BACKWARD + setnz al + invoke CheckDlgButton,[hwnd_dlg],ID_BACKWARD,eax + xor eax,eax + test [search_settings],FEFIND_INWHOLETEXT + setnz al + invoke CheckDlgButton,[hwnd_dlg],ID_INWHOLETEXT,eax + jmp .update + .command: + cmp [wparam],ID_TEXT + CBN_EDITCHANGE shl 16 + je .update + cmp [wparam],ID_TEXT + CBN_SELCHANGE shl 16 + je .selchange + cmp [wparam],IDCANCEL + je .close + cmp [wparam],IDOK + jne .processed + xor ebx,ebx + invoke IsDlgButtonChecked,[hwnd_dlg],ID_CASESENSITIVE + or eax,eax + jz .casesensitive_ok + or ebx,FEFIND_CASESENSITIVE + .casesensitive_ok: + invoke IsDlgButtonChecked,[hwnd_dlg],ID_WHOLEWORDS + or eax,eax + jz .wholewords_ok + or ebx,FEFIND_WHOLEWORDS + .wholewords_ok: + invoke IsDlgButtonChecked,[hwnd_dlg],ID_BACKWARD + or eax,eax + jz .backward_ok + or ebx,FEFIND_BACKWARD + .backward_ok: + invoke IsDlgButtonChecked,[hwnd_dlg],ID_INWHOLETEXT + or eax,eax + jz .inwholetext_ok + or ebx,FEFIND_INWHOLETEXT + .inwholetext_ok: + mov [search_settings],ebx + stdcall AddStringToHistory,search_string + invoke EndDialog,[hwnd_dlg],TRUE + jmp .processed + .selchange: + invoke PostMessage,[hwnd_dlg],WM_COMMAND,ID_TEXT + CBN_EDITCHANGE shl 16,0 + jmp .processed + .update: + invoke GetDlgItemText,[hwnd_dlg],ID_TEXT,search_string,1000h + xor ebx,ebx + cmp [search_string],0 + setnz bl + invoke GetDlgItem,[hwnd_dlg],IDOK + invoke EnableWindow,eax,ebx + jmp .processed + .close: + invoke EndDialog,[hwnd_dlg],FALSE + .processed: + mov eax,1 + .finish: + pop edi esi ebx + ret +endp + +proc ReplaceDialog hwnd_dlg,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_INITDIALOG + je .initdialog + cmp [msg],WM_COMMAND + je .command + jmp .finish + .initdialog: + invoke SetDlgItemText,[hwnd_dlg],ID_NEWTEXT,replace_string + invoke GetDlgItem,[hwnd_dlg],ID_NEWTEXT + stdcall GetStringsFromHistory,eax + xor eax,eax + test [command_flags],1 + setnz al + invoke CheckDlgButton,[hwnd_dlg],ID_PROMPT,eax + jmp .finish + .command: + cmp [wparam],IDOK + jne .finish + invoke GetDlgItemText,[hwnd_dlg],ID_NEWTEXT,replace_string,1000h + xor ebx,ebx + invoke IsDlgButtonChecked,[hwnd_dlg],ID_PROMPT + or eax,eax + jz .prompt_ok + or ebx,1 + .prompt_ok: + mov [command_flags],ebx + stdcall AddStringToHistory,replace_string + .finish: + stdcall FindDialog,[hwnd_dlg],[msg],[wparam],[lparam] + pop edi esi ebx + ret +endp + +proc CompileDialog hwnd_dlg,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_INITDIALOG + je .initdialog + cmp [msg],WM_COMMAND + je .command + cmp [msg],WM_CLOSE + je .close + xor eax,eax + jmp .finish + .initdialog: + mov eax,[hwnd_dlg] + mov [hwnd_compiler],eax + invoke GetDlgItem,[hwnd_dlg],ID_PROGRESS + mov [hwnd_progress],eax + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,[lparam],ei + invoke CreateMutex,NULL,FALSE,NULL + mov [mutex],eax + invoke HeapAlloc,[hheap],HEAP_ZERO_MEMORY,4 + mov [stdout],eax + invoke HeapAlloc,[hheap],HEAP_ZERO_MEMORY,4 + mov [stderr],eax + call system_init + invoke GetFullPathName,[ei.pszpath],1000h,path_buffer,param_buffer + invoke CreateThread,NULL,10000h,flat_assembler,path_buffer,0,param_buffer + mov [hthread],eax + jmp .processed + .command: + cmp [wparam],IDCANCEL + je .close + cmp [wparam],IDOK + jne .finish + .get_exit_code: + invoke WaitForSingleObject,[hthread],-1 + invoke GetExitCodeThread,[hthread],param_buffer + invoke CloseHandle,[hthread] + invoke CloseHandle,[mutex] + call system_shutdown + invoke EndDialog,[hwnd_dlg],[param_buffer] + jmp .processed + .close: + invoke WaitForSingleObject,[mutex],-1 + cmp eax,WAIT_ABANDONED + je .processed + invoke TerminateThread,[hthread],-1 + test eax,eax + jz .processed + invoke ReleaseMutex,[mutex] + invoke CloseHandle,[hthread] + invoke CloseHandle,[mutex] + call system_shutdown + invoke HeapFree,[hheap],0,[stdout] + invoke HeapFree,[hheap],0,[stderr] + .cancel: + invoke EndDialog,[hwnd_dlg],-1 + .processed: + mov eax,1 + .finish: + pop edi esi ebx + ret +endp + +proc ShowLine pszPath,nLine + mov [ei.header.mask],TCIF_PARAM + invoke SendMessage,[hwnd_tabctrl],TCM_GETCURSEL,0,0 + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,eax,ei + invoke lstrcmpi,[ei.pszpath],[pszPath] + or eax,eax + jz current_file_ok + xor ebx,ebx + find_file_window: + invoke SendMessage,[hwnd_tabctrl],TCM_GETITEM,ebx,ei + or eax,eax + jz load_for_show + invoke lstrcmpi,[ei.pszpath],[pszPath] + or eax,eax + jz show_file + inc ebx + jmp find_file_window + load_for_show: + mov esi,[pszPath] + mov edi,path_buffer + copy_path_for_show: + lodsb + stosb + or al,al + jnz copy_path_for_show + invoke GetFileTitle,path_buffer,name_buffer,100h + invoke SendMessage,[hwnd_main],FM_OPEN,name_buffer,path_buffer + cmp eax,-1 + je show_failed + jmp current_file_ok + show_file: + invoke SendMessage,[hwnd_tabctrl],TCM_SETCURSEL,ebx,0 + invoke SendMessage,[hwnd_main],FM_SELECT,ebx,0 + current_file_ok: + mov eax,[nLine] + mov [fepos.selectionLine],eax + mov [fepos.caretLine],eax + get_lines_to_show: + invoke SendMessage,[hwnd_fedit],FEM_GETLINELENGTH,[nLine],0 + mov esi,string_buffer + cmp eax,1000h + jb get_line_data + mov edi,eax + invoke VirtualAlloc,0,edi,MEM_COMMIT,PAGE_READWRITE + or eax,eax + jz show_lines + mov esi,eax + get_line_data: + invoke SendMessage,[hwnd_fedit],FEM_GETLINE,[nLine],esi + cmp esi,string_buffer + je show_lines + invoke VirtualFree,esi,edi,MEM_DECOMMIT + show_lines: + mov [fepos.selectionPosition],1 + inc [fepos.caretLine] + mov [fepos.caretPosition],1 + invoke SendMessage,[hwnd_fedit],FEM_GETLINELENGTH,[fepos.caretLine],0 + cmp eax,-1 + jne show_ok + dec [fepos.caretLine] + invoke SendMessage,[hwnd_fedit],FEM_GETLINELENGTH,[fepos.caretLine],0 + inc eax + mov [fepos.caretPosition],eax + show_ok: + invoke SendMessage,[hwnd_fedit],FEM_SETPOS,fepos,0 + invoke SendMessage,[hwnd_fedit],FEM_GETMODE,0,0 + and eax,not FEMODE_VERTICALSEL + invoke SendMessage,[hwnd_fedit],FEM_SETMODE,eax,0 + mov eax,[fepos.selectionLine] + xchg eax,[fepos.caretLine] + mov [fepos.selectionLine],eax + mov eax,[fepos.selectionPosition] + xchg eax,[fepos.caretPosition] + mov [fepos.selectionPosition],eax + invoke SendMessage,[hwnd_fedit],FEM_SETPOS,fepos,0 + xor eax,eax + ret + show_failed: + or eax,-1 + ret +endp + +proc SummaryDialog hwnd_dlg,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_INITDIALOG + je .initdialog + cmp [msg],WM_COMMAND + je .command + cmp [msg],WM_CLOSE + je .close + xor eax,eax + jmp .finish + .initdialog: + invoke GetDlgItem,[hwnd_dlg],ID_DISPLAY + invoke SendMessage,eax,WM_SETFONT,[hfont],FALSE + mov eax,[stdout] + add eax,4 + invoke SetDlgItemText,[hwnd_dlg],ID_DISPLAY,eax + mov edi,[stderr] + add edi,4 + invoke SetDlgItemText,[hwnd_dlg],ID_MESSAGE,edi + cmp [lparam],0 + je .processed + invoke LoadIcon,0,IDI_HAND + invoke SendDlgItemMessage,[hwnd_dlg],ID_ICON,STM_SETICON,eax,0 + cmp [lparam],2 + jne .processed + invoke GetDlgItem,[hwnd_dlg],ID_INSTRUCTION + invoke SendMessage,eax,WM_SETFONT,[hfont],FALSE + mov ebx,error_pointers + .list_errors: + mov edx,edi + xor al,al + or ecx,-1 + repne scasb + repne scasb + inc edi + mov eax,[edi] + add edi,4 + mov [ebx],edx + add ebx,4 + mov [param_buffer],edi + mov [param_buffer+4],eax + test eax,eax + jz .add_error + invoke GetFullPathName,edi,1000h,path_buffer,param_buffer + .add_error: + invoke wvsprintf,string_buffer,_line_number,param_buffer + invoke SendDlgItemMessage,[hwnd_dlg],ID_ERRORS,LB_ADDSTRING,0,string_buffer + .next_error: + xor al,al + or ecx,-1 + repne scasb + mov esi,[stderr] + lodsd + add eax,esi + cmp edi,eax + jb .list_errors + cmp esi,[error_pointers] + jne .processed + invoke SendDlgItemMessage,[hwnd_dlg],ID_ERRORS,LB_SETCURSEL,0,0 + .show_error: + invoke SendDlgItemMessage,[hwnd_dlg],ID_ERRORS,LB_GETCURSEL,0,0 + cmp eax,LB_ERR + je .processed + mov edi,[error_pointers+eax*4] + invoke SetDlgItemText,[hwnd_dlg],ID_MESSAGE,edi + xor al,al + or ecx,-1 + repne scasb + invoke SetDlgItemText,[hwnd_dlg],ID_INSTRUCTION,edi + mov edx,edi + xor al,al + or ecx,-1 + repne scasb + mov ebx,TRUE + cmp byte [edi],SOURCE_CALM + jne .instruction_ok + cmp byte [edx],0 + jne .instruction_ok + .instruction_calm: + invoke SetDlgItemText,[hwnd_dlg],ID_INSTRUCTION,_calm + mov ebx,FALSE + jmp .instruction_ok + .instruction_ok: + invoke GetDlgItem,[hwnd_dlg],ID_INSTRUCTION + invoke EnableWindow,eax,ebx + add edi,1+4 + cmp byte [edi],0 + je .processed + invoke GetFullPathName,edi,1000h,path_buffer,param_buffer + stdcall ShowLine,path_buffer,dword [edi-4] + jmp .processed + .command: + cmp [wparam],ID_ERRORS + LBN_SELCHANGE shl 16 + je .show_error + cmp [wparam],IDCANCEL + je .close + cmp [wparam],IDOK + jne .finish + .close: + invoke EndDialog,[hwnd_dlg],0 + .processed: + mov eax,1 + .finish: + pop edi esi ebx + ret +endp + +proc AddStrings hwnd_combobox,lpstrings + push ebx esi + mov esi,[lpstrings] + .add_string: + cmp byte [esi],0 + je .finish + invoke SendMessage,[hwnd_combobox],CB_ADDSTRING,0,esi + .next_string: + lodsb + or al,al + jnz .next_string + jmp .add_string + .finish: + pop esi ebx + ret +endp + +proc AppearanceSetup hwnd_dlg,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_INITDIALOG + je .initdialog + cmp [msg],WM_DESTROY + je .destroy + cmp [msg],WM_COMMAND + je .command + cmp [msg],WM_CLOSE + je .close + .notprocessed: + xor eax,eax + jmp .finish + .initdialog: + xor eax,eax + test [fedit_style],FES_CONSOLECARET + setnz al + invoke CheckDlgButton,[hwnd_dlg],ID_CONSOLECARET,eax + mov [cf.lStructSize],sizeof.CHOOSEFONT + mov eax,[hwnd_dlg] + mov [cf.hwndOwner],eax + mov [cf.Flags],CF_FIXEDPITCHONLY+CF_SCREENFONTS+CF_FORCEFONTEXIST+CF_INITTOLOGFONTSTRUCT + mov [cf.lpLogFont],tmp_font + mov [cc.lStructSize],sizeof.CHOOSECOLOR + mov eax,[hinstance] + mov [cc.hInstance],eax + mov eax,[hwnd_dlg] + mov [cc.hwndOwner],eax + mov [cc.lpCustColors],user_colors + mov [cc.Flags],CC_RGBINIT + mov esi,font + mov edi,tmp_font + mov ecx,sizeof.LOGFONT shr 2 + rep movsd + mov esi,editor_colors + mov edi,tmp_colors + mov ecx,8 + rep movsd + mov esi,editor_colors + mov edi,user_colors+20h + mov ecx,8 + rep movsd + invoke GetDlgItem,[hwnd_dlg],ID_SETTING + stdcall AddStrings,eax,_appearance_settings + invoke SendDlgItemMessage,[hwnd_dlg],ID_SETTING,CB_SETCURSEL,0,0 + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,WM_SETTEXT,0,preview_text + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,FEM_SETPOS,preview_selection,0 + invoke CreateFontIndirect,[cf.lpLogFont] + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,WM_SETFONT,eax,0 + .update_colors: + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,FEM_SETTEXTCOLOR,[tmp_colors],[tmp_colors+4] + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,FEM_SETSELCOLOR,[tmp_colors+8],[tmp_colors+12] + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,FEM_SETSYNTAXHIGHLIGHT,tmp_colors+16,fasm_syntax + jmp .processed + .destroy: + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,WM_GETFONT,0,0 + invoke DeleteObject,eax + jmp .finish + .command: + cmp [wparam],IDCANCEL + je .close + cmp [wparam],IDOK + je .ok + cmp [wparam],ID_CHANGE + jne .processed + invoke SendDlgItemMessage,[hwnd_dlg],ID_SETTING,CB_GETCURSEL,0,0 + or eax,eax + jz .change_font + cmp eax,8 + ja .processed + lea ebx,[tmp_colors+(eax-1)*4] + mov eax,[ebx] + mov [cc.rgbResult],eax + invoke ChooseColor,cc + or eax,eax + jz .processed + mov eax,[cc.rgbResult] + mov [ebx],eax + jmp .update_colors + .change_font: + mov esi,tmp_font + mov edi,backup_font + mov ecx,sizeof.LOGFONT shr 2 + rep movsd + invoke ChooseFont,cf + or eax,eax + jz .change_font_cancelled + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,WM_GETFONT,0,0 + mov ebx,eax + invoke CreateFontIndirect,[cf.lpLogFont] + invoke SendDlgItemMessage,[hwnd_dlg],ID_PREVIEW,WM_SETFONT,eax,0 + invoke DeleteObject,ebx + jmp .processed + .change_font_cancelled: + mov esi,backup_font + mov edi,tmp_font + mov ecx,sizeof.LOGFONT shr 2 + rep movsd + jmp .processed + .ok: + mov esi,tmp_colors + mov edi,editor_colors + mov ecx,8 + rep movsd + mov esi,tmp_font + mov edi,font + mov ecx,sizeof.LOGFONT shr 2 + rep movsd + invoke CreateFontIndirect,font + xchg eax,[hfont] + invoke DeleteObject,eax + invoke IsDlgButtonChecked,[hwnd_dlg],ID_CONSOLECARET + or eax,eax + setnz al + neg eax + and eax,FES_CONSOLECARET + and [fedit_style],not FES_CONSOLECARET + or [fedit_style],eax + invoke EndDialog,[hwnd_dlg],TRUE + jmp .finish + .close: + invoke EndDialog,[hwnd_dlg],FALSE + .processed: + mov eax,1 + .finish: + pop edi esi ebx + ret +endp + +proc CompilerSetup hwnd_dlg,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_INITDIALOG + je .initdialog + cmp [msg],WM_COMMAND + je .command + cmp [msg],WM_CLOSE + je .close + .notprocessed: + xor eax,eax + jmp .finish + .initdialog: + invoke SendDlgItemMessage,[hwnd_dlg],ID_INCLUDEPATH,CB_ADDSTRING,0,include_path + mov [string_buffer],0 + invoke GetEnvironmentVariable,_key_environment_include,string_buffer,1000h + invoke GetPrivateProfileString,_section_environment,_key_environment_include,string_buffer,path_buffer,4000h,ini_path + invoke SetDlgItemText,[hwnd_dlg],ID_INCLUDEPATH,path_buffer + invoke SendDlgItemMessage,[hwnd_dlg],ID_SOURCEHEADER,CB_ADDSTRING,0,default_source_header + invoke SetDlgItemText,[hwnd_dlg],ID_SOURCEHEADER,source_header + invoke GetDlgItem,[hwnd_dlg],ID_PRIORITY + stdcall AddStrings,eax,_priority_settings + invoke SetDlgItemInt,[hwnd_dlg],ID_PASSES,[maximum_number_of_passes],FALSE + invoke SetDlgItemInt,[hwnd_dlg],ID_RECURSION,[maximum_depth_of_stack],FALSE + mov eax,[compiler_priority] + cmp eax,2 + jg .realtime + cmp eax,-2 + jl .idle + jmp .priority_ok + .idle: + mov eax,-4 + jmp .priority_ok + .realtime: + mov eax,4 + .priority_ok: + sar eax,1 + add eax,2 + invoke SendDlgItemMessage,[hwnd_dlg],ID_PRIORITY,CB_SETCURSEL,eax,0 + jmp .processed + .command: + cmp [wparam],IDCANCEL + je .close + cmp [wparam],IDOK + jne .finish + invoke GetDlgItemInt,[hwnd_dlg],ID_PASSES,param_buffer,FALSE + mov [maximum_number_of_passes],eax + invoke GetDlgItemInt,[hwnd_dlg],ID_RECURSION,param_buffer,FALSE + mov [maximum_depth_of_stack],eax + invoke SendDlgItemMessage,[hwnd_dlg],ID_PRIORITY,CB_GETCURSEL,0,0 + sub eax,2 + sal eax,1 + cmp eax,4 + je .set_realtime + cmp eax,-4 + je .set_idle + jmp .set_priority + .set_idle: + mov eax,-15 + jmp .set_priority + .set_realtime: + mov eax,15 + .set_priority: + mov [compiler_priority],eax + invoke GetDlgItemText,[hwnd_dlg],ID_INCLUDEPATH,path_buffer,4000h + invoke GetDlgItemText,[hwnd_dlg],ID_SOURCEHEADER,source_header,1000h + invoke WritePrivateProfileString,_section_environment,_key_environment_include,path_buffer,ini_path + invoke EndDialog,[hwnd_dlg],TRUE + jmp .finish + .close: + invoke EndDialog,[hwnd_dlg],FALSE + .processed: + mov eax,1 + .finish: + pop edi esi ebx + ret +endp + +proc CalculatorDialog hwnd,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_INITDIALOG + je .init + cmp [msg],WM_COMMAND + je .command + cmp [msg],WM_CLOSE + je .close + xor eax,eax + jmp .finish + .init: + invoke SendDlgItemMessage,[hwnd],ID_EXPRESSION,EM_SETLIMITTEXT,EXPRESSION_MAX_LENGTH-1,0 + invoke CheckDlgButton,[hwnd],ID_DECSELECT,BST_CHECKED + mov [maximum_number_of_errors],1 + call system_init + xor al,al + call assembly_init + jmp .processed + .command: + cmp [wparam],IDCANCEL + je .close + cmp [wparam],IDOK + je .evaluate + cmp [wparam],ID_EXPRESSION + EN_CHANGE shl 16 + jne .processed + invoke GetDlgItemText,[hwnd],ID_EXPRESSION,expression_buffer,EXPRESSION_MAX_LENGTH + call discard_errors + mov esi,calculator_string + xor edx,edx + call assembly_pass + jnc .calculation_failed + cmp [first_error],0 + jne .calculation_failed + call get_output_length + test edx,edx + jnz .calculation_failed + mov [result_size],eax + lea ecx,[eax*8+12] + mov [digits_size],ecx + add eax,ecx + invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE + test eax,eax + jz .calculation_failed + mov [result_address],eax + mov ecx,[result_size] + jecxz .result_zero + mov edi,eax + mov [value_length],ecx + xor eax,eax + mov dword [file_offset],eax + mov dword [file_offset+4],eax + call read_from_output + jmp .result_ready + .result_zero: + inc [result_size] + dec [digits_size] + mov byte [eax],0 + .result_ready: + mov esi,[result_address] + mov edx,[result_size] + lea edi,[esi+edx] + mov al,[edi-1] + sar al,7 + mov [edi],al + mov [digits_address],edi + add edi,[digits_size] + sub edi,2 + mov word [edi],'b' + xor cl,cl + .to_bin: + mov al,[esi] + shr al,cl + and al,1 + add al,'0' + dec edi + mov [edi],al + inc cl + and cl,111b + jnz .to_bin + inc esi + dec edx + jnz .to_bin + test byte [esi-1],80h + jz .bin_ok + dec edi + mov ecx,3 + mov al,'.' + std + rep stosb + cld + inc edi + .bin_ok: + invoke SetDlgItemText,[hwnd],ID_BINRESULT,edi + mov esi,[result_address] + mov ecx,[result_size] + mov edi,[digits_address] + add edi,[digits_size] + sub edi,2 + mov word [edi],'h' + .to_hex: + mov al,[esi] + and al,0Fh + cmp al,10 + sbb al,69h + das + dec edi + mov [edi],al + lodsb + shr al,4 + cmp al,10 + sbb al,69h + das + dec edi + mov [edi],al + loop .to_hex + test byte [esi-1],80h + jz .hex_ok + dec edi + mov ecx,3 + mov al,'.' + std + rep stosb + cld + inc edi + .hex_ok: + invoke SetDlgItemText,[hwnd],ID_HEXRESULT,edi + mov esi,[result_address] + mov edx,[result_size] + mov edi,[digits_address] + add edi,[digits_size] + sub edi,2 + mov word [edi],'o' + xor cl,cl + .to_oct: + mov ax,[esi] + shr ax,cl + and al,7 + add al,'0' + dec edi + mov [edi],al + add cl,3 + cmp cl,8 + jb .to_oct + sub cl,8 + inc esi + dec edx + jnz .to_oct + test byte [esi-1],80h + jz .oct_ok + dec edi + mov ecx,3 + mov al,'.' + std + rep stosb + cld + inc edi + .oct_ok: + invoke SetDlgItemText,[hwnd],ID_OCTRESULT,edi + mov esi,[result_address] + mov ecx,[result_size] + mov edi,[digits_address] + rep movsb + test byte [esi-1],80h + jnz .negative + xor eax,eax + stosd + jmp .to_dec + .negative: + or eax,-1 + stosd + mov esi,[digits_address] + mov ecx,edi + sub ecx,esi + stc + .negate: + not byte [esi] + adc byte [esi],0 + inc esi + loop .negate + .to_dec: + mov edi,[digits_address] + add edi,[digits_size] + dec edi + and byte [edi],0 + mov esi,[digits_address] + mov ecx,[result_size] + dec ecx + and ecx,not 11b + .obtain_digit: + xor edx,edx + .divide_highest_dwords: + mov eax,[esi+ecx] + call div10 + test eax,eax + jnz .more_digits_to_come + sub ecx,4 + jnc .divide_highest_dwords + .store_final_digit: + add dl,'0' + dec edi + mov [edi],dl + mov esi,[result_address] + add esi,[result_size] + test byte [esi-1],80h + jz .dec_ok + dec edi + mov byte [edi],'-' + jmp .dec_ok + .more_digits_to_come: + mov ebx,ecx + .divide_remaining_dwords: + mov [esi+ebx],eax + sub ebx,4 + jc .store_digit + mov eax,[esi+ebx] + call div10 + jmp .divide_remaining_dwords + .store_digit: + add dl,'0' + dec edi + mov [edi],dl + jmp .obtain_digit + .dec_ok: + invoke SetDlgItemText,[hwnd],ID_DECRESULT,edi + invoke VirtualFree,[result_address],0,MEM_RELEASE + jmp .processed + .calculation_failed: + invoke SetDlgItemText,[hwnd],ID_BINRESULT,_null + invoke SetDlgItemText,[hwnd],ID_DECRESULT,_null + invoke SetDlgItemText,[hwnd],ID_HEXRESULT,_null + invoke SetDlgItemText,[hwnd],ID_OCTRESULT,_null + jmp .processed + .evaluate: + mov ebx,ID_BINRESULT + invoke IsDlgButtonChecked,[hwnd],ID_BINSELECT + cmp eax,BST_CHECKED + je .get_result + mov ebx,ID_HEXRESULT + invoke IsDlgButtonChecked,[hwnd],ID_HEXSELECT + cmp eax,BST_CHECKED + je .get_result + mov ebx,ID_OCTRESULT + invoke IsDlgButtonChecked,[hwnd],ID_OCTSELECT + cmp eax,BST_CHECKED + je .get_result + mov ebx,ID_DECRESULT + .get_result: + invoke GetDlgItemText,[hwnd],ebx,expression_buffer,EXPRESSION_MAX_LENGTH + invoke SetDlgItemText,[hwnd],ID_EXPRESSION,expression_buffer + invoke GetDlgItem,[hwnd],ID_EXPRESSION + invoke SendMessage,[hwnd],WM_NEXTDLGCTL,eax,TRUE + jmp .processed + .close: + call assembly_shutdown + call system_shutdown + invoke EndDialog,[hwnd],0 + .processed: + mov eax,1 + .finish: + pop edi esi ebx + ret +endp + +proc AboutDialog hwnd,msg,wparam,lparam + push ebx esi edi + cmp [msg],WM_COMMAND + je .close + cmp [msg],WM_CLOSE + je .close + xor eax,eax + jmp .finish + .close: + invoke EndDialog,[hwnd],0 + .processed: + mov eax,1 + .finish: + pop edi esi ebx + ret +endp + +include 'fasmg.inc' + +section '.idata' import data readable writeable + + library kernel,'KERNEL32.DLL',\ + advapi,'ADVAPI32.DLL',\ + user,'USER32.DLL',\ + gdi,'GDI32.DLL',\ + comctl,'COMCTL32.DLL',\ + comdlg,'COMDLG32.DLL',\ + shell,'SHELL32.DLL' + + import kernel,\ + GetModuleHandle,'GetModuleHandleA',\ + LoadLibrary,'LoadLibraryA',\ + GetProcAddress,'GetProcAddress',\ + GetCommandLine,'GetCommandLineA',\ + GetFileAttributes,'GetFileAttributesA',\ + GetFullPathName,'GetFullPathNameA',\ + GetCurrentDirectory,'GetCurrentDirectoryA',\ + SetCurrentDirectory,'SetCurrentDirectoryA',\ + CreateFile,'CreateFileA',\ + GetFileSize,'GetFileSize',\ + ReadFile,'ReadFile',\ + WriteFile,'WriteFile',\ + SetFilePointer,'SetFilePointer',\ + CloseHandle,'CloseHandle',\ + lstrcmpi,'lstrcmpiA',\ + GlobalAlloc,'GlobalAlloc',\ + GlobalReAlloc,'GlobalReAlloc',\ + GlobalLock,'GlobalLock',\ + GlobalUnlock,'GlobalUnlock',\ + GlobalFree,'GlobalFree',\ + GetProcessHeap,'GetProcessHeap',\ + HeapCreate,'HeapCreate',\ + HeapSize,'HeapSize',\ + HeapDestroy,'HeapDestroy',\ + HeapAlloc,'HeapAlloc',\ + HeapReAlloc,'HeapReAlloc',\ + HeapFree,'HeapFree',\ + VirtualAlloc,'VirtualAlloc',\ + VirtualFree,'VirtualFree',\ + CreateThread,'CreateThread',\ + SetThreadPriority,'SetThreadPriority',\ + TerminateThread,'TerminateThread',\ + ExitThread,'ExitThread',\ + GetExitCodeThread,'GetExitCodeThread',\ + WaitForSingleObject,'WaitForSingleObject',\ + CreateMutex,'CreateMutexA',\ + ReleaseMutex,'ReleaseMutex',\ + CreateProcess,'CreateProcessA',\ + AllocConsole,'AllocConsole',\ + SetConsoleTitle,'SetConsoleTitleA',\ + FreeConsole,'FreeConsole',\ + GetEnvironmentVariable,'GetEnvironmentVariableA',\ + GetSystemTime,'GetSystemTime',\ + SystemTimeToFileTime,'SystemTimeToFileTime',\ + GetTickCount,'GetTickCount',\ + GetPrivateProfileString,'GetPrivateProfileStringA',\ + WritePrivateProfileString,'WritePrivateProfileStringA',\ + GetLastError,'GetLastError',\ + ExitProcess,'ExitProcess' + + import advapi,\ + RegOpenKeyEx,'RegOpenKeyExA',\ + RegQueryValueEx,'RegQueryValueExA',\ + RegCloseKey,'RegCloseKey' + + import user,\ + RegisterClass,'RegisterClassA',\ + CreateCaret,'CreateCaret',\ + ShowCaret,'ShowCaret',\ + HideCaret,'HideCaret',\ + SetCaretPos,'SetCaretPos',\ + DestroyCaret,'DestroyCaret',\ + BeginPaint,'BeginPaint',\ + EndPaint,'EndPaint',\ + GetDC,'GetDC',\ + GetUpdateRect,'GetUpdateRect',\ + ReleaseDC,'ReleaseDC',\ + DrawText,'DrawTextA',\ + FillRect,'FillRect',\ + InvalidateRect,'InvalidateRect',\ + GetKeyboardState,'GetKeyboardState',\ + ToAscii,'ToAscii',\ + GetScrollInfo,'GetScrollInfo',\ + SetScrollInfo,'SetScrollInfo',\ + SetCapture,'SetCapture',\ + ReleaseCapture,'ReleaseCapture',\ + GetCursorPos,'GetCursorPos',\ + ClientToScreen,'ClientToScreen',\ + OpenClipboard,'OpenClipboard',\ + CloseClipboard,'CloseClipboard',\ + EmptyClipboard,'EmptyClipboard',\ + GetClipboardData,'GetClipboardData',\ + SetClipboardData,'SetClipboardData',\ + LoadCursor,'LoadCursorA',\ + LoadIcon,'LoadIconA',\ + LoadBitmap,'LoadBitmapA',\ + LoadMenu,'LoadMenuA',\ + EnableMenuItem,'EnableMenuItem',\ + CheckMenuItem,'CheckMenuItem',\ + GetSubMenu,'GetSubMenu',\ + TrackPopupMenu,'TrackPopupMenu',\ + LoadAccelerators,'LoadAcceleratorsA',\ + IsClipboardFormatAvailable,'IsClipboardFormatAvailable',\ + CharLower,'CharLowerA',\ + CharUpper,'CharUpperA',\ + wsprintf,'wsprintfA',\ + wvsprintf,'wvsprintfA',\ + MessageBox,'MessageBoxA',\ + WinHelp,'WinHelpA',\ + DialogBoxParam,'DialogBoxParamA',\ + GetDlgItem,'GetDlgItem',\ + GetDlgItemInt,'GetDlgItemInt',\ + SetDlgItemInt,'SetDlgItemInt',\ + GetDlgItemText,'GetDlgItemTextA',\ + SetDlgItemText,'SetDlgItemTextA',\ + CheckDlgButton,'CheckDlgButton',\ + IsDlgButtonChecked,'IsDlgButtonChecked',\ + SendDlgItemMessage,'SendDlgItemMessageA',\ + EndDialog,'EndDialog',\ + FindWindow,'FindWindowA',\ + SetForegroundWindow,'SetForegroundWindow',\ + CreateWindowEx,'CreateWindowExA',\ + DestroyWindow,'DestroyWindow',\ + GetWindowLong,'GetWindowLongA',\ + SetWindowLong,'SetWindowLongA',\ + DefWindowProc,'DefWindowProcA',\ + GetClientRect,'GetClientRect',\ + GetWindowRect,'GetWindowRect',\ + MoveWindow,'MoveWindow',\ + SetWindowPos,'SetWindowPos',\ + GetWindowPlacement,'GetWindowPlacement',\ + SetWindowPlacement,'SetWindowPlacement',\ + ShowWindow,'ShowWindow',\ + EnableWindow,'EnableWindow',\ + UpdateWindow,'UpdateWindow',\ + IsZoomed,'IsZoomed',\ + SetFocus,'SetFocus',\ + GetSystemMetrics,'GetSystemMetrics',\ + GetSysColor,'GetSysColor',\ + SendMessage,'SendMessageA',\ + GetMessage,'GetMessageA',\ + TranslateAccelerator,'TranslateAccelerator',\ + TranslateMessage,'TranslateMessage',\ + DispatchMessage,'DispatchMessageA',\ + PostMessage,'PostMessageA',\ + PostQuitMessage,'PostQuitMessage' + + import gdi,\ + SetBkColor,'SetBkColor',\ + SetTextColor,'SetTextColor',\ + CreateSolidBrush,'CreateSolidBrush',\ + CreateFont,'CreateFontA',\ + CreateFontIndirect,'CreateFontIndirectA',\ + GetTextMetrics,'GetTextMetricsA',\ + GetTextExtentPoint32,'GetTextExtentPoint32A',\ + CreateCompatibleDC,'CreateCompatibleDC',\ + DeleteDC,'DeleteDC',\ + CreateBitmap,'CreateBitmap',\ + SelectObject,'SelectObject',\ + GetObject,'GetObjectA',\ + DeleteObject,'DeleteObject' + + import comctl,\ + CreateStatusWindow,'CreateStatusWindowA',\ + ImageList_Create,'ImageList_Create',\ + ImageList_Add,'ImageList_Add',\ + ImageList_Destroy,'ImageList_Destroy' + + import comdlg,\ + GetOpenFileName,'GetOpenFileNameA',\ + GetSaveFileName,'GetSaveFileNameA',\ + GetFileTitle,'GetFileTitleA',\ + ChooseFont,'ChooseFontA',\ + ChooseColor,'ChooseColorA' + + import shell,\ + DragAcceptFiles,'DragAcceptFiles',\ + DragQueryFile,'DragQueryFile',\ + DragFinish,'DragFinish',\ + ShellExecute,'ShellExecuteA' + +section '.rsrc' resource data readable + + directory RT_MENU,menus,\ + RT_ACCELERATOR,accelerators,\ + RT_DIALOG,dialogs,\ + RT_GROUP_ICON,group_icons,\ + RT_ICON,icons,\ + RT_BITMAP,bitmaps,\ + RT_VERSION,versions + + resource menus,\ + IDM_MAIN,LANG_ENGLISH+SUBLANG_DEFAULT,main_menu,\ + IDM_TAB,LANG_ENGLISH+SUBLANG_DEFAULT,popup_menu + + resource accelerators,\ + IDA_MAIN,LANG_ENGLISH+SUBLANG_DEFAULT,main_keys + + resource dialogs,\ + IDD_POSITION,LANG_ENGLISH+SUBLANG_DEFAULT,position_dialog,\ + IDD_FIND,LANG_ENGLISH+SUBLANG_DEFAULT,find_dialog,\ + IDD_REPLACE,LANG_ENGLISH+SUBLANG_DEFAULT,replace_dialog,\ + IDD_COMPILE,LANG_ENGLISH+SUBLANG_DEFAULT,compile_dialog,\ + IDD_SUMMARY,LANG_ENGLISH+SUBLANG_DEFAULT,summary_dialog,\ + IDD_ERRORSUMMARY,LANG_ENGLISH+SUBLANG_DEFAULT,error_summary_dialog,\ + IDD_APPEARANCE,LANG_ENGLISH+SUBLANG_DEFAULT,appearance_dialog,\ + IDD_COMPILERSETUP,LANG_ENGLISH+SUBLANG_DEFAULT,compiler_setup_dialog,\ + IDD_CALCULATOR,LANG_ENGLISH+SUBLANG_DEFAULT,calculator_dialog,\ + IDD_ABOUT,LANG_ENGLISH+SUBLANG_DEFAULT,about_dialog + + resource group_icons,\ + IDI_MAIN,LANG_NEUTRAL,main_icon + + resource icons,\ + 1,LANG_NEUTRAL,main_icon_data + + resource bitmaps,\ + IDB_ASSIGN,LANG_NEUTRAL,assign_bitmap + + resource versions,\ + 1,LANG_NEUTRAL,version + + IDM_MAIN = 101 + IDM_TAB = 102 + IDA_MAIN = 201 + IDD_POSITION = 301 + IDD_FIND = 302 + IDD_REPLACE = 303 + IDD_COMPILE = 304 + IDD_SUMMARY = 305 + IDD_ERRORSUMMARY = 306 + IDD_APPEARANCE = 307 + IDD_COMPILERSETUP = 308 + IDD_ABOUT = 309 + IDD_CALCULATOR = 310 + IDI_MAIN = 401 + IDB_ASSIGN = 501 + + IDM_NEW = 1101 + IDM_OPEN = 1102 + IDM_SAVE = 1103 + IDM_SAVEAS = 1104 + IDM_NEXT = 1105 + IDM_PREVIOUS = 1106 + IDM_OPENFOLDER = 1107 + IDM_CLOSE = 1108 + IDM_EXIT = 1109 + IDM_SELECTFILE = 1110 + IDM_UNDO = 1201 + IDM_REDO = 1202 + IDM_CUT = 1203 + IDM_COPY = 1204 + IDM_PASTE = 1205 + IDM_DELETE = 1206 + IDM_SELECTALL = 1207 + IDM_VERTICAL = 1208 + IDM_DISCARD_UNDO = 1209 + IDM_READONLY = 1210 + IDM_POSITION = 1301 + IDM_FIND = 1302 + IDM_FINDNEXT = 1303 + IDM_REPLACE = 1304 + IDM_RUN = 1401 + IDM_COMPILE = 1402 + IDM_DEBUG = 1403 + IDM_ASSIGN = 1409 + IDM_APPEARANCE = 1501 + IDM_COMPILERSETUP = 1502 + IDM_SECURESEL = 1505 + IDM_AUTOBRACKETS = 1506 + IDM_AUTOINDENT = 1507 + IDM_SMARTTABS = 1508 + IDM_OPTIMALFILL = 1509 + IDM_REVIVEDEADKEYS = 1510 + IDM_TIMESCROLL = 1511 + IDM_ONEINSTANCEONLY = 1512 + IDM_CONTENTS = 1901 + IDM_KEYWORD = 1902 + IDM_PICKHELP = 1903 + IDM_CALCULATOR = 1904 + IDM_ABOUT = 1909 + + ID_CHANGE = 2001 + ID_SELECT = 2101 + ID_CASESENSITIVE = 2102 + ID_WHOLEWORDS = 2103 + ID_BACKWARD = 2104 + ID_INWHOLETEXT = 2105 + ID_PROMPT = 2106 + ID_CONSOLECARET = 2107 + ID_ROW = 2201 + ID_COLUMN = 2202 + ID_DISPLAY = 2203 + ID_INSTRUCTION = 2204 + ID_EXPRESSION = 2205 + ID_DECRESULT = 2206 + ID_HEXRESULT = 2207 + ID_BINRESULT = 2208 + ID_OCTRESULT = 2209 + ID_TEXT = 2301 + ID_NEWTEXT = 2302 + ID_SETTING = 2401 + ID_PREVIEW = 2402 + ID_PRIORITY = 2505 + ID_PASSES = 2506 + ID_RECURSION = 2507 + ID_INCLUDEPATH = 2508 + ID_SOURCEHEADER = 2509 + ID_DECSELECT = 2601 + ID_HEXSELECT = 2602 + ID_BINSELECT = 2603 + ID_OCTSELECT = 2604 + ID_PROGRESS = 2801 + ID_ICON = 2901 + ID_MESSAGE = 2902 + ID_ERRORS = 2903 + + _ equ ,09h, + + menu main_menu + menuitem '&File',0,MFR_POPUP + menuitem '&New' _ 'Ctrl+N',IDM_NEW + menuitem '&Open...' _ 'Ctrl+O',IDM_OPEN + menuitem '&Save' _ 'Ctrl+S',IDM_SAVE + menuitem 'Save &as...',IDM_SAVEAS + menuseparator + menuitem 'E&xit' _ 'Alt+X',IDM_EXIT,MFR_END + menuitem '&Edit',0,MFR_POPUP + menuitem '&Undo' _ 'Ctrl+Z',IDM_UNDO + menuitem '&Redo' _ 'Ctrl+Shift+Z',IDM_REDO + menuseparator + menuitem 'Cu&t' _ 'Ctrl+X',IDM_CUT + menuitem '&Copy' _ 'Ctrl+C',IDM_COPY + menuitem '&Paste' _ 'Ctrl+V',IDM_PASTE + menuitem '&Delete',IDM_DELETE + menuseparator + menuitem 'Select &all' _ 'Ctrl+A',IDM_SELECTALL + menuseparator + menuitem '&Vertical selection' _ 'Alt+Ins',IDM_VERTICAL,MFR_END + menuitem '&Search',0,MFR_POPUP + menuitem '&Position...' _ 'Ctrl+G',IDM_POSITION + menuseparator + menuitem '&Find...' _ 'Ctrl+F',IDM_FIND + menuitem 'Find &next' _ 'F3',IDM_FINDNEXT + menuitem '&Replace...' _ 'Ctrl+H',IDM_REPLACE,MFR_END + menuitem '&Run',0,MFR_POPUP + menuitem '&Run' _ 'F9',IDM_RUN + menuitem '&Compile' _ 'Ctrl+F9',IDM_COMPILE,MFR_END + menuitem '&Options',0,MFR_POPUP + menuitem '&Appearance...',IDM_APPEARANCE + menuitem '&Compiler setup...',IDM_COMPILERSETUP + menuseparator + menuitem '&Secure selection',IDM_SECURESEL + menuitem 'Automatic &brackets',IDM_AUTOBRACKETS + menuitem 'Automatic &indents',IDM_AUTOINDENT + menuitem 'Smart &tabulation',IDM_SMARTTABS + menuitem '&Optimal fill on saving',IDM_OPTIMALFILL + menuitem '&Revive dead keys',IDM_REVIVEDEADKEYS + menuitem 'Ti&me scrolling',IDM_TIMESCROLL + menuitem 'O&ne instance only',IDM_ONEINSTANCEONLY,MFR_END + menuitem '&Help',0,MFR_POPUP + MFR_END + menuitem '&Contents' _ 'Alt+F1',IDM_CONTENTS + menuitem '&Keyword search' _ 'F1',IDM_KEYWORD + menuseparator + menuitem '&Pick help file...',IDM_PICKHELP + menuseparator + menuitem 'Ca&lculator...' _ 'Ctrl+F6',IDM_CALCULATOR + menuseparator + menuitem '&About...',IDM_ABOUT,MFR_END + + menu popup_menu + menuitem '',0,MFR_POPUP+MFR_END + menuitem '&Assign to compiler' _ 'Shift+F9',IDM_ASSIGN + menuitem 'Open &folder',IDM_OPENFOLDER + menuitem '&Read-only mode' _ 'Shift+F6',IDM_READONLY + menuseparator + menuitem '&Close' _ 'Esc',IDM_CLOSE,MFR_END + + accelerator main_keys,\ + FVIRTKEY+FNOINVERT+FCONTROL,'N',IDM_NEW,\ + FVIRTKEY+FNOINVERT+FCONTROL,'O',IDM_OPEN,\ + FVIRTKEY+FNOINVERT+FCONTROL,'S',IDM_SAVE,\ + FVIRTKEY+FNOINVERT+FCONTROL,'Z',IDM_UNDO,\ + FVIRTKEY+FNOINVERT+FCONTROL+FSHIFT,'Z',IDM_REDO,\ + FVIRTKEY+FNOINVERT+FCONTROL,'X',IDM_CUT,\ + FVIRTKEY+FNOINVERT+FCONTROL,'C',IDM_COPY,\ + FVIRTKEY+FNOINVERT+FCONTROL,'V',IDM_PASTE,\ + FVIRTKEY+FNOINVERT+FCONTROL,'A',IDM_SELECTALL,\ + FVIRTKEY+FNOINVERT+FCONTROL,'G',IDM_POSITION,\ + FVIRTKEY+FNOINVERT+FCONTROL,'F',IDM_FIND,\ + FVIRTKEY+FNOINVERT+FCONTROL,'H',IDM_REPLACE,\ + FVIRTKEY+FNOINVERT+FCONTROL,VK_TAB,IDM_NEXT,\ + FVIRTKEY+FNOINVERT+FCONTROL+FSHIFT,VK_TAB,IDM_PREVIOUS,\ + FVIRTKEY+FNOINVERT,VK_F1,IDM_KEYWORD,\ + FVIRTKEY+FNOINVERT+FALT,VK_F1,IDM_CONTENTS,\ + FVIRTKEY+FNOINVERT,VK_F2,IDM_SAVE,\ + FVIRTKEY+FNOINVERT+FSHIFT,VK_F2,IDM_SAVEAS,\ + FVIRTKEY+FNOINVERT,VK_F4,IDM_OPEN,\ + FVIRTKEY+FNOINVERT,VK_F3,IDM_FINDNEXT,\ + FVIRTKEY+FNOINVERT,VK_F5,IDM_POSITION,\ + FVIRTKEY+FNOINVERT+FSHIFT,VK_F6,IDM_READONLY,\ + FVIRTKEY+FNOINVERT,VK_F7,IDM_FIND,\ + FVIRTKEY+FNOINVERT+FSHIFT,VK_F7,IDM_FINDNEXT,\ + FVIRTKEY+FNOINVERT+FCONTROL,VK_F7,IDM_REPLACE,\ + FVIRTKEY+FNOINVERT,VK_F9,IDM_RUN,\ + FVIRTKEY+FNOINVERT+FCONTROL,VK_F9,IDM_COMPILE,\ + FVIRTKEY+FNOINVERT,VK_F8,IDM_DEBUG,\ + FVIRTKEY+FNOINVERT+FSHIFT,VK_F9,IDM_ASSIGN,\ + FVIRTKEY+FNOINVERT+FCONTROL,VK_F6,IDM_CALCULATOR,\ + FVIRTKEY+FNOINVERT,VK_ESCAPE,IDM_CLOSE,\ + FVIRTKEY+FNOINVERT+FALT,VK_DELETE,IDM_DISCARD_UNDO,\ + FVIRTKEY+FNOINVERT+FALT,'X',IDM_EXIT,\ + FVIRTKEY+FNOINVERT+FALT,'1',IDM_SELECTFILE+1,\ + FVIRTKEY+FNOINVERT+FALT,'2',IDM_SELECTFILE+2,\ + FVIRTKEY+FNOINVERT+FALT,'3',IDM_SELECTFILE+3,\ + FVIRTKEY+FNOINVERT+FALT,'4',IDM_SELECTFILE+4,\ + FVIRTKEY+FNOINVERT+FALT,'5',IDM_SELECTFILE+5,\ + FVIRTKEY+FNOINVERT+FALT,'6',IDM_SELECTFILE+6,\ + FVIRTKEY+FNOINVERT+FALT,'7',IDM_SELECTFILE+7,\ + FVIRTKEY+FNOINVERT+FALT,'8',IDM_SELECTFILE+8,\ + FVIRTKEY+FNOINVERT+FALT,'9',IDM_SELECTFILE+9 + + dialog position_dialog,'Position',40,40,126,54,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'STATIC','&Row:',-1,4,8,28,8,WS_VISIBLE+SS_RIGHT + dialogitem 'EDIT','',ID_ROW,36,6,34,12,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_NUMBER + dialogitem 'STATIC','&Column:',-1,4,26,28,8,WS_VISIBLE+SS_RIGHT + dialogitem 'EDIT','',ID_COLUMN,36,24,34,12,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_NUMBER + dialogitem 'BUTTON','&Select',ID_SELECT,36,42,48,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','OK',IDOK,78,6,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + dialogitem 'BUTTON','C&ancel',IDCANCEL,78,22,42,14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON + enddialog + + dialog find_dialog,'Find',60,60,254,54,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'STATIC','&Text to find:',-1,4,8,40,8,WS_VISIBLE+SS_RIGHT + dialogitem 'COMBOBOX','',ID_TEXT,48,6,150,64,WS_VISIBLE+WS_BORDER+WS_TABSTOP+CBS_DROPDOWN+CBS_AUTOHSCROLL+WS_VSCROLL + dialogitem 'BUTTON','&Case sensitive',ID_CASESENSITIVE,48,24,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&Whole words',ID_WHOLEWORDS,48,38,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&Backward',ID_BACKWARD,124,24,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&In whole text',ID_INWHOLETEXT,124,38,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&Find first',IDOK,206,6,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + dialogitem 'BUTTON','C&ancel',IDCANCEL,206,22,42,14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON + enddialog + + dialog replace_dialog,'Replace',60,60,254,86,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'STATIC','&Text to find:',-1,4,8,40,8,WS_VISIBLE+SS_RIGHT + dialogitem 'COMBOBOX','',ID_TEXT,48,6,150,64,WS_VISIBLE+WS_BORDER+WS_TABSTOP+CBS_DROPDOWN+CBS_AUTOHSCROLL+WS_VSCROLL + dialogitem 'STATIC','&New text:',-1,4,26,40,8,WS_VISIBLE+SS_RIGHT + dialogitem 'COMBOBOX','',ID_NEWTEXT,48,24,150,64,WS_VISIBLE+WS_BORDER+WS_TABSTOP+CBS_DROPDOWN+CBS_AUTOHSCROLL+WS_VSCROLL + dialogitem 'BUTTON','&Case sensitive',ID_CASESENSITIVE,48,42,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&Whole words',ID_WHOLEWORDS,48,56,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&Backward',ID_BACKWARD,124,42,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&In whole text',ID_INWHOLETEXT,124,56,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&Prompt on replace',ID_PROMPT,48,70,70,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','&Replace',IDOK,206,6,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + dialogitem 'BUTTON','C&ancel',IDCANCEL,206,22,42,14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON + enddialog + + dialog compile_dialog,'Compile',64,64,192,42,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'msctls_progress32','',ID_PROGRESS,8,6,176,12,WS_VISIBLE + dialogitem 'BUTTON','C&ancel',IDCANCEL,75,24,42,14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON + enddialog + + dialog summary_dialog,'Compile',50,50,244,140,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'BUTTON','OK',IDCANCEL,194,120,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + dialogitem 'STATIC',IDI_ASTERISK,ID_ICON,8,4,0,0,WS_VISIBLE+SS_ICON + dialogitem 'STATIC','',ID_MESSAGE,36,10,200,8,WS_VISIBLE + dialogitem 'STATIC','&Display:',-1,8,28,220,8,WS_VISIBLE + dialogitem 'EDIT','',ID_DISPLAY,8,40,228,74,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_MULTILINE+ES_READONLY+ES_AUTOHSCROLL+ES_AUTOVSCROLL+WS_VSCROLL + enddialog + + dialog error_summary_dialog,'Compile',50,50,248,186,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'STATIC','&Errors:',-1,8,116,176,8,WS_VISIBLE + dialogitem 'LISTBOX','',ID_ERRORS,8,128,160,54,WS_VISIBLE+WS_BORDER+WS_TABSTOP+WS_VSCROLL+LBS_NOTIFY + dialogitem 'BUTTON','OK',IDCANCEL,194,164,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + dialogitem 'STATIC',IDI_HAND,ID_ICON,8,4,0,0,WS_VISIBLE+SS_ICON + dialogitem 'STATIC','',ID_MESSAGE,36,10,200,28,WS_VISIBLE + dialogitem 'STATIC','&Display:',-1,8,28,24,8,WS_VISIBLE + dialogitem 'EDIT','',ID_DISPLAY,8,40,228,44,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_MULTILINE+ES_READONLY+ES_AUTOHSCROLL+ES_AUTOVSCROLL+WS_VSCROLL + dialogitem 'STATIC','Effective &instruction:',-1,8,88,220,8,WS_VISIBLE + dialogitem 'EDIT','',ID_INSTRUCTION,8,100,228,12,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_READONLY+ES_AUTOHSCROLL + enddialog + + dialog appearance_dialog,'Appearance',50,20,186,166,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'COMBOBOX','',ID_SETTING,8,6,120,140,WS_VISIBLE+WS_TABSTOP+CBS_DROPDOWNLIST+WS_VSCROLL + dialogitem 'BUTTON','C&hange...',ID_CHANGE,134,6,42,13,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON + dialogitem 'FEDIT','',ID_PREVIEW,8,24,168,120,WS_VISIBLE+WS_BORDER+WS_DISABLED+ES_NOHIDESEL + dialogitem 'BUTTON','&Console caret',ID_CONSOLECARET,8,151,80,8,WS_VISIBLE+WS_TABSTOP+BS_AUTOCHECKBOX + dialogitem 'BUTTON','OK',IDOK,88,148,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + dialogitem 'BUTTON','C&ancel',IDCANCEL,134,148,42,14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON + enddialog + + dialog compiler_setup_dialog,'Compiler setup',54,28,200,108,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'STATIC','&Include path(s):',-1,8,4,184,8,WS_VISIBLE+SS_LEFT + dialogitem 'COMBOBOX','',ID_INCLUDEPATH,8,14,184,48,WS_VISIBLE+WS_BORDER+WS_TABSTOP+CBS_DROPDOWN+WS_VSCROLL+CBS_AUTOHSCROLL + dialogitem 'STATIC','Source &header:',-1,8,30,184,8,WS_VISIBLE+SS_LEFT + dialogitem 'COMBOBOX','',ID_SOURCEHEADER,8,40,184,48,WS_VISIBLE+WS_BORDER+WS_TABSTOP+CBS_DROPDOWN+WS_VSCROLL+CBS_AUTOHSCROLL + dialogitem 'STATIC','&Passes limit:',-1,8,56,60,8,WS_VISIBLE+SS_LEFT + dialogitem 'EDIT','',ID_PASSES,8,66,54,12,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_NUMBER + dialogitem 'STATIC','&Recursion limit:',-1,72,56,60,8,WS_VISIBLE+SS_LEFT + dialogitem 'EDIT','',ID_RECURSION,72,66,54,12,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_NUMBER + dialogitem 'STATIC','&Thread priority:',-1,136,56,60,8,WS_VISIBLE+SS_LEFT + dialogitem 'COMBOBOX','',ID_PRIORITY,136,66,56,96,WS_VISIBLE+WS_TABSTOP+CBS_DROPDOWNLIST+WS_VSCROLL + dialogitem 'BUTTON','OK',IDOK,104,90,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + dialogitem 'BUTTON','C&ancel',IDCANCEL,150,90,42,14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON + enddialog + + dialog calculator_dialog,'Calculator',48,32,380,80,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'STATIC','&Expression:',-1,4,8,44,8,WS_VISIBLE+SS_RIGHT + dialogitem 'EDIT','',ID_EXPRESSION,52,6,274,12,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_AUTOHSCROLL + dialogitem 'BUTTON','&Decimal:',ID_DECSELECT,4,20,56,12,WS_VISIBLE+WS_TABSTOP+BS_AUTORADIOBUTTON+BS_RIGHT+BS_LEFTTEXT + dialogitem 'EDIT','',ID_DECRESULT,62,22,264,10,WS_VISIBLE+ES_READONLY+ES_AUTOHSCROLL + dialogitem 'BUTTON','&Hexadecimal:',ID_HEXSELECT,4,34,56,12,WS_VISIBLE+WS_TABSTOP+BS_AUTORADIOBUTTON+BS_RIGHT+BS_LEFTTEXT + dialogitem 'EDIT','',ID_HEXRESULT,62,36,264,10,WS_VISIBLE+ES_READONLY+ES_AUTOHSCROLL + dialogitem 'BUTTON','&Binary:',ID_BINSELECT,4,48,56,12,WS_VISIBLE+WS_TABSTOP+BS_AUTORADIOBUTTON+BS_RIGHT+BS_LEFTTEXT + dialogitem 'EDIT','',ID_BINRESULT,62,50,264,10,WS_VISIBLE+ES_READONLY+ES_AUTOHSCROLL + dialogitem 'BUTTON','&Octal:',ID_OCTSELECT,4,62,56,12,WS_VISIBLE+WS_TABSTOP+BS_AUTORADIOBUTTON+BS_RIGHT+BS_LEFTTEXT + dialogitem 'EDIT','',ID_OCTRESULT,62,64,264,10,WS_VISIBLE+ES_READONLY+ES_AUTOHSCROLL + dialogitem 'BUTTON','E&valuate',IDOK,332,6,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + dialogitem 'BUTTON','&Close',IDCANCEL,332,22,42,14,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON + enddialog + + dialog about_dialog,'About',40,40,172,60,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME + dialogitem 'STATIC',<'flat assembler IDE for Windows',0Dh,0Ah,'Copyright ',0A9h,' 1999-2024 Tomasz Grysztar.'>,-1,27,10,144,40,WS_VISIBLE+SS_CENTER + dialogitem 'STATIC',IDI_MAIN,-1,8,8,32,32,WS_VISIBLE+SS_ICON + dialogitem 'STATIC','',-1,4,34,164,11,WS_VISIBLE+SS_ETCHEDHORZ + dialogitem 'STATIC',<'flat assembler g.',VERSION>,-1,4,38,100,20,WS_VISIBLE+SS_LEFT + dialogitem 'STATIC',<'flat editor ',FEDIT_VERSION_STRING>,-1,4,48,100,20,WS_VISIBLE+SS_LEFT + dialogitem 'BUTTON','OK',IDOK,124,40,42,14,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON + enddialog + + icon main_icon,main_icon_data,'resource\fasmgw.ico' + + bitmap assign_bitmap,'resource\assign.bmp' + + versioninfo version,VOS__WINDOWS32,VFT_APP,VFT2_UNKNOWN,LANG_ENGLISH+SUBLANG_DEFAULT,0,\ + 'FileDescription','flat assembler 2',\ + 'LegalCopyright',<'Copyright ',0A9h,' 1999-2024 Tomasz Grysztar.'>,\ + 'FileVersion','2',\ + 'ProductVersion',VERSION,\ + 'OriginalFilename','FASMGW.EXE' diff --git a/toolchain/fasm2/source/ide/windows/fedit.ash b/toolchain/fasm2/source/ide/windows/fedit.ash new file mode 100644 index 0000000..9d4e330 --- /dev/null +++ b/toolchain/fasm2/source/ide/windows/fedit.ash @@ -0,0 +1,69 @@ + +; flat editor mode flags + +FEMODE_OVERWRITE = 1 +FEMODE_VERTICALSEL = 2 +FEMODE_NOUNDO = 4 +FEMODE_READONLY = 8 + +; flat editor search flags + +FEFIND_CASESENSITIVE = 1 +FEFIND_WHOLEWORDS = 2 +FEFIND_BACKWARD = 4 +FEFIND_INWHOLETEXT = 8 + +; flat editor styles + +FES_AUTOINDENT = 0001h +FES_AUTOBRACKETS = 0002h +FES_SMARTTABS = 0004h +FES_SECURESEL = 0008h +FES_OPTIMALFILL = 0010h +FES_CONSOLECARET = 0020h +FES_REVIVEDEADKEYS = 0040h +FES_TIMESCROLL = 0080h + +; flat editor messages + +FEM_SETMODE = WM_USER + 0 +FEM_GETMODE = WM_USER + 1 +FEM_SETPOS = WM_USER + 2 +FEM_GETPOS = WM_USER + 3 +FEM_SETSYNTAXHIGHLIGHT = WM_USER + 4 +FEM_SETRIGHTCLICKMENU = WM_USER + 5 +FEM_SETTEXTCOLOR = WM_USER + 6 +FEM_SETSELCOLOR = WM_USER + 7 +FEM_FINDFIRST = WM_USER + 8 +FEM_FINDNEXT = WM_USER + 9 +FEM_CANFINDNEXT = WM_USER + 10 +FEM_GETLINELENGTH = WM_USER + 11 +FEM_GETLINE = WM_USER + 12 +FEM_GETWORDATCARET = WM_USER + 13 +FEM_BEGINOPERATION = WM_USER + 14 +FEM_ENDOPERATION = WM_USER + 15 +FEM_MARKUNMODIFIED = WM_USER + 16 +FEM_ISUNMODIFIED = WM_USER + 17 +FEM_GETSEARCHTEXT = WM_USER + 18 +FEM_GETSEARCHFLAGS = WM_USER + 19 +FEM_RELEASESEARCH = WM_USER + 20 +FEM_REDO = WM_USER + 84 +FEM_CANREDO = WM_USER + 85 + +; flat editor notifications + +FEN_SETFOCUS = 01h +FEN_KILLFOCUS = 02h +FEN_TEXTCHANGE = 03h +FEN_POSCHANGE = 04h +FEN_MODECHANGE = 05h +FEN_OUTOFMEMORY = 0Fh + +; flat editor position structure + +struct FEPOS + selectionPosition dd ? + selectionLine dd ? + caretPosition dd ? + caretLine dd ? +ends diff --git a/toolchain/fasm2/source/ide/windows/fedit.inc b/toolchain/fasm2/source/ide/windows/fedit.inc new file mode 100644 index 0000000..47bc2a1 --- /dev/null +++ b/toolchain/fasm2/source/ide/windows/fedit.inc @@ -0,0 +1,2279 @@ + +; flat editor interface for Win32 IDE +; Copyright (c) 2001-2014, Tomasz Grysztar. +; All rights reserved. + +SEGMENT_LENGTH = 100h +BLOCK_LENGTH = 400h * SEGMENT_LENGTH +SEGMENT_HEADER_LENGTH = 16 +SEGMENT_DATA_LENGTH = SEGMENT_LENGTH - SEGMENT_HEADER_LENGTH + +include '../version.inc' + +WM_MOUSEHWHEEL = 0x0000020E + +proc FlatEditor hwnd,wmsg,wparam,lparam + + locals + + editor_style dd ? + + label editor_data + + include '../variable.inc' + + editor_font dd ? + font_width dd ? + font_height dd ? + font_overhang dd ? + screen_base dd ? + screen_offset dd ? + screen_width dd ? + screen_height dd ? + screen_size dd ? + line_buffer dd ? + line_buffer_size dd ? + background_color dd ? + text_color dd ? + selection_background dd ? + selection_text dd ? + syntax_proc dd ? + syntax_colors dd ? + caret_x dd ? + caret_y dd ? + pan_x dw ? + pan_y dw ? + menu_handle dd ? + menu_window dd ? + current_operation db ? + last_operation db ? + was_selection db ? + mouse_select db ? + focus db ? + macro_operation db ? + + editor_data_size = $ - editor_data + + if editor_data_size > SEGMENT_DATA_LENGTH + err + end if + + return_value dd ? + background_brush dd ? + selection_brush dd ? + line_number dd ? + ps PAINTSTRUCT + tm TEXTMETRIC + sc SCROLLINFO + gestureconfig GESTURECONFIG + gestureinfo GESTUREINFO + point POINT + rect RECT + size SIZE + char dd ? + kbstate rb 100h + line_selection db ? + clipboard_opened db ? + redraw_now db ? + notification db ? + + endl + + push ebx esi edi + invoke GetWindowLong,[hwnd],GWL_STYLE + mov [editor_style],eax + cmp [wmsg],WM_CREATE + je wm_create + cmp [wmsg],WM_GETDLGCODE + je wm_getdlgcode + invoke GetWindowLong,[hwnd],0 + or eax,eax + jz defwndproc + mov [editor_memory],eax + lea esi,[eax+SEGMENT_HEADER_LENGTH] + lea edi,[editor_data] + mov ecx,editor_data_size + rep movsb + test [editor_style],ES_READONLY + jz editor_mode_ok + or [editor_mode],FEMODE_READONLY + editor_mode_ok: + mov [return_value],0 + mov [notification],0 + mov [redraw_now],0 + mov [clipboard_opened],0 + cmp [wmsg],WM_DESTROY + je wm_destroy + cmp [wmsg],WM_PAINT + je wm_paint + cmp [wmsg],WM_HSCROLL + je wm_hscroll + cmp [wmsg],WM_VSCROLL + je wm_vscroll + cmp [wmsg],WM_GESTURE + je wm_gesture + cmp [wmsg],WM_SIZE + je wm_size + mov eax,[selection_line] + or eax,eax + jz no_selection + cmp eax,[caret_line] + jne selection_present + mov eax,[selection_position] + cmp eax,[caret_position] + je no_selection + selection_present: + mov [was_selection],1 + jmp selection_status_ok + no_selection: + mov [was_selection],0 + selection_status_ok: + xor al,al + xchg [current_operation],al + mov [last_operation],al + mov eax,[wmsg] + cmp eax,WM_SETFOCUS + je wm_setfocus + cmp eax,WM_KILLFOCUS + je wm_killfocus + cmp eax,WM_KEYDOWN + je wm_keydown + cmp eax,WM_SYSKEYDOWN + je wm_syskeydown + cmp eax,WM_CHAR + je wm_char + cmp eax,WM_LBUTTONDOWN + je wm_lbuttondown + cmp eax,WM_LBUTTONUP + je wm_lbuttonup + cmp eax,WM_MOUSEMOVE + je wm_mousemove + cmp eax,WM_LBUTTONDBLCLK + je wm_lbuttondblclk + cmp eax,WM_MOUSEWHEEL + je wm_mousewheel + cmp eax,WM_MOUSEHWHEEL + je wm_mousehwheel + cmp eax,WM_RBUTTONDOWN + je wm_rbuttondown + cmp eax,WM_COPY + je wm_copy + cmp eax,WM_CUT + je wm_cut + cmp eax,WM_PASTE + je wm_paste + cmp eax,WM_CLEAR + je wm_clear + cmp eax,WM_SETTEXT + je wm_settext + cmp eax,WM_GETTEXTLENGTH + je wm_gettextlength + cmp eax,WM_GETTEXT + je wm_gettext + cmp eax,WM_SETFONT + je wm_setfont + cmp eax,WM_GETFONT + je wm_getfont + cmp eax,WM_UNDO + je wm_undo + cmp eax,EM_UNDO + je wm_undo + cmp eax,EM_CANUNDO + je em_canundo + cmp eax,FEM_REDO + je fem_redo + cmp eax,FEM_CANREDO + je fem_canredo + cmp eax,EM_EMPTYUNDOBUFFER + je em_emptyundobuffer + cmp eax,EM_REPLACESEL + je em_replacesel + cmp eax,FEM_SETMODE + je fem_setmode + cmp eax,FEM_GETMODE + je fem_getmode + cmp eax,FEM_SETSYNTAXHIGHLIGHT + je fem_setsyntaxhighlight + cmp eax,FEM_SETRIGHTCLICKMENU + je fem_setrightclickmenu + cmp eax,FEM_GETLINELENGTH + je fem_getlinelength + cmp eax,FEM_GETLINE + je fem_getline + cmp eax,FEM_SETPOS + je fem_setpos + cmp eax,FEM_GETPOS + je fem_getpos + cmp eax,FEM_FINDFIRST + je fem_findfirst + cmp eax,FEM_FINDNEXT + je fem_findnext + cmp eax,FEM_CANFINDNEXT + je fem_canfindnext + cmp eax,FEM_GETWORDATCARET + je fem_getwordatcaret + cmp eax,FEM_SETTEXTCOLOR + je fem_settextcolor + cmp eax,FEM_SETSELCOLOR + je fem_setselcolor + cmp eax,FEM_BEGINOPERATION + je fem_beginoperation + cmp eax,FEM_ENDOPERATION + je fem_endoperation + cmp eax,FEM_MARKUNMODIFIED + je fem_setunmodified + cmp eax,FEM_ISUNMODIFIED + je fem_isunmodified + cmp eax,FEM_GETSEARCHTEXT + je fem_getsearchtext + cmp eax,FEM_GETSEARCHFLAGS + je fem_getsearchflags + cmp eax,FEM_RELEASESEARCH + je fem_releasesearch +defwndproc: + invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] + jmp finish_wndproc +wm_create: + call init_editor_memory + jc create_failed + invoke SetWindowLong,[hwnd],0,[editor_memory] + mov [syntax_proc],SyntaxProc + mov [syntax_colors],0 + mov [macro_operation],0 + mov [current_operation],0 + mov [focus],0 + mov [mouse_select],0 + mov [menu_handle],0 + mov eax,SEGMENT_DATA_LENGTH*2 + mov [line_buffer_size],eax + invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE + or eax,eax + jz create_failed + mov [line_buffer],eax + mov [screen_base],0 + invoke GetSysColor,COLOR_WINDOW + mov [background_color],eax + invoke GetSysColor,COLOR_WINDOWTEXT + mov [text_color],eax + invoke GetSysColor,COLOR_HIGHLIGHT + mov [selection_background],eax + invoke GetSysColor,COLOR_HIGHLIGHTTEXT + mov [selection_text],eax + mov eax,[fedit_font] + mov [editor_font],eax + invoke GetDC,[hwnd] + mov ebx,eax + invoke SelectObject,ebx,[editor_font] + lea edi,[char] + mov byte [edi],20h + lea eax,[size] + invoke GetTextExtentPoint32,ebx,edi,1,eax + lea eax,[tm] + invoke GetTextMetrics,ebx,eax + mov eax,[size.cy] + mov [font_height],eax + mov eax,[size.cx] + mov [font_width],eax + mov ecx,[tm.tmMaxCharWidth] + sub ecx,eax + mov [font_overhang],ecx + invoke ReleaseDC,[hwnd],ebx + mov [return_value],0 + cmp [SetGestureConfig],0 + je done + mov [gestureconfig.dwID],GID_PAN + mov [gestureconfig.dwWant],GC_PAN+GC_PAN_WITH_SINGLE_FINGER_VERTICALLY+GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY+GC_PAN_WITH_INERTIA + mov [gestureconfig.dwBlock],0 + lea edx,[gestureconfig] + invoke SetGestureConfig,[hwnd],0,1,edx,sizeof.GESTURECONFIG + jmp done + create_failed: + or eax,-1 + jmp finish_wndproc +wm_destroy: + invoke VirtualFree,[line_buffer],0,MEM_RELEASE + invoke VirtualFree,[screen_base],0,MEM_RELEASE + call release_search_data + call release_editor_memory + invoke SetWindowLong,[hwnd],0,0 + xor eax,eax + jmp finish_wndproc +wm_getdlgcode: + mov eax,DLGC_WANTCHARS+DLGC_WANTARROWS + jmp finish_wndproc +wm_paint: + lea eax,[rect] + invoke GetUpdateRect,[hwnd],eax,FALSE + or eax,eax + jz finish_wndproc + cmp [screen_base],0 + je finish_wndproc + lea eax,[ps] + invoke BeginPaint,[hwnd],eax + mov ebx,eax + invoke CreateSolidBrush,[background_color] + mov [background_brush],eax + invoke CreateSolidBrush,[selection_background] + mov [selection_brush],eax + invoke SelectObject,ebx,[editor_font] + mov esi,[screen_base] + add esi,[screen_offset] + mov eax,[screen_width] + mul [screen_height] + lea edi,[esi+eax] + mov [rect.top],0 + mov eax,[font_height] + mov [rect.bottom],eax + mov ecx,[screen_height] + paint_screen: + push ecx + mov [rect.left],0 + mov ecx,[screen_width] + paint_line: + cmp byte [esi],0 + je paint_empty_block + mov edx,1 + mov al,[edi] + get_characters_block: + cmp edx,ecx + je get_color + cmp al,[edi+edx] + jne get_color + cmp byte [esi+edx],0 + je get_color + inc edx + jmp get_characters_block + paint_empty_block: + mov edx,1 + test byte [edi],80h + jnz get_empty_selection + get_empty_block: + cmp edx,ecx + je fill_empty_block + cmp byte [esi+edx],0 + jne fill_empty_block + test byte [edi+edx],80h + jnz fill_empty_block + inc edx + jmp get_empty_block + fill_empty_block: + push ecx edx + mov eax,[font_width] + mul edx + add eax,[rect.left] + mov [rect.right],eax + lea eax,[rect] + invoke FillRect,ebx,eax,[background_brush] + jmp paint_next_block + get_empty_selection: + cmp edx,ecx + je fill_empty_selection + cmp byte [esi+edx],0 + jne fill_empty_selection + test byte [edi+edx],80h + jz fill_empty_selection + inc edx + jmp get_empty_selection + fill_empty_selection: + push ecx edx + mov eax,[font_width] + mul edx + add eax,[rect.left] + mov [rect.right],eax + lea eax,[rect] + invoke FillRect,ebx,eax,[selection_brush] + jmp paint_next_block + get_color: + push ecx edx + test byte [edi],80h + jnz highlight_color + invoke SetBkColor,ebx,[background_color] + mov al,[edi] + or al,al + jnz syntax_color + default_color: + invoke SetTextColor,ebx,[text_color] + jmp color_ok + syntax_color: + movzx eax,al + mov edx,[syntax_colors] + or edx,edx + jz default_color + mov eax,[edx+(eax-1)*4] + invoke SetTextColor,ebx,eax + jmp color_ok + highlight_color: + invoke SetBkColor,ebx,[selection_background] + invoke SetTextColor,ebx,[selection_text] + color_ok: + mov ecx,[esp] + mov eax,[font_width] + mul ecx + add eax,[rect.left] + mov [rect.right],eax + lea eax,[rect] + invoke DrawText,ebx,esi,ecx,eax,DT_LEFT+DT_NOPREFIX+DT_SINGLELINE + paint_next_block: + pop edx ecx + sub ecx,edx + add esi,edx + add edi,edx + mov eax,[rect.right] + mov [rect.left],eax + or ecx,ecx + jnz paint_line + mov eax,[font_height] + add [rect.top],eax + add [rect.bottom],eax + pop ecx + dec ecx + jnz paint_screen + invoke DeleteObject,[background_brush] + invoke DeleteObject,[selection_brush] + lea eax,[ps] + invoke EndPaint,[hwnd],eax + xor eax,eax + jmp finish_wndproc +wm_setfocus: + or [focus],-1 + call create_caret + mov [notification],FEN_SETFOCUS + cmp [was_selection],0 + je done + jmp moved_window +wm_killfocus: + mov [focus],0 + invoke DestroyCaret + mov [notification],FEN_KILLFOCUS + cmp [was_selection],0 + je done + jmp moved_window +wm_hscroll: + mov [sc.cbSize],sizeof.SCROLLINFO + mov [sc.fMask],SIF_ALL + lea eax,[sc] + invoke GetScrollInfo,[hwnd],SB_HORZ,eax + movzx eax,word [wparam] + cmp eax,SB_LINEUP + je hscroll_left + cmp eax,SB_LINEDOWN + je hscroll_right + cmp eax,SB_THUMBTRACK + je hscroll_pos + cmp eax,SB_PAGEUP + je hscroll_wleft + cmp eax,SB_PAGEDOWN + je hscroll_wright + hscroll_ignore: + jmp done + hscroll_left: + cmp [window_position],0 + je hscroll_ignore + dec [window_position] + jmp moved_window + hscroll_right: + mov eax,[maximum_position] + sub eax,[sc.nPage] + cmp [window_position],eax + jge hscroll_ignore + inc [window_position] + jmp moved_window + hscroll_pos: + movzx eax,word [wparam+2] + mov [window_position],eax + jmp moved_window + hscroll_wleft: + mov eax,[sc.nPage] + sub [window_position],eax + jnc moved_window + mov [window_position],0 + jmp moved_window + hscroll_wright: + mov eax,[sc.nPage] + mov ecx,[maximum_position] + sub ecx,eax + add [window_position],eax + cmp [window_position],ecx + jbe moved_window + mov [window_position],ecx + jmp moved_window +wm_vscroll: + mov [sc.cbSize],sizeof.SCROLLINFO + mov [sc.fMask],SIF_ALL + lea eax,[sc] + invoke GetScrollInfo,[hwnd],SB_VERT,eax + movzx eax,word [wparam] + cmp eax,SB_LINEUP + je vscroll_up + cmp eax,SB_LINEDOWN + je vscroll_down + cmp eax,SB_THUMBTRACK + je vscroll_pos + cmp eax,SB_PAGEUP + je vscroll_pageup + cmp eax,SB_PAGEDOWN + je vscroll_pagedown + vscroll_ignore: + jmp done + vscroll_up: + mov esi,[window_line] + mov esi,[esi+4] + or esi,esi + jz vscroll_ignore + dec [window_line_number] + mov [window_line],esi + jmp moved_window + vscroll_down: + mov eax,[sc.nPos] + add eax,[sc.nPage] + cmp eax,[sc.nMax] + ja vscroll_ignore + mov esi,[window_line] + vscroll_skip_line: + mov esi,[esi] + btr esi,0 + jc vscroll_skip_line + or esi,esi + jz vscroll_ignore + inc [window_line_number] + mov [window_line],esi + jmp moved_window + vscroll_pos: + mov eax,[sc.nTrackPos] + call find_line + or esi,esi + jz vscroll_ignore + mov [window_line],esi + mov [window_line_number],ecx + jmp moved_window + vscroll_pageup: + mov esi,[window_line] + mov ecx,[sc.nPage] + scrolling_up: + mov eax,[esi+4] + or eax,eax + jz scroll_ok + dec [window_line_number] + mov esi,eax + loop scrolling_up + jmp scroll_ok + vscroll_pagedown: + mov esi,[window_line] + mov eax,[sc.nPos] + add eax,[sc.nPage] + mov ecx,[sc.nMax] + sub ecx,eax + inc ecx + cmp ecx,[sc.nPage] + jbe scrolling_down + mov ecx,[sc.nPage] + scrolling_down: + mov eax,esi + scroll_one_line: + mov eax,[eax] + test eax,eax + jz scroll_ok + btr eax,0 + jc scroll_one_line + or eax,eax + jz scroll_ok + inc [window_line_number] + mov esi,eax + loop scrolling_down + scroll_ok: + mov [window_line],esi + jmp moved_window +wm_gesture: + cmp [GetGestureInfo],0 + je defwndproc + mov [gestureinfo.cbSize],sizeof.GESTUREINFO + lea edx,[gestureinfo] + invoke GetGestureInfo,[lparam],edx + test eax,eax + jz defwndproc + cmp [gestureinfo.dwID],GID_PAN + jne defwndproc + invoke CloseGestureInfoHandle,[lparam] + mov eax,[gestureinfo.dwFlags] + test eax,GF_BEGIN + jnz begin_panning + mov ax,[gestureinfo.ptsLocation.x] + sub ax,[pan_x] + cwde + cdq + idiv [font_width] + sub [gestureinfo.ptsLocation.x],dx + sub [window_position],eax + cmp [window_position],0 + jl horizontal_home + jmp horizontal_pan_ok + horizontal_home: + mov [window_position],0 + horizontal_pan_ok: + mov ax,[gestureinfo.ptsLocation.y] + sub ax,[pan_y] + cwde + cdq + idiv [font_height] + sub [gestureinfo.ptsLocation.y],dx + mov ecx,eax + mov eax,dword [gestureinfo.ptsLocation] + mov dword [pan_x],eax + mov esi,[window_line] + cmp ecx,0 + jz moved_window + jg scrolling_up + neg ecx + jmp scrolling_down + begin_panning: + mov eax,dword [gestureinfo.ptsLocation] + mov dword [pan_x],eax + jmp done +wm_mousewheel: + test [editor_style],FES_TIMESCROLL + jz space_scroll + lea ebx,[kbstate] + invoke GetKeyboardState,ebx + test [kbstate+VK_MENU],80h + jz space_scroll + test [kbstate+VK_CONTROL],80h + jnz time_scroll + space_scroll: + mov esi,[window_line] + mov ecx,[wheel_scroll_lines] + cmp ecx,-1 + jne calculate_scroll + mov [sc.cbSize],sizeof.SCROLLINFO + mov [sc.fMask],SIF_PAGE + push eax + lea eax,[sc] + invoke GetScrollInfo,[hwnd],SB_VERT,eax + pop eax + mov ecx,[sc.nPage] + calculate_scroll: + mov eax,[wparam] + sar eax,16 + imul ecx + mov ecx,120 + idiv ecx + mov ecx,eax + cmp ecx,0 + jg scrolling_up + neg ecx + jnz scrolling_down + jmp done + time_scroll: + test [editor_mode],FEMODE_READONLY + jnz ignore + test [editor_mode],FEMODE_NOUNDO + jnz enable_undo + move_through_time: + cmp word [wparam+2],0 + jge backward_in_time + neg word [wparam+2] + jmp forward_in_time + backward_in_time: + sub word [wparam+2],120 + jc time_scroll_done + mov eax,[undo_data] + test eax,eax + jz time_scroll_done + call undo_changes + jmp backward_in_time + forward_in_time: + sub word [wparam+2],120 + jc time_scroll_done + mov eax,[redo_data] + test eax,eax + jz time_scroll_done + call redo_changes + jmp forward_in_time + time_scroll_done: + call create_caret + mov [last_operation],0 + jmp text_changed +wm_mousehwheel: + lea eax,[sc] + invoke GetScrollInfo,[hwnd],SB_HORZ,eax + mov esi,[window_line] + cmp [wparam],0 + jl hscroll_left + jg hscroll_right + jmp done +wm_size: + call update_positions + mov eax,[screen_width] + mul [screen_height] + mov [screen_size],eax + mov [screen_offset],0 + shl eax,2 + or eax,eax + jz screen_allocated + mov ebx,eax + mov eax,[screen_base] + or eax,eax + jz screen_released + invoke VirtualFree,eax,0,MEM_RELEASE + screen_released: + invoke VirtualAlloc,0,ebx,MEM_COMMIT,PAGE_READWRITE + screen_allocated: + mov [screen_base],eax + call update_screen + lea ebx,[rect] + invoke GetClientRect,[hwnd],ebx + invoke InvalidateRect,[hwnd],ebx,FALSE + jmp done +wm_keydown: + lea ebx,[kbstate] + invoke GetKeyboardState,ebx + cmp [was_selection],0 + jne process_key + mov eax,[caret_line] + mov [selection_line],eax + mov eax,[caret_position] + mov [selection_position],eax + mov eax,[caret_line_number] + mov [selection_line_number],eax + process_key: + mov eax,[wparam] + cmp eax,VK_LEFT + je left_key + cmp eax,VK_RIGHT + je right_key + cmp eax,VK_UP + je up_key + cmp eax,VK_DOWN + je down_key + cmp eax,VK_BACK + je backspace_key + cmp eax,VK_HOME + je home_key + cmp eax,VK_END + je end_key + cmp eax,VK_PGUP + je pgup_key + cmp eax,VK_PGDN + je pgdn_key + cmp eax,VK_APPS + je menu_key + cmp eax,VK_INSERT + je ins_key + cmp eax,VK_DELETE + je del_key + cmp eax,VK_F6 + je f6_key + test [kbstate+VK_CONTROL],80h + jz convert_to_ascii + cmp eax,'Y' + je ctrl_y_key + convert_to_ascii: + mov ax,word [lparam+2] + and eax,7Fh + lea ebx,[kbstate] + lea edx,[char] + invoke ToAscii,[wparam],eax,ebx,edx,FALSE + cmp eax,2 + je two_characters + or eax,eax + jz ignore + jg process_character + test [editor_style],FES_REVIVEDEADKEYS + je ignore + lea edx,[char] + invoke ToAscii,VK_SPACE,0,ebx,edx,FALSE + jmp process_character + two_characters: + movzx eax,byte [char+1] + invoke PostMessage,[hwnd],WM_CHAR,eax,1 shl 31 + process_character: + mov al,byte [char] + cmp al,20h + jae character + cmp al,0Dh + je character + cmp al,9 + je character + jmp ignore + left_key: + test [kbstate+VK_MENU],80h + jnz scroll_left + test [kbstate+VK_CONTROL],80h + jnz word_left + cmp [caret_position],0 + jle moved_caret + dec [caret_position] + jmp moved_caret + right_key: + test [kbstate+VK_MENU],80h + jnz scroll_right + test [kbstate+VK_CONTROL],80h + jnz word_right + mov eax,[caret_position] + cmp eax,[maximum_position] + jae moved_caret + inc [caret_position] + jmp moved_caret + up_key: + test [kbstate+VK_MENU],80h + jnz scroll_up + call move_line_up + jmp moved_caret + down_key: + test [kbstate+VK_MENU],80h + jnz scroll_down + call move_line_down + jmp moved_caret + home_key: + test [kbstate+VK_CONTROL],80h + jnz screen_home + mov [caret_position],0 + jmp moved_caret + end_key: + test [kbstate+VK_CONTROL],80h + jnz screen_end + call move_to_line_end + jmp moved_caret + screen_home: + mov eax,[window_line] + mov [caret_line],eax + mov eax,[window_line_number] + mov [caret_line_number],eax + jmp moved_caret + screen_end: + mov eax,[window_line_number] + add eax,[window_height] + dec eax + call find_line + mov [caret_line],esi + mov [caret_line_number],ecx + jmp moved_caret + pgup_key: + test [kbstate+VK_CONTROL],80h + jnz text_home + call move_page_up + jmp moved_caret + pgdn_key: + test [kbstate+VK_CONTROL],80h + jnz text_end + call move_page_down + jmp moved_caret + text_home: + mov eax,[first_line] + mov [caret_line],eax + mov [caret_line_number],1 + jmp moved_caret + text_end: + or eax,-1 + call find_line + mov [caret_line],esi + mov [caret_line_number],ecx + jmp moved_caret + word_left: + call move_to_previous_word + jmp moved_caret + word_right: + call get_caret_segment + call move_to_next_word + jmp moved_caret + scroll_left: + cmp [window_position],0 + je scroll_done + dec [window_position] + jmp scroll_done + scroll_right: + inc [window_position] + jmp scroll_done + scroll_up: + mov esi,[window_line] + mov esi,[esi+4] + or esi,esi + jz scroll_done + mov [window_line],esi + dec [window_line_number] + jmp scroll_done + scroll_down: + mov esi,[window_line] + find_next_window_line: + mov esi,[esi] + btr esi,0 + jc find_next_window_line + or esi,esi + jz scroll_done + mov [window_line],esi + inc [window_line_number] + scroll_done: + cmp [was_selection],0 + jne moved_window + mov [selection_line],0 + jmp moved_window + ins_key: + test [kbstate+VK_MENU],80h + jnz switch_blocks + test [kbstate+VK_CONTROL],80h + jnz wm_copy + test [kbstate+VK_SHIFT],80h + jnz wm_paste + xor [editor_mode],FEMODE_OVERWRITE + mov [notification],FEN_MODECHANGE + call create_caret + cmp [was_selection],1 + je done + mov [selection_line],0 + jmp done + del_key: + test [editor_mode],FEMODE_READONLY + jnz ignore + test [kbstate+VK_CONTROL],80h + jnz wm_clear + test [kbstate+VK_SHIFT],80h + jnz wm_cut + cmp [was_selection],0 + je no_selection_on_del + test [editor_style],FES_SECURESEL + jz wm_clear + no_selection_on_del: + mov esi,[caret_line] + test [editor_mode],FEMODE_OVERWRITE + jnz delete_char + call check_line_length + cmp ecx,[caret_position] + ja delete_char + cmp dword [esi],0 + je ignore + call make_undopoint + call cut_line_break + call finish_edit + jmp text_altered + delete_char: + mov [current_operation],VK_DELETE + cmp [last_operation],VK_DELETE + jne undopoint_for_delete + mov eax,[unmodified_state] + cmp eax,[undo_data] + jne undo_delete_ok + or [unmodified_state],-1 + undopoint_for_delete: + call make_undopoint + undo_delete_ok: + call delete_character + call finish_edit + jmp text_altered + backspace_key: + test [editor_mode],FEMODE_READONLY + jnz ignore + test [kbstate+VK_MENU],80h + jnz undo_key + cmp [was_selection],0 + je no_selection_to_clear + test [editor_style],FES_SECURESEL + jz wm_clear + no_selection_to_clear: + cmp [caret_position],0 + je line_back + test [kbstate+VK_CONTROL],80h + jnz word_back + mov [current_operation],VK_BACK + cmp [last_operation],VK_BACK + jne backspace_undopoint + mov eax,[unmodified_state] + cmp eax,[undo_data] + jne undo_backspace_ok + or [unmodified_state],-1 + jmp undo_backspace_ok + backspace_undopoint: + call make_undopoint + undo_backspace_ok: + dec [caret_position] + call delete_character + call finish_edit + jmp text_altered + line_back: + test [editor_mode],FEMODE_OVERWRITE + jnz ignore + mov esi,[caret_line] + mov esi,[esi+4] + or esi,esi + jz ignore + call make_undopoint + mov [caret_line],esi + dec [caret_line_number] + call check_line_length + mov [caret_position],ecx + call cut_line_break + call finish_edit + jmp text_altered + word_back: + call make_undopoint + push [caret_position] + mov esi,[caret_line] + xor eax,eax + xchg eax,[esi+4] + push eax + call move_to_previous_word + pop eax + mov esi,[caret_line] + mov [esi+4],eax + pop ecx + sub ecx,[caret_position] + call delete_from_line + call finish_edit + jmp text_altered + character: + test [editor_mode],FEMODE_READONLY + jnz ignore + cmp al,0Dh + je enter_key + cmp al,9 + je tab_key + cmp [was_selection],0 + je no_selection_to_replace + call make_undopoint + test [editor_style],FES_SECURESEL + jnz character_undo_ok + push eax + call delete_block + pop eax + call put_character + call finish_edit + jmp text_altered + no_selection_to_replace: + mov [current_operation],VK_SPACE + cmp [last_operation],VK_SPACE + jne character_undopoint + mov edx,[unmodified_state] + cmp edx,[undo_data] + jne character_undo_ok + or [unmodified_state],-1 + jmp character_undo_ok + character_undopoint: + call make_undopoint + character_undo_ok: + call put_character + call finish_edit + jmp text_altered + tab_key: + test [editor_mode],FEMODE_READONLY + jnz ignore + call make_undopoint + cmp [was_selection],0 + je tab_securesel + test [editor_style],FES_SECURESEL + jnz tab_securesel + call delete_block + tab_securesel: + call tabulate + call finish_edit + jmp text_altered + enter_key: + test [editor_mode],FEMODE_READONLY + jnz ignore + call make_undopoint + cmp [was_selection],0 + je enter_secureselection_ok + test [editor_style],FES_SECURESEL + jnz enter_secureselection_ok + call delete_block + enter_secureselection_ok: + call carriage_return + test [editor_mode],FEMODE_OVERWRITE + jnz text_altered + call finish_edit + jmp text_altered + ctrl_y_key: + test [editor_mode],FEMODE_READONLY + jnz ignore + call make_undopoint + call remove_line + jmp text_altered + f6_key: + test [editor_mode],FEMODE_READONLY + jnz ignore + call make_undopoint + call duplicate_line + jmp text_altered + menu_key: + cmp [menu_handle],0 + je ignore + lea ebx,[point] + mov eax,[caret_x] + mov [ebx+POINT.x],eax + mov eax,[caret_y] + add eax,[font_height] + mov [ebx+POINT.y],eax + invoke ClientToScreen,[hwnd],ebx + invoke TrackPopupMenu,[menu_handle],TPM_RIGHTBUTTON,[ebx+POINT.x],[ebx+POINT.y],0,[menu_window],0 + jmp ignore +wm_syskeydown: + lea ebx,[kbstate] + invoke GetKeyboardState,ebx + mov eax,[wparam] + cmp eax,VK_INSERT + je switch_blocks + cmp eax,VK_LEFT + je scroll_left + cmp eax,VK_RIGHT + je scroll_right + cmp eax,VK_UP + je scroll_up + cmp eax,VK_DOWN + je scroll_down + cmp eax,VK_BACK + je undo_key + mov al,[last_operation] + mov [current_operation],al + jmp defwndproc + switch_blocks: + xor [editor_mode],FEMODE_VERTICALSEL + mov [notification],FEN_MODECHANGE + cmp [was_selection],0 + je ignore + jmp moved_window +wm_char: + test [lparam],1 shl 31 + jz ignore + mov eax,[wparam] + jmp character +wm_lbuttondown: + cmp [focus],0 + jne focus_ok + invoke SetFocus,[hwnd] + mov esi,[editor_memory] + add esi,SEGMENT_HEADER_LENGTH + lea edi,[editor_data] + mov ecx,editor_data_size + rep movsb + focus_ok: + lea ebx,[kbstate] + invoke GetKeyboardState,ebx + cmp [was_selection],0 + jne selection_ok + mov eax,[caret_line] + mov [selection_line],eax + mov eax,[caret_position] + mov [selection_position],eax + mov eax,[caret_line_number] + mov [selection_line_number],eax + selection_ok: + call get_mouse_position + invoke SetCapture,[hwnd] + or [mouse_select],-1 + jmp moved_caret + get_mouse_position: + mov ax,word [lparam] + cwde + cdq + test [editor_style],FES_CONSOLECARET + jnz get_mouse_column + test [editor_mode],FEMODE_OVERWRITE + jnz get_mouse_column + mov ebx,[font_width] + shr ebx,1 + adc eax,ebx + get_mouse_column: + idiv [font_width] + add eax,[window_position] + cmp eax,[maximum_position] + jg mouse_out_of_line + cmp eax,0 + jge click_position_ok + xor eax,eax + jmp click_position_ok + mouse_out_of_line: + mov eax,[maximum_position] + click_position_ok: + mov [caret_position],eax + mov ax,word [lparam+2] + cwde + cdq + idiv [font_height] + add eax,[window_line_number] + cmp eax,0 + jg click_line_ok + mov eax,1 + click_line_ok: + call find_line + mov [caret_line],esi + mov [caret_line_number],ecx + retn +wm_lbuttonup: + invoke ReleaseCapture + mov [mouse_select],0 + jmp done +wm_mousemove: + cmp [mouse_select],0 + je ignore + cmp [was_selection],0 + jne select + mov eax,[caret_line] + mov ebx,[caret_line_number] + mov [selection_line],eax + mov [selection_line_number],ebx + mov eax,[caret_position] + mov [selection_position],eax + select: + call get_mouse_position + jmp moved_selection +wm_lbuttondblclk: + mov [mouse_select],0 + call get_mouse_position + call get_word_at_caret + mov [selection_position],edx + add edx,ecx + mov [caret_position],edx + mov eax,[caret_line] + mov [selection_line],eax + mov eax,[caret_line_number] + mov [selection_line_number],eax + jmp moved_selection +wm_rbuttondown: + cmp [menu_handle],0 + je ignore + lea eax,[point] + invoke GetCursorPos,eax + invoke TrackPopupMenu,[menu_handle],TPM_RIGHTBUTTON,[point.x],[point.y],0,[menu_window],0 + jmp ignore +wm_copy: + cmp [was_selection],0 + je ignore + call copy_to_clipboard + jmp ignore + copy_to_clipboard: + call get_block_length + inc ecx + invoke GlobalAlloc,GMEM_MOVEABLE+GMEM_DDESHARE,ecx + mov ebx,eax + invoke GlobalLock,ebx + mov edi,eax + push ebx + call copy_block + pop ebx + invoke GlobalUnlock,ebx + invoke OpenClipboard,[hwnd] + invoke EmptyClipboard + invoke SetClipboardData,CF_TEXT,ebx + or eax,eax + jz copy_failed + invoke CloseClipboard + retn + copy_failed: + invoke GlobalFree,ebx + retn +wm_cut: + test [editor_mode],FEMODE_READONLY + jnz ignore + cmp [was_selection],0 + je ignore + call copy_to_clipboard +wm_clear: + test [editor_mode],FEMODE_READONLY + jnz ignore + cmp [was_selection],0 + je ignore + call make_undopoint + call delete_block + mov [selection_line],0 + jmp text_changed +wm_paste: + test [editor_mode],FEMODE_READONLY + jnz ignore + call make_undopoint + cmp [was_selection],0 + je paste_secureselection_ok + test [editor_style],FES_SECURESEL + jnz paste_secureselection_ok + call delete_block + paste_secureselection_ok: + invoke OpenClipboard,NULL + invoke GetClipboardData,CF_TEXT + or eax,eax + jnz do_paste + invoke CloseClipboard + jmp ignore + do_paste: + or [clipboard_opened],-1 + push eax + invoke GlobalLock,dword [esp] + mov esi,eax + call insert_block + jc paste_failed + pop ebx + invoke GlobalUnlock,ebx + invoke CloseClipboard + mov [clipboard_opened],0 + test [editor_style],FES_SECURESEL + jz no_selection_after_paste + mov eax,[caret_line] + mov ecx,[caret_line_number] + mov edx,[caret_position] + xchg eax,[selection_line] + xchg ecx,[selection_line_number] + xchg edx,[selection_position] + mov [caret_line],eax + mov [caret_line_number],ecx + mov [caret_position],edx + jmp text_changed + no_selection_after_paste: + mov [selection_line],0 + jmp text_changed + paste_failed: + call undo_changes + pop ebx + invoke GlobalUnlock,ebx + invoke CloseClipboard + mov [clipboard_opened],0 + jmp text_changed +wm_settext: + mov esi,[lparam] + call set_text + mov [return_value],TRUE + jmp text_changed +wm_gettextlength: + mov esi,[first_line] + count_text_length: + mov eax,[esi+8] + add [return_value],eax + skip_counted_line_segments: + mov esi,[esi] + or esi,esi + jz ignore + btr esi,0 + jc skip_counted_line_segments + add [return_value],2 + jmp count_text_length +wm_gettext: + mov esi,[first_line] + mov edi,[lparam] + sub [wparam],1 + jc ignore + mov [line_number],0 + copy_text: + inc [line_number] + mov ecx,[esi+8] + test [editor_style],FES_OPTIMALFILL + jz direct_copy + cmp ecx,8 + jb direct_copy + push edi ecx + mov edi,[line_buffer] + xor edx,edx + call copy_from_line + push esi + mov esi,[line_buffer] + mov edi,[line_buffer] + add edi,[peak_line_length] + mov ebx,edi + mov ecx,[esp+4] + xor al,al + rep stosb + mov ecx,[esp+4] + invoke syntax_proc,esi,ecx,ebx + pop esi ecx edi + mov eax,[return_value] + add eax,ecx + cmp eax,[wparam] + jbe optimal_fill_size_ok + mov ecx,[wparam] + sub eax,[return_value] + optimal_fill_size_ok: + push esi edi + mov esi,[line_buffer] + mov ebx,[peak_line_length] + jecxz optimal_fill_done + xor edx,edx + optimal_fill: + lodsb + cmp al,20h + jne store_character + cmp byte [esi-1+ebx],0 + jne store_character + mov eax,esi + sub eax,[line_buffer] + test eax,111b + jz store_tab + inc edx + mov al,20h + stosb + loop optimal_fill + jmp optimal_fill_done + store_tab: + mov al,20h + or edx,edx + jz store_character + sub edi,edx + mov al,9 + store_character: + stosb + xor edx,edx + loop optimal_fill + optimal_fill_done: + pop eax + neg eax + add eax,edi + add [return_value],eax + pop esi + jmp line_copied + direct_copy: + mov eax,[return_value] + add eax,ecx + cmp eax,[wparam] + jbe direct_copy_size_ok + mov ecx,[wparam] + sub eax,[return_value] + direct_copy_size_ok: + add [return_value],ecx + xor edx,edx + call copy_from_line + line_copied: + or esi,esi + jz text_copied + mov ecx,[return_value] + add ecx,2 + cmp ecx,[wparam] + ja text_copied + mov ax,0A0Dh + stosw + mov [return_value],ecx + cmp ecx,[wparam] + jne copy_text + text_copied: + xor al,al + stosb + jmp ignore +fem_getlinelength: + mov esi,[caret_line] + mov eax,[wparam] + or eax,eax + jz return_length + call find_line + cmp ecx,[wparam] + je return_length + or [return_value],-1 + jmp ignore + return_length: + mov ecx,[esi+8] + mov [return_value],ecx + jmp ignore +fem_getline: + mov esi,[caret_line] + mov eax,[wparam] + or eax,eax + jz get_line_contents + call find_line + cmp ecx,[wparam] + jne ignore + get_line_contents: + mov ecx,[esi+8] + mov [return_value],ecx + mov edi,[lparam] + xor edx,edx + call copy_from_line + xor al,al + stosb + jmp ignore +wm_setfont: + mov esi,[wparam] + or esi,esi + jnz get_metrics + mov esi,[fedit_font] + get_metrics: + invoke GetDC,[hwnd] + mov ebx,eax + invoke SelectObject,ebx,esi + lea edi,[char] + mov byte [edi],20h + lea eax,[size] + invoke GetTextExtentPoint32,ebx,edi,1,eax + lea eax,[tm] + invoke GetTextMetrics,ebx,eax + invoke ReleaseDC,[hwnd],ebx + test [tm.tmPitchAndFamily],TMPF_FIXED_PITCH + jnz ignore + mov [return_value],esi + mov [editor_font],esi + mov eax,[size.cy] + mov [font_height],eax + mov eax,[size.cx] + mov [font_width],eax + mov ecx,[tm.tmMaxCharWidth] + sub ecx,eax + mov [font_overhang],ecx + mov eax,[lparam] + mov [redraw_now],al + cmp [focus],0 + je wm_size + call create_caret + jmp wm_size +wm_getfont: + mov eax,[editor_font] + cmp eax,[fedit_font] + je ignore + mov [return_value],eax + jmp ignore +wm_undo: + test [editor_mode],FEMODE_READONLY + jnz ignore + test [editor_mode],FEMODE_NOUNDO + jnz enable_undo + mov eax,[undo_data] + test eax,eax + jz ignore + call undo_changes + call create_caret + mov [last_operation],0 + jmp text_changed + enable_undo: + and [editor_mode],not FEMODE_NOUNDO + jmp ignore +em_canundo: + test [editor_mode],FEMODE_READONLY + jnz ignore + mov eax,[undo_data] + or eax,eax + jz ignore + mov [return_value],TRUE + jmp ignore + undo_key: + test [kbstate+VK_SHIFT],80h + jz wm_undo +fem_redo: + test [editor_mode],FEMODE_READONLY + jnz ignore + cmp [redo_data],0 + je ignore + call redo_changes + call create_caret + mov [last_operation],0 + jmp text_changed +fem_canredo: + test [editor_mode],FEMODE_READONLY + jnz ignore + mov eax,[redo_data] + or eax,eax + jz ignore + mov [return_value],TRUE + jmp ignore +fem_isunmodified: + mov eax,[undo_data] + cmp eax,[unmodified_state] + jne ignore + mov [return_value],TRUE + jmp ignore +em_emptyundobuffer: + call clear_redo_data + call clear_undo_data + jmp ignore +fem_setunmodified: + mov eax,[undo_data] + mov [unmodified_state],eax + jmp ignore +em_replacesel: + test [editor_mode],FEMODE_VERTICALSEL + FEMODE_OVERWRITE + FEMODE_READONLY + jnz ignore + cmp [undo_data],0 + je replacesel_undopoint + cmp [wparam],0 + je replace_undo_ok + replacesel_undopoint: + call make_undopoint + replace_undo_ok: + cmp [was_selection],0 + je simple_replace + push [caret_line_number] + push [caret_position] + call delete_block + pop edx ecx + cmp ecx,[caret_line_number] + jne simple_replace + cmp edx,[caret_position] + jne simple_replace + mov esi,[lparam] + call insert_block + mov esi,[caret_line] + mov ecx,[caret_line_number] + mov edx,[caret_position] + xchg esi,[selection_line] + xchg ecx,[selection_line_number] + xchg edx,[selection_position] + mov [caret_line],esi + mov [caret_line_number],ecx + mov [caret_position],edx + jmp text_changed + simple_replace: + mov esi,[lparam] + call insert_block + jmp text_changed +fem_setmode: + mov eax,[wparam] + xchg [editor_mode],eax + cmp eax,[editor_mode] + je ignore + mov [notification],FEN_MODECHANGE + call create_caret + cmp [was_selection],0 + jne moved_window + jmp done +fem_getmode: + mov eax,[editor_mode] + mov [return_value],eax + jmp ignore +fem_setsyntaxhighlight: + mov eax,[wparam] + mov ebx,[lparam] + mov [syntax_colors],eax + mov [syntax_proc],ebx + or eax,eax + jnz wm_size + mov [syntax_proc],SyntaxProc + jmp wm_size +fem_setrightclickmenu: + mov eax,[wparam] + mov ebx,[lparam] + mov [menu_handle],eax + mov [menu_window],ebx + jmp ignore +fem_settextcolor: + mov eax,[wparam] + mov ebx,[lparam] + mov [text_color],eax + mov [background_color],ebx + jmp wm_size +fem_setselcolor: + mov eax,[wparam] + mov ebx,[lparam] + mov [selection_text],eax + mov [selection_background],ebx + jmp wm_size +fem_setpos: + mov edi,[wparam] + virtual at edi + pos FEPOS + end virtual + cmp [selection_line],0 + jne selection_current_ok + mov eax,[caret_line] + mov [selection_line],eax + mov eax,[caret_line_number] + mov [selection_line_number],eax + mov eax,[caret_position] + mov [selection_position],eax + selection_current_ok: + mov eax,[pos.selectionLine] + or eax,eax + jz selection_line_ok + call find_line + mov [selection_line],esi + mov [selection_line_number],ecx + selection_line_ok: + mov eax,[pos.selectionPosition] + sub eax,1 + jc selection_position_set + mov [selection_position],eax + selection_position_set: + mov eax,[pos.caretLine] + or eax,eax + jz caret_line_ok + call find_line + mov [caret_line],esi + mov [caret_line_number],ecx + caret_line_ok: + mov eax,[pos.caretPosition] + sub eax,1 + jc moved_selection + mov [caret_position],eax + jmp moved_selection +fem_getpos: + mov edi,[wparam] + mov eax,[caret_line_number] + mov [pos.selectionLine],eax + mov [pos.caretLine],eax + mov eax,[caret_position] + inc eax + mov [pos.selectionPosition],eax + mov [pos.caretPosition],eax + cmp [selection_line],0 + je ignore + mov eax,[selection_line_number] + mov [pos.selectionLine],eax + mov eax,[selection_position] + inc eax + mov [pos.selectionPosition],eax + jmp ignore +fem_findfirst: + mov esi,[lparam] + mov eax,[wparam] + call find_first + jnc show_found_text + jmp ignore +fem_findnext: + call find_next + jc ignore + show_found_text: + mov [return_value],TRUE + cmp [macro_operation],0 + jne moved_selection + mov eax,[caret_position] + xchg eax,[selection_position] + mov [caret_position],eax + call update_window + call let_caret_appear + call update_positions + mov eax,[caret_position] + xchg eax,[selection_position] + mov [caret_position],eax + jmp moved_selection +fem_getsearchtext: + call get_search_text_length + mov edx,[lparam] + jc store_required_buffer_size + inc ecx + cmp ecx,[edx] + ja store_required_buffer_size + mov edi,[wparam] + call get_search_text + mov [return_value],TRUE + jmp ignore + store_required_buffer_size: + mov [edx],ecx + jmp ignore +fem_getsearchflags: + cmp [search_data],0 + je ignore + mov eax,[search_flags] + mov [return_value],eax + jmp ignore +fem_releasesearch: + call release_search_data + jmp ignore +fem_canfindnext: + cmp [search_data],0 + je ignore + mov [return_value],TRUE + jmp ignore +fem_getwordatcaret: + cmp [wparam],0 + je ignore + call get_word_at_caret + mov edi,[lparam] + mov eax,[wparam] + dec eax + jz word_copied + cmp ecx,eax + jbe copy_word + mov ecx,eax + copy_word: + mov [return_value],ecx + mov esi,[caret_line] + call copy_from_line + word_copied: + xor al,al + stosb + jmp ignore +fem_beginoperation: + test [editor_mode],FEMODE_READONLY + jnz ignore + mov [macro_operation],1 + call store_status_for_undo + jmp done +fem_endoperation: + test [editor_mode],FEMODE_READONLY + jnz ignore + xor al,al + xchg al,[macro_operation] + test al,2 + jnz text_changed + test al,4 + jz update_all + mov [notification],FEN_POSCHANGE + jmp update_all +moved_caret: + test [kbstate+VK_SHIFT],80h + jnz moved_selection + mov [selection_line],0 +moved_selection: + cmp [macro_operation],0 + jne position_changed_by_macro_operation + mov [notification],FEN_POSCHANGE + jmp update_all +moved_window: + call update_positions + jmp refresh +text_altered: + mov [selection_line],0 +text_changed: + cmp [macro_operation],0 + jne text_changed_by_macro_operation + mov [notification],FEN_TEXTCHANGE + mov eax,[peak_line_length] + xor edx,edx + mov ebx,SEGMENT_DATA_LENGTH + div ebx + inc eax + mul ebx + shl eax,1 + cmp eax,[line_buffer_size] + je update_all + mov [line_buffer_size],eax + invoke VirtualAlloc,0,[line_buffer_size],MEM_COMMIT,PAGE_READWRITE + or eax,eax + jz memory_shortage + xchg [line_buffer],eax + invoke VirtualFree,eax,0,MEM_RELEASE + update_all: + cmp [macro_operation],0 + jne done + call update_window + call let_caret_appear + call update_positions + refresh: + cmp [macro_operation],0 + jne done + cmp [screen_base],0 + je wm_size + mov eax,[screen_size] + shl eax,1 + xor [screen_offset],eax + call update_screen + mov esi,[screen_base] + mov eax,[screen_size] + lea edi,[esi+eax*2] + mov [rect.top],0 + mov edx,[font_height] + mov [rect.bottom],edx + mov ecx,[screen_height] + refresh_screen: + push ecx + mov ebx,[screen_size] + mov edx,[font_width] + xor eax,eax + mov [rect.left],eax + mov [rect.right],eax + mov ecx,[screen_width] + refresh_line: + mov al,[esi] + mov ah,[esi+ebx] + cmp al,[edi] + jne refresh_changed + cmp ah,[edi+ebx] + jne refresh_changed + inc esi + inc edi + add [rect.left],edx + add [rect.right],edx + loop refresh_line + jmp refresh_next_line + refresh_changed: + mov al,[esi] + mov ah,[esi+ebx] + inc esi + add [rect.right],edx + cmp al,[edi] + jne changed_more + cmp ah,[edi+ebx] + jne changed_more + inc edi + jmp invalidate + changed_more: + inc edi + loop refresh_changed + invalidate: + push ecx edx + push [rect.right] + mov eax,[font_overhang] + sub [rect.left],eax + add [rect.right],eax + lea edx,[rect] + invoke InvalidateRect,[hwnd],edx,FALSE + pop eax + mov [rect.left],eax + mov [rect.right],eax + pop edx ecx + jecxz refresh_next_line + loop refresh_line + refresh_next_line: + mov eax,[font_height] + add [rect.top],eax + add [rect.bottom],eax + pop ecx + dec ecx + jnz refresh_screen + jmp done + position_changed_by_macro_operation: + or [macro_operation],4 + jmp done + text_changed_by_macro_operation: + or [macro_operation],2 + jmp done +ignore: + mov dl,[last_operation] + mov [current_operation],dl + cmp [was_selection],0 + jne done + mov [selection_line],0 +done: + cmp [focus],0 + je caret_ok + call update_caret_position + caret_ok: + lea esi,[editor_data] + mov edi,[editor_memory] + add edi,SEGMENT_HEADER_LENGTH + mov ecx,editor_data_size + rep movsb + cmp [notification],0 + je notification_ok + invoke GetWindowLong,[hwnd],GWL_HWNDPARENT + mov edi,eax + invoke GetWindowLong,[hwnd],GWL_ID + movzx ebx,[notification] + shl ebx,16 + or eax,ebx + invoke SendMessage,edi,WM_COMMAND,eax,[hwnd] + notification_ok: + cmp [redraw_now],0 + je redraw_ok + invoke UpdateWindow,[hwnd] + redraw_ok: + mov eax,[return_value] +finish_wndproc: + pop edi esi ebx + ret +not_enough_memory: + lea esp,[editor_memory-10h] + mov [notification],FEN_OUTOFMEMORY + or [return_value],-1 + cmp [clipboard_opened],0 + je ignore + invoke CloseClipboard + mov [clipboard_opened],0 + jmp ignore +get_memory: + invoke VirtualAlloc,0,ecx,MEM_COMMIT,PAGE_READWRITE + mov ebx,eax + retn +release_memory: + invoke VirtualFree,ebx,0,MEM_RELEASE + retn +make_undopoint: + cmp [macro_operation],0 + jne undopoint_ok + call store_status_for_undo + undopoint_ok: + retn +update_positions: + lea eax,[rect] + invoke GetClientRect,[hwnd],eax + mov eax,[rect.right] + sub eax,[rect.left] + cdq + div [font_width] + mov [window_width],eax + add edx,-1 + adc eax,0 + mov [screen_width],eax + mov eax,[rect.bottom] + sub eax,[rect.top] + cdq + div [font_height] + mov [window_height],eax + add edx,-1 + adc eax,0 + mov [screen_height],eax + call update_window + setup_vscroll: + mov ecx,[lines_count] + mov [sc.cbSize],sizeof.SCROLLINFO + mov [sc.fMask],SIF_DISABLENOSCROLL+SIF_RANGE+SIF_PAGE+SIF_POS + mov [sc.nMin],1 + mov [sc.nMax],ecx + mov eax,[window_height] + mov [sc.nPage],eax + mov edx,[window_line_number] + mov [sc.nPos],edx + test [editor_style],WS_VSCROLL + jz setup_hscroll + lea eax,[sc] + invoke SetScrollInfo,[hwnd],SB_VERT,eax,TRUE + setup_hscroll: + mov ecx,[maximum_position] + mov [sc.nMin],0 + mov [sc.nMax],ecx + mov eax,[window_width] + mov [sc.nPage],eax + mov edx,[window_position] + mov [sc.nPos],edx + test [editor_style],WS_HSCROLL + jz setup_caret + lea eax,[sc] + invoke SetScrollInfo,[hwnd],SB_HORZ,eax,TRUE + setup_caret: + mov eax,[font_width] + mov edx,[caret_position] + sub edx,[window_position] + imul eax,edx + mov [caret_x],eax + mov eax,[font_height] + mov edx,[caret_line_number] + sub edx,[window_line_number] + imul eax,edx + mov [caret_y],eax + retn +create_caret: + xor eax,eax + test [editor_mode],FEMODE_OVERWRITE + jnz block_caret + test [editor_style],FES_CONSOLECARET + jnz console_caret + invoke CreateCaret,[hwnd],NULL,0,[font_height] + jmp show_caret + block_caret: + invoke CreateCaret,[hwnd],NULL,[font_width],[font_height] + jmp show_caret + console_caret: + invoke CreateCaret,[hwnd],NULL,[font_width],2 + show_caret: + invoke ShowCaret,[hwnd] +update_caret_position: + mov eax,[caret_y] + test [editor_mode],FEMODE_OVERWRITE + jnz set_position + test [editor_style],FES_CONSOLECARET + jz set_position + add eax,[font_height] + sub eax,2 + set_position: + invoke SetCaretPos,[caret_x],eax + retn +update_screen: + mov edi,[screen_base] + or edi,edi + jz screen_prepared + add edi,[screen_offset] + mov ebx,[screen_size] + add ebx,edi + push ebx + mov ecx,[screen_height] + mov edx,[window_line_number] + mov [line_number],edx + mov esi,[window_line] + prepare_screen: + push ecx + test byte [esi],1 + jnz prepare_long_line + push esi + add esi,SEGMENT_HEADER_LENGTH + mov ecx,SEGMENT_DATA_LENGTH + call prepare_line + pop esi + mov esi,[esi] + jmp prepare_next_line + prepare_long_line: + push edi + mov edi,[line_buffer] + xor eax,eax + combine_long_line_segments: + add esi,SEGMENT_HEADER_LENGTH + mov ecx,SEGMENT_DATA_LENGTH + rep movsb + add eax,SEGMENT_DATA_LENGTH + mov esi,[esi-SEGMENT_LENGTH] + btr esi,0 + jc combine_long_line_segments + mov ecx,eax + mov eax,esi + mov esi,edi + sub esi,ecx + pop edi + push eax + call prepare_line + pop esi + prepare_next_line: + inc [line_number] + pop ecx + dec ecx + jz prepare_selection + or esi,esi + jnz prepare_screen + prepare_empty_lines: + imul ecx,[screen_width] + xor al,al + mov edx,ecx + rep stosb + xchg edi,ebx + mov ecx,edx + rep stosb + prepare_selection: + pop ebx + test [editor_style],ES_NOHIDESEL + jnz hideselection_ok + cmp [focus],0 + je screen_prepared + hideselection_ok: + cmp [selection_line],0 + je screen_prepared + mov eax,[window_line_number] + mov esi,[selection_line_number] + mov edi,[caret_line_number] + sub esi,eax + sub edi,eax + mov ecx,[window_position] + mov eax,[selection_position] + mov edx,[caret_position] + sub eax,ecx + sub edx,ecx + cmp esi,edi + jle selection_boundaries_ok + xchg esi,edi + xchg eax,edx + selection_boundaries_ok: + mov ecx,[screen_height] + cmp edi,0 + jl screen_prepared + cmp esi,ecx + jge screen_prepared + cmp esi,edi + je prepare_vsel + test [editor_mode],FEMODE_VERTICALSEL + jz prepare_hsel + prepare_vsel: + cmp eax,edx + jle vselection_boundaries_ok + xchg eax,edx + vselection_boundaries_ok: + cmp esi,0 + jge vselection_start_ok + xor esi,esi + vselection_start_ok: + inc edi + cmp edi,ecx + jle vselection_end_ok + mov edi,ecx + vselection_end_ok: + mov ecx,[screen_width] + cmp edx,0 + jl screen_prepared + cmp eax,ecx + jge screen_prepared + cmp eax,0 + jge vselection_line_start_ok + xor eax,eax + vselection_line_start_ok: + cmp edx,ecx + jle vselection_line_end_ok + mov edx,ecx + vselection_line_end_ok: + mov ecx,edi + sub ecx,esi + imul esi,[screen_width] + add ebx,esi + prepare_vselection_line: + push eax ecx + mov edi,ebx + mov ecx,edx + sub ecx,eax + lea edi,[ebx+eax] + mov al,80h + rep stosb + add ebx,[screen_width] + pop ecx eax + loop prepare_vselection_line + jmp screen_prepared + prepare_hsel: + cmp esi,0 + jge hselection_start_ok + xor esi,esi + xor eax,eax + hselection_start_ok: + cmp edi,ecx + jl hselection_end_ok + mov edi,ecx + xor edx,edx + hselection_end_ok: + inc esi + mov ecx,edi + sub ecx,esi + imul ecx,[screen_width] + imul esi,[screen_width] + lea edi,[ebx+esi] + neg eax + add eax,[screen_width] + cmp eax,0 + jle hselection_start_line_ok + sub edi,eax + add ecx,eax + sub eax,[screen_width] + jle hselection_start_line_ok + add edi,eax + sub ecx,eax + hselection_start_line_ok: + cmp edx,0 + jle hselection_end_line_ok + add ecx,edx + sub edx,[screen_width] + jle hselection_end_line_ok + sub ecx,edx + hselection_end_line_ok: + mov al,80h + rep stosb + screen_prepared: + retn + prepare_line: + push edi ecx + mov ecx,[esp] + mov edi,[line_buffer] + add edi,ecx + shr ecx,2 + xor eax,eax + rep stosd + mov ecx,[esp] + sub edi,ecx + invoke syntax_proc,esi,ecx,edi + mov edx,edi + pop eax edi + push esi edx + mov edx,[window_position] + lea esi,[esi+edx] + sub eax,edx + jnc line_position_ok + xor eax,eax + jmp line_length_ok + line_position_ok: + cmp eax,[screen_width] + jbe line_length_ok + mov eax,[screen_width] + line_length_ok: + mov ecx,eax + rep movsb + pop esi + add esi,edx + mov ecx,eax + xchg edi,ebx + rep movsb + xchg edi,ebx + pop esi + cmp eax,[screen_width] + jb after_end_of_line + retn + after_end_of_line: + mov ecx,[screen_width] + sub ecx,eax + xor al,al + mov edx,ecx + rep stosb + xchg edi,ebx + mov ecx,edx + rep stosb + xchg edi,ebx + retn + +include '..\memory.inc' +include '..\navigate.inc' +include '..\edit.inc' +include '..\blocks.inc' +include '..\search.inc' +include '..\undo.inc' + +endp + +proc SyntaxProc lpLine,uChars,lpColors + ret +endp diff --git a/toolchain/fasm2/source/ide/windows/resource/assign.bmp b/toolchain/fasm2/source/ide/windows/resource/assign.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3680a6eb0013b741dd0ebf6a8955c71fc0b3f2a8 GIT binary patch literal 206 zcmZvUu@!(Y2t?2K>?~NrIqdBn!%9mTjR~A38{h#+XTseFE-%~uqRvIE)Y3I!&frM@ xGX+>sEzsFg3NvHiS#Xbz;*AyUj&lMJ2Tw||F^(CKA{Q}>L+X9&^ufr-e;;+)Jf#2t literal 0 HcmV?d00001 diff --git a/toolchain/fasm2/source/ide/windows/resource/fasmgw.ico b/toolchain/fasm2/source/ide/windows/resource/fasmgw.ico new file mode 100644 index 0000000000000000000000000000000000000000..b8a53c6bbf65d0cf9c02bf3f5b2b988de6bc3a68 GIT binary patch literal 766 zcmbtQF;2uV5S(0)>@HNa7m0=+P##aXr?}g6v1rcE%12HLRFqWYic^-^B&Wm@(6GsP zJu_bK%0R)duJ2*-u>&5MpNN`xAqw1a1tPtlBhsW3~XK&CuzGs_h7VCfV{! zoR7KjH;>5uoIB32^(E&{VujE~Q)W}LS^giYd)2X;@x}a3yb`-gM>xHr)Ck^91TePh9DZU}1+!d+d3^ffu!^9pCJY$m1KFoVy7C literal 0 HcmV?d00001 diff --git a/toolchain/fasm2/source/ide/windows/resource/fasmw.ico b/toolchain/fasm2/source/ide/windows/resource/fasmw.ico new file mode 100644 index 0000000000000000000000000000000000000000..f90f438ea5ab8128552ca93b2e3d0419f46195da GIT binary patch literal 766 zcmbtQF>Zt~5F8+q-H|HoA*IO=QXWrow{%!(&d=fj_Xv_IaF-HYJRYE?VF**me1Z>1Nxo&W#< literal 0 HcmV?d00001 diff --git a/toolchain/fasm2/source/libc/ccall.inc b/toolchain/fasm2/source/libc/ccall.inc new file mode 100644 index 0000000..4c8a0b7 --- /dev/null +++ b/toolchain/fasm2/source/libc/ccall.inc @@ -0,0 +1,23 @@ + +macro ccall proc*,[arg] +{ + common + local size,count + mov ebp,esp + if size + sub esp,size + end if + and esp,0FFFFFFF0h + count = 0 + if ~ arg eq + forward + mov dword [esp+count*4],arg + count = count + 1 + common + end if + size = count*4 + call proc + mov esp,ebp +} + +macro cinvoke proc*,arg& { ccall [proc],arg } diff --git a/toolchain/fasm2/source/libc/fasmg.asm b/toolchain/fasm2/source/libc/fasmg.asm new file mode 100644 index 0000000..b17cd65 --- /dev/null +++ b/toolchain/fasm2/source/libc/fasmg.asm @@ -0,0 +1,489 @@ + + format ELF + public main + +include '../version.inc' + +include 'macro/struct.inc' +include 'macro/proc32.inc' + +extrn 'malloc' as libc.malloc +extrn 'realloc' as libc.realloc +extrn 'free' as libc.free +extrn 'fopen' as libc.fopen +extrn 'fclose' as libc.fclose +extrn 'fread' as libc.fread +extrn 'fwrite' as libc.fwrite +extrn 'fseek' as libc.fseek +extrn 'ftell' as libc.ftell +extrn 'time' as libc.time +extrn 'write' as libc.write + +extrn getenv +extrn gettimeofday +extrn exit + +struct timeval + time_t dd ? + suseconds_t dd ? +ends + +section '.text' executable align 16 + + main: + mov ecx,[esp+4] + mov [argc],ecx + mov ebx,[esp+8] + mov [argv],ebx + + call system_init + + call get_arguments + mov bl,al + cmp [no_logo],0 + jne logo_ok + mov esi,_logo + xor ecx,ecx + call display_string + logo_ok: + test bl,bl + jnz display_usage_information + + xor al,al + mov ecx,[verbosity_level] + jecxz init + or al,TRACE_ERROR_STACK + dec ecx + jz init + or al,TRACE_DISPLAY + init: + call assembly_init + + ccall gettimeofday,start_time,0 + + assemble: + mov esi,[initial_commands] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,_code_cannot_be_generated + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + jmp assembly_failed + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + cmp [no_logo],0 + jne summary_done + mov eax,[current_pass] + xor edx,edx + call itoa + call display_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_string + ccall gettimeofday,end_time,0 + mov eax,[end_time.time_t] + sub eax,[start_time.time_t] + mov ecx,1000000 + mul ecx + add eax,[end_time.suseconds_t] + adc edx,0 + sub eax,[start_time.suseconds_t] + sbb edx,0 + add eax,50000 + mov ecx,1000000 + div ecx + mov ebx,eax + mov eax,edx + xor edx,edx + mov ecx,100000 + div ecx + mov [tenths_of_second],eax + xchg eax,ebx + or ebx,eax + jz display_output_length + xor edx,edx + call itoa + call display_string + mov esi,_message_suffix + mov ecx,1 + call display_string + mov eax,[tenths_of_second] + xor edx,edx + call itoa + call display_string + mov esi,_seconds + xor ecx,ecx + call display_string + display_output_length: + call get_output_length + push eax edx + call itoa + call display_string + pop edx eax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_string + mov esi,_new_line + xor ecx,ecx + call display_string + summary_done: + + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + call assembly_shutdown + call system_shutdown + + ccall exit,0 + + assembly_failed: + + call show_errors + + call assembly_shutdown + call system_shutdown + + ccall exit,2 + + write_failed: + mov ebx,_write_failed + jmp fatal_error + + out_of_memory: + mov ebx,_out_of_memory + jmp fatal_error + + fatal_error: + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + call assembly_shutdown + call system_shutdown + + ccall exit,3 + + display_usage_information: + + mov esi,_usage + xor ecx,ecx + call display_string + + call system_shutdown + + ccall exit,1 + + get_arguments: + xor eax,eax + mov [initial_commands],eax + mov [source_path],eax + mov [output_path],eax + mov [no_logo],al + mov [verbosity_level],eax + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1 + mov [maximum_depth_of_stack],10000 + mov ecx,[argc] + mov ebx,[argv] + add ebx,4 + dec ecx + jz error_in_arguments + get_argument: + mov esi,[ebx] + mov al,[esi] + cmp al,'-' + je get_option + cmp [source_path],0 + jne get_output_file + mov [source_path],esi + jmp next_argument + get_output_file: + cmp [output_path],0 + jne error_in_arguments + mov [output_path],esi + jmp next_argument + get_option: + inc esi + lodsb + cmp al,'e' + je set_errors_limit + cmp al,'E' + je set_errors_limit + cmp al,'i' + je insert_initial_command + cmp al,'I' + je insert_initial_command + cmp al,'p' + je set_passes_limit + cmp al,'P' + je set_passes_limit + cmp al,'r' + je set_recursion_limit + cmp al,'R' + je set_recursion_limit + cmp al,'v' + je set_verbose_mode + cmp al,'V' + je set_verbose_mode + cmp al,'n' + je set_no_logo + cmp al,'N' + jne error_in_arguments + set_no_logo: + or [no_logo],-1 + cmp byte [esi],0 + je next_argument + error_in_arguments: + or al,-1 + ret + set_verbose_mode: + cmp byte [esi],0 + jne get_verbose_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_verbose_setting: + call get_option_value + cmp edx,2 + ja error_in_arguments + mov [verbosity_level],edx + jmp next_argument + set_errors_limit: + cmp byte [esi],0 + jne get_errors_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_errors_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_errors],edx + jmp next_argument + set_recursion_limit: + cmp byte [esi],0 + jne get_recursion_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_recursion_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_depth_of_stack],edx + jmp next_argument + set_passes_limit: + cmp byte [esi],0 + jne get_passes_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_passes_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_passes],edx + next_argument: + add ebx,4 + dec ecx + jnz get_argument + cmp [source_path],0 + je error_in_arguments + xor al,al + ret + get_option_value: + xor eax,eax + mov edx,eax + find_option_value: + cmp byte [esi],20h + jne get_option_digit + inc esi + jmp find_option_value + get_option_digit: + lodsb + test al,al + jz option_value_ok + sub al,30h + jc invalid_option_value + cmp al,9 + ja invalid_option_value + imul edx,10 + jo invalid_option_value + add edx,eax + jc invalid_option_value + jmp get_option_digit + option_value_ok: + dec esi + clc + ret + invalid_option_value: + stc + ret + insert_initial_command: + cmp byte [esi],0 + jne measure_initial_command + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + measure_initial_command: + push ebx ecx edi + mov edi,esi + or ecx,-1 + xor al,al + repne scasb + not ecx + dec ecx + mov edi,[initial_commands] + lea eax,[ecx+2] + test edi,edi + jz allocate_initial_commands_buffer + mov edx,[initial_commands_length] + add edi,edx + add eax,edx + cmp eax,[initial_commands_maximum_length] + ja grow_initial_commands_buffer + copy_initial_command: + rep movsb + mov ax,0Ah + stosw + dec edi + sub edi,[initial_commands] + mov [initial_commands_length],edi + pop edi ecx ebx + jmp next_argument + allocate_initial_commands_buffer: + push ecx + mov ecx,eax + call malloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + pop ecx + jmp copy_initial_command + grow_initial_commands_buffer: + push ecx + mov ecx,eax + mov eax,[initial_commands] + call realloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + add edi,[initial_commands_length] + pop ecx + jmp copy_initial_command + + include 'system.inc' + + include '../assembler.inc' + include '../symbols.inc' + include '../expressions.inc' + include '../conditions.inc' + include '../floats.inc' + include '../directives.inc' + include '../calm.inc' + include '../errors.inc' + include '../map.inc' + include '../reader.inc' + include '../output.inc' + include '../console.inc' + +section '.data' + + _logo db 'flat assembler version g.',VERSION,10,0 + + _usage db 'Usage: fasmg source [output]',10 + db 'Optional settings:',10 + db ' -p limit Set the maximum allowed number of passes (default 100)',10 + db ' -e limit Set the maximum number of displayed errors (default 1)',10 + db ' -r limit Set the maximum depth of the stack (default 10000)',10 + db ' -v flag Enable or disable showing all lines from the stack (default 0)',10 + db ' -i command Insert instruction at the beginning of source',13,10 + db ' -n Do not show logo nor summary',13,10 + db 0 + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'failed to write the output file',0 + _out_of_memory db 'not enough memory to complete the assembly',0 + _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 + + _open_mode db 'r',0 + _create_mode db 'w',0 + + include '../tables.inc' + include '../messages.inc' + +section '.bss' writeable align 4 + + include '../variables.inc' + + source_path dd ? + output_path dd ? + maximum_number_of_passes dd ? + + initial_commands dd ? + initial_commands_length dd ? + initial_commands_maximum_length dd ? + + argc dd ? + argv dd ? + timestamp dq ? + + start_time timeval + end_time timeval + tenths_of_second dd ? + + verbosity_level dd ? + no_logo db ? + + path_buffer rb 1000h diff --git a/toolchain/fasm2/source/libc/selfhost.inc b/toolchain/fasm2/source/libc/selfhost.inc new file mode 100644 index 0000000..f624753 --- /dev/null +++ b/toolchain/fasm2/source/libc/selfhost.inc @@ -0,0 +1,60 @@ + +include '../../examples/x86/include/80386.inc' + +macro format?.ELF? variant + match , variant + format binary as 'o' + include '../../examples/x86/include/format/elf32.inc' + use32 + else match =executable? settings, variant: + match brand =at? base:, settings + ELF.Settings.ABI = brand + ELF.Settings.BaseAddress = base + else match =at? base:, settings + ELF.Settings.BaseAddress = base + else match brand:, settings + ELF.Settings.ABI = brand + end match + include '../../examples/x86/include/format/elfexe.inc' + use32 + else + err 'invalid argument' + end match +end macro + + +macro struct? name + macro ends?! + end namespace + esc end struc + virtual at 0 + name name + sizeof.name = $ + end virtual + purge ends? + end macro + esc struc name + label . : sizeof.name + namespace . +end macro + +macro ccall? proc*,args& + local size + mov ebp,esp + if size + sub esp,size + end if + and esp,0FFFFFFF0h + match any, args + iterate arg, args + mov dword [esp+(%-1)*4],arg + if % = 1 + size := %%*4 + end if + end iterate + else + size := 0 + end match + call proc + mov esp,ebp +end macro diff --git a/toolchain/fasm2/source/libc/struct.inc b/toolchain/fasm2/source/libc/struct.inc new file mode 100644 index 0000000..7b0cb60 --- /dev/null +++ b/toolchain/fasm2/source/libc/struct.inc @@ -0,0 +1,17 @@ + +macro struct name* +{ + local body + define body struc name \{ + irp d, db,rb,dw,rw,dd,rd,dq,rq \{ struc d value& \\{ define body \\\.\\#. d value \\} \} + macro ends + \{ + define body \\} + irp d, db,rb,dw,rw,dd,rd,dq,rq \\{ restruc d \\} + irpv line, body \\{ line \\} + virtual at 0 + name name + sizeof.#name = $ + end virtual + \} +} diff --git a/toolchain/fasm2/source/libc/system.inc b/toolchain/fasm2/source/libc/system.inc new file mode 100644 index 0000000..0461692 --- /dev/null +++ b/toolchain/fasm2/source/libc/system.inc @@ -0,0 +1,225 @@ + +LINE_FEED = 0Ah + +system_init: + ccall libc.time,timestamp + retn + +system_shutdown: + retn + +malloc: +malloc_fixed: +malloc_growable: +; in: ecx = requested size +; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi +; note: +; use of malloc_fixed hints that block will be kept as is until the end of assembly +; use of malloc_growable hints that block is likely to be resized + push ebx ecx esi edi + ccall libc.malloc,ecx + pop edi esi ecx ebx + test eax,eax + jz out_of_memory + retn +realloc: +; in: eax - memory block, ecx = requested size +; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi + push ebx ecx esi edi + ccall libc.realloc,eax,ecx + pop edi esi ecx ebx + test eax,eax + jz out_of_memory + retn +mfree: +; in: eax - memory block +; out: cf set on error +; preserves: ebx, esi, edi +; note: eax may have value 0 or -1, it should be treated as invalid input then + test eax,eax + jz interface_error + cmp eax,-1 + je interface_error + push ebx esi edi + ccall libc.free,eax + pop edi esi ebx + clc + retn + interface_error: + stc + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push esi edi + call adapt_path + ccall libc.fopen,ebx,_open_mode + pop edi esi + test eax,eax + jz interface_error + mov ebx,eax + clc + retn + adapt_path: + xor ecx,ecx + mov ebx,path_buffer + copy_path: + mov al,[edx+ecx] + cmp al,'\' + jne path_char_ok + mov al,'/' + path_char_ok: + cmp ecx,1000h + jae out_of_memory + mov [ebx+ecx],al + inc ecx + test al,al + jnz copy_path + retn +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push esi edi + call adapt_path + ccall libc.fopen,ebx,_create_mode + pop edi esi + test eax,eax + jz interface_error + mov ebx,eax + clc + retn +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ebx ecx esi edi + ccall libc.fwrite,edx,1,ecx,ebx + pop edi esi ecx ebx + cmp eax,ecx + jne interface_error + clc + ret +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ebx ecx esi edi + ccall libc.fread,edx,1,ecx,ebx + pop edi esi ecx ebx + cmp eax,ecx + jne interface_error + clc + ret +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + ccall libc.fclose,ebx + ret +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + test edx,edx + jnz interface_error + push esi edi ebx + movzx ecx,cl + ccall libc.fseek,ebx,eax,ecx + test eax,eax + jnz lseek_error + mov ebx,[esp] + ccall libc.ftell,ebx + cmp eax,-1 + je lseek_error + xor edx,edx + pop ebx edi esi + clc + ret + lseek_error: + pop ebx edi esi + stc + ret + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx esi + test ecx,ecx + jnz write_string_to_stdout + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stdout: + ccall libc.write,1,esi,ecx + pop esi ebx + retn + +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx esi + test ecx,ecx + jnz write_string_to_stderr + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stderr: + ccall libc.write,2,esi,ecx + pop esi ebx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push ebx ecx esi edi + ccall getenv,esi + pop edi esi ecx ebx + test eax,eax + jz no_environment_variable + push esi + mov esi,eax + xor eax,eax + copy_environment_variable: + mov dl,[esi+eax] + cmp eax,ecx + jae next_environment_variable_character + mov [edi+eax],dl + next_environment_variable_character: + inc eax + test dl,dl + jnz copy_environment_variable + pop esi + environment_variable_ok: + ret + no_environment_variable: + mov eax,1 + jecxz environment_variable_ok + and byte [edi],0 + ret diff --git a/toolchain/fasm2/source/linux/fasmg.asm b/toolchain/fasm2/source/linux/fasmg.asm new file mode 100644 index 0000000..464a34c --- /dev/null +++ b/toolchain/fasm2/source/linux/fasmg.asm @@ -0,0 +1,503 @@ + +include 'macro/struct.inc' + +format ELF executable 3 +entry start + +include '../version.inc' + +struct timeval + time_t dd ? + suseconds_t dd ? +ends + +segment readable executable + + start: + + mov ecx,[esp] + mov [argc],ecx + lea ebx,[esp+4] + mov [argv],ebx + lea esi,[esp+4+ecx*4+4] + mov [env],esi + + call system_init + + call get_arguments + mov bl,al + cmp [no_logo],0 + jne logo_ok + mov esi,_logo + xor ecx,ecx + call display_string + logo_ok: + test bl,bl + jnz display_usage_information + + xor al,al + mov ecx,[verbosity_level] + jecxz init + or al,TRACE_ERROR_STACK + dec ecx + jz init + or al,TRACE_DISPLAY + init: + call assembly_init + + mov eax,78 ; sys_gettimeofday + mov ebx,start_time + xor ecx,ecx + int 0x80 + + assemble: + mov esi,[initial_commands] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,_code_cannot_be_generated + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + jmp assembly_failed + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + cmp [no_logo],0 + jne summary_done + mov eax,[current_pass] + xor edx,edx + call itoa + call display_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_string + mov eax,78 ; sys_gettimeofday + mov ebx,end_time + xor ecx,ecx + int 0x80 + mov eax,[end_time.time_t] + sub eax,[start_time.time_t] + mov ecx,1000000 + mul ecx + add eax,[end_time.suseconds_t] + adc edx,0 + sub eax,[start_time.suseconds_t] + sbb edx,0 + add eax,50000 + mov ecx,1000000 + div ecx + mov ebx,eax + mov eax,edx + xor edx,edx + mov ecx,100000 + div ecx + mov [tenths_of_second],eax + xchg eax,ebx + or ebx,eax + jz display_output_length + xor edx,edx + call itoa + call display_string + mov esi,_message_suffix + mov ecx,1 + call display_string + mov eax,[tenths_of_second] + xor edx,edx + call itoa + call display_string + mov esi,_seconds + xor ecx,ecx + call display_string + display_output_length: + call get_output_length + push eax edx + call itoa + call display_string + pop edx eax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_string + mov esi,_new_line + xor ecx,ecx + call display_string + summary_done: + + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + call assembly_shutdown + call system_shutdown + + xor ebx,ebx + mov eax,1 ; sys_exit + int 0x80 + + assembly_failed: + + call show_errors + + call assembly_shutdown + call system_shutdown + + mov ebx,2 + mov eax,1 ; sys_exit + int 0x80 + + write_failed: + mov ebx,_write_failed + jmp fatal_error + + out_of_memory: + mov ebx,_out_of_memory + jmp fatal_error + + fatal_error: + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + call assembly_shutdown + call system_shutdown + + mov ebx,3 + mov eax,1 ; sys_exit + int 0x80 + + display_usage_information: + + mov esi,_usage + xor ecx,ecx + call display_string + + call system_shutdown + + mov ebx,1 + mov eax,1 ; sys_exit + int 0x80 + + get_arguments: + xor eax,eax + mov [initial_commands],eax + mov [source_path],eax + mov [output_path],eax + mov [no_logo],al + mov [verbosity_level],eax + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1 + mov [maximum_depth_of_stack],10000 + mov ecx,[argc] + mov ebx,[argv] + add ebx,4 + dec ecx + jz error_in_arguments + get_argument: + mov esi,[ebx] + mov al,[esi] + cmp al,'-' + je get_option + cmp [source_path],0 + jne get_output_file + mov [source_path],esi + jmp next_argument + get_output_file: + cmp [output_path],0 + jne error_in_arguments + mov [output_path],esi + jmp next_argument + get_option: + inc esi + lodsb + cmp al,'e' + je set_errors_limit + cmp al,'E' + je set_errors_limit + cmp al,'i' + je insert_initial_command + cmp al,'I' + je insert_initial_command + cmp al,'p' + je set_passes_limit + cmp al,'P' + je set_passes_limit + cmp al,'r' + je set_recursion_limit + cmp al,'R' + je set_recursion_limit + cmp al,'v' + je set_verbose_mode + cmp al,'V' + je set_verbose_mode + cmp al,'n' + je set_no_logo + cmp al,'N' + jne error_in_arguments + set_no_logo: + or [no_logo],-1 + cmp byte [esi],0 + je next_argument + error_in_arguments: + or al,-1 + ret + set_verbose_mode: + cmp byte [esi],0 + jne get_verbose_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_verbose_setting: + call get_option_value + cmp edx,2 + ja error_in_arguments + mov [verbosity_level],edx + jmp next_argument + set_errors_limit: + cmp byte [esi],0 + jne get_errors_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_errors_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_errors],edx + jmp next_argument + set_recursion_limit: + cmp byte [esi],0 + jne get_recursion_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_recursion_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_depth_of_stack],edx + jmp next_argument + set_passes_limit: + cmp byte [esi],0 + jne get_passes_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_passes_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_passes],edx + next_argument: + add ebx,4 + dec ecx + jnz get_argument + cmp [source_path],0 + je error_in_arguments + xor al,al + ret + get_option_value: + xor eax,eax + mov edx,eax + find_option_value: + cmp byte [esi],20h + jne get_option_digit + inc esi + jmp find_option_value + get_option_digit: + lodsb + test al,al + jz option_value_ok + sub al,30h + jc invalid_option_value + cmp al,9 + ja invalid_option_value + imul edx,10 + jo invalid_option_value + add edx,eax + jc invalid_option_value + jmp get_option_digit + option_value_ok: + dec esi + clc + ret + invalid_option_value: + stc + ret + insert_initial_command: + cmp byte [esi],0 + jne measure_initial_command + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + measure_initial_command: + push ebx ecx edi + mov edi,esi + or ecx,-1 + xor al,al + repne scasb + not ecx + dec ecx + mov edi,[initial_commands] + lea eax,[ecx+2] + test edi,edi + jz allocate_initial_commands_buffer + mov edx,[initial_commands_length] + add edi,edx + add eax,edx + cmp eax,[initial_commands_maximum_length] + ja grow_initial_commands_buffer + copy_initial_command: + rep movsb + mov ax,0Ah + stosw + dec edi + sub edi,[initial_commands] + mov [initial_commands_length],edi + pop edi ecx ebx + jmp next_argument + allocate_initial_commands_buffer: + push ecx + mov ecx,eax + call malloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + pop ecx + jmp copy_initial_command + grow_initial_commands_buffer: + push ecx + mov ecx,eax + mov eax,[initial_commands] + call realloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + add edi,[initial_commands_length] + pop ecx + jmp copy_initial_command + + include 'system.inc' + + include '../malloc.inc' + include '../assembler.inc' + include '../symbols.inc' + include '../expressions.inc' + include '../conditions.inc' + include '../floats.inc' + include '../directives.inc' + include '../calm.inc' + include '../errors.inc' + include '../map.inc' + include '../reader.inc' + include '../output.inc' + include '../console.inc' + +segment readable + + _logo db 'flat assembler version g.',VERSION,10,0 + + _usage db 'Usage: fasmg source [output]',10 + db 'Optional settings:',10 + db ' -p limit Set the maximum allowed number of passes (default 100)',10 + db ' -e limit Set the maximum number of displayed errors (default 1)',10 + db ' -r limit Set the maximum depth of the stack (default 10000)',10 + db ' -v flag Enable or disable showing all lines from the stack (default 0)',10 + db ' -i command Insert instruction at the beginning of source',13,10 + db ' -n Do not show logo nor summary',13,10 + db 0 + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'failed to write the output file',0 + _out_of_memory db 'not enough memory to complete the assembly',0 + _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 + + _open_mode db 'r',0 + _create_mode db 'w',0 + + include '../tables.inc' + include '../messages.inc' + +segment readable writeable + + align 16 + + include '../variables.inc' + + align 16 + + timestamp dq ? + + loff dq ? + argc dd ? + argv dd ? + env dd ? + + mmap_args rd 6 + malloc_freelist dd ? + + source_path dd ? + output_path dd ? + maximum_number_of_passes dd ? + + initial_commands dd ? + initial_commands_length dd ? + initial_commands_maximum_length dd ? + + + start_time timeval + end_time timeval + tenths_of_second dd ? + + verbosity_level dd ? + no_logo db ? + + path_buffer rb 1000h + +segment readable writeable gnustack diff --git a/toolchain/fasm2/source/linux/system.inc b/toolchain/fasm2/source/linux/system.inc new file mode 100644 index 0000000..d1b0847 --- /dev/null +++ b/toolchain/fasm2/source/linux/system.inc @@ -0,0 +1,298 @@ + +LINE_FEED = 0Ah + +O_ACCMODE = 0003o +O_RDONLY = 0000o +O_WRONLY = 0001o +O_RDWR = 0002o +O_CREAT = 0100o +O_EXCL = 0200o +O_NOCTTY = 0400o +O_TRUNC = 1000o +O_APPEND = 2000o +O_NONBLOCK = 4000o + +S_ISUID = 4000o +S_ISGID = 2000o +S_ISVTX = 1000o +S_IRUSR = 0400o +S_IWUSR = 0200o +S_IXUSR = 0100o +S_IRGRP = 0040o +S_IWGRP = 0020o +S_IXGRP = 0010o +S_IROTH = 0004o +S_IWOTH = 0002o +S_IXOTH = 0001o + +system_init: + mov eax,13 ; sys_time + mov ebx,timestamp + int 0x80 + retn + +system_shutdown: + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push esi edi ebp + call adapt_path + mov eax,5 ; sys_open + mov ecx,O_RDONLY + xor edx,edx + int 0x80 + pop ebp edi esi + test eax,eax + js interface_error + mov ebx,eax + clc + retn + adapt_path: + xor ecx,ecx + mov ebx,path_buffer + copy_path: + mov al,[edx+ecx] + cmp al,'\' + jne path_char_ok + mov al,'/' + path_char_ok: + cmp ecx,1000h + jae out_of_memory + mov [ebx+ecx],al + inc ecx + test al,al + jnz copy_path + retn + interface_error: + stc + retn +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push esi edi ebp + call adapt_path + mov eax,5 ; sys_open + mov ecx,O_CREAT+O_TRUNC+O_WRONLY + mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH + int 0x80 + pop ebp edi esi + test eax,eax + js interface_error + mov ebx,eax + clc + retn +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ebx ecx esi edi ebp + mov eax,4 ; sys_write + xchg ecx,edx + int 0x80 + pop ebp edi esi ecx ebx + test eax,eax + js interface_error + cmp eax,ecx + jne interface_error + clc + ret +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ebx ecx esi edi ebp + mov eax,3 ; sys_read + xchg ecx,edx + int 0x80 + pop ebp edi esi ecx ebx + test eax,eax + js interface_error + cmp eax,ecx + jne interface_error + clc + ret +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + push ebx esi edi ebp + mov eax,6 ; sys_close + int 0x80 + pop ebp edi esi ebx + ret +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + test edx,edx + jnz interface_error + push esi edi ebx ebp + movzx edi,cl + mov ecx,edx + mov edx,eax + mov eax,140 ; sys_llseek + mov esi,loff + int 0x80 + pop ebp ebx edi esi + test eax,eax + js interface_error + mov eax,dword [loff] + mov edx,dword [loff+4] + clc + ret + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx esi ebp + test ecx,ecx + jnz write_string_to_stdout + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stdout: + mov eax,4 ; sys_write + mov ebx,1 + mov edx,ecx + mov ecx,esi + int 0x80 + pop ebp esi ebx + retn + +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx esi ebp + test ecx,ecx + jnz write_string_to_stderr + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stderr: + mov eax,4 ; sys_write + mov ebx,2 + mov edx,ecx + mov ecx,esi + int 0x80 + pop ebp esi ebx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push ebx ecx + mov edx,[env] + scan_environment: + mov ebx,[edx] + test ebx,ebx + jz no_environment_variable + xor ecx,ecx + compare_character: + mov al,[ebx+ecx] + mov ah,[esi+ecx] + inc ecx + cmp al,'=' + je end_of_variable_name + test ah,ah + jz next_variable + sub ah,al + je compare_character + cmp ah,20h + jne next_variable + cmp al,'A' + jb next_variable + cmp al,'Z' + jna compare_character + next_variable: + add edx,4 + jmp scan_environment + end_of_variable_name: + test ah,ah + jnz next_variable + add ebx,ecx + pop ecx + xor eax,eax + copy_environment_variable: + mov dl,[ebx+eax] + cmp eax,ecx + jae next_environment_variable_character + mov [edi+eax],dl + next_environment_variable_character: + inc eax + test dl,dl + jnz copy_environment_variable + environment_variable_ok: + pop ebx + ret + no_environment_variable: + pop ecx + mov eax,1 + jecxz environment_variable_ok + and byte [edi],0 + pop ebx + ret + +VALLOC_MINIMUM_SIZE = 100000h + +valloc: +; in: ecx = requested minimum size +; out: eax - allocated block, ecx = allocated size, zero if failed +; preserves: ebx, esi, edi + cmp ecx,VALLOC_MINIMUM_SIZE + jbe valloc_size_minimum + dec ecx + and ecx,(-1) shl 12 + add ecx,1 shl 12 + jmp valloc_size_ready + valloc_size_minimum: + mov ecx,VALLOC_MINIMUM_SIZE + valloc_size_ready: + push ebx edi + mov ebx,mmap_args + mov edi,ebx + xor eax,eax + stosd + mov eax,ecx + stosd + mov eax,3 ; PROT_READ + PROT_WRITE + stosd + mov eax,22h ; MAP_PRIVATE + MAP_ANONYMOUS + stosd + or eax,-1 + stosd + xor eax,eax + stosd + mov eax,0x5A ; old_mmap + int 0x80 + cmp eax,-1 + jne valloc_ok + xor ecx,ecx + valloc_ok: + pop edi ebx + retn diff --git a/toolchain/fasm2/source/linux/x64/32on64.alm b/toolchain/fasm2/source/linux/x64/32on64.alm new file mode 100644 index 0000000..1b09131 --- /dev/null +++ b/toolchain/fasm2/source/linux/x64/32on64.alm @@ -0,0 +1,79 @@ + +macro use32on64? + + define esp rsp + + define promote + + iterate , eax,rax, ebx,rbx, ecx,rcx, edx,rdx, esi,rsi, edi,rdi, esp,rsp, ebp,rbp + promote.reg32? equ reg64 + end iterate + + iterate instr, jmp,call + calminstruction instr? arg + local tmp + match [tmp], arg + jyes zero_extend + transform arg, promote + arrange tmp, =instr arg + assemble tmp + exit + zero_extend: + arrange tmp, =mov =r8d,[tmp] + assemble tmp + arrange tmp, =instr =r8 + assemble tmp + end calminstruction + end iterate + + calminstruction push? arg + local car, cdr + match car cdr?, arg + loop: + transform car, promote + jno non_reg + arrange car, =push car + assemble car + match car cdr?, cdr + jyes loop + exit + non_reg: + arrange tmp, =mov =r8d,arg + assemble tmp + arrange tmp, =push =r8 + assemble tmp + exit + end calminstruction + + calminstruction pop? arg + local car, cdr + match car cdr?, arg + loop: + transform car, promote + jno non_reg + arrange car, =pop car + assemble car + match car cdr?, cdr + jyes loop + exit + non_reg: + arrange tmp, =pop =r8 + assemble tmp + arrange tmp, =mov arg,=r8d + assemble tmp + exit + end calminstruction + + macro jecxz? target + if target-($+1) < 80h & target-($+1) >= -80h + jecxz target + else + local j,k + jecxz j + jmp k + j: jmp target + k: + end if + end macro + +end macro diff --git a/toolchain/fasm2/source/linux/x64/32on64.inc b/toolchain/fasm2/source/linux/x64/32on64.inc new file mode 100644 index 0000000..898d23e --- /dev/null +++ b/toolchain/fasm2/source/linux/x64/32on64.inc @@ -0,0 +1,124 @@ + +macro use32on64 +{ + + define esp rsp + + define promote.eax rax + define promote.ebx rbx + define promote.ecx rcx + define promote.edx rdx + define promote.esi rsi + define promote.edi rdi + define promote.ebp rbp + define promote.esp rsp + + macro push args + \{ + local list,arg,status + define list + define arg + irps sym, args \\{ + define status + match =dword, sym \\\{ + define status : + \\\} + match [any, status arg sym \\\{ + define arg [any + match [mem], arg \\\\{ + match previous, list \\\\\{ define list previous,[mem] \\\\\} + match , list \\\\\{ define list [mem] \\\\\} + define arg + \\\\} + define status : + \\\} + match [, status arg sym \\\{ + define arg [ + define status : + \\\} + match , status \\\{ + match previous, list \\\\{ define list previous,sym \\\\} + match , list \\\\{ define list sym \\\\} + \\\} + \\} + match ops,list \\{ + irp op, ops \\\{ + if op eqtype eax + push promote.\\\#op + else + mov r8d,op + push r8 + end if + \\\} + \\} + \} + + macro pop args + \{ + local list,arg,status + define list + define arg + irps sym, args \\{ + define status + match =dword, sym \\\{ + define status : + \\\} + match [any, status arg sym \\\{ + define arg [any + match [mem], arg \\\\{ + match previous, list \\\\\{ define list previous,[mem] \\\\\} + match , list \\\\\{ define list [mem] \\\\\} + define arg + \\\\} + define status : + \\\} + match [, status arg sym \\\{ + define arg [ + define status : + \\\} + match , status \\\{ + match previous, list \\\\{ define list previous,sym \\\\} + match , list \\\\{ define list sym \\\\} + \\\} + \\} + match ops,list \\{ + irp op, ops \\\{ + if op eqtype eax + pop promote.\\\#op + else + pop r8 + mov op,r8d + end if + \\\} + \\} + \} + + irp instr, jmp,call + \{ + macro instr op + \\{ + if op eqtype [0] + mov r8d,op + instr r8 + else if op eqtype 0 + instr op + else + instr promote.\\#op + end if + \\} + \} + + macro jecxz target + \{ + if target-($+1) < 80h & target-($+1) >= -80h + jecxz target + else + local j,k + jecxz j + jmp k + j: jmp target + k: + end if + \} + +} diff --git a/toolchain/fasm2/source/linux/x64/fasmg.asm b/toolchain/fasm2/source/linux/x64/fasmg.asm new file mode 100644 index 0000000..dd86212 --- /dev/null +++ b/toolchain/fasm2/source/linux/x64/fasmg.asm @@ -0,0 +1,546 @@ + +match ,{ + + include '32on64.inc' + +} match -,{ +else + + include '32on64.alm' + +end match +_ equ } + +include 'macro/struct.inc' + +format ELF64 executable 3 +entry start + +include '../../version.inc' + +struct timeval + time_t dq ? + suseconds_t dq ? +ends + +segment readable executable + + start: + + mov rcx,[rsp] + mov [argc],rcx + lea rbx,[rsp+8] + mov [argv],rbx + lea rsi,[rsp+8+rcx*8+8] + mov [env],rsi + + call system_init + + call get_arguments + mov bl,al + cmp [no_logo],0 + jne logo_ok + mov esi,_logo + xor ecx,ecx + call display_string + logo_ok: + test bl,bl + jnz display_usage_information + + xor al,al + mov ecx,[verbosity_level] + jecxz init + or al,TRACE_ERROR_STACK + dec ecx + jz init + or al,TRACE_DISPLAY + init: + call assembly_init + + mov eax,96 ; sys_gettimeofday + mov edi,start_time + xor esi,esi + syscall + + assemble: + mov esi,[initial_commands] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,_code_cannot_be_generated + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + jmp assembly_failed + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + cmp [no_logo],0 + jne summary_done + mov eax,[current_pass] + xor edx,edx + call itoa + call display_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_string + mov eax,96 ; sys_gettimeofday + mov edi,end_time + xor esi,esi + syscall + mov rax,[end_time.time_t] + sub rax,[start_time.time_t] + mov rcx,1000000 + mul rcx + add rax,[end_time.suseconds_t] + adc rdx,0 + sub rax,[start_time.suseconds_t] + sbb rdx,0 + add rax,50000 + mov rcx,1000000 + div rcx + mov rbx,rax + mov rax,rdx + xor rdx,rdx + mov rcx,100000 + div rcx + mov [tenths_of_second],eax + xchg rax,rbx + or rbx,rax + jz display_output_length + mov rdx,rax + shr rdx,32 + call itoa + call display_string + mov esi,_message_suffix + mov ecx,1 + call display_string + mov eax,[tenths_of_second] + xor edx,edx + call itoa + call display_string + mov esi,_seconds + xor ecx,ecx + call display_string + display_output_length: + call get_output_length + push rax rdx + call itoa + call display_string + pop rdx rax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_string + mov esi,_new_line + xor ecx,ecx + call display_string + summary_done: + + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + call assembly_shutdown + call system_shutdown + + xor edi,edi ; exit code 0 + mov eax,60 ; sys_exit + syscall + + assembly_failed: + + call show_errors + + call assembly_shutdown + call system_shutdown + + mov edi,2 + mov eax,60 ; sys_exit + syscall + + write_failed: + mov ebx,_write_failed + jmp fatal_error + + out_of_memory: + mov ebx,_out_of_memory + jmp fatal_error + + fatal_error: + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + call assembly_shutdown + call system_shutdown + + mov edi,3 + mov eax,60 ; sys_exit + syscall + + internal_error: + int3 + + display_usage_information: + + mov esi,_usage + xor ecx,ecx + call display_string + + call system_shutdown + + mov edi,1 + mov eax,60 ; sys_exit + syscall + + get_arguments: + xor eax,eax + mov [initial_commands],eax + mov [source_path],eax + mov [output_path],eax + mov [no_logo],al + mov [verbosity_level],eax + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1 + mov [maximum_depth_of_stack],10000 + mov rcx,[argc] + mov rbx,[argv] + add rbx,8 + dec ecx + jz error_in_arguments + get_argument: + mov rsi,[rbx] + mov al,[rsi] + cmp al,'-' + je get_option + cmp [source_path],0 + jne get_output_file + call strdup + mov [source_path],eax + jmp next_argument + get_output_file: + cmp [output_path],0 + jne error_in_arguments + call strdup + mov [output_path],eax + jmp next_argument + get_option: + inc rsi + lodsb + cmp al,'e' + je set_errors_limit + cmp al,'E' + je set_errors_limit + cmp al,'i' + je insert_initial_command + cmp al,'I' + je insert_initial_command + cmp al,'p' + je set_passes_limit + cmp al,'P' + je set_passes_limit + cmp al,'r' + je set_recursion_limit + cmp al,'R' + je set_recursion_limit + cmp al,'v' + je set_verbose_mode + cmp al,'V' + je set_verbose_mode + cmp al,'n' + je set_no_logo + cmp al,'N' + jne error_in_arguments + set_no_logo: + or [no_logo],-1 + cmp byte [rsi],0 + je next_argument + error_in_arguments: + or al,-1 + ret + set_verbose_mode: + cmp byte [rsi],0 + jne get_verbose_setting + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + get_verbose_setting: + call get_option_value + cmp edx,2 + ja error_in_arguments + mov [verbosity_level],edx + jmp next_argument + set_errors_limit: + cmp byte [rsi],0 + jne get_errors_setting + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + get_errors_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_errors],edx + jmp next_argument + set_recursion_limit: + cmp byte [rsi],0 + jne get_recursion_setting + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + get_recursion_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_depth_of_stack],edx + jmp next_argument + set_passes_limit: + cmp byte [rsi],0 + jne get_passes_setting + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + get_passes_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_passes],edx + next_argument: + add rbx,8 + dec ecx + jnz get_argument + cmp [source_path],0 + je error_in_arguments + xor al,al + ret + get_option_value: + xor eax,eax + mov edx,eax + find_option_value: + cmp byte [rsi],20h + jne get_option_digit + inc rsi + jmp find_option_value + get_option_digit: + lodsb + test al,al + jz option_value_ok + sub al,30h + jc invalid_option_value + cmp al,9 + ja invalid_option_value + imul edx,10 + jo invalid_option_value + add edx,eax + jc invalid_option_value + jmp get_option_digit + option_value_ok: + dec rsi + clc + ret + invalid_option_value: + stc + ret + insert_initial_command: + cmp byte [rsi],0 + jne measure_initial_command + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + measure_initial_command: + push rbx rcx rdi + mov rdi,rsi + or ecx,-1 + xor al,al + repne scasb + not ecx + dec ecx + mov edi,[initial_commands] + lea eax,[ecx+2] + test edi,edi + jz allocate_initial_commands_buffer + mov edx,[initial_commands_length] + add edi,edx + add eax,edx + cmp eax,[initial_commands_maximum_length] + ja grow_initial_commands_buffer + copy_initial_command: + rep movsb + mov ax,0Ah + stosw + dec edi + sub edi,[initial_commands] + mov [initial_commands_length],edi + pop rdi rcx rbx + jmp next_argument + allocate_initial_commands_buffer: + push rsi rcx + mov ecx,eax + call malloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + pop rcx rsi + jmp copy_initial_command + grow_initial_commands_buffer: + push rsi rcx + mov ecx,eax + mov eax,[initial_commands] + call realloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + add edi,[initial_commands_length] + pop rcx rsi + jmp copy_initial_command + + strdup: + ; in: rsi - ASCIIZ string + ; out: eax - copy of the string in 32-bit addressable memory + ; preserves: rbx, rcx, rsi + push rbx rcx rsi + mov rdi,rsi + or ecx,-1 + xor al,al + repne scasb + not ecx + push rsi rcx + call malloc + pop rcx rsi + mov edi,eax + rep movsb + pop rsi rcx rbx + ret + + include 'system.inc' + + use32on64 + + include '../../malloc.inc' + include '../../assembler.inc' + include '../../symbols.inc' + include '../../expressions.inc' + include '../../conditions.inc' + include '../../floats.inc' + include '../../directives.inc' + include '../../calm.inc' + include '../../errors.inc' + include '../../map.inc' + include '../../reader.inc' + include '../../output.inc' + include '../../console.inc' + +segment readable + + _logo db 'flat assembler version g.',VERSION,10,0 + + _usage db 'Usage: fasmg source [output]',10 + db 'Optional settings:',10 + db ' -p limit Set the maximum allowed number of passes (default 100)',10 + db ' -e limit Set the maximum number of displayed errors (default 1)',10 + db ' -r limit Set the maximum depth of the stack (default 10000)',10 + db ' -v flag Enable or disable showing all lines from the stack (default 0)',10 + db ' -i command Insert instruction at the beginning of source',13,10 + db ' -n Do not show logo nor summary',13,10 + db 0 + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'failed to write the output file',0 + _out_of_memory db 'not enough memory to complete the assembly',0 + _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 + + include '../../tables.inc' + include '../../messages.inc' + +segment readable writeable + + align 16 + + include '../../variables.inc' + + align 16 + + timestamp dq ? + + argc dq ? + argv dq ? + env dq ? + + mmap_hint dd ? + malloc_freelist dd ? + + source_path dd ? + output_path dd ? + maximum_number_of_passes dd ? + + initial_commands dd ? + initial_commands_length dd ? + initial_commands_maximum_length dd ? + + start_time timeval + end_time timeval + tenths_of_second dd ? + + verbosity_level dd ? + no_logo db ? + + local_heap_available db ? + + path_buffer rb 1000h + +segment readable writeable + + align 1000h + + LOCAL_HEAP_SIZE = 1000000h + + local_heap rb LOCAL_HEAP_SIZE + +segment readable writeable gnustack diff --git a/toolchain/fasm2/source/linux/x64/system.inc b/toolchain/fasm2/source/linux/x64/system.inc new file mode 100644 index 0000000..053d313 --- /dev/null +++ b/toolchain/fasm2/source/linux/x64/system.inc @@ -0,0 +1,334 @@ + +LINE_FEED = 0Ah + +O_ACCMODE = 0003o +O_RDONLY = 0000o +O_WRONLY = 0001o +O_RDWR = 0002o +O_CREAT = 0100o +O_EXCL = 0200o +O_NOCTTY = 0400o +O_TRUNC = 1000o +O_APPEND = 2000o +O_NONBLOCK = 4000o + +S_ISUID = 4000o +S_ISGID = 2000o +S_ISVTX = 1000o +S_IRUSR = 0400o +S_IWUSR = 0200o +S_IXUSR = 0100o +S_IRGRP = 0040o +S_IWGRP = 0020o +S_IXGRP = 0010o +S_IROTH = 0004o +S_IWOTH = 0002o +S_IXOTH = 0001o + +system_init: + mov eax,201 ; sys_time + mov edi,timestamp + syscall + or [local_heap_available],1 + retn + +system_shutdown: + call mcheck + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push rsi rdi + call adapt_path + mov eax,2 ; sys_open + mov esi,O_RDONLY + xor edx,edx + syscall + pop rdi rsi + test eax,eax + js interface_error + mov ebx,eax + clc + ret + interface_error: + stc + ret + adapt_path: + xor ecx,ecx + mov edi,path_buffer + copy_path: + mov al,[edx+ecx] + cmp al,'\' + jne path_char_ok + mov al,'/' + path_char_ok: + cmp ecx,1000h + jae out_of_memory + mov [edi+ecx],al + inc ecx + test al,al + jnz copy_path + retn +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push rsi rdi + call adapt_path + mov esi,O_CREAT+O_TRUNC+O_WRONLY + mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH + mov eax,2 ; sys_open + syscall + pop rdi rsi + test eax,eax + js interface_error + mov ebx,eax + clc + retn +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push rsi rdi + mov eax,1 ; sys_write + mov edi,ebx + mov esi,edx + mov edx,ecx + syscall + pop rdi rsi + test eax,eax + js interface_error + cmp eax,edx + jne interface_error + clc + ret +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push rsi rdi + mov eax,0 ; sys_read + mov edi,ebx + mov esi,edx + mov edx,ecx + syscall + pop rdi rsi + test eax,eax + js interface_error + cmp eax,edx + jne interface_error + clc + ret +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + push rdi + mov edi,ebx + mov eax,3 ; sys_close + syscall + pop rdi + ret +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + push rsi rdi + mov edi,ebx + mov esi,edx + mov eax,eax + shl rsi,32 + or rsi,rax + xor edx,edx + mov dl,cl + mov eax,8 ; sys_lseek + syscall + pop rdi rsi + cmp rax,-1 + je interface_error + mov rdx,rax + shr rdx,32 + clc + ret + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push rbx rsi rbp + test ecx,ecx + jnz write_string_to_stdout + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stdout: + mov eax,1 ; sys_write + mov edi,1 + mov edx,ecx + syscall + pop rbp rsi rbx + retn + +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push rbx rsi rbp + test ecx,ecx + jnz write_string_to_stderr + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stderr: + mov eax,1 ; sys_write + mov edi,2 + mov edx,ecx + syscall + pop rbp rsi rbx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push rbx rcx + mov rdx,[env] + scan_environment: + mov rbx,[rdx] + test rbx,rbx + jz no_environment_variable + xor ecx,ecx + compare_character: + mov al,[rbx+rcx] + mov ah,[esi+ecx] + inc ecx + cmp al,'=' + je end_of_variable_name + test ah,ah + jz next_variable + sub ah,al + je compare_character + cmp ah,20h + jne next_variable + cmp al,'A' + jb next_variable + cmp al,'Z' + jna compare_character + next_variable: + add rdx,8 + jmp scan_environment + end_of_variable_name: + test ah,ah + jnz next_variable + add rbx,rcx + pop rcx + xor eax,eax + copy_environment_variable: + mov dl,[rbx+rax] + cmp eax,ecx + jae next_environment_variable_character + mov [edi+eax],dl + next_environment_variable_character: + inc eax + test dl,dl + jnz copy_environment_variable + environment_variable_ok: + pop rbx + ret + no_environment_variable: + pop rcx + mov eax,1 + jecxz environment_variable_ok + and byte [edi],0 + pop rbx + ret + +VALLOC_MINIMUM_SIZE = 100000h + +valloc: +; in: ecx = requested minimum size +; out: eax - allocated block, ecx = allocated size, zero if failed +; preserves: ebx, esi, edi + cmp ecx,VALLOC_MINIMUM_SIZE + jbe valloc_size_minimum + dec ecx + and ecx,(-1) shl 12 + add ecx,1 shl 12 + jmp valloc_size_ready + valloc_size_minimum: + mov ecx,VALLOC_MINIMUM_SIZE + valloc_size_ready: + push rbx rsi rdi + cmp [local_heap_available],0 + je valloc_mmap + cmp ecx,LOCAL_HEAP_SIZE + ja valloc_mmap + and [local_heap_available],0 + mov eax,local_heap + mov ecx,LOCAL_HEAP_SIZE + jmp valloc_ok + valloc_mmap: + xor r9d,r9d + or r8,-1 + mov r10d,62h ; MAP_PRIVATE + MAP_ANONYMOUS + MAP_32BIT + mov edx,3 ; PROT_READ + PROT_WRITE + mov esi,ecx + xor edi,edi + mov eax,9 ; sys_mmap + syscall + cmp eax,-1 + je valloc_mmap_with_hint + mov ecx,eax + cmp rcx,rax + jne valloc_mmap_unusable + add ecx,esi + jnc mmap_ok + valloc_mmap_unusable: + mov rdi,rax + mov eax,11 ; sys_munmap + syscall + valloc_mmap_with_hint: + mov r10d,22h ; MAP_PRIVATE + MAP_ANONYMOUS + mov edx,3 ; PROT_READ + PROT_WRITE + mov edi,[mmap_hint] + mov eax,9 ; sys_mmap + syscall + cmp eax,-1 + je valloc_failed + mov ecx,eax + cmp rcx,rax + jne valloc_failed + add ecx,esi + jc valloc_failed + mmap_ok: + sub ecx,eax + valloc_ok: + lea edx,[eax+ecx] + mov [mmap_hint],edx + pop rdi rsi rbx + retn + valloc_failed: + xor ecx,ecx + pop rdi rsi rbx + retn diff --git a/toolchain/fasm2/source/macos/fasmg.asm b/toolchain/fasm2/source/macos/fasmg.asm new file mode 100644 index 0000000..9ab79fd --- /dev/null +++ b/toolchain/fasm2/source/macos/fasmg.asm @@ -0,0 +1,495 @@ + +include 'macro/struct.inc' +include 'macro/proc32.inc' + +format MachO executable +entry start + +include '../version.inc' + +interpreter '/usr/lib/dyld' +uses '/usr/lib/libSystem.B.dylib' + +import libc.malloc,'_malloc',\ + libc.realloc,'_realloc',\ + libc.free,'_free',\ + libc.fopen,'_fopen',\ + libc.fclose,'_fclose',\ + libc.fread,'_fread',\ + libc.fwrite,'_fwrite',\ + libc.fseek,'_fseek',\ + libc.ftell,'_ftell',\ + libc.time,'_time',\ + libc.write,'_write',\ + getenv,'_getenv',\ + gettimeofday,'_gettimeofday',\ + exit,'_exit' + +struct timeval + time_t dd ? + suseconds_t dd ? +ends + +segment '__TEXT' readable executable + +section '__text' align 16 + + start: + mov ecx,[esp] + mov [argc],ecx + lea ebx,[esp+4] + mov [argv],ebx + + call system_init + + call get_arguments + mov bl,al + cmp [no_logo],0 + jne logo_ok + mov esi,_logo + xor ecx,ecx + call display_string + logo_ok: + test bl,bl + jnz display_usage_information + + xor al,al + mov ecx,[verbosity_level] + jecxz init + or al,TRACE_ERROR_STACK + dec ecx + jz init + or al,TRACE_DISPLAY + init: + call assembly_init + + ccall gettimeofday,start_time,0 + + assemble: + mov esi,[initial_commands] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,_code_cannot_be_generated + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + jmp assembly_failed + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + cmp [no_logo],0 + jne summary_done + mov eax,[current_pass] + xor edx,edx + call itoa + call display_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_string + ccall gettimeofday,end_time,0 + mov eax,[end_time.time_t] + sub eax,[start_time.time_t] + mov ecx,1000000 + mul ecx + add eax,[end_time.suseconds_t] + adc edx,0 + sub eax,[start_time.suseconds_t] + sbb edx,0 + add eax,50000 + mov ecx,1000000 + div ecx + mov ebx,eax + mov eax,edx + xor edx,edx + mov ecx,100000 + div ecx + mov [tenths_of_second],eax + xchg eax,ebx + or ebx,eax + jz display_output_length + xor edx,edx + call itoa + call display_string + mov esi,_message_suffix + mov ecx,1 + call display_string + mov eax,[tenths_of_second] + xor edx,edx + call itoa + call display_string + mov esi,_seconds + xor ecx,ecx + call display_string + display_output_length: + call get_output_length + push eax edx + call itoa + call display_string + pop edx eax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_string + mov esi,_new_line + xor ecx,ecx + call display_string + summary_done: + + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + call assembly_shutdown + call system_shutdown + + ccall exit,0 + + assembly_failed: + + call show_errors + + call assembly_shutdown + call system_shutdown + + ccall exit,2 + + write_failed: + mov ebx,_write_failed + jmp fatal_error + + out_of_memory: + mov ebx,_out_of_memory + jmp fatal_error + + fatal_error: + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + call assembly_shutdown + call system_shutdown + + ccall exit,3 + + display_usage_information: + + mov esi,_usage + xor ecx,ecx + call display_string + + call system_shutdown + + ccall exit,1 + + get_arguments: + xor eax,eax + mov [initial_commands],eax + mov [source_path],eax + mov [output_path],eax + mov [no_logo],al + mov [verbosity_level],eax + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1 + mov [maximum_depth_of_stack],10000 + mov ecx,[argc] + mov ebx,[argv] + add ebx,4 + dec ecx + jz error_in_arguments + get_argument: + mov esi,[ebx] + mov al,[esi] + cmp al,'-' + je get_option + cmp [source_path],0 + jne get_output_file + mov [source_path],esi + jmp next_argument + get_output_file: + cmp [output_path],0 + jne error_in_arguments + mov [output_path],esi + jmp next_argument + get_option: + inc esi + lodsb + cmp al,'e' + je set_errors_limit + cmp al,'E' + je set_errors_limit + cmp al,'i' + je insert_initial_command + cmp al,'I' + je insert_initial_command + cmp al,'p' + je set_passes_limit + cmp al,'P' + je set_passes_limit + cmp al,'r' + je set_recursion_limit + cmp al,'R' + je set_recursion_limit + cmp al,'v' + je set_verbose_mode + cmp al,'V' + je set_verbose_mode + cmp al,'n' + je set_no_logo + cmp al,'N' + jne error_in_arguments + set_no_logo: + or [no_logo],-1 + cmp byte [esi],0 + je next_argument + error_in_arguments: + or al,-1 + ret + set_verbose_mode: + cmp byte [esi],0 + jne get_verbose_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_verbose_setting: + call get_option_value + cmp edx,2 + ja error_in_arguments + mov [verbosity_level],edx + jmp next_argument + set_errors_limit: + cmp byte [esi],0 + jne get_errors_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_errors_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_errors],edx + jmp next_argument + set_recursion_limit: + cmp byte [esi],0 + jne get_recursion_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_recursion_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_depth_of_stack],edx + jmp next_argument + set_passes_limit: + cmp byte [esi],0 + jne get_passes_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_passes_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_passes],edx + next_argument: + add ebx,4 + dec ecx + jnz get_argument + cmp [source_path],0 + je error_in_arguments + xor al,al + ret + get_option_value: + xor eax,eax + mov edx,eax + find_option_value: + cmp byte [esi],20h + jne get_option_digit + inc esi + jmp find_option_value + get_option_digit: + lodsb + test al,al + jz option_value_ok + sub al,30h + jc invalid_option_value + cmp al,9 + ja invalid_option_value + imul edx,10 + jo invalid_option_value + add edx,eax + jc invalid_option_value + jmp get_option_digit + option_value_ok: + dec esi + clc + ret + invalid_option_value: + stc + ret + insert_initial_command: + cmp byte [esi],0 + jne measure_initial_command + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + measure_initial_command: + push ebx ecx edi + mov edi,esi + or ecx,-1 + xor al,al + repne scasb + not ecx + dec ecx + mov edi,[initial_commands] + lea eax,[ecx+2] + test edi,edi + jz allocate_initial_commands_buffer + mov edx,[initial_commands_length] + add edi,edx + add eax,edx + cmp eax,[initial_commands_maximum_length] + ja grow_initial_commands_buffer + copy_initial_command: + rep movsb + mov ax,0Ah + stosw + dec edi + sub edi,[initial_commands] + mov [initial_commands_length],edi + pop edi ecx ebx + jmp next_argument + allocate_initial_commands_buffer: + push ecx + mov ecx,eax + call malloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + pop ecx + jmp copy_initial_command + grow_initial_commands_buffer: + push ecx + mov ecx,eax + mov eax,[initial_commands] + call realloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + add edi,[initial_commands_length] + pop ecx + jmp copy_initial_command + + include 'system.inc' + + include '../assembler.inc' + include '../symbols.inc' + include '../expressions.inc' + include '../conditions.inc' + include '../floats.inc' + include '../directives.inc' + include '../calm.inc' + include '../errors.inc' + include '../map.inc' + include '../reader.inc' + include '../output.inc' + include '../console.inc' + +section '__cstring' align 4 + + _logo db 'flat assembler version g.',VERSION,10,0 + + _usage db 'Usage: fasmg source [output]',10 + db 'Optional settings:',10 + db ' -p limit Set the maximum allowed number of passes (default 100)',10 + db ' -e limit Set the maximum number of displayed errors (default 1)',10 + db ' -r limit Set the maximum depth of the stack (default 10000)',10 + db ' -v flag Enable or disable showing all lines from the stack (default 0)',10 + db ' -i command Insert instruction at the beginning of source',13,10 + db ' -n Do not show logo nor summary',13,10 + db 0 + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'failed to write the output file',0 + _out_of_memory db 'not enough memory to complete the assembly',0 + _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 + + _open_mode db 'r',0 + _create_mode db 'w',0 + + include '../tables.inc' + include '../messages.inc' + +segment '__DATA' readable writable + +section '__bss' align 4 + + include '../variables.inc' + + source_path dd ? + output_path dd ? + maximum_number_of_passes dd ? + + initial_commands dd ? + initial_commands_length dd ? + initial_commands_maximum_length dd ? + + argc dd ? + argv dd ? + timestamp dq ? + + start_time timeval + end_time timeval + tenths_of_second dd ? + + verbosity_level dd ? + no_logo db ? + + path_buffer rb 1000h diff --git a/toolchain/fasm2/source/macos/fasmg.o.asm b/toolchain/fasm2/source/macos/fasmg.o.asm new file mode 100644 index 0000000..cb5d0c5 --- /dev/null +++ b/toolchain/fasm2/source/macos/fasmg.o.asm @@ -0,0 +1,489 @@ + +include 'macro/struct.inc' +include 'macro/proc32.inc' + +format MachO +public main as '_main' + +include '../version.inc' + +extrn '_malloc' as libc.malloc +extrn '_realloc' as libc.realloc +extrn '_free' as libc.free +extrn '_fopen' as libc.fopen +extrn '_fclose' as libc.fclose +extrn '_fread' as libc.fread +extrn '_fwrite' as libc.fwrite +extrn '_fseek' as libc.fseek +extrn '_ftell' as libc.ftell +extrn '_time' as libc.time +extrn '_write' as libc.write + +extrn '_getenv' as getenv +extrn '_gettimeofday' as gettimeofday +extrn '_exit' as exit + +struct timeval + time_t dd ? + suseconds_t dd ? +ends + +section '__TEXT':'__text' align 16 + + main: + mov ecx,[esp+4] + mov [argc],ecx + mov ebx,[esp+8] + mov [argv],ebx + + call system_init + + call get_arguments + mov bl,al + cmp [no_logo],0 + jne logo_ok + mov esi,_logo + xor ecx,ecx + call display_string + logo_ok: + test bl,bl + jnz display_usage_information + + xor al,al + mov ecx,[verbosity_level] + jecxz init + or al,TRACE_ERROR_STACK + dec ecx + jz init + or al,TRACE_DISPLAY + init: + call assembly_init + + ccall gettimeofday,start_time,0 + + assemble: + mov esi,[initial_commands] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,_code_cannot_be_generated + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + jmp assembly_failed + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + cmp [no_logo],0 + jne summary_done + mov eax,[current_pass] + xor edx,edx + call itoa + call display_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_string + ccall gettimeofday,end_time,0 + mov eax,[end_time.time_t] + sub eax,[start_time.time_t] + mov ecx,1000000 + mul ecx + add eax,[end_time.suseconds_t] + adc edx,0 + sub eax,[start_time.suseconds_t] + sbb edx,0 + add eax,50000 + mov ecx,1000000 + div ecx + mov ebx,eax + mov eax,edx + xor edx,edx + mov ecx,100000 + div ecx + mov [tenths_of_second],eax + xchg eax,ebx + or ebx,eax + jz display_output_length + xor edx,edx + call itoa + call display_string + mov esi,_message_suffix + mov ecx,1 + call display_string + mov eax,[tenths_of_second] + xor edx,edx + call itoa + call display_string + mov esi,_seconds + xor ecx,ecx + call display_string + display_output_length: + call get_output_length + push eax edx + call itoa + call display_string + pop edx eax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_string + mov esi,_new_line + xor ecx,ecx + call display_string + summary_done: + + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + call assembly_shutdown + call system_shutdown + + ccall exit,0 + + assembly_failed: + + call show_errors + + call assembly_shutdown + call system_shutdown + + ccall exit,2 + + write_failed: + mov ebx,_write_failed + jmp fatal_error + + out_of_memory: + mov ebx,_out_of_memory + jmp fatal_error + + fatal_error: + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + call assembly_shutdown + call system_shutdown + + ccall exit,3 + + display_usage_information: + + mov esi,_usage + xor ecx,ecx + call display_string + + call system_shutdown + + ccall exit,1 + + get_arguments: + xor eax,eax + mov [initial_commands],eax + mov [source_path],eax + mov [output_path],eax + mov [no_logo],al + mov [verbosity_level],eax + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1 + mov [maximum_depth_of_stack],10000 + mov ecx,[argc] + mov ebx,[argv] + add ebx,4 + dec ecx + jz error_in_arguments + get_argument: + mov esi,[ebx] + mov al,[esi] + cmp al,'-' + je get_option + cmp [source_path],0 + jne get_output_file + mov [source_path],esi + jmp next_argument + get_output_file: + cmp [output_path],0 + jne error_in_arguments + mov [output_path],esi + jmp next_argument + get_option: + inc esi + lodsb + cmp al,'e' + je set_errors_limit + cmp al,'E' + je set_errors_limit + cmp al,'i' + je insert_initial_command + cmp al,'I' + je insert_initial_command + cmp al,'p' + je set_passes_limit + cmp al,'P' + je set_passes_limit + cmp al,'r' + je set_recursion_limit + cmp al,'R' + je set_recursion_limit + cmp al,'v' + je set_verbose_mode + cmp al,'V' + je set_verbose_mode + cmp al,'n' + je set_no_logo + cmp al,'N' + jne error_in_arguments + set_no_logo: + or [no_logo],-1 + cmp byte [esi],0 + je next_argument + error_in_arguments: + or al,-1 + ret + set_verbose_mode: + cmp byte [esi],0 + jne get_verbose_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_verbose_setting: + call get_option_value + cmp edx,2 + ja error_in_arguments + mov [verbosity_level],edx + jmp next_argument + set_errors_limit: + cmp byte [esi],0 + jne get_errors_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_errors_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_errors],edx + jmp next_argument + set_recursion_limit: + cmp byte [esi],0 + jne get_recursion_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_recursion_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_depth_of_stack],edx + jmp next_argument + set_passes_limit: + cmp byte [esi],0 + jne get_passes_setting + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + get_passes_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_passes],edx + next_argument: + add ebx,4 + dec ecx + jnz get_argument + cmp [source_path],0 + je error_in_arguments + xor al,al + ret + get_option_value: + xor eax,eax + mov edx,eax + find_option_value: + cmp byte [esi],20h + jne get_option_digit + inc esi + jmp find_option_value + get_option_digit: + lodsb + test al,al + jz option_value_ok + sub al,30h + jc invalid_option_value + cmp al,9 + ja invalid_option_value + imul edx,10 + jo invalid_option_value + add edx,eax + jc invalid_option_value + jmp get_option_digit + option_value_ok: + dec esi + clc + ret + invalid_option_value: + stc + ret + insert_initial_command: + cmp byte [esi],0 + jne measure_initial_command + dec ecx + jz error_in_arguments + add ebx,4 + mov esi,[ebx] + measure_initial_command: + push ebx ecx edi + mov edi,esi + or ecx,-1 + xor al,al + repne scasb + not ecx + dec ecx + mov edi,[initial_commands] + lea eax,[ecx+2] + test edi,edi + jz allocate_initial_commands_buffer + mov edx,[initial_commands_length] + add edi,edx + add eax,edx + cmp eax,[initial_commands_maximum_length] + ja grow_initial_commands_buffer + copy_initial_command: + rep movsb + mov ax,0Ah + stosw + dec edi + sub edi,[initial_commands] + mov [initial_commands_length],edi + pop edi ecx ebx + jmp next_argument + allocate_initial_commands_buffer: + push ecx + mov ecx,eax + call malloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + pop ecx + jmp copy_initial_command + grow_initial_commands_buffer: + push ecx + mov ecx,eax + mov eax,[initial_commands] + call realloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + add edi,[initial_commands_length] + pop ecx + jmp copy_initial_command + + include 'system.inc' + + include '../assembler.inc' + include '../symbols.inc' + include '../expressions.inc' + include '../conditions.inc' + include '../floats.inc' + include '../directives.inc' + include '../calm.inc' + include '../errors.inc' + include '../map.inc' + include '../reader.inc' + include '../output.inc' + include '../console.inc' + +section '__TEXT':'__cstring' align 4 + + _logo db 'flat assembler version g.',VERSION,10,0 + + _usage db 'Usage: fasmg source [output]',10 + db 'Optional settings:',10 + db ' -p limit Set the maximum allowed number of passes (default 100)',10 + db ' -e limit Set the maximum number of displayed errors (default 1)',10 + db ' -r limit Set the maximum depth of the stack (default 10000)',10 + db ' -v flag Enable or disable showing all lines from the stack (default 0)',10 + db ' -i command Insert instruction at the beginning of source',13,10 + db ' -n Do not show logo nor summary',13,10 + db 0 + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'failed to write the output file',0 + _out_of_memory db 'not enough memory to complete the assembly',0 + _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 + + _open_mode db 'r',0 + _create_mode db 'w',0 + + include '../tables.inc' + include '../messages.inc' + +section '__DATA':'__data' align 4 + + include '../variables.inc' + + source_path dd ? + output_path dd ? + maximum_number_of_passes dd ? + + initial_commands dd ? + initial_commands_length dd ? + initial_commands_maximum_length dd ? + + argc dd ? + argv dd ? + timestamp dq ? + + start_time timeval + end_time timeval + tenths_of_second dd ? + + verbosity_level dd ? + no_logo db ? + + path_buffer rb 1000h diff --git a/toolchain/fasm2/source/macos/macho.inc b/toolchain/fasm2/source/macos/macho.inc new file mode 100644 index 0000000..9c34277 --- /dev/null +++ b/toolchain/fasm2/source/macos/macho.inc @@ -0,0 +1,1174 @@ + +CPU_TYPE_ANY = -1 +CPU_ARCH_ABI64 = 0x1000000 +CPU_TYPE_VAX = 1 +CPU_TYPE_ROMP = 2 +CPU_TYPE_NS32032 = 4 +CPU_TYPE_NS32332 = 5 +CPU_TYPE_MC680x0 = 6 +CPU_TYPE_I386 = 7 +CPU_TYPE_X86_64 = CPU_TYPE_I386 or CPU_ARCH_ABI64 +CPU_TYPE_MIPS = 8 +CPU_TYPE_NS32532 = 9 +CPU_TYPE_HPPA = 11 +CPU_TYPE_ARM = 12 +CPU_TYPE_MC88000 = 13 +CPU_TYPE_SPARC = 14 +CPU_TYPE_I860 = 15 +CPU_TYPE_I860_LITTLE = 16 +CPU_TYPE_RS6000 = 17 +CPU_TYPE_MC98000 = 18 +CPU_TYPE_POWERPC = 18 +CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC or CPU_ARCH_ABI64 +CPU_TYPE_VEO = 255 + +CPU_SUBTYPE_MASK = 0xff000000 +CPU_SUBTYPE_LIB64 = 0x80000000 + +CPU_SUBTYPE_I386_ALL = 3 +CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386_ALL +CPU_SUBTYPE_386 = 3 +CPU_SUBTYPE_486 = 4 +CPU_SUBTYPE_486SX = 4 + 128 +CPU_SUBTYPE_586 = 5 +CPU_SUBTYPE_PENT = 5 + 0 shl 4 +CPU_SUBTYPE_PENTPRO = 6 + 1 shl 4 +CPU_SUBTYPE_PENTII_M3 = 6 + 3 shl 4 +CPU_SUBTYPE_PENTII_M5 = 6 + 5 shl 4 +CPU_SUBTYPE_PENTIUM_4 = 10 + 0 shl 4 + +MH_OBJECT = 0x1 +MH_EXECUTE = 0x2 +MH_FVMLIB = 0x3 +MH_CORE = 0x4 +MH_PRELOAD = 0x5 +MH_DYLIB = 0x6 +MH_DYLINKER = 0x7 +MH_BUNDLE = 0x8 +MH_DYLIB_STUB = 0x9 +MH_DSYM = 0xA +MH_KEXT_BUNDLE = 0xB + +MH_NOUNDEFS = 0x1 +MH_INCRLINK = 0x2 +MH_DYLDLINK = 0x4 +MH_BINDATLOAD = 0x8 +MH_PREBOUND = 0x10 +MH_SPLIT_SEGS = 0x20 +MH_LAZY_INIT = 0x40 +MH_TWOLEVEL = 0x80 +MH_FORCE_FLAT = 0x100 +MH_NOMULTIDEFS = 0x200 +MH_NOFIXPREBINDING = 0x400 +MH_PREBINDABLE = 0x800 +MH_ALLMODSBOUND = 0x1000 +MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000 +MH_CANONICAL = 0x4000 +MH_WEAK_DEFINES = 0x8000 +MH_BINDS_TO_WEAK = 0x10000 +MH_ALLOW_STACK_EXECUTION = 0x20000 +MH_ROOT_SAFE = 0x40000 +MH_SETUID_SAFE = 0x80000 +MH_NO_REEXPORTED_DYLIBS = 0x100000 +MH_PIE = 0x200000 +MH_DEAD_STRIPPABLE_DYLIB = 0x400000 +MH_HAS_TLV_DESCRIPTORS = 0x800000 +MH_NO_HEAP_EXECUTION = 0x1000000 +MH_APP_EXTENSION_SAFE = 0x2000000 + +LC_REQ_DYLD = 0x80000000 +LC_SEGMENT = 0x1 +LC_SYMTAB = 0x2 +LC_SYMSEG = 0x3 +LC_THREAD = 0x4 +LC_UNIXTHREAD = 0x5 +LC_LOADFVMLIB = 0x6 +LC_IDFVMLIB = 0x7 +LC_IDENT = 0x8 +LC_FVMFILE = 0x9 +LC_PREPAGE = 0xa +LC_DYSYMTAB = 0xb +LC_LOAD_DYLIB = 0xc +LC_ID_DYLIB = 0xd +LC_LOAD_DYLINKER = 0xe +LC_ID_DYLINKER = 0xf +LC_PREBOUND_DYLIB = 0x10 +LC_ROUTINES = 0x11 +LC_SUB_FRAMEWORK = 0x12 +LC_SUB_UMBRELLA = 0x13 +LC_SUB_CLIENT = 0x14 +LC_SUB_LIBRARY = 0x15 +LC_TWOLEVEL_HINTS = 0x16 +LC_PREBIND_CKSUM = 0x17 +LC_LOAD_WEAK_DYLIB = 0x18 +LC_SEGMENT_64 = 0x19 +LC_ROUTINES_64 = 0x1a +LC_UUID = 0x1b +LC_RPATH = 0x1c + LC_REQ_DYLD +LC_CODE_SIGNATURE = 0x1d +LC_SEGMENT_SPLIT_INFO = 0x1e +LC_REEXPORT_DYLIB = 0x1f + LC_REQ_DYLD +LC_LAZY_LOAD_DYLIB = 0x20 +LC_ENCRYPTION_INFO = 0x21 +LC_DYLD_INFO = 0x22 +LC_DYLD_INFO_ONLY = 0x22 + LC_REQ_DYLD + +SG_HIGHVM = 0x1 +SG_FVMLIB = 0x2 +SG_NORELOC = 0x4 + +SECTION_TYPE = 0x000000ff +SECTION_ATTRIBUTES = 0xffffff00 + +S_REGULAR = 0x0 +S_ZEROFILL = 0x1 +S_CSTRING_LITERALS = 0x2 +S_4BYTE_LITERALS = 0x3 +S_8BYTE_LITERALS = 0x4 +S_LITERAL_POINTERS = 0x5 +S_NON_LAZY_SYMBOL_POINTERS = 0x6 +S_LAZY_SYMBOL_POINTERS = 0x7 +S_SYMBOL_STUBS = 0x8 +S_MOD_INIT_FUNC_POINTERS = 0x9 +S_MOD_TERM_FUNC_POINTERS = 0x0a +S_COALESCED = 0x0b +S_GB_ZEROFILL = 0x0c +S_INTERPOSING = 0x0d +S_16BYTE_LITERALS = 0x0e +S_DTRACE_DOF = 0x0f +S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10 +S_THREAD_LOCAL_REGULAR = 0x11 +S_THREAD_LOCAL_ZEROFILL = 0x12 +S_THREAD_LOCAL_VARIABLES = 0x13 +S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14 +S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15 + +SECTION_ATTRIBUTES_USR = 0xff000000 +S_ATTR_PURE_INSTRUCTIONS = 0x80000000 +S_ATTR_NO_TOC = 0x40000000 +S_ATTR_STRIP_STATIC_SYMS = 0x20000000 +S_ATTR_NO_DEAD_STRIP = 0x10000000 +S_ATTR_LIVE_SUPPORT = 0x08000000 +S_ATTR_SELF_MODIFYING_CODE = 0x04000000 +S_ATTR_DEBUG = 0x02000000 + +SECTION_ATTRIBUTES_SYS = 0x00ffff00 +S_ATTR_SOME_INSTRUCTIONS = 0x00000400 +S_ATTR_EXT_RELOC = 0x00000200 +S_ATTR_LOC_RELOC = 0x00000100 + +VM_PROT_NONE = 0x00 +VM_PROT_READ = 0x01 +VM_PROT_WRITE = 0x02 +VM_PROT_EXECUTE = 0x04 +VM_PROT_DEFAULT = VM_PROT_READ or VM_PROT_WRITE +VM_PROT_ALL = VM_PROT_READ or VM_PROT_WRITE or VM_PROT_EXECUTE +VM_PROT_NO_CHANGE = 0x08 +VM_PROT_COPY = 0x10 +VM_PROT_WANTS_COPY = 0x10 + +x86_THREAD_STATE32 = 1 +x86_FLOAT_STATE32 = 2 +x86_EXCEPTION_STATE32 = 3 +x86_THREAD_STATE64 = 4 +x86_FLOAT_STATE64 = 5 +x86_EXCEPTION_STATE64 = 6 +x86_THREAD_STATE = 7 +x86_FLOAT_STATE = 8 +x86_EXCEPTION_STATE = 9 +x86_DEBUG_STATE32 = 10 +x86_DEBUG_STATE64 = 11 +x86_DEBUG_STATE = 12 +THREAD_STATE_NONE = 13 + +N_STAB = 0xe0 +N_PEXT = 0x10 +N_TYPE = 0x0e +N_EXT = 0x01 +N_UNDF = 0x0 +N_ABS = 0x2 +N_SECT = 0xe +N_PBUD = 0xc +N_INDR = 0xa + +NO_SECT = 0 +MAX_SECT = 255 + +REFERENCE_TYPE = 0xf +REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0 +REFERENCE_FLAG_UNDEFINED_LAZY = 1 +REFERENCE_FLAG_DEFINED = 2 +REFERENCE_FLAG_PRIVATE_DEFINED = 3 +REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4 +REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5 +REFERENCED_DYNAMICALLY = 0x0010 + +GENERIC_RELOC_VANILLA = 0 +GENERIC_RELOC_PAIR = 1 +GENERIC_RELOC_SECTDIFF = 2 +GENERIC_RELOC_PB_LA_PTR = 3 +GENERIC_RELOC_LOCAL_SECTDIFF = 4 +GENERIC_RELOC_TLV = 5 + +X86_64_RELOC_UNSIGNED = 0 +X86_64_RELOC_SIGNED = 1 +X86_64_RELOC_BRANCH = 2 +X86_64_RELOC_GOT_LOAD = 3 +X86_64_RELOC_GOT = 4 +X86_64_RELOC_SUBTRACTOR = 5 +X86_64_RELOC_SIGNED_1 = 6 +X86_64_RELOC_SIGNED_2 = 7 +X86_64_RELOC_SIGNED_4 = 8 +X86_64_RELOC_TLV = 9 + +; Basic layer: command headers + +MachO:: + +namespace MachO + + if defined Settings.ProcessorType + CPUTYPE := Settings.ProcessorType + else + CPUTYPE := CPU_TYPE_I386 + end if + + if defined Settings.ProcessorSubtype + CPUSUBTYPE := Settings.ProcessorSubtype + else + if CPUTYPE and CPU_ARCH_ABI64 + CPUSUBTYPE := CPU_SUBTYPE_I386_ALL + CPU_SUBTYPE_LIB64 + else + CPUSUBTYPE := CPU_SUBTYPE_I386_ALL + end if + end if + + if defined Settings.FileType + FILETYPE := Settings.FileType + else + FILETYPE := MH_EXECUTE + end if + + if defined Settings.Flags + FLAGS := Settings.Flags + else if FILETYPE <> MH_OBJECT + FLAGS := MH_NOUNDEFS + MH_DYLDLINK + else + FLAGS := 0 + end if + + if defined Settings.SegmentAlignment + SEGMENT_ALIGNMENT := Settings.SegmentAlignment + else + SEGMENT_ALIGNMENT := 1000h + end if + + if defined Settings.FileAlignment + FILE_ALIGNMENT := Settings.FileAlignment + else + FILE_ALIGNMENT := 1000h + end if + + if CPUTYPE and CPU_ARCH_ABI64 + magic dd 0xFEEDFACF + else + magic dd 0xFEEDFACE + end if + cputype dd CPUTYPE + cpusubtype dd CPUSUBTYPE + filetype dd FILETYPE + ncmds dd NUMBER_OF_COMMANDS + sizeofcmds dd SIZE_OF_COMMANDS + flags dd FLAGS + if CPUTYPE and CPU_ARCH_ABI64 + reserved dd ? + end if + + COMMAND_NUMBER = 0 + COMMAND_POSITION = $ + + commands db SIZE_OF_COMMANDS dup 0 + + org $ + + macro command type + if MachO.COMMAND_POSITION > 0 + virtual at MachO.COMMAND_POSITION + MachO.COMMAND_POSITION = 0 + end if + match t, type + if MachO.COMMAND_NUMBER > 0 + repeat 1, p:MachO.COMMAND_NUMBER + MachO.load#p.SIZE := $ - MachO.load#p.cmd + end repeat + end if + MachO.COMMAND_NUMBER = MachO.COMMAND_NUMBER + 1 + MachO.COMMAND = $ + repeat 1, n:MachO.COMMAND_NUMBER + namespace MachO.load#n + cmd dd t + cmdsize dd SIZE + end namespace + end repeat + end match + end macro + + macro text + if MachO.COMMAND_POSITION = 0 + MachO.COMMAND_POSITION = $ + load MachO.COMMAND_DATA:$-$$ from $$ + store MachO.COMMAND_DATA:$-$$ at MachO:$$ + end virtual + end if + end macro + +end namespace + +macro align? boundary,value:? + db (boundary-1)-($+boundary-1) mod boundary dup value +end macro + +postpone + MachO.text + namespace MachO + if COMMAND_NUMBER > 0 + repeat 1, p:COMMAND_NUMBER + load#p.SIZE := COMMAND_POSITION - MachO.load#p.cmd + end repeat + end if + NUMBER_OF_COMMANDS := COMMAND_NUMBER + SIZE_OF_COMMANDS := COMMAND_POSITION - commands + end namespace +end postpone + +; Intermediate layer: segments and sections + +namespace MachO + + if defined Settings.BaseAddress + + VM_ADDRESS = Settings.BaseAddress + + if CPUTYPE and CPU_ARCH_ABI64 + MachO.command LC_SEGMENT_64 + else + MachO.command LC_SEGMENT + end if + namespace MachO.segment1 + segname emit 16: '__PAGEZERO' + if CPUTYPE and CPU_ARCH_ABI64 + vmaddr dq 0 + vmsize dq VM_ADDRESS + fileoff dq 0 + filesize dq 0 + else + vmaddr dd 0 + vmsize dd VM_ADDRESS + fileoff dd 0 + filesize dd 0 + end if + maxprot dd 0 + initprot dd 0 + nsects dd 0 + flags dd 0 + end namespace + + SEGMENT_NUMBER = 1 + else + VM_ADDRESS = 0 + SEGMENT_NUMBER = 0 + end if + + GLOBAL_SECTION_NUMBER = 0 + TEXT_OFFSET = $% + +end namespace + +macro MachO.segment declaration + MachO.close_segment + + local NAME,VMADDR,VMSIZE,FILEOFF,FILESIZE,MAXPROT,INITPROT,NSECTS + + INITPROT = VM_PROT_NONE + MAXPROT = VM_PROT_ALL + match name attributes, declaration + NAME = name + local sequence + define sequence attributes: + while 1 + match attribute tail, sequence + match =readable?, attribute + INITPROT = INITPROT or VM_PROT_READ + MAXPROT = MAXPROT or VM_PROT_READ + else match =notreadable?, attribute + INITPROT = INITPROT and not VM_PROT_READ + MAXPROT = MAXPROT and not VM_PROT_READ + else match =writeable?, attribute + INITPROT = INITPROT or VM_PROT_WRITE + MAXPROT = MAXPROT or VM_PROT_WRITE + else match =writable?, attribute + INITPROT = INITPROT or VM_PROT_WRITE + MAXPROT = MAXPROT or VM_PROT_WRITE + else match =notwriteable?, attribute + INITPROT = INITPROT and not VM_PROT_WRITE + MAXPROT = MAXPROT and not VM_PROT_WRITE + else match =notwritable?, attribute + INITPROT = INITPROT and not VM_PROT_WRITE + MAXPROT = MAXPROT and not VM_PROT_WRITE + else match =executable?, attribute + INITPROT = INITPROT or VM_PROT_EXECUTE + MAXPROT = MAXPROT or VM_PROT_EXECUTE + else match =notexecutable?, attribute + INITPROT = INITPROT and not VM_PROT_EXECUTE + MAXPROT = MAXPROT and not VM_PROT_EXECUTE + else + err 'invalid argument' + end match + redefine sequence tail + else + break + end match + end while + else + NAME = definition + end match + if NAME eqtype '' & lengthof NAME > 16 + err 'name too long' + end if + + VMADDR := MachO.VM_ADDRESS + + if $% = MachO.TEXT_OFFSET & FILESIZE > 0 & MachO.FILETYPE <> MH_OBJECT + MachO.FILE_OFFSET = 0 + else + MachO.FILE_OFFSET = $% + end if + + if FILESIZE + FILEOFF := MachO.FILE_OFFSET + else + FILEOFF := 0 + end if + + MachO.SEGMENT_NUMBER = MachO.SEGMENT_NUMBER + 1 + if MachO.CPUTYPE and CPU_ARCH_ABI64 + MachO.command LC_SEGMENT_64 + else + MachO.command LC_SEGMENT + end if + repeat 1, s:MachO.SEGMENT_NUMBER + namespace MachO.segment#s + segname emit 16: NAME + if MachO.CPUTYPE and CPU_ARCH_ABI64 + vmaddr dq VMADDR + vmsize dq VMSIZE + fileoff dq FILEOFF + filesize dq FILESIZE + else + vmaddr dd VMADDR + vmsize dd VMSIZE + fileoff dd FILEOFF + filesize dd FILESIZE + end if + maxprot dd MAXPROT + initprot dd INITPROT + nsects dd NSECTS + flags dd 0 + end namespace + repeat NSECTS + namespace MachO.segment#s#_section#% + sectname emit 16: ? + segname emit 16: ? + if MachO.CPUTYPE and CPU_ARCH_ABI64 + addr dq ? + size dq ? + else + addr dd ? + size dd ? + end if + offset dd ? + align. dd ? + reloff dd ? + nreloc dd ? + flags dd ? + reserved1 dd ? + reserved2 dd ? + if MachO.CPUTYPE and CPU_ARCH_ABI64 + dd ? + end if + end namespace + end repeat + end repeat + + macro MachO.close_segment + MachO.close_section + local OFFSET,NEXT,TOP,FILL + TOP = $% + NSECTS := MachO.SECTION_NUMBER + if MachO.FILE_OFFSET >= $%% + FILL = MachO.FILE_OFFSET + else + FILL = $%% + end if + repeat 1, s:MachO.SEGMENT_NUMBER + repeat NSECTS, n:2 + if % = 1 + load OFFSET from MachO:MachO.segment#s#_section#%.offset + else + OFFSET = NEXT + end if + if % < %% + load NEXT from MachO:MachO.segment#s#_section#n.offset + else + NEXT = TOP + end if + if OFFSET >= $%% + store S_ZEROFILL at MachO:MachO.segment#s#_section#%.flags + store 0 at MachO:MachO.segment#s#_section#%.size + else + FILL = NEXT + end if + end repeat + end repeat + FILESIZE := FILL - MachO.FILE_OFFSET + FILL = FILL - $%% + MachO.SECTION_BYPASS = 1 + section MachO.VM_ADDRESS + FILESIZE - FILL + restore MachO.SECTION_BYPASS + db FILL dup 0 + if FILESIZE + rb (MachO.FILE_ALIGNMENT-$%) and (MachO.FILE_ALIGNMENT-1) + end if + MachO.VM_ADDRESS = MachO.VM_ADDRESS + TOP - MachO.FILE_OFFSET + MachO.VM_ADDRESS = MachO.VM_ADDRESS + (MachO.SEGMENT_ALIGNMENT-MachO.VM_ADDRESS) and (MachO.SEGMENT_ALIGNMENT-1) + VMSIZE := MachO.VM_ADDRESS - VMADDR + purge MachO.close_segment + end macro + + MachO.text + org VMADDR + $% - MachO.FILE_OFFSET + MachO.SECTION_NUMBER = 0 + +end macro + +macro MachO.section declaration + if MachO.SEGMENT_NUMBER = 0 + MachO.segment '__TEXT' readable writable executable + end if + MachO.close_section + + local SECTNAME,SEGNAME,FLAGS,ALIGN,RESERVED1,RESERVED2 + + FLAGS = S_REGULAR + ALIGN = 0 + RESERVED1 = 0 + RESERVED2 = 0 + + local sequence + match segname:sectname tail, declaration: + SECTNAME = sectname + SEGNAME = segname + define sequence tail + else match name tail, declaration: + SECTNAME = name + repeat 1, s:MachO.SEGMENT_NUMBER + load SEGNAME from MachO:MachO.segment#s.segname + end repeat + define sequence tail + end match + + while 1 + match :, sequence + break + else match =align? boundary tail, sequence + ALIGN = bsf boundary + if bsf boundary <> bsr boundary + err 'invalid alignment value' + end if + redefine sequence tail + else match =flags?(value) tail, sequence + FLAGS = value + redefine sequence tail + else match =reserved1?(value) tail, sequence + RESERVED1 = value + redefine sequence tail + else match =reserved2?(value) tail, sequence + RESERVED2 = value + redefine sequence tail + else + err 'invalid arguments' + end match + end while + + MachO.text + if ALIGN + align 1 shl ALIGN + end if + + MachO.SECTION_ALIGN = 1 shl ALIGN + + MachO.SECTION_NUMBER = MachO.SECTION_NUMBER + 1 + MachO.GLOBAL_SECTION_NUMBER = MachO.GLOBAL_SECTION_NUMBER + 1 + + repeat 1, s:MachO.SEGMENT_NUMBER, t:MachO.SECTION_NUMBER + if ~ defined MachO.segment#s#_section#t.sectname + MachO.command + namespace MachO.segment#s#_section#t + sectname emit 16: ? + segname emit 16: ? + if MachO.CPUTYPE and CPU_ARCH_ABI64 + addr dq ? + size dq ? + else + addr dd ? + size dd ? + end if + offset dd ? + align. dd ? + reloff dd ? + nreloc dd ? + flags dd ? + reserved1 dd ? + reserved2 dd ? + if MachO.CPUTYPE and CPU_ARCH_ABI64 + dd ? + end if + end namespace + MachO.text + end if + store SECTNAME at MachO:MachO.segment#s#_section#t.sectname + store SEGNAME at MachO:MachO.segment#s#_section#t.segname + store $ at MachO:MachO.segment#s#_section#t.addr + store $% at MachO:MachO.segment#s#_section#t.offset + store FLAGS at MachO:MachO.segment#s#_section#t.flags + store ALIGN at MachO:MachO.segment#s#_section#t.align + store RESERVED1 at MachO:MachO.segment#s#_section#t.reserved1 + store RESERVED2 at MachO:MachO.segment#s#_section#t.reserved2 + end repeat + +end macro + +macro MachO.close_section + MachO.text + if MachO.SECTION_NUMBER + local SIZE + repeat 1, s:MachO.SEGMENT_NUMBER, t:MachO.SECTION_NUMBER + load OFFSET from MachO:MachO.segment#s#_section#t.offset + store $%-OFFSET at MachO:MachO.segment#s#_section#t.size + end repeat + end if +end macro + +macro MachO.close_segment +end macro + +postpone + MachO.close_segment + if MachO.FILETYPE <> MH_OBJECT & $%% < 1000h + store 0:byte at $-1 ; enforce minimum file size for OS X 10.10.5 and higher + end if +end postpone + +macro segment? args& + MachO.segment args +end macro + +macro section? args& + if defined MachO.SECTION_BYPASS + section args + else + MachO.section args + end if +end macro + +macro entry? regs& + iterate reg, regs + match name:value, reg + MachO.thread.name? := value + else if MachO.CPUTYPE = CPU_TYPE_I386 + MachO.thread.eip? := reg + else if MachO.CPUTYPE = CPU_TYPE_X86_64 + MachO.thread.rip? := reg + end if + end iterate + MachO.command LC_UNIXTHREAD + if MachO.CPUTYPE = CPU_TYPE_I386 + MachO.thread.flavor dd x86_THREAD_STATE32 + iterate name, eax,ebx,ecx,edx,edi,esi,ebp,esp,ss,eflags,eip,cs,ds,es,fs,gs + if % = 1 + MachO.thread.count dd %% + end if + if defined MachO.thread.name? + dd MachO.thread.name? + else + dd ? + end if + end iterate + else if MachO.CPUTYPE = CPU_TYPE_X86_64 + MachO.thread.flavor dd x86_THREAD_STATE64 + iterate name, rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp,r8,r9,r10,r11,r12,r13,r14,r15,rip,rflags,cs,fs,gs + if % = 1 + MachO.thread.count dd %%*2 + end if + if defined MachO.thread.name? + dq MachO.thread.name? + else + dq ? + end if + end iterate + else + err 'CPU not supported' + end if + MachO.text +end macro + +; Upper layer: symbol tables + +define macroBuilder? + +macro macroBuilder? declaration& + macro macroBuilder?.definition + esc macro declaration + end macro +end macro + +macro macroBuilder?.line? content& + macro macroBuilder?.definition + macroBuilder?.definition + content + end macro +end macro + +macro macroBuilder?.end? + macroBuilder?.definition + esc end macro +end macro + +if MachO.FILETYPE <> MH_OBJECT + + namespace MachO + NSYMS = 0 + LIB_NUMBER = 0 + end namespace + + macro interpreter? path + MachO.command LC_LOAD_DYLINKER + namespace MachO.dylinker_command + lc_str dd dylinker-MachO.COMMAND + dylinker db path,0 + if MachO.CPUTYPE and CPU_ARCH_ABI64 + align 8 + else + align 4 + end if + end namespace + end macro + + macro uses? lib& + MachO.LIB_NUMBER = MachO.LIB_NUMBER + 1 + MachO.command LC_LOAD_DYLIB + repeat 1, l:MachO.LIB_NUMBER + namespace MachO.dylib#l#_command + lc_str dd dylib-MachO.COMMAND + timestamp dd 2 + match path (a.b.c=,x.y.z), lib + current_version dd (x and 0FFFFh) shl 16 + y shl 8 + z + compatibility_version dd (a and 0FFFFh) shl 16 + b shl 8 + c + dylib db path,0 + else + current_version dd 10000h + compatibility_version dd 10000h + dylib db lib,0 + end match + if MachO.CPUTYPE and CPU_ARCH_ABI64 + align 8 + else + align 4 + end if + end namespace + end repeat + end macro + + macro import? definitions& + iterate , definitions + MachO.NSYMS = MachO.NSYMS + 1 + define MachO.nlist name + name.imported := 1 + name.type := N_EXT + name.desc := REFERENCE_FLAG_UNDEFINED_NON_LAZY + define name.str string + end iterate + end macro + + MachO.__TEXT = 0 + MachO.__DATA = 0 + + macro segment? args& + MachO.segment args + if MachO.NSYMS + repeat 1, s:MachO.SEGMENT_NUMBER + load MachO.SEGNAME from MachO:MachO.segment#s.segname + end repeat + if ~MachO.__TEXT & MachO.SEGNAME = '__TEXT' + MachO.__TEXT = 1 + MachO.__stubs + else if ~MachO.__DATA & MachO.SEGNAME = '__DATA' + MachO.__DATA = 1 + MachO.__nl_symbol_ptr + end if + end if + end macro + + postpone + if MachO.NSYMS + + macroBuilder MachO.__stubs + + macroBuilder.line section '__stubs' flags(S_SYMBOL_STUBS+S_ATTR_SOME_INSTRUCTIONS+S_ATTR_PURE_INSTRUCTIONS) reserved1(0) reserved2(MachO.JUMP_SIZE) align 16 + + irpv sym, MachO.nlist + if sym.imported + macroBuilder.line sym: jmp [sym.ptr] + if % = 1 + macroBuilder.line MachO.JUMP_SIZE := $ - sym + end if + end if + end irpv + + macroBuilder.end + + macroBuilder MachO.__nl_symbol_ptr + + if MachO.CPUTYPE and CPU_ARCH_ABI64 + macroBuilder.line section '__nl_symbol_ptr' flags(S_NON_LAZY_SYMBOL_POINTERS) reserved1(0) align 8 + else + macroBuilder.line section '__nl_symbol_ptr' flags(S_NON_LAZY_SYMBOL_POINTERS) reserved1(0) align 4 + end if + + irpv sym, MachO.nlist + if sym.imported + if MachO.CPUTYPE and CPU_ARCH_ABI64 + macroBuilder.line sym.ptr dq 0 + else + macroBuilder.line sym.ptr dd 0 + end if + end if + end irpv + + macroBuilder.end + + if ~MachO.__TEXT + segment '__TEXT' readable executable + end if + + if ~MachO.__DATA + segment '__DATA' readable writable + end if + + segment '__LINKEDIT' readable + + MachO.SYMOFF := $% + irpv sym, MachO.nlist + namespace MachO.nlist#% + n_strx dd sym.strx + n_type db sym.type + n_sect db 0 + n_desc dw sym.desc + if MachO.CPUTYPE and CPU_ARCH_ABI64 + n_value dq sym + else + n_value dd sym + end if + end namespace + end irpv + + MachO.INDIRECTSYMOFF := $% + irpv sym, MachO.nlist + if sym.imported + dd %-1 + end if + end irpv + + MachO.STROFF := $% + db 20h,0 + irpv sym, MachO.nlist + sym.strx := $% - MachO.STROFF + db string sym.str, 0 + end irpv + MachO.STRSIZE := $% - MachO.STROFF + + MachO.command LC_SYMTAB + namespace MachO.symtab_command + symoff dd SYMOFF + nsyms dd NSYMS + stroff dd STROFF + strsize dd STRSIZE + end namespace + + MachO.command LC_DYSYMTAB + namespace MachO.dysymtab_command + ilocalsym dd 0 + nlocalsym dd 0 + iextdefsym dd 0 + nextdefsym dd 0 + iundefsym dd 0 + nundefsym dd NSYMS + tocoff dd 0 + ntoc dd 0 + modtaboff dd 0 + nmodtab dd 0 + extrefsymoff dd 0 + nextrefsyms dd 0 + indirectsymoff dd INDIRECTSYMOFF + nindirectsyms dd NSYMS + extreloff dd 0 + nextrel dd 0 + locreloff dd 0 + nlocrel dd 0 + end namespace + + end if + end postpone + +else + + namespace MachO + + element MachO.section? + element MachO.symbol? + + VM_ADDRESS = 0 + + define nlist null + null.value := 0 + null.type := 0 + null.sect := 0 + null.desc := 0 + null.str := '' + + NSYMS = 1 + NRELOC = 0 + + end namespace + + segment 0 readable writable executable + + macro MachO.section declaration + if MachO.SECTION_NUMBER + org 0 scaleof (1 metadataof $) + 0 scaleof $ + end if + MachO.section declaration + local sym + element sym : MachO.GLOBAL_SECTION_NUMBER * MachO.section + $ + org sym + MachO.SECTION_OFFSET = $% + MachO.SECTION_REL_INDEX = MachO.NRELOC + repeat 1, s:MachO.SEGMENT_NUMBER, t:MachO.SECTION_NUMBER + store MachO.RELOFF+MachO.SECTION_REL_INDEX*8 at MachO:MachO.segment#s#_section#t.reloff + end repeat + end macro + + macro MachO.close_section + MachO.close_section + if MachO.SECTION_NUMBER + repeat 1, s:MachO.SEGMENT_NUMBER, t:MachO.SECTION_NUMBER + store MachO.NRELOC-MachO.SECTION_REL_INDEX at MachO:MachO.segment#s#_section#t.nreloc + end repeat + end if + end macro + + macro public? declaration* + local name + define MachO.nlist name + match value =as? namestr, declaration + name = value + define name.str string namestr + else + name = declaration + define name.str `declaration + end match + if name relativeto 1 elementof name & 1 elementof (1 metadataof name) eq MachO.section + name.value := 0 scaleof (1 metadataof name) + 0 scaleof name + name.type := N_SECT + N_EXT + name.sect := 1 scaleof (1 metadataof name) + else + name.value := name + name.type := N_ABS + name.sect := 0 + end if + name.desc := REFERENCE_FLAG_DEFINED + MachO.NSYMS = MachO.NSYMS + 1 + end macro + + macro extrn? declaration* + match namestr =as? sym, declaration + define MachO.nlist sym + define sym.str string namestr + else + define MachO.nlist declaration + define declaration.str `declaration + end match + match sym, MachO.nlist + element sym : MachO.NSYMS * MachO.symbol + sym.type := N_EXT + sym.sect := 0 + sym.desc := 0 + sym.value := 0 + end match + MachO.NSYMS = MachO.NSYMS + 1 + end macro + + macro dword? value + local v + v = value + if ~ v relativeto 0 & v relativeto 1 elementof v & (1 elementof (1 metadataof v) eq MachO.section | 1 elementof (1 metadataof v) eq MachO.symbol) + MachO.reloc =: $% - MachO.SECTION_OFFSET + (1 scaleof (1 metadataof v)) shl 32 + 2 shl 57 + GENERIC_RELOC_VANILLA shl 60 + if 1 elementof (1 metadataof v) eq MachO.symbol + MachO.reloc = MachO.reloc + 1 shl 59 + end if + MachO.NRELOC = MachO.NRELOC + 1 + emit dword: 0 scaleof (1 metadataof v) + 0 scaleof v + else if ~ v relativeto 0 & (v + $) relativeto 1 elementof (v + $) & (1 elementof (1 metadataof (v + $)) eq MachO.section | 1 elementof (1 metadataof (v + $)) eq MachO.symbol) + if MachO.CPUTYPE = CPU_TYPE_X86_64 + if 1 elementof (1 metadataof (v + $)) eq MachO.symbol + v = v + $ + 4 + else + v = v + 0 scaleof (1 metadataof v) - 0 scaleof (1 metadataof $) + end if + MachO.reloc =: $% - MachO.SECTION_OFFSET + (1 scaleof (1 metadataof (v + $))) shl 32 + 1 shl 56 + 2 shl 57 + X86_64_RELOC_SIGNED_4 shl 60 + else + v = v + 0 scaleof (1 metadataof v) - 0 scaleof (1 metadataof $) + MachO.reloc =: $% - MachO.SECTION_OFFSET + (1 scaleof (1 metadataof (v + $))) shl 32 + 1 shl 56 + 2 shl 57 + GENERIC_RELOC_VANILLA shl 60 + end if + if 1 elementof (1 metadataof (v + $)) eq MachO.symbol + MachO.reloc = MachO.reloc + 1 shl 59 + end if + MachO.NRELOC = MachO.NRELOC + 1 + emit dword: 0 scaleof v + else + emit dword: v + end if + end macro + + postpone + if MachO.NSYMS + + MachO.close_section + macro MachO.close_section + MachO.text + end macro + + rb (-$%) and 11b + + MachO.RELOFF := $% + irpv rel, MachO.reloc + dq rel + end irpv + + MachO.SYMOFF := $% + irpv sym, MachO.nlist + namespace MachO.nlist#% + n_strx dd sym.strx + n_type db sym.type + n_sect db sym.sect + n_desc dw sym.desc + if MachO.CPUTYPE and CPU_ARCH_ABI64 + n_value dq sym.value + else + n_value dd sym.value + end if + end namespace + end irpv + + MachO.STROFF := $% + irpv sym, MachO.nlist + sym.strx := $% - MachO.STROFF + db string sym.str, 0 + end irpv + MachO.STRSIZE := $% - MachO.STROFF + + MachO.command LC_SYMTAB + namespace MachO.symtab_command + symoff dd SYMOFF + nsyms dd NSYMS + stroff dd STROFF + strsize dd STRSIZE + end namespace + + end if + end postpone + + macro align? boundary,value:? + if $ relativeto 0 | MachO.SECTION_ALIGN mod (boundary) = 0 + db (boundary-1)-(0 scaleof $+boundary-1) mod boundary dup value + else + err 'section not aligned enough' + end if + end macro + + macro dd? definitions& + iterate value,definitions + match ?, value + dd ? + else match n =dup? ?, value + dd n dup ? + else match n =dup? (?), value + dd n dup ? + else match n =dup? v, value + repeat n + dword v + end repeat + else + dword value + end match + end iterate + end macro + + struc dd? definitions& + label . : dword + iterate value,definitions + match ?, value + dd ? + else match n =dup? ?, value + dd n dup ? + else match n =dup? (?), value + dd n dup ? + else match n =dup? v, value + repeat n + dword v + end repeat + else + dword value + end match + end iterate + end struc + + macro store? disposition + match data =at? area:address, disposition + store data at area:address + else match data =at? address, disposition + local value,length + match val:len, data + value = val + length = len + else + value = data + length = sizeof(address) + end match + if elementsof value + $%? = $%?-($-address) + virtual at address + if length = 4 + dword value + load value:dword from address + end if + end virtual + restore $%? + end if + store value:length at address + else + store disposition + end match + end macro + +end if diff --git a/toolchain/fasm2/source/macos/system.inc b/toolchain/fasm2/source/macos/system.inc new file mode 100644 index 0000000..0461692 --- /dev/null +++ b/toolchain/fasm2/source/macos/system.inc @@ -0,0 +1,225 @@ + +LINE_FEED = 0Ah + +system_init: + ccall libc.time,timestamp + retn + +system_shutdown: + retn + +malloc: +malloc_fixed: +malloc_growable: +; in: ecx = requested size +; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi +; note: +; use of malloc_fixed hints that block will be kept as is until the end of assembly +; use of malloc_growable hints that block is likely to be resized + push ebx ecx esi edi + ccall libc.malloc,ecx + pop edi esi ecx ebx + test eax,eax + jz out_of_memory + retn +realloc: +; in: eax - memory block, ecx = requested size +; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi + push ebx ecx esi edi + ccall libc.realloc,eax,ecx + pop edi esi ecx ebx + test eax,eax + jz out_of_memory + retn +mfree: +; in: eax - memory block +; out: cf set on error +; preserves: ebx, esi, edi +; note: eax may have value 0 or -1, it should be treated as invalid input then + test eax,eax + jz interface_error + cmp eax,-1 + je interface_error + push ebx esi edi + ccall libc.free,eax + pop edi esi ebx + clc + retn + interface_error: + stc + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push esi edi + call adapt_path + ccall libc.fopen,ebx,_open_mode + pop edi esi + test eax,eax + jz interface_error + mov ebx,eax + clc + retn + adapt_path: + xor ecx,ecx + mov ebx,path_buffer + copy_path: + mov al,[edx+ecx] + cmp al,'\' + jne path_char_ok + mov al,'/' + path_char_ok: + cmp ecx,1000h + jae out_of_memory + mov [ebx+ecx],al + inc ecx + test al,al + jnz copy_path + retn +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push esi edi + call adapt_path + ccall libc.fopen,ebx,_create_mode + pop edi esi + test eax,eax + jz interface_error + mov ebx,eax + clc + retn +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ebx ecx esi edi + ccall libc.fwrite,edx,1,ecx,ebx + pop edi esi ecx ebx + cmp eax,ecx + jne interface_error + clc + ret +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ebx ecx esi edi + ccall libc.fread,edx,1,ecx,ebx + pop edi esi ecx ebx + cmp eax,ecx + jne interface_error + clc + ret +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + ccall libc.fclose,ebx + ret +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + test edx,edx + jnz interface_error + push esi edi ebx + movzx ecx,cl + ccall libc.fseek,ebx,eax,ecx + test eax,eax + jnz lseek_error + mov ebx,[esp] + ccall libc.ftell,ebx + cmp eax,-1 + je lseek_error + xor edx,edx + pop ebx edi esi + clc + ret + lseek_error: + pop ebx edi esi + stc + ret + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx esi + test ecx,ecx + jnz write_string_to_stdout + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stdout: + ccall libc.write,1,esi,ecx + pop esi ebx + retn + +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx esi + test ecx,ecx + jnz write_string_to_stderr + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stderr: + ccall libc.write,2,esi,ecx + pop esi ebx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push ebx ecx esi edi + ccall getenv,esi + pop edi esi ecx ebx + test eax,eax + jz no_environment_variable + push esi + mov esi,eax + xor eax,eax + copy_environment_variable: + mov dl,[esi+eax] + cmp eax,ecx + jae next_environment_variable_character + mov [edi+eax],dl + next_environment_variable_character: + inc eax + test dl,dl + jnz copy_environment_variable + pop esi + environment_variable_ok: + ret + no_environment_variable: + mov eax,1 + jecxz environment_variable_ok + and byte [edi],0 + ret diff --git a/toolchain/fasm2/source/macos/x64/ccall.inc b/toolchain/fasm2/source/macos/x64/ccall.inc new file mode 100644 index 0000000..e75193f --- /dev/null +++ b/toolchain/fasm2/source/macos/x64/ccall.inc @@ -0,0 +1,23 @@ + +; Adapted and tested by Jacob Young (jacobly.alt@gmail.com) + +iterate reg, rdi, rsi, rdx, rcx, r8, r9 + arguments.%? equ reg +end iterate + +macro ccall? proc*,args& + local size + mov rbp,rsp + and rsp,0FFFFFFFFFFFFFFF0h + match any, args + iterate arg, args + if sizeof (arg) + lea arguments.%,[arg] + else if ~ arg eq arguments.% + mov arguments.%,arg + end if + end iterate + end match + call proc + mov rsp,rbp +end macro diff --git a/toolchain/fasm2/source/macos/x64/fasmg.asm b/toolchain/fasm2/source/macos/x64/fasmg.asm new file mode 100644 index 0000000..4baa6d7 --- /dev/null +++ b/toolchain/fasm2/source/macos/x64/fasmg.asm @@ -0,0 +1,540 @@ + +; Adapted and tested by Jacob Young (jacobly.alt@gmail.com) + +include 'macro/struct.inc' + +include 'ccall.inc' + +format MachO64 executable at 1000h +entry start + +include '../../linux/x64/32on64.alm' + +include '../../version.inc' + +interpreter '/usr/lib/dyld' +uses '/usr/lib/libSystem.B.dylib' + +import libc.fopen,'_fopen',\ + libc.fclose,'_fclose',\ + libc.fread,'_fread',\ + libc.fwrite,'_fwrite',\ + libc.fseek,'_fseek',\ + libc.ftell,'_ftell',\ + libc.time,'_time',\ + libc.write,'_write',\ + mmap,'_mmap',\ + munmap,'_munmap',\ + getenv,'_getenv',\ + gettimeofday,'_gettimeofday',\ + exit,'_exit' + +struct timeval + time_t dq ? + suseconds_t dd ?,? +ends + +segment '__TEXT' readable executable + +section '__text' align 16 + + start: + mov rcx,[rsp] + mov [argc],rcx + lea rbx,[rsp+8] + mov [argv],rbx + + call system_init + + call get_arguments + mov bl,al + cmp [no_logo],0 + jne logo_ok + mov esi,_logo + xor ecx,ecx + call display_string + logo_ok: + test bl,bl + jnz display_usage_information + + xor al,al + mov ecx,[verbosity_level] + jecxz init + or al,TRACE_ERROR_STACK + dec ecx + jz init + or al,TRACE_DISPLAY + init: + call assembly_init + + ccall gettimeofday,start_time,0 + + assemble: + mov esi,[initial_commands] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,_code_cannot_be_generated + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + jmp assembly_failed + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + cmp [no_logo],0 + jne summary_done + mov eax,[current_pass] + xor edx,edx + call itoa + call display_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_string + ccall gettimeofday,end_time,0 + mov rax,[end_time.time_t] + sub rax,[start_time.time_t] + mov rcx,1000000 + mul rcx + mov ecx,[end_time.suseconds_t] + add ecx,50000 + add rax,rcx + adc rdx,0 + mov ecx,[start_time.suseconds_t] + sub rax,rcx + sbb rdx,0 + mov rcx,1000000 + div rcx + mov rbx,rax + mov rax,rdx + xor edx,edx + mov rcx,100000 + div rcx + mov [tenths_of_second],eax + xchg rax,rbx + or rbx,rax + jz display_output_length + mov rdx,rax + shr rdx,32 + call itoa + call display_string + mov esi,_message_suffix + mov ecx,1 + call display_string + mov eax,[tenths_of_second] + xor edx,edx + call itoa + call display_string + mov esi,_seconds + xor ecx,ecx + call display_string + display_output_length: + call get_output_length + push rax rdx + call itoa + call display_string + pop rdx rax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_string + mov esi,_new_line + xor ecx,ecx + call display_string + summary_done: + + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + call assembly_shutdown + call system_shutdown + + ccall exit,0 + + assembly_failed: + + call show_errors + + call assembly_shutdown + call system_shutdown + + ccall exit,2 + + write_failed: + mov ebx,_write_failed + jmp fatal_error + + out_of_memory: + mov ebx,_out_of_memory + jmp fatal_error + + fatal_error: + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + call assembly_shutdown + call system_shutdown + + ccall exit,3 + + display_usage_information: + + mov esi,_usage + xor ecx,ecx + call display_string + + call system_shutdown + + ccall exit,1 + + get_arguments: + xor eax,eax + mov [initial_commands],eax + mov [source_path],eax + mov [output_path],eax + mov [no_logo],al + mov [verbosity_level],eax + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1 + mov [maximum_depth_of_stack],10000 + mov rcx,[argc] + mov rbx,[argv] + add rbx,8 + dec ecx + jz error_in_arguments + get_argument: + mov rsi,[rbx] + mov al,[rsi] + cmp al,'-' + je get_option + cmp [source_path],0 + jne get_output_file + call strdup + mov [source_path],eax + jmp next_argument + get_output_file: + cmp [output_path],0 + jne error_in_arguments + call strdup + mov [output_path],eax + jmp next_argument + get_option: + inc rsi + lodsb + cmp al,'e' + je set_errors_limit + cmp al,'E' + je set_errors_limit + cmp al,'i' + je insert_initial_command + cmp al,'I' + je insert_initial_command + cmp al,'p' + je set_passes_limit + cmp al,'P' + je set_passes_limit + cmp al,'r' + je set_recursion_limit + cmp al,'R' + je set_recursion_limit + cmp al,'v' + je set_verbose_mode + cmp al,'V' + je set_verbose_mode + cmp al,'n' + je set_no_logo + cmp al,'N' + jne error_in_arguments + set_no_logo: + or [no_logo],-1 + cmp byte [rsi],0 + je next_argument + error_in_arguments: + or al,-1 + ret + set_verbose_mode: + cmp byte [rsi],0 + jne get_verbose_setting + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + get_verbose_setting: + call get_option_value + cmp edx,2 + ja error_in_arguments + mov [verbosity_level],edx + jmp next_argument + set_errors_limit: + cmp byte [rsi],0 + jne get_errors_setting + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + get_errors_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_errors],edx + jmp next_argument + set_recursion_limit: + cmp byte [rsi],0 + jne get_recursion_setting + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + get_recursion_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_depth_of_stack],edx + jmp next_argument + set_passes_limit: + cmp byte [rsi],0 + jne get_passes_setting + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + get_passes_setting: + call get_option_value + test edx,edx + jz error_in_arguments + mov [maximum_number_of_passes],edx + next_argument: + add rbx,8 + dec ecx + jnz get_argument + cmp [source_path],0 + je error_in_arguments + xor al,al + ret + get_option_value: + xor eax,eax + mov edx,eax + find_option_value: + cmp byte [rsi],20h + jne get_option_digit + inc rsi + jmp find_option_value + get_option_digit: + lodsb + test al,al + jz option_value_ok + sub al,30h + jc invalid_option_value + cmp al,9 + ja invalid_option_value + imul edx,10 + jo invalid_option_value + add edx,eax + jc invalid_option_value + jmp get_option_digit + option_value_ok: + dec rsi + clc + ret + invalid_option_value: + stc + ret + insert_initial_command: + cmp byte [rsi],0 + jne measure_initial_command + dec ecx + jz error_in_arguments + add rbx,8 + mov rsi,[rbx] + measure_initial_command: + push rbx rcx rdi + mov rdi,rsi + or ecx,-1 + xor al,al + repne scasb + not ecx + dec ecx + mov edi,[initial_commands] + lea eax,[ecx+2] + test edi,edi + jz allocate_initial_commands_buffer + mov edx,[initial_commands_length] + add edi,edx + add eax,edx + cmp eax,[initial_commands_maximum_length] + ja grow_initial_commands_buffer + copy_initial_command: + rep movsb + mov ax,0Ah + stosw + dec edi + sub edi,[initial_commands] + mov [initial_commands_length],edi + pop rdi rcx rbx + jmp next_argument + allocate_initial_commands_buffer: + push rsi rcx + mov ecx,eax + call malloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + pop rcx rsi + jmp copy_initial_command + grow_initial_commands_buffer: + push rsi rcx + mov ecx,eax + mov eax,[initial_commands] + call realloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + add edi,[initial_commands_length] + pop rcx rsi + jmp copy_initial_command + + strdup: + ; in: rsi - ASCIIZ string + ; out: eax - copy of the string in 32-bit addressable memory + ; preserves: rbx, rcx, rsi + push rbx rcx rsi + mov rdi,rsi + or ecx,-1 + xor al,al + repne scasb + not ecx + push rsi rcx + call malloc + pop rcx rsi + mov edi,eax + rep movsb + pop rsi rcx rbx + ret + + include 'system.inc' + + use32on64 + + include '../../malloc.inc' + include '../../assembler.inc' + include '../../symbols.inc' + include '../../expressions.inc' + include '../../conditions.inc' + include '../../floats.inc' + include '../../directives.inc' + include '../../calm.inc' + include '../../errors.inc' + include '../../map.inc' + include '../../reader.inc' + include '../../output.inc' + include '../../console.inc' + +section '__cstring' align 4 + + _logo db 'flat assembler version g.',VERSION,10,0 + + _usage db 'Usage: fasmg source [output]',10 + db 'Optional settings:',10 + db ' -p limit Set the maximum allowed number of passes (default 100)',10 + db ' -e limit Set the maximum number of displayed errors (default 1)',10 + db ' -r limit Set the maximum depth of the stack (default 10000)',10 + db ' -v flag Enable or disable showing all lines from the stack (default 0)',10 + db ' -i command Insert instruction at the beginning of source',13,10 + db ' -n Do not show logo nor summary',13,10 + db 0 + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'failed to write the output file',0 + _out_of_memory db 'not enough memory to complete the assembly',0 + _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 + + _open_mode db 'r',0 + _create_mode db 'w',0 + + include '../../tables.inc' + include '../../messages.inc' + +segment '__DATA' readable writable + +section '__bss' align 4 + + include '../../variables.inc' + + mmap_hint dd ? + malloc_freelist dd ? + + source_path dd ? + output_path dd ? + maximum_number_of_passes dd ? + + initial_commands dd ? + initial_commands_length dd ? + initial_commands_maximum_length dd ? + + files dd ? + files_count dd ? + files_maximum_count dd ? + + argc dq ? + argv dq ? + timestamp dq ? + + start_time timeval + end_time timeval + tenths_of_second dd ? + + verbosity_level dd ? + no_logo db ? + + local_heap_available db ? + + path_buffer rb 1000h + + align 1000h + + LOCAL_HEAP_SIZE = 1000000h + + local_heap rb LOCAL_HEAP_SIZE diff --git a/toolchain/fasm2/source/macos/x64/system.inc b/toolchain/fasm2/source/macos/x64/system.inc new file mode 100644 index 0000000..55e0a92 --- /dev/null +++ b/toolchain/fasm2/source/macos/x64/system.inc @@ -0,0 +1,287 @@ + +; Adapted and tested by Jacob Young (jacobly.alt@gmail.com) + +LINE_FEED = 0Ah + +system_init: + ccall libc.time,timestamp + or [local_heap_available],1 + retn + +system_shutdown: + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push rsi rdi + call adapt_path + ccall libc.fopen,rbx,_open_mode + put_file_entry: + pop rdi rsi + test rax,rax + jz interface_error + push rax + mov eax,[files] + mov ecx,[files_count] + mov ebx,ecx + inc ecx + mov [files_count],ecx + cmp ecx,[files_maximum_count] + ja grow_files_buffer + store_file_entry: + pop rdx + mov [eax+ebx*8],rdx + clc + retn + interface_error: + stc + retn + grow_files_buffer: + shl ecx,4 + test eax,eax + jz allocate_files_buffer + call realloc + jmp allocated_files_buffer + allocate_files_buffer: + call malloc + allocated_files_buffer: + mov [files],eax + shr ecx,3 + mov [files_maximum_count],ecx + jmp store_file_entry + adapt_path: + xor ecx,ecx + mov ebx,path_buffer + copy_path: + mov al,[edx+ecx] + cmp al,'\' + jne path_char_ok + mov al,'/' + path_char_ok: + cmp ecx,1000h + jae out_of_memory + mov [ebx+ecx],al + inc ecx + test al,al + jnz copy_path + retn +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + push rsi rdi + call adapt_path + ccall libc.fopen,rbx,_create_mode + jmp put_file_entry +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push rbx rcx rsi rdi + mov eax,[files] + mov rax,[eax+ebx*8] + ccall libc.fwrite,rdx,1,rcx,rax + pop rdi rsi rcx rbx + cmp eax,ecx + jne interface_error + clc + ret +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push rbx rcx rsi rdi + mov eax,[files] + mov rax,[eax+ebx*8] + ccall libc.fread,rdx,1,rcx,rax + pop rdi rsi rcx rbx + cmp eax,ecx + jne interface_error + clc + ret +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + push rsi rdi + mov edi,[files] + mov rdi,[edi+ebx*8] + ccall libc.fclose,rdi + pop rdi rsi + ret +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + push rsi rdi rbx + shl rdx,32 + or rax,rdx + movzx ecx,cl + mov edi,[files] + mov rdi,[edi+ebx*8] + push rdi + ccall libc.fseek,rdi,rax,rcx + test eax,eax + jnz lseek_error + pop rdi + ccall libc.ftell,rdi + cmp rax,-1 + je lseek_error + mov rdx,rax + shr rdx,32 + mov eax,eax + pop rbx rdi rsi + clc + ret + lseek_error: + pop rbx rdi rsi + stc + ret + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push rbx rsi + test ecx,ecx + jnz write_string_to_stdout + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stdout: + ccall libc.write,1,rsi,rcx + pop rsi rbx + retn + +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push rbx rsi + test ecx,ecx + jnz write_string_to_stderr + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stderr: + ccall libc.write,2,rsi,rcx + pop rsi rbx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push rbx rcx rsi rdi + ccall getenv,rsi + pop rdi rsi rcx rbx + test rax,rax + jz no_environment_variable + push rsi + mov rsi,rax + xor eax,eax + copy_environment_variable: + mov dl,[rsi+rax] + cmp eax,ecx + jae next_environment_variable_character + mov [edi+eax],dl + next_environment_variable_character: + inc eax + test dl,dl + jnz copy_environment_variable + pop rsi + environment_variable_ok: + ret + no_environment_variable: + mov eax,1 + jecxz environment_variable_ok + and byte [edi],0 + ret + +VALLOC_MINIMUM_SIZE = 100000h + +valloc: +; in: ecx = requested minimum size +; out: eax - allocated block, ecx = allocated size, zero if failed +; preserves: ebx, esi, edi + cmp ecx,VALLOC_MINIMUM_SIZE + jbe valloc_size_minimum + dec ecx + and ecx,(-1) shl 12 + add ecx,1 shl 12 + jmp valloc_size_ready + valloc_size_minimum: + mov ecx,VALLOC_MINIMUM_SIZE + valloc_size_ready: + push rbx rsi rdi + cmp [local_heap_available],0 + je valloc_mmap + cmp ecx,LOCAL_HEAP_SIZE + ja valloc_mmap + and [local_heap_available],0 + mov eax,local_heap + mov ecx,LOCAL_HEAP_SIZE + jmp valloc_ok + valloc_mmap: + push rcx + ccall mmap,0,rcx, \ + 3, \ ; PROT_READ + PROT_WRITE + 9002h, \ ; MAP_PRIVATE + MAP_ANONYMOUS + MAP_32BIT + -1,0 + pop rsi + cmp eax,-1 + je valloc_mmap_with_hint + mov ecx,eax + cmp rcx,rax + jne valloc_mmap_unusable + add ecx,esi + jnc mmap_ok + valloc_mmap_unusable: + ccall munmap,rax,rsi + valloc_mmap_with_hint: + push rsi + mov edi,[mmap_hint] + ccall mmap,rdi,rsi, \ + 3, \ ; PROT_READ + PROT_WRITE + 1002h, \ ; MAP_PRIVATE + MAP_ANONYMOUS + -1,0 + pop rsi + cmp eax,-1 + je valloc_failed + mov ecx,eax + cmp rcx,rax + jne valloc_failed + add ecx,esi + jc valloc_failed + mmap_ok: + sub ecx,eax + valloc_ok: + lea edx,[eax+ecx] + mov [mmap_hint],edx + pop rdi rsi rbx + retn + valloc_failed: + xor ecx,ecx + pop rdi rsi rbx + retn \ No newline at end of file diff --git a/toolchain/fasm2/source/malloc.inc b/toolchain/fasm2/source/malloc.inc new file mode 100644 index 0000000..9b99e46 --- /dev/null +++ b/toolchain/fasm2/source/malloc.inc @@ -0,0 +1,343 @@ + +; a very basic implementation of malloc/realloc +; for porting fasmg to systems that do not have such API natively + +struct MemoryHeader + size dd ? ; total size of this block, the lowest bit set for blocks in use + preceding_size dd ? ; total size of the block that precedes this one in memory (zero if this is an initial block of address range) +ends + +struct FreeMemory + header MemoryHeader + right dd ? ; next free block in cyclic list + left dd ? ; previous free block in cyclic list +ends + +assert defined valloc +; in: ecx = requested minimum size +; out: eax - allocated block, ecx = allocated size, zero if failed +; preserves: ebx, esi, edi +; note: +; valloc is called to request raw memory from the OS; +; it is encouraged to allocate more memory than requested (even entire available memory), +; the obtained memory is kept indefinitely in the pool for malloc +; and should be released by OS automatically when the process ends; +; if the OS does not do it automatically, additional list of the memory areas +; may need to be maintained to release them before exit + +malloc: +malloc_fixed: +malloc_growable: +; in: ecx = requested size +; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi + add ecx,sizeof.MemoryHeader-1 + jc out_of_memory + and ecx,(-1) shl 2 + add ecx,1 shl 2 + jc out_of_memory + cmp ecx,sizeof.FreeMemory + jae malloc_size_ok + mov ecx,sizeof.FreeMemory + malloc_size_ok: + mov eax,[malloc_freelist] + test eax,eax + jz malloc_new + find_fit: + cmp ecx,[eax+MemoryHeader.size] + jbe malloc_use_block + mov eax,[eax+FreeMemory.left] + cmp eax,[malloc_freelist] + jne find_fit + malloc_new: + push ecx + add ecx,sizeof.MemoryHeader + jc out_of_memory + call valloc + test ecx,ecx + jz out_of_memory + xor edx,edx + mov [eax+MemoryHeader.preceding_size],edx + pop edx + push eax + sub ecx,edx + cmp ecx,sizeof.FreeMemory+sizeof.MemoryHeader + jb no_space_for_free_block + mov [eax+MemoryHeader.size],edx + add eax,edx + mov [eax+MemoryHeader.preceding_size],edx + mov edx,ecx + sub edx,sizeof.MemoryHeader + dec edx + and edx,(-1) shl 2 + add edx,1 shl 2 + mov [eax+MemoryHeader.size],edx + mov ecx,[malloc_freelist] + jecxz freelist_empty + mov [eax+FreeMemory.left],ecx + mov edx,eax + xchg edx,[ecx+FreeMemory.right] + mov [eax+FreeMemory.right],edx + mov [edx+FreeMemory.left],eax + mov edx,[eax+MemoryHeader.size] + jmp free_block_ready + no_space_for_free_block: + sub ecx,sizeof.MemoryHeader + add edx,ecx + mov [eax+MemoryHeader.size],edx + jmp append_limiter + freelist_empty: + mov [eax+FreeMemory.left],eax + mov [eax+FreeMemory.right],eax + free_block_ready: + mov [malloc_freelist],eax + append_limiter: + add eax,edx + mov [eax+MemoryHeader.preceding_size],edx + mov [eax+MemoryHeader.size],sizeof.MemoryHeader or 1 ; cannot be freed + pop eax + finish_malloc: + mov ecx,[eax+MemoryHeader.size] + or [eax+MemoryHeader.size],1 + add eax,sizeof.MemoryHeader + sub ecx,sizeof.MemoryHeader + retn + malloc_use_block: + mov edx,[eax+MemoryHeader.size] + sub edx,ecx + cmp edx,sizeof.FreeMemory + jb use_whole_block + mov [eax+MemoryHeader.size],ecx + mov [eax+ecx+MemoryHeader.preceding_size],ecx + add ecx,eax + mov [malloc_freelist],ecx + mov [ecx+MemoryHeader.size],edx + mov [ecx+edx+MemoryHeader.preceding_size],edx + mov edx,[eax+FreeMemory.right] + cmp edx,eax + je update_free_singleton + mov [ecx+FreeMemory.right],edx + mov [edx+FreeMemory.left],ecx + mov edx,[eax+FreeMemory.left] + mov [ecx+FreeMemory.left],edx + mov [edx+FreeMemory.right],ecx + jmp finish_malloc + update_free_singleton: + mov [ecx+FreeMemory.left],ecx + mov [ecx+FreeMemory.right],ecx + jmp finish_malloc + use_whole_block: + mov edx,[eax+FreeMemory.right] + cmp edx,eax + je depleted_freelist + mov ecx,[eax+FreeMemory.left] + mov [ecx+FreeMemory.right],edx + mov [edx+FreeMemory.left],ecx + mov [malloc_freelist],edx + jmp finish_malloc + depleted_freelist: + and [malloc_freelist],0 + jmp finish_malloc + +mfree: +; in: eax - memory block +; out: cf set on error +; preserves: ebx, esi, edi +; note: eax may have value 0 or -1, it should be treated as invalid input then + test eax,eax + jz mfree_error + cmp eax,-1 + je mfree_error + sub eax,sizeof.MemoryHeader + mov ecx,[eax+MemoryHeader.size] + btr ecx,0 + jnc mfree_error + cmp ecx,sizeof.FreeMemory + jb mfree_error + cmp [eax+ecx+MemoryHeader.preceding_size],ecx + jne mfree_error + mov [eax+MemoryHeader.size],ecx + mov edx,eax + sub edx,[eax+MemoryHeader.preceding_size] + cmp edx,eax + je no_preceding_block + test [edx+MemoryHeader.size],1 + jz coalesce_with_preceding_block + no_preceding_block: + test [eax+ecx+MemoryHeader.size],1 + jz coalesce_with_following_block + mov ecx,[malloc_freelist] + jecxz mfree_init_freelist + mov edx,[ecx+FreeMemory.right] + mov [eax+FreeMemory.left],ecx + mov [edx+FreeMemory.left],eax + mov [eax+FreeMemory.right],edx + mov [ecx+FreeMemory.right],eax + mfree_ok: + mov [malloc_freelist],eax + clc + retn + mfree_init_freelist: + mov [eax+FreeMemory.left],eax + mov [eax+FreeMemory.right],eax + jmp mfree_ok + mfree_error: + stc + retn + coalesce_with_preceding_block: + add ecx,[edx+MemoryHeader.size] + test [edx+ecx+MemoryHeader.size],1 + jz coalesce_on_both_ends + mov [edx+MemoryHeader.size],ecx + mov [edx+ecx+MemoryHeader.preceding_size],ecx + clc + retn + coalesce_on_both_ends: + lea eax,[edx+ecx] + add ecx,[eax+MemoryHeader.size] + mov [edx+MemoryHeader.size],ecx + mov [edx+ecx+MemoryHeader.preceding_size],ecx + mov [malloc_freelist],edx + mov ecx,[eax+FreeMemory.left] + mov edx,[eax+FreeMemory.right] + mov [edx+FreeMemory.left],ecx + mov [ecx+FreeMemory.right],edx + clc + retn + coalesce_with_following_block: + push ebx + lea ebx,[eax+ecx] + add ecx,[ebx+MemoryHeader.size] + mov [eax+MemoryHeader.size],ecx + mov [eax+ecx+MemoryHeader.preceding_size],ecx + mov ecx,[ebx+FreeMemory.left] + mov edx,[ebx+FreeMemory.right] + mov [ecx+FreeMemory.right],eax + mov [edx+FreeMemory.left],eax + mov ecx,[ebx+FreeMemory.left] + mov edx,[ebx+FreeMemory.right] + mov [eax+FreeMemory.left],ecx + mov [eax+FreeMemory.right],edx + pop ebx + jmp mfree_ok + +realloc: +; in: eax - memory block, ecx = requested size +; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi + add ecx,sizeof.MemoryHeader-1 + jc out_of_memory + and ecx,(-1) shl 2 + add ecx,1 shl 2 + jc out_of_memory + sub eax,sizeof.MemoryHeader + mov edx,[eax+MemoryHeader.size] + and edx,not 1 + cmp ecx,edx + jbe realloc_retain + test [eax+edx+MemoryHeader.size],1 + jnz realloc_and_copy + add edx,[eax+edx+MemoryHeader.size] + cmp ecx,edx + ja realloc_and_copy + sub edx,ecx + cmp edx,sizeof.FreeMemory + jb append_whole_block + push esi edi + push ecx edx + lea edi,[eax+ecx] + xchg ecx,[eax+MemoryHeader.size] + and ecx,not 1 + lea esi,[eax+ecx] + mov ecx,[esi+FreeMemory.left] + mov edx,[esi+FreeMemory.right] + mov [edx+FreeMemory.left],edi + mov [ecx+FreeMemory.right],edi + mov ecx,[esi+FreeMemory.left] + mov edx,[esi+FreeMemory.right] + mov [edi+FreeMemory.left],ecx + mov [edi+FreeMemory.right],edx + mov [malloc_freelist],edi + pop edx ecx + mov [edi+MemoryHeader.size],edx + mov [edi+edx+MemoryHeader.preceding_size],edx + mov [edi+MemoryHeader.preceding_size],ecx + pop edi esi + jmp finish_malloc + append_whole_block: + add edx,ecx + mov [eax+edx+MemoryHeader.preceding_size],edx + xchg edx,[eax+MemoryHeader.size] + and edx,not 1 + add edx,eax + mov ecx,[edx+FreeMemory.left] + cmp ecx,edx + je depleted_freelist + mov edx,[edx+FreeMemory.right] + mov [ecx+FreeMemory.right],edx + mov [edx+FreeMemory.left],ecx + mov [malloc_freelist],ecx + jmp finish_malloc + realloc_retain: + and [eax+MemoryHeader.size],not 1 + jmp finish_malloc + realloc_and_copy: + push esi edi + lea esi,[eax+sizeof.MemoryHeader] + call malloc_growable + push eax ecx + mov edi,eax + mov eax,esi + mov ecx,[esi-sizeof.MemoryHeader+MemoryHeader.size] + shr ecx,2 + rep movsd + call mfree + pop ecx eax + pop edi esi + retn + +if used mcheck + + mcheck: + pushf + push eax ebx ecx edx + mov eax,[malloc_freelist] + test eax,eax + jz integrity_verified + verify_freelist: + mov ebx,eax + verify_preceding_blocks: + mov ecx,[ebx+MemoryHeader.preceding_size] + jecxz preceding_blocks_ok + sub ebx,ecx + mov edx,[ebx+MemoryHeader.size] + and edx,not 1 + cmp ecx,edx + je verify_preceding_blocks + jmp internal_error + preceding_blocks_ok: + mov ebx,eax + verify_following_blocks: + mov ecx,[ebx+MemoryHeader.size] + and ecx,not 1 + cmp ecx,sizeof.MemoryHeader + je following_blocks_ok + add ebx,ecx + cmp ecx,[ebx+MemoryHeader.preceding_size] + je verify_following_blocks + jmp internal_error + following_blocks_ok: + mov edx,[eax+FreeMemory.right] + cmp eax,[edx+FreeMemory.left] + je verify_next + jmp internal_error + verify_next: + mov eax,edx + cmp eax,[malloc_freelist] + jne verify_freelist + integrity_verified: + pop edx ecx ebx eax + popf + retn + +end if diff --git a/toolchain/fasm2/source/map.inc b/toolchain/fasm2/source/map.inc new file mode 100644 index 0000000..a4f3579 --- /dev/null +++ b/toolchain/fasm2/source/map.inc @@ -0,0 +1,237 @@ + +; this is a simple map used primarily for the source cache + +struct Map + hash_mask dd ? + linked_blocks dd ? + free_space dd ? + free_space_length dd ? +ends + +struct MapEntry + name dd ? + name_length dd ? + value dd ? + next_entry dd ? +ends + +create_string_map: +; in: cl = number of hash bits +; out: ebx - new map +; preserves: esi + mov ebx,1 + shl ebx,cl + shl ebx,2 + lea ecx,[sizeof.Map+ebx*4] + call malloc_fixed + xchg ebx,eax + mov ecx,eax + dec eax + mov [ebx+Map.hash_mask],eax + lea edi,[ebx+sizeof.Map] + xor eax,eax + rep stosd + mov ecx,1000h + call malloc_fixed + mov [ebx+Map.linked_blocks],eax + xor edx,edx + mov [eax],edx + add eax,10h + mov [ebx+Map.free_space],eax + mov [ebx+Map.free_space_length],1000h-10h + retn + +destroy_string_map: +; in: ebx - map +; preserves: esi, edi + mov eax,ebx + mov ebx,[ebx+Map.linked_blocks] + call mfree + free_map_blocks: + test ebx,ebx + jz string_map_destroyed + mov eax,ebx + mov ebx,[ebx] + call mfree + jmp free_map_blocks + string_map_destroyed: + retn + +get_from_map: +; in: +; ebx - map +; esi - string +; ecx = string length, zero for ASCIIZ string +; out: +; eax = value +; cf set when no entry found +; preserves: ebx, [esi], edi +; note: when entry is found, esi is replaced with pointer to the same string in persistent storage + call get_bucket + test eax,eax + jz not_found_in_map + call find_map_entry + jc not_found_in_map + mov eax,[eax+MapEntry.value] + retn + get_bucket: + call hash_string + and edx,[ebx+Map.hash_mask] + mov eax,[ebx+sizeof.Map+edx*4] + retn + find_map_entry: + cmp [eax+MapEntry.name_length],ecx + jne next_map_entry + push edi + mov edi,[eax+MapEntry.name] + test edi,edi + jz not_this_map_entry + push ecx esi + repe cmpsb + pop esi ecx + jne not_this_map_entry + mov esi,edi + sub esi,ecx + pop edi + clc + retn + not_this_map_entry: + pop edi + next_map_entry: + mov eax,[eax+MapEntry.next_entry] + test eax,eax + jnz find_map_entry + not_found_in_map: + stc + retn + +put_into_map: +; in: +; ebx - map +; esi - string +; ecx = string length, zero for ASCIIZ string +; eax = value +; preserves: ebx, [esi], edi +; note: +; esi is replaced with pointer to the same string in persistent storage, +; an ASCIIZ string is a key with length including the terminating zero +; and when it is put into persistent storage, final zero is copied as well + push eax + call get_bucket + test eax,eax + jz new_bucket + call find_map_entry + jnc put_value_into_map_entry + mov eax,[ebx+sizeof.Map+edx*4] + find_free_map_entry: + cmp [eax+MapEntry.name],0 + je fill_map_entry + mov edx,eax + mov eax,[eax+MapEntry.next_entry] + test eax,eax + jnz find_free_map_entry + call allocate_map_entry + mov [edx+MapEntry.next_entry],eax + jmp new_map_entry + new_bucket: + call allocate_map_entry + mov [ebx+sizeof.Map+edx*4],eax + new_map_entry: + mov [eax+MapEntry.next_entry],0 + fill_map_entry: + mov [eax+MapEntry.name_length],ecx + push eax + call store_string + pop eax + mov [eax+MapEntry.name],esi + put_value_into_map_entry: + pop [eax+MapEntry.value] + retn + allocate_map_entry: + mov eax,[ebx+Map.free_space] + add [ebx+Map.free_space],sizeof.MapEntry + sub [ebx+Map.free_space_length],sizeof.MapEntry + jc map_out_of_free_space + retn + map_out_of_free_space: + push ecx edx + mov ecx,1000h + call malloc_fixed + mov edx,eax + xchg [ebx+Map.linked_blocks],edx + mov [eax],edx + add eax,10h + mov [ebx+Map.free_space],eax + mov [ebx+Map.free_space_length],1000h-10h + pop edx ecx + jmp allocate_map_entry + +remove_from_map: +; in: +; ebx - map +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, [esi], edi + call get_bucket + test eax,eax + jz not_found_in_map + call find_map_entry + jc not_found_in_map + mov dword [eax+MapEntry.name],0 + retn + +iterate_through_map: +; in: +; ebx - map +; edi - callback function +; callback: +; eax = value +; esi - string +; ecx = string length +; edx - MapEntry + mov ecx,[ebx+Map.hash_mask] + inc ecx + add ebx,sizeof.Map + iterate_through_hash_table: + mov edx,[ebx] + iterate_through_bucket: + test edx,edx + jz end_of_bucket + push ebx ecx edx edi + mov eax,[edx+MapEntry.value] + mov esi,[edx+MapEntry.name] + mov ecx,[edx+MapEntry.name_length] + call edi + pop edi edx ecx ebx + mov edx,[edx+MapEntry.next_entry] + jmp iterate_through_bucket + end_of_bucket: + add ebx,4 + loop iterate_through_hash_table + retn + +hash_string: +; in: esi - string, ecx = string length, zero for ASCIIZ string +; out: ecx = string length, edx = 32-bit hash +; preserves: ebx, esi, edi + mov edx,FNV_OFFSET + jecxz hash_asciiz + mov eax,ecx + hash_known_length: + xor dl,[esi] + inc esi + imul edx,FNV_PRIME + loop hash_known_length + mov ecx,eax + sub esi,ecx + retn + hash_asciiz: + inc ecx + lodsb + xor dl,al + imul edx,FNV_PRIME + test al,al + jnz hash_asciiz + hash_ready: + sub esi,ecx + retn diff --git a/toolchain/fasm2/source/messages.inc b/toolchain/fasm2/source/messages.inc new file mode 100644 index 0000000..be37c77 --- /dev/null +++ b/toolchain/fasm2/source/messages.inc @@ -0,0 +1,52 @@ + +_macro_source db 'macro ',0 +_preprocessed_source db 'assemble ',0 +_unnamed_source db '?',0 +_memory_source db 'eval',0 +_space db ' ',0 +_line_number_prefix db ' [',0 +_line_number_suffix db ']',0 +_line_content_prefix db ':' +_line_segment_prefix db LINE_FEED,9,0 +_calm_source db ' (CALM)',0 +_single_quote db 27h,0 +_preprocessed_text_prefix db 'Processed: ',0 +_error_prefix db 'Error: ',0 +_custom_error_prefix db 'Custom error: ',0 +_message_suffix db '.' +_new_line db LINE_FEED,0 + +_source_file_not_found db "source file '%s' not found",0 +_error_reading_file db "error reading file '%s'",0 +_missing_end_quote db "missing end quote",0 +_illegal_instruction db "illegal instruction",0 +_invalid_argument db "invalid argument",0 +_missing_argument db "missing argument",0 +_extra_characters_on_line db "extra characters on line",0 +_invalid_identifier db "invalid identifier",0 +_invalid_number db "invalid number",0 +_undefined_symbol db "symbol '%i' is undefined or out of scope",0 +_invalid_symbol_value db "the value of symbol '%i' is not valid for this use",0 +_conflicting_definition db "definition of '%i' in conflict with already defined symbol",0 +_cannot_apply_to_constant db "cannot apply this operation to constant",0 +_symbolic_self_reference db "detected a circular reference of symbolic values",0 +_unexpected_instruction db "unexpected instruction",0 +_missing_end_directive db "missing end directive",0 +_missing_closing_chevron db "missing closing chevron",0 +_invalid_value db "value of type not allowed in this context",0 +_invalid_expression db "invalid expression",0 +_missing_closing_parenthesis db "missing closing parenthesis",0 +_excess_closing_parenthesis db "excess closing parenthesis",0 +_value_out_of_range db "value out of allowed range",0 +_indeterminate_result db "expression has indeterminate, infinite, or infinitesimal result",0 +_misused_variable_term db "variable term used where not expected",0 +_nonlinear_polynomial db "cannot multiply variable terms",0 +_subdivided_variable_term db "cannot subdivide variable term",0 +_values_not_comparable db "values not comparable",0 +_assertion_failed db "assertion failed",0 +_area_overflow db "exceeded the maximum allowed length of output area",0 +_address_out_of_range db "address out of range",0 +_invalid_area db "invalid or inaccessible addressing area",0 +_stack_limit_exceeded db "exceeded the maximum allowed depth of the stack",0 +_repeated_declaration db "choice has already been declared",0 +_undefined_jump_target db "the target of the jump is not defined in this instruction",0 diff --git a/toolchain/fasm2/source/output.inc b/toolchain/fasm2/source/output.inc new file mode 100644 index 0000000..091c87a --- /dev/null +++ b/toolchain/fasm2/source/output.inc @@ -0,0 +1,883 @@ + +struct OutputArea + cached_offset dq ? + definition dd ? ; pointer to ValueDefinition +ends + +struct AreaHeader + flags dd ? ; AREA_# + base_address_length dd ? + uninitialized_length dd ? +ends + +AREA_VIRTUAL = 1 +AREA_VARIABLE = 2 +AREA_SHIFT_TRACKING_DISABLED = 4 + +create_output_area: +; in: +; esi - base address in format of VALTYPE_NUMERIC value +; ecx = length of base address value +; out: +; ebx - AreaHeader +; edx - ValueDefinition + mov eax,[current_output_area_entry] + test eax,eax + jz create_first_output_area + push ecx + lea ecx,[eax+sizeof.OutputArea*2] + cmp ecx,[output_areas_list_end] + jbe get_next_output_entry + mov eax,[output_areas_list] + sub ecx,eax + sub [current_output_area_entry],eax + sub [initial_output_area_entry],eax + sub [output_areas_list_end],eax + call grow_stack + mov [output_areas_list],eax + add [current_output_area_entry],eax + add [initial_output_area_entry],eax + add eax,ecx + mov edi,eax + xchg [output_areas_list_end],eax + sub ecx,eax + sub edi,ecx + shr ecx,2 + xor eax,eax + rep stosd + mov eax,[current_output_area_entry] + get_next_output_entry: + add eax,sizeof.OutputArea + cmp [initial_output_area_entry],0 + je another_initial_output_area + mov edi,[eax-sizeof.OutputArea+OutputArea.definition] + mov ecx,[edi+ValueDefinition.value_length] + mov edi,[edi+ValueDefinition.value] + mov ebx,[edi+AreaHeader.uninitialized_length] + sub ecx,sizeof.AreaHeader + sub ecx,[edi+AreaHeader.base_address_length] + jz prior_uninitialized_length_ok + and dword [prior_uninitialized_length],0 + and dword [prior_uninitialized_length+4],0 + prior_uninitialized_length_ok: + add dword [prior_uninitialized_length],ebx + adc dword [prior_uninitialized_length+4],0 + xor edx,edx + add ecx,ebx + adc edx,0 + add ecx,dword [eax-sizeof.OutputArea+OutputArea.cached_offset] + adc edx,dword [eax-sizeof.OutputArea+OutputArea.cached_offset+4] + mov dword [eax+OutputArea.cached_offset],ecx + mov dword [eax+OutputArea.cached_offset+4],edx + pop ecx + jmp new_output_entry_ready + another_initial_output_area: + pop ecx + jmp create_initial_output_area + create_first_output_area: + mov eax,[output_areas_list] + create_initial_output_area: + mov [initial_output_area_entry],eax + and dword [eax+OutputArea.cached_offset],0 + and dword [eax+OutputArea.cached_offset+4],0 + and dword [prior_uninitialized_length],0 + and dword [prior_uninitialized_length+4],0 + new_output_entry_ready: + mov [current_output_area_entry],eax + lea ebx,[eax+OutputArea.definition] + call create_area + retn + +create_area: +; in: +; ebx - where pointer to ValueDefinition should be stored, may already hold a previously used one (should contain null otherwise) +; esi - base address in format of VALTYPE_NUMERIC value +; ecx = length of base address value +; out: +; ebx - AreaHeader +; edx - ValueDefinition + mov [address_length],ecx + mov edx,[ebx] + test edx,edx + jz current_area_definition_unusable + cmp [edx+ValueDefinition.reference_count],1 + je area_definition_ready + dec [edx+ValueDefinition.reference_count] + current_area_definition_unusable: + mov ecx,retired_definition + retrieve_retired_detached_value: + mov edx,[ecx] + test edx,edx + jz create_area_definition + cmp [edx+ValueDefinition.reference_count],0 + jne retired_detached_value_immutable + xor eax,eax + xchg eax,[edx+ValueDefinition.previous] + mov [ecx],eax + jmp adopt_area_definition + retired_detached_value_immutable: + lea ecx,[edx+ValueDefinition.previous] + jmp retrieve_retired_detached_value + create_area_definition: + mov ecx,sizeof.ValueDefinition + call create_tree_element + mov ecx,eax + xchg ecx,[value_definition_chain] + mov [eax+ValueDefinition.interlink],ecx + mov edx,eax + adopt_area_definition: + mov [ebx],edx + or [edx+ValueDefinition.flags],VAL_DETACHED + inc [edx+ValueDefinition.reference_count] + area_definition_ready: + mov ecx,[address_length] + add ecx,sizeof.AreaHeader + mov eax,[edx+ValueDefinition.block_length] + test eax,eax + jz allocate_area_block + cmp ecx,eax + jbe initialize_area_block + push ecx edx + xor eax,eax + xchg eax,[edx+ValueDefinition.value] + call mfree + pop edx ecx + allocate_area_block: + push edx + call malloc_growable + pop edx + mov [edx+ValueDefinition.value],eax + mov [edx+ValueDefinition.block_length],ecx + initialize_area_block: + mov ebx,[edx+ValueDefinition.value] + lea edi,[ebx+sizeof.AreaHeader] + mov ecx,[address_length] + mov [ebx+AreaHeader.base_address_length],ecx + rep movsb + mov [ebx+AreaHeader.uninitialized_length],ecx + mov [ebx+AreaHeader.flags],ecx + sub edi,ebx + mov [edx+ValueDefinition.value_length],edi + mov [edx+ValueDefinition.type],VALTYPE_AREA + mov ecx,[current_pass] + mov [edx+ValueDefinition.pass],ecx + retn + +initialize_output: +; in: ecx = number of bytes that should be added to output +; out: edi - output buffer to be filled with data +; preserves: esi + mov edx,[current_area] + mov ebx,[edx+ValueDefinition.value] + add ecx,[ebx+AreaHeader.uninitialized_length] + jc output_out_of_memory + mov eax,[edx+ValueDefinition.value_length] + lea edi,[ebx+eax] + add ecx,eax + jc output_out_of_memory + mov [edx+ValueDefinition.value_length],ecx + cmp ecx,[edx+ValueDefinition.block_length] + jbe area_reserve_sufficient + mov eax,[edx+ValueDefinition.value] + sub edi,eax + push edx + push ecx + bsr edx,ecx + xchg ecx,edx + dec cl + shr edx,cl + inc edx + shl edx,cl + pop ecx + cmp edx,ecx + jbe output_out_of_memory + xchg ecx,edx + call realloc + pop edx + mov ebx,eax + add edi,eax + mov [edx+ValueDefinition.value],ebx + mov [edx+ValueDefinition.block_length],ecx + area_reserve_sufficient: + mov ecx,[ebx+AreaHeader.uninitialized_length] + jecxz output_buffer_ready + xor eax,eax + rep stosb + mov [ebx+AreaHeader.uninitialized_length],eax + output_buffer_ready: + retn + output_out_of_memory: + jmp out_of_memory + +uninitialized_output: +; in: ecx = number of uninitialized bytes to be added to output +; preserves: ebx, ecx, esi, edi + mov edx,[current_area] + mov eax,[edx+ValueDefinition.value] + add [eax+AreaHeader.uninitialized_length],ecx + jc area_overflow + mov edx,[edx+ValueDefinition.value_length] + sub edx,sizeof.AreaHeader + sub edx,[eax+AreaHeader.base_address_length] + add edx,[eax+AreaHeader.uninitialized_length] + jc area_overflow + retn + area_overflow: + mov edx,_area_overflow + call register_error + mov edx,[current_area] + or ecx,-1 + mov eax,[edx+ValueDefinition.value] + sub ecx,[edx+ValueDefinition.value_length] + add ecx,sizeof.AreaHeader + add ecx,[eax+AreaHeader.base_address_length] + mov [eax+AreaHeader.uninitialized_length],ecx + retn + +trim_output: +; preserves: ecx, esi + xor eax,eax + mov dword [prior_uninitialized_length],eax + mov dword [prior_uninitialized_length+4],eax + mov edi,[current_output_area_entry] + trim_current_output_area: + mov edx,[edi+OutputArea.definition] + mov eax,[edx+ValueDefinition.value] + and [eax+AreaHeader.uninitialized_length],0 + mov ebx,[edx+ValueDefinition.value_length] + sub ebx,sizeof.AreaHeader + sub ebx,[eax+AreaHeader.base_address_length] + jnz output_trimmed + cmp edi,[initial_output_area_entry] + je output_trimmed + sub edi,sizeof.OutputArea + jmp trim_current_output_area + output_trimmed: + mov [current_output_area_entry],edi + retn + +load_from_area: +; in: +; [value_length] = length of data to load +; edi - buffer for loaded data +; edx - ValueDefinition with VALTYPE_AREA +; [data_area_symbol] - SymbolTree_Leaf linked to the same ValueDefinition with update_value_link (required only for predicted loads, can be null) +; [data_offset] = offset within the area +; out: +; cf set when data could not be loaded +; when cf = 0, buffer filled with loaded data +; preserves: esi + mov eax,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.pass] + cmp ecx,[current_pass] + je area_ok + test [eax+AreaHeader.flags],AREA_VARIABLE + jnz source_area_inaccessible + area_ok: + mov ebx,[data_offset] + add ebx,[eax+AreaHeader.base_address_length] + jc area_offset_unavailable + add ebx,sizeof.AreaHeader + jc area_offset_unavailable + mov ecx,[edx+ValueDefinition.value_length] + sub ecx,ebx + jb load_out_of_initialized_data + call prepare_load_length + jc area_offset_unavailable + xchg esi,ebx + add esi,eax + rep movsb + mov esi,ebx + cmp [value_length],0 + je load_ok + mov ecx,[eax+AreaHeader.uninitialized_length] + jmp load_uninitialized_data + load_out_of_initialized_data: + add ecx,[eax+AreaHeader.uninitialized_length] + jc load_uninitialized_data + xor ecx,ecx + load_uninitialized_data: + call prepare_load_length + jc area_offset_unavailable + xor al,al + rep stosb + cmp [value_length],0 + je load_ok + xor ebx,ebx + xchg ebx,[data_area_symbol] + test ebx,ebx + jz area_offset_unavailable + mov edx,[ebx+SymbolTree_Leaf.retired_definition] + test edx,edx + jz area_with_no_history + mov ecx,[current_pass] + sub ecx,[edx+ValueDefinition.pass] + cmp ecx,1 + ja area_with_no_history + or [ebx+SymbolTree_Leaf.flags],SYM_LINK_PREDICTED + mov eax,[edx+ValueDefinition.value] + jmp load_from_area + prepare_load_length: + cmp ecx,[value_length] + jbe value_length_ok + mov ecx,[value_length] + value_length_ok: + add [data_offset],ecx + jc load_length_ready + sub [value_length],ecx + load_length_ready: + retn + source_area_inaccessible: + mov edx,_invalid_area + jmp load_failed + area_with_no_history: + or [next_pass_needed],1 + area_offset_unavailable: + mov edx,_address_out_of_range + load_failed: + call register_error + stc + retn + load_ok: + clc + retn + +prepare_area_to_write: +; in: +; [data_area] - ValueDefinition with VALTYPE_AREA +; [data_offset] = offset within the area +; [value_length] = length of data to be written +; out: +; cf set when writing specified length is not possible +; when cf = 0: +; edi - buffer for specified number of bytes directly within the area +; preserves: esi + mov edx,[data_area] + mov eax,[edx+ValueDefinition.value] + or [eax+AreaHeader.flags],AREA_VARIABLE + mov ebx,[data_offset] + xor ecx,ecx + add ebx,[eax+AreaHeader.base_address_length] + adc ecx,0 + add ebx,sizeof.AreaHeader + adc ecx,0 + add ebx,[value_length] + adc ecx,0 + jnz write_outside_initialized_area + cmp ebx,[edx+ValueDefinition.value_length] + ja write_outside_initialized_area + lea edi,[eax+ebx] + mov ecx,[value_length] + sub edi,ecx + retn + area_to_write_not_accessible: + stc + retn + write_outside_initialized_area: + sub ebx,[edx+ValueDefinition.value_length] + sbb ecx,0 + jnz write_outside_boundaries + sub [eax+AreaHeader.uninitialized_length],ebx + jnc extend_area + add [eax+AreaHeader.uninitialized_length],ebx + write_outside_boundaries: + push edx + mov edx,_address_out_of_range + call register_error + pop edx + test ecx,ecx + jnz area_to_write_not_accessible + test [eax+AreaHeader.flags],AREA_VIRTUAL + jz area_to_write_not_accessible + test [edx+ValueDefinition.flags],VAL_IN_USE + jnz area_to_write_not_accessible + and [eax+AreaHeader.uninitialized_length],0 + extend_virtual_area: + call expand_value + jmp prepare_area_to_write + extend_area: + test [eax+AreaHeader.flags],AREA_VIRTUAL + jnz extend_virtual_area + call expand_value + call update_output_offsets + jmp prepare_area_to_write + +find_output_area: +; in: +; [file_offset] = offset within the output +; out: +; cf set when not found an area that would contain a byte at specified offset +; when cf = 0: +; ebx - OutputArea +; [file_offset] = offset relative to the beginning of the found area (upper 32 bits are zero) + mov esi,[initial_output_area_entry] + mov edi,[current_output_area_entry] + add edi,sizeof.OutputArea + search_areas: + mov ebx,edi + sub ebx,esi + jz output_area_not_found + test ebx,1 shl bsf sizeof.OutputArea + jz bisect_areas_list + sub ebx,sizeof.OutputArea + bisect_areas_list: + shr ebx,1 + add ebx,esi + mov eax,dword [file_offset] + mov edx,dword [file_offset+4] + sub eax,dword [ebx+OutputArea.cached_offset] + sbb edx,dword [ebx+OutputArea.cached_offset+4] + jc search_earlier_areas + jnz search_later_areas + mov edx,[ebx+OutputArea.definition] + mov ecx,[edx+ValueDefinition.value_length] + mov edx,[edx+ValueDefinition.value] + sub ecx,sizeof.AreaHeader + sub ecx,[edx+AreaHeader.base_address_length] + add ecx,[edx+AreaHeader.uninitialized_length] + cmp eax,ecx + jae search_later_areas + output_area_found: + mov dword [file_offset],eax + and dword [file_offset+4],0 + ; clc + retn + output_area_not_found: + stc + retn + search_later_areas: + lea esi,[ebx+sizeof.OutputArea] + jmp search_areas + search_earlier_areas: + mov edi,ebx + jmp search_areas + +read_from_output: +; in: +; edi - buffer for read data +; [value_length] = length of data to read +; [file_offset] = offset within the output +; out: +; [value_length] = number of bytes that were not in the existing output and could not be read + push edi + call find_output_area + pop edi + jc output_reading_done + read_output_areas: + cmp [value_length],0 + je output_reading_done + mov edx,[ebx+OutputArea.definition] + mov ecx,[edx+ValueDefinition.value_length] + mov eax,ecx + mov edx,[edx+ValueDefinition.value] + sub ecx,sizeof.AreaHeader + sub ecx,[edx+AreaHeader.base_address_length] + sub dword [file_offset],ecx + jnc initialized_load_done + lea esi,[edx+eax] + mov ecx,dword [file_offset] + add esi,ecx + neg ecx + cmp ecx,[value_length] + jbe initialized_load_length_ok + mov ecx,[value_length] + initialized_load_length_ok: + sub [value_length],ecx + rep movsb + mov dword [file_offset],ecx + initialized_load_done: + mov ecx,[edx+AreaHeader.uninitialized_length] + sub dword [file_offset],ecx + jnc uninitialized_load_done + mov ecx,dword [file_offset] + neg ecx + cmp ecx,[value_length] + jbe uninitialized_load_length_ok + mov ecx,[value_length] + uninitialized_load_length_ok: + sub [value_length],ecx + xor al,al + rep stosb + mov dword [file_offset],ecx + uninitialized_load_done: + cmp ebx,[current_output_area_entry] + je output_reading_done + add ebx,sizeof.OutputArea + jmp read_output_areas + output_reading_done: + retn + +rewrite_output: +; in: +; esi - data to write +; [value_length] = length of data to write +; [file_offset] = offset within the output +; out: +; [value_length] = number of bytes that were not in the existing output and could not be rewritten + push esi + call find_output_area + pop esi + jc output_rewriting_done + rewrite_output_areas: + cmp [value_length],0 + je output_rewriting_done + mov edx,[ebx+OutputArea.definition] + mov ecx,[edx+ValueDefinition.value_length] + mov edx,[edx+ValueDefinition.value] + sub ecx,sizeof.AreaHeader + sub ecx,[edx+AreaHeader.base_address_length] + mov edi,[edx+AreaHeader.uninitialized_length] + add ecx,edi + sub dword [file_offset],ecx + jnc rewrite_next_area + mov eax,[value_length] + xor ecx,ecx + add eax,edi + adc ecx,ecx + add eax,dword [file_offset] + adc ecx,0 + jz rewrite_initialized_data + cmp eax,edi + jbe rewrite_uninitialized_data + mov eax,edi + rewrite_uninitialized_data: + test eax,eax + jz rewrite_initialized_data + push ebx + sub [edx+AreaHeader.uninitialized_length],eax + mov edx,[ebx+OutputArea.definition] + mov ebx,eax + call expand_value + call update_output_offsets + pop ebx + rewrite_initialized_data: + mov edx,[ebx+OutputArea.definition] + mov ecx,[edx+ValueDefinition.value_length] + mov edi,[edx+ValueDefinition.value] + or [edi+AreaHeader.flags],AREA_VARIABLE + add edi,[edi+AreaHeader.uninitialized_length] + add edi,ecx + mov ecx,dword [file_offset] + add edi,ecx + neg ecx + cmp ecx,[value_length] + jbe rewrite_length_ok + mov ecx,[value_length] + rewrite_length_ok: + sub [value_length],ecx + rep movsb + mov dword [file_offset],ecx + rewrite_next_area: + cmp ebx,[current_output_area_entry] + je output_rewriting_done + add ebx,sizeof.OutputArea + jmp rewrite_output_areas + output_rewriting_done: + retn + +update_output_offsets: +; in: +; edx - ValueDefinition of output area that had some of uninitialized data made initialized +; preserves: esi + mov eax,[current_output_area_entry] + cmp edx,[eax+OutputArea.definition] + je output_offsets_ok + and dword [prior_uninitialized_length],0 + and dword [prior_uninitialized_length+4],0 + recount_prior_uninitialized_length: + cmp eax,[initial_output_area_entry] + je output_offsets_ok + sub eax,sizeof.OutputArea + mov edi,[eax+OutputArea.definition] + mov ebx,[edi+ValueDefinition.value] + mov ecx,[ebx+AreaHeader.uninitialized_length] + add dword [prior_uninitialized_length],ecx + adc dword [prior_uninitialized_length+4],0 + cmp edx,edi + je output_offsets_ok + mov ecx,[edi+ValueDefinition.value_length] + sub ecx,sizeof.AreaHeader + sub ecx,[ebx+AreaHeader.base_address_length] + jz recount_prior_uninitialized_length + output_offsets_ok: + retn + +get_current_address_value: +; out: +; esi - address in format of VALTYPE_NUMERIC value +; ecx = length of address value +; note: the returned value is placed in assembly workspace + mov eax,[current_area] + mov esi,[eax+ValueDefinition.value] + mov ebx,[eax+ValueDefinition.value_length] + mov edx,assembly_workspace + mov edi,[edx+Workspace.memory_start] + mov ecx,[esi+AreaHeader.base_address_length] + add ecx,4 + call reserve_workspace + mov ecx,[esi+AreaHeader.base_address_length] + sub ebx,ecx + sub ebx,sizeof.AreaHeader + add ebx,[esi+AreaHeader.uninitialized_length] + ; jc internal_error + add esi,sizeof.AreaHeader + xor eax,eax + stosd + lodsd + mov ecx,eax + xor edx,edx + jecxz offset_added_to_base_address + add_offset_to_base_address: + lodsb + add al,bl + setc dl + stosb + shr ebx,8 + add ebx,edx + loop add_offset_to_base_address + offset_added_to_base_address: + mov edx,[assembly_workspace.memory_start] + add edx,4 + mov eax,ebx + cmp byte [esi-1],80h + cmc + sbb eax,0 + stosd + optimize_base_address: + movsx eax,byte [edi-2] + cmp ah,[edi-1] + jne base_address_ready + dec edi + cmp edi,edx + jne optimize_base_address + base_address_ready: + mov ecx,edi + sub ecx,edx + mov [edx-4],ecx + mov ecx,esi + measure_variable_terms: + lodsd + test eax,eax + jz variable_terms_measured + lodsd + add esi,eax + jmp measure_variable_terms + variable_terms_measured: + xchg ecx,esi + sub ecx,esi + rep movsb + mov esi,[assembly_workspace.memory_start] + mov ecx,edi + sub ecx,esi + retn + +get_output_length: +; out: +; edx:eax = length of current output (not counting uninitialized data) +; preserves: esi + mov ebx,[current_output_area_entry] + mov eax,dword [ebx+OutputArea.cached_offset] + mov edx,dword [ebx+OutputArea.cached_offset+4] + mov edi,[ebx+OutputArea.definition] + mov ecx,[edi+ValueDefinition.value_length] + mov edi,[edi+ValueDefinition.value] + sub ecx,sizeof.AreaHeader + sub ecx,[edi+AreaHeader.base_address_length] + jz current_area_entirely_uninitialized + add eax,ecx + adc edx,0 + retn + current_area_entirely_uninitialized: + sub eax,dword [prior_uninitialized_length] + sbb edx,dword [prior_uninitialized_length+4] + retn + +get_output_position: +; out: +; edx:eax = current position in the output (including uninitialized data) +; preserves: esi + mov ebx,[current_output_area_entry] + mov eax,dword [ebx+OutputArea.cached_offset] + mov edx,dword [ebx+OutputArea.cached_offset+4] + mov edi,[ebx+OutputArea.definition] + mov ecx,[edi+ValueDefinition.value_length] + mov edi,[edi+ValueDefinition.value] + sub ecx,sizeof.AreaHeader + sub ecx,[edi+AreaHeader.base_address_length] + add ecx,[edi+AreaHeader.uninitialized_length] + add eax,ecx + adc edx,0 + retn + +create_output_path: +; in: +; ebx - base path and name +; esi - file extension +; ecx = length of the extension +; out: +; edx - output path (generated in temporary storage) + push ecx + mov edi,ebx + xor al,al + or ecx,-1 + repne scasb + dec edi + mov ecx,edi + locate_extension: + cmp edi,ebx + je copy_path_name + dec edi + mov al,[edi] + cmp al,'\' + je copy_path_name + cmp al,'/' + je copy_path_name + cmp al,'.' + jne locate_extension + mov ecx,edi + copy_path_name: + sub ecx,ebx + push ecx + mov edi,[preprocessing_workspace.memory_start] + inc ecx + mov edx,preprocessing_workspace + call reserve_workspace + pop ecx + xchg esi,ebx + rep movsb + mov esi,ebx + pop ecx + mov ebx,ecx + add ecx,2 + call reserve_workspace + mov ecx,ebx + jecxz extension_attached + mov al,'.' + stosb + rep movsb + extension_attached: + xor al,al + stosb + mov edx,[preprocessing_workspace.memory_start] + retn + +write_output_file: +; in: +; ebx - source path +; edi - output path +; out: +; cf set when write failed +; note: +; when output path is null, source path is used with replaced or attached extension + mov [base_path],edi + xor eax,eax + mov [output_failures],eax + mov dword [uninitialized_length],eax + mov dword [uninitialized_length+4],eax + mov edx,edi + test edx,edx + jnz create_output_file + mov [base_path],ebx + mov esi,[output_extension] + mov ecx,[output_extension_length] + call create_output_path + create_output_file: + call create + jc output_write_failed + mov esi,[initial_output_area_entry] + write_area: + mov edx,[esi+OutputArea.definition] + mov eax,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + sub ecx,[eax+AreaHeader.base_address_length] + sub ecx,sizeof.AreaHeader + jz write_next_area + mov eax,dword [uninitialized_length] + or eax,dword [uninitialized_length+4] + jz write_initialized_data + write_uninitialized_data: + mov edi,[assembly_workspace.memory_start] + mov ecx,1000h shr 2 + xor eax,eax + rep stosd + mov ecx,1000h + cmp dword [uninitialized_length+4],0 + jne portion_length_ok + cmp ecx,dword [uninitialized_length] + jbe portion_length_ok + mov ecx,dword [uninitialized_length] + portion_length_ok: + sub dword [uninitialized_length],ecx + sbb dword [uninitialized_length+4],0 + mov edx,[assembly_workspace.memory_start] + call write + jc file_write_failed + mov eax,dword [uninitialized_length] + or eax,dword [uninitialized_length+4] + jnz write_uninitialized_data + write_initialized_data: + mov edx,[esi+OutputArea.definition] + mov eax,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + mov edx,[eax+AreaHeader.base_address_length] + add edx,sizeof.AreaHeader + sub ecx,edx + add edx,eax + call write + jc file_write_failed + write_next_area: + mov edx,[esi+OutputArea.definition] + mov eax,[edx+ValueDefinition.value] + mov eax,[eax+AreaHeader.uninitialized_length] + add dword [uninitialized_length],eax + adc dword [uninitialized_length+4],0 + cmp esi,[current_output_area_entry] + je close_output_file + add esi,sizeof.OutputArea + jmp write_area + close_output_file: + call close + mov ebx,[auxiliary_output_areas] + mov edi,write_auxiliary_output_area + call iterate_through_map + cmp [output_failures],0 + jne output_write_failed + clc + retn + file_write_failed: + call close + output_write_failed: + stc + retn + +write_auxiliary_output_area: +; in: +; eax = ValueDefinition, null for cached extension not used for auxiliary output +; esi - file extension +; ecx = length of the extension + test eax,eax + jz auxiliary_output_processed + mov ebx,[base_path] + test ebx,ebx + jz auxiliary_output_processed + push eax + call create_output_path + call create + pop edx + jc auxiliary_file_creation_failed + mov eax,[edx+ValueDefinition.value] + mov ecx,[edx+ValueDefinition.value_length] + mov edx,[eax+AreaHeader.base_address_length] + add edx,sizeof.AreaHeader + sub ecx,edx + add edx,eax + call write + jc auxiliary_file_write_failed + call close + auxiliary_output_processed: + retn + auxiliary_file_write_failed: + call close + auxiliary_file_creation_failed: + inc [output_failures] + retn diff --git a/toolchain/fasm2/source/reader.inc b/toolchain/fasm2/source/reader.inc new file mode 100644 index 0000000..e7f0790 --- /dev/null +++ b/toolchain/fasm2/source/reader.inc @@ -0,0 +1,451 @@ + +; note: +; to not interfere with code resolving, all external input must stay unchanged +; in subsequent passes of the assembly; for this reason all data read from files is +; permanently cached (source texts are cached in tokenized form) + +struct FileData + length dq ? + cache dd ? ; pointer to FileCache +ends + +struct FileCache + offset dq ? + length dd ? + next dd ? ; pointer to another FileCache +ends + +read_source: +; in: +; esi - source path +; out: +; eax - tokenized source, null when file not found +; esi - source path in persistent storage + mov ebx,[file_source_cache] + xor ecx,ecx + call get_from_map + jc read_source_file + cmp eax,-1 + je get_erroneous_source + retn + read_source_file: + mov edx,esi + call open + jc source_file_not_found + xor eax,eax + mov edx,eax + mov cl,2 + call lseek + jc error_reading_file + test edx,edx + jnz out_of_memory + push eax + xor eax,eax + mov edx,eax + mov cl,al + call lseek + jc error_reading_file + pop ecx + inc ecx + mov [source_text_length],ecx + call malloc + mov [source_text],eax + mov edx,eax + mov ecx,[source_text_length] + dec ecx + mov byte [edx+ecx],0 + call read + jc error_reading_file + call close + push esi + call tokenize_source + mov eax,[source_text] + call mfree + pop esi + mov eax,[tokenization_buffer] + xor ecx,ecx + mov ebx,[file_source_cache] + call put_into_map + mov eax,[tokenization_buffer] + retn + source_file_not_found: + xor eax,eax + xor ecx,ecx + mov ebx,[file_source_cache] + call put_into_map + xor eax,eax + retn + error_reading_file: + or eax,-1 + xor ecx,ecx + mov ebx,[file_source_cache] + call put_into_map + get_erroneous_source: + mov ebx,esi + mov edx,_error_reading_file + call register_error + mov eax,zero_value + retn + +use_source: +; in: +; esi - ASCIIZ source string +; out: +; eax - tokenized source +; esi - source text in persistent storage + mov edi,esi + xor al,al + or ecx,-1 + repne scasb + not ecx + mov [source_text_length],ecx + mov ebx,[memory_source_cache] + xor eax,eax + call get_from_map + jc adapt_memory_source + retn + adapt_memory_source: + mov [source_text],esi + call tokenize_source + mov eax,[tokenization_buffer] + mov esi,[source_text] + mov ecx,[source_text_length] + mov ebx,[memory_source_cache] + call put_into_map + mov eax,[tokenization_buffer] + retn + +tokenize_source: +; in: +; [source_text] - ASCIIZ text +; [source_text_length] = length of text (including terminating character) +; out: +; [tokenization_buffer] - tokenized source +; [tokenization_buffer_length] = length of tokenized source + mov ecx,[source_text_length] + shl ecx,1 + add ecx,18 + call malloc_growable + mov [tokenization_buffer],eax + mov [tokenization_buffer_length],ecx + add eax,ecx + sub eax,[source_text] + sub eax,[source_text_length] + mov [buffer_end_offset],eax + mov esi,[source_text] + mov edi,[tokenization_buffer] + mov [last_token],0Ah + tokenize: + mov eax,[buffer_end_offset] + add eax,esi + sub eax,edi + cmp eax,18 + jae tokenization_buffer_reserve_ok + mov ecx,esi + sub ecx,[source_text] + mov eax,[source_text_length] + mul [tokenization_buffer_length] + div ecx + mov ecx,eax + add ecx,18 + mov eax,[tokenization_buffer] + call realloc + sub edi,[tokenization_buffer] + add edi,eax + mov [tokenization_buffer],eax + mov [tokenization_buffer_length],ecx + add eax,ecx + sub eax,[source_text] + sub eax,[source_text_length] + mov [buffer_end_offset],eax + tokenization_buffer_reserve_ok: + movzx eax,byte [esi] + inc esi + mov ah,[characters+eax] + cmp ah,20h + je control_character + test ah,ah + jnz make_name_token + character_token: + stosb + mov [last_token],al + jmp tokenize + make_string_token: + mov dl,al + mov byte [edi],22h + mov [last_token],22h + add edi,5 + xor ecx,ecx + copy_string: + mov al,[esi] + cmp al,0Dh + je broken_string + cmp al,0Ah + je broken_string + cmp al,1Ah + je broken_string + test al,al + jz broken_string + inc esi + cmp al,dl + jne copy_string_character + cmp byte [esi],al + jne finish_string_token + inc esi + copy_string_character: + mov [edi+ecx],al + inc ecx + jmp copy_string + broken_string: + mov byte [edi-5],27h + finish_string_token: + mov al,[edi-5] + mov [edi-4],ecx + add edi,ecx + jmp tokenize + make_name_token: + cmp al,22h + je make_string_token + cmp al,27h + je make_string_token + mov byte [edi],1Ah + mov [last_token],1Ah + add edi,5 + xor ebx,ebx + mov ecx,FNV_OFFSET + mov edx,ecx + hash_name: + mov [edi+ebx],al + inc ebx + xor cl,al + xor dl,ah + imul ecx,FNV_PRIME + imul edx,FNV_PRIME + movzx eax,byte [esi] + inc esi + mov ah,[characters+eax] + cmp ah,20h + je finish_name_token + test ah,ah + jnz hash_name + finish_name_token: + mov [edi-4],ebx + add edi,ebx + mov [edi],ecx + mov [edi+4],edx + xor ecx,ecx + mov [edi+8],ecx + add edi,12 + cmp ah,20h + jne character_token + control_character: + cmp al,20h + je whitespace + cmp al,9 + je whitespace + cmp [last_token],20h + je mark_end_of_line + inc edi + mark_end_of_line: + mov byte [edi-1],0Ah + mov [last_token],0Ah + cmp al,0Dh + je cr + cmp al,0Ah + je lf + xor al,al + stosb + mov ecx,edi + mov eax,[tokenization_buffer] + sub ecx,eax + call realloc + mov [tokenization_buffer],eax + mov [tokenization_buffer_length],ecx + retn + cr: + cmp byte [esi],0Ah + jne tokenize + inc esi + jmp tokenize + lf: + cmp byte [esi],0Dh + jne tokenize + inc esi + jmp tokenize + whitespace: + cmp [last_token],0Ah + je tokenize + cmp [last_token],20h + je tokenize + mov al,20h + stosb + mov [last_token],al + jmp tokenize + +get_file_data: +; in: +; esi - file path +; out: +; ebx - FileData, null when file not found +; esi - file path in persistent storage +; preserves: edi + mov ebx,[file_data_cache] + xor ecx,ecx + call get_from_map + jc initialize_file_data + mov ebx,eax + retn + initialize_file_data: + mov edx,esi + call open + jc remember_file_not_found + push edi + mov ecx,sizeof.FileData + call malloc_fixed + mov edi,eax + xor eax,eax + mov edx,eax + mov cl,2 + call lseek + jc file_not_seekable + mov dword [edi+FileData.length],eax + mov dword [edi+FileData.length+4],edx + call close + mov eax,edi + xor ecx,ecx + mov [eax+FileData.cache],ecx + mov ebx,[file_data_cache] + call put_into_map + mov ebx,edi + pop edi + retn + file_not_seekable: + pop edi + remember_file_not_found: + xor eax,eax + mov ecx,eax + mov ebx,[file_data_cache] + call put_into_map + xor ebx,ebx + retn + +read_file_data: +; in: +; esi - file path +; ebx - FileData +; edi - buffer for data +; [file_offset] = offset of data +; [data_length] = length of data +; out: +; cf set when read failed +; preserves: esi + mov [file_data],ebx + lea eax,[ebx+FileData.cache] + mov [file_cache_pointer],eax + mov ebx,[eax] + read_from_file_cache: + mov ecx,[data_length] + test ecx,ecx + jz file_data_read + test ebx,ebx + jz new_trailing_file_cache_entry + mov eax,dword [file_offset] + mov edx,dword [file_offset+4] + sub eax,dword [ebx+FileCache.offset] + sbb edx,dword [ebx+FileCache.offset+4] + jc new_file_cache_entry + jnz next_entry + mov edx,[ebx+FileCache.length] + sub edx,eax + jbe next_entry + cmp ecx,edx + jbe length_to_read_ok + mov ecx,edx + length_to_read_ok: + sub [data_length],ecx + add dword [file_offset],ecx + adc dword [file_offset+4],0 + mov edx,esi + lea esi,[ebx+sizeof.FileCache+eax] + rep movsb + mov esi,edx + next_entry: + lea eax,[ebx+FileCache.next] + mov [file_cache_pointer],eax + mov ebx,[eax] + jmp read_from_file_cache + file_data_read: + clc + retn + new_trailing_file_cache_entry: + mov ebx,[file_data] + mov ecx,dword [ebx+FileData.length] + mov edx,dword [ebx+FileData.length+4] + cmp ecx,dword [file_offset] + jne measure_cache_gap + cmp edx,dword [file_offset+4] + jne measure_cache_gap + stc + retn + new_file_cache_entry: + mov ecx,dword [ebx+FileCache.offset] + mov edx,dword [ebx+FileCache.offset+4] + measure_cache_gap: + mov eax,dword [file_offset] + and eax,not 0FFFh + sub ecx,eax + sbb edx,dword [file_offset+4] + jnz compute_aligned_length + cmp ecx,[data_length] + jbe read_into_cache + compute_aligned_length: + mov eax,dword [file_offset] + and eax,0FFFh + add eax,[data_length] + dec eax + shr eax,12 + inc eax + shl eax,12 + test edx,edx + jnz use_aligned_length + cmp eax,ecx + jae read_into_cache + use_aligned_length: + mov ecx,eax + read_into_cache: + push ecx + add ecx,sizeof.FileCache + call malloc_fixed + mov ebx,eax + mov eax,[file_cache_pointer] + mov edx,ebx + xchg edx,[eax] + mov [ebx+FileCache.next],edx + pop [ebx+FileCache.length] + mov eax,dword [file_offset] + and eax,not 0FFFh + mov edx,dword [file_offset+4] + mov dword [ebx+FileCache.offset],eax + mov dword [ebx+FileCache.offset+4],edx + push ebx edi + mov edi,ebx + mov edx,esi + call open + jc file_access_error + mov eax,dword [edi+FileCache.offset] + mov edx,dword [edi+FileCache.offset+4] + xor cl,cl + call lseek + jc file_access_error + lea edx,[edi+sizeof.FileCache] + mov ecx,[edi+FileCache.length] + call read + jc file_access_error + call close + pop edi ebx + jmp read_from_file_cache + file_access_error: + pop edi ebx + stc + retn + \ No newline at end of file diff --git a/toolchain/fasm2/source/symbols.inc b/toolchain/fasm2/source/symbols.inc new file mode 100644 index 0000000..9d3a243 --- /dev/null +++ b/toolchain/fasm2/source/symbols.inc @@ -0,0 +1,1547 @@ + +struct SymbolTree_Root + attributes db ? ; SYMTREE_# + flags db ? ; NAMESPACE_# + parameters db ? ; SPECPARM_# + reserved db ? + parent_branch dd ? ; pointer to namespace SymbolTree_Foliage + current_label dd ? ; pointer to selected SymbolTree_Foliage + chain dd ? ; pointer to another SymbolTree_Root + ; root_node SymbolTree_Node +ends + +struct SymbolTree_Node + branches rd 1 shl TREE_NODE_BITS +ends + +struct SymbolTree_LocalNode + branches rd 1 shl LOCAL_TREE_NODE_BITS +ends + +struct SymbolTree_Foliage + name_kind db ? ; NAME_# + flags db ? ; FOLIAGE_# + reserved dw ? + name_length dd ? + name_data dd ? + root dd ? ; pointer to SymbolTree_Root + next dd ? ; pointer to another SymbolTree_Foliage + child_namespace dd ? ; pointer to descendant SymbolTree_Root + ; first_leaf SymbolTree_Leaf +ends + +struct SymbolTree_Leaf + class db ? ; SYMCLASS_# + flags db ? ; SYM_# + extra_flags db ? ; SYMX_# + reserved db ? + definition dd ? ; pointer to ValueDefinition + retired_definition dd ? + last_use_pass dd ? + next dd ? ; pointer to another SymbolTree_Leaf within SymbolTree_Foliage + branch dd ? ; pointer to SymbolTree_Foliage + fallback_neighbour dd ? ; pointer to another SymbolTree_Leaf + fallback_parent dd ? ; pointer to another SymbolTree_Leaf +ends + +struct ValueDefinition + type db ? ; VALTYPE_# + flags db ? ; VAL_# + attribute db ? + reserved db ? + pass dd ? + value dd ? + value_length dd ? + block_length dd ? + reference_count dd ? ; number of distinct references to current value + previous dd ? ; pointer to another ValueDefinition + interlink dd ? +ends + +TREE_HEIGHT = 4 +TREE_NODE_BITS = 5 +LOCAL_TREE_HEIGHT = 1 +LOCAL_TREE_NODE_BITS = 6 + +FNV_PRIME = 16777619 +FNV_OFFSET = 2166136261 + +SYMTREE_LOCAL = 1 +SYMTREE_WITH_CASEINSENSITIVE_PARAMETERS = 2 + +NAMESPACE_UNATTACHED = 1 +NAMESPACE_LABEL_FORWARDING = 2 +NAMESPACE_CALM = 10h +NAMESPACE_LOCAL = 20h + +SPECPARM_COUNTER = 1 +SPECPARM_LIMIT = 2 + +FOLIAGE_WITH_TOKEN = 1 + +NAME_CASESENSITIVE = 0 +NAME_CASEINSENSITIVE = 1 +NAME_NUMERIC = 2 +NAME_ABSTRACT = 3 + +SYMCLASS_EXPRESSION = 0 +SYMCLASS_INSTRUCTION = 1 +SYMCLASS_STRUCTURE = 2 +SYMCLASS_PARAMETER = 3 +SYMCLASS_CALM_LOCATION = 10h + +SYM_CONSTANT = 1 +SYM_VARIABLE = 2 +SYM_PREDICTED = 4 +SYM_PREDICTED_DEFINED = 8 +SYM_USAGE_PREDICTED = 10h +SYM_PREDICTED_USED = 20h +SYM_LINK = 40h +SYM_LINK_PREDICTED = 80h + +SYMX_INSTRUCTION_PREDICTED = 1 + +VALTYPE_RESERVED = 0 +VALTYPE_SYMBOLIC = 1 +VALTYPE_NUMERIC = 2 +VALTYPE_STRING = 3 +VALTYPE_FLOAT = 4 +VALTYPE_ELEMENT = 5 +VALTYPE_AREA = 6 +VALTYPE_CALM = 7 +VALTYPE_SYMBOLIC_SEQUENCE = 11h +VALTYPE_NUMERIC_SEQUENCE = 12h +VALTYPE_PLAIN = 20h +VALTYPE_NATIVE_COMMAND = 40h +VALTYPE_NATIVE_COMPARATOR = 41h +VALTYPE_NATIVE_FUNCTION = 42h +VALTYPE_NATIVE_PREPOSITION = 43h + +VAL_INTERNAL = 1 +VAL_IN_USE = 2 +VAL_UNCONDITIONAL = 4 +VAL_NONRECURSIVE = 8 +VAL_SHIFTABLE = 10h +VAL_DETACHED = 20h + +RECOGNIZE_CASE_INSENSITIVE = 1 +RECOGNIZE_DEFINITION = 2 + +recognize_symbol: +; in: +; ebx - SymbolTree_Root (namespace), null for standard recognition regime +; ecx = name length +; esi - name followed by two hashes (as in name token) +; dl = SYMCLASS_# +; dh = any combination of RECOGNIZE_# flags +; [recognition_context.base_namespace] - namespace for standard recognition regime +; [name_volatile] = non-zero when name is provided in a temporary storage +; [name_token] = null or pointer to the contents of a preprocessed token +; out: +; ebx - SymbolTree_Leaf +; edx - SymbolTree_Foliage +; edi - SymbolTree_Root +; [name_volatile] zeroed when name has been moved to persistent storage +; note: +; when RECOGNIZE_DEFINITION option is not selected and no defined symbol of requested class is found, +; the provided result is as if RECOGNIZE_DEFINITION option was specified and expression class requested + mov [symbol_class],dl + test dh,RECOGNIZE_DEFINITION + setnz [symbol_expected] + or [symbol_required],1 + test dh,RECOGNIZE_CASE_INSENSITIVE + mov al,NAME_CASEINSENSITIVE + mov edx,[esi+ecx+4] + mov [case_insensitive_hash],edx + jnz name_kind_ok + mov al,NAME_CASESENSITIVE + mov edx,[esi+ecx] + mov [case_sensitive_hash],edx + name_kind_ok: + mov [name_kind],al + test ebx,ebx + jz standard_recognition + call scan_namespace + jnc symbol_recognized + mov [kept_symbol],ebx + mov [kept_symbol_flags],al + mov edi,[symbol_root] + cmp [name_kind],NAME_CASEINSENSITIVE + je no_defined_symbol + mov [current_symbol],ebx + mov ebx,[ebx+SymbolTree_Leaf.fallback_neighbour] + test ebx,ebx + jnz check_namespace_fallback + mov [name_kind],NAME_CASEINSENSITIVE + mov edx,[case_insensitive_hash] + mov ebx,edi + call scan_namespace + mov eax,[current_symbol] + mov [eax+SymbolTree_Leaf.fallback_neighbour],ebx + jc no_defined_symbol + symbol_recognized: + mov edi,[symbol_root] + retn + standard_recognition: + mov ebx,[recognition_context.base_namespace] + call scan_namespace + jnc symbol_recognized + mov [kept_symbol],ebx + mov [kept_symbol_flags],al + mov edi,[symbol_root] + find_in_wider_scope: + mov edx,[case_insensitive_hash] + mov [current_symbol],ebx + cmp [name_kind],NAME_CASEINSENSITIVE + je find_in_namespace_chain + mov ebx,[ebx+SymbolTree_Leaf.fallback_neighbour] + test ebx,ebx + jnz check_fallback_neighbour + mov [name_kind],NAME_CASEINSENSITIVE + mov ebx,[symbol_root] + call scan_namespace + mov eax,[current_symbol] + mov [eax+SymbolTree_Leaf.fallback_neighbour],ebx + jnc symbol_recognized + no_neighbour_found: + mov ebx,[current_symbol] + mov [name_kind],NAME_CASESENSITIVE + mov edx,[case_sensitive_hash] + find_in_namespace_chain: + mov ebx,[ebx+SymbolTree_Leaf.fallback_parent] + test ebx,ebx + jnz check_fallback_parent + mov edi,[symbol_root] + mov ebx,[edi+SymbolTree_Root.parent_branch] + test ebx,ebx + jz no_defined_symbol + mov ebx,[ebx+SymbolTree_Foliage.root] + call scan_namespace + mov eax,[current_symbol] + mov [eax+SymbolTree_Leaf.fallback_parent],ebx + jc find_in_wider_scope + mov edi,[symbol_root] + retn + check_fallback_neighbour: + call get_available_value + jc no_neighbour_found + fallback_neighbour_ok: + mov edx,[ebx+SymbolTree_Leaf.branch] + mov edi,[edx+SymbolTree_Foliage.root] + retn + check_fallback_parent: + call get_available_value + mov edx,[ebx+SymbolTree_Leaf.branch] + mov edi,[edx+SymbolTree_Foliage.root] + mov [symbol_root],edi + jc find_in_wider_scope + retn + check_namespace_fallback: + call get_available_value + jnc fallback_neighbour_ok + no_defined_symbol: + cmp [symbol_class],SYMCLASS_EXPRESSION + je return_kept_symbol + mov [symbol_class],SYMCLASS_EXPRESSION + or [symbol_expected],1 + mov ebx,[kept_symbol] + mov ebx,[ebx+SymbolTree_Leaf.branch] + mov edi,[ebx+SymbolTree_Foliage.root] + jmp scan_symbol_branch + return_kept_symbol: + mov ebx,[kept_symbol] + mov edx,[ebx+SymbolTree_Leaf.branch] + mov edi,[edx+SymbolTree_Foliage.root] + mov al,[kept_symbol_flags] + mov [ebx+SymbolTree_Leaf.flags],al + retn + +scan_namespace: +; in: +; ebx - SymbolTree_Root +; edx = hash +; ecx = name length +; esi - name +; [name_kind] = NAME_# +; [name_volatile] = non-zero when name is provided in a temporary storage +; [name_token] = null or pointer to the contents of a preprocessed token +; [symbol_class] = SYMCLASS_# +; [symbol_required] = non-zero when symbol needs to be added if not found +; [symbol_expected] = non-zero when symbol needs not be checked for its value availability +; out: +; ebx - SymbolTree_Leaf, null when nothing found +; edx - SymbolTree_Foliage, null when no such branch exists +; [symbol_root] - SymbolTree_Root +; [symbol_branch] - SymbolTree_Foliage +; [name_volatile] zeroed when name has been moved to persistent storage +; when [symbol_expected] = 0: +; cf set when symbol not found or has no defined value +; al = copy of symbol prediction flags before they were affected by this function +; when [symbol_expected] = 1: +; cf set when symbol not found +; preserves: ecx, [esi] + mov [symbol_root],ebx + test [ebx+SymbolTree_Root.attributes],SYMTREE_LOCAL + jnz scan_local_namespace + add ebx,sizeof.SymbolTree_Root + if TREE_HEIGHT > 1 + mov edi,TREE_HEIGHT + follow_tree: + mov eax,edx + and eax,(1 shl TREE_NODE_BITS)-1 + shr edx,TREE_NODE_BITS + lea ebx,[ebx+eax*4] + else + and edx,(1 shl TREE_NODE_BITS)-1 + lea ebx,[ebx+edx*4] + end if + mov eax,[ebx] + test eax,eax + jz unregistered_hash + mov ebx,eax + if TREE_HEIGHT > 1 + dec edi + jnz follow_tree + end if + scan_foliage_branches: + movzx eax,[name_kind] + cmp [ebx+SymbolTree_Foliage.name_kind],al + jne next_foliage_branch + cmp [ebx+SymbolTree_Foliage.name_length],ecx + jne next_foliage_branch + mov edi,[ebx+SymbolTree_Foliage.name_data] + cmp esi,edi + je scan_symbol_branch + cmp al,NAME_ABSTRACT + je next_foliage_branch + jecxz scan_symbol_branch + repe cmpsb + jne names_not_identical + mov esi,edi + mov ecx,[ebx+SymbolTree_Foliage.name_length] + sub esi,ecx + and [name_volatile],0 + mov edx,[name_token] + test edx,edx + jz scan_symbol_branch + test [ebx+SymbolTree_Foliage.flags],FOLIAGE_WITH_TOKEN + jz use_token_for_foliage + sub esi,4 + mov eax,[edx] + mov [edx],esi + mov [eax+4+ecx+8],esi + add esi,4 + jmp scan_symbol_branch + use_token_for_foliage: + mov esi,[edx] + add esi,4 + mov [ebx+SymbolTree_Foliage.name_data],esi + or [ebx+SymbolTree_Foliage.flags],FOLIAGE_WITH_TOKEN + jmp scan_symbol_branch + hash_collision: + add esi,ecx + mov ecx,[ebx+SymbolTree_Foliage.name_length] + sub esi,ecx + next_foliage_branch: + mov eax,[ebx+SymbolTree_Foliage.next] + test eax,eax + jz unregistered_name + mov ebx,eax + jmp scan_foliage_branches + names_not_identical: + cmp al,NAME_CASEINSENSITIVE + jne hash_collision + dec esi + dec edi + inc ecx + case_insensitive_compare: + lodsb + mov dl,[characters+eax] + mov al,[edi] + inc edi + dec ecx + cmp dl,[characters+eax] + jne hash_collision + test ecx,ecx + jnz case_insensitive_compare + mov ecx,[ebx+SymbolTree_Foliage.name_length] + sub esi,ecx + scan_symbol_branch: + ; in: + ; ebx - SymbolTree_Foliage + ; [symbol_class] = SYMCLASS_# + ; [symbol_required] = non-zero when symbol needs to be added if not found + ; [symbol_expected] = non-zero when symbol needs not be checked for its value availability + ; out: + ; ebx - SymbolTree_Leaf, null when nothing found + ; edx - SymbolTree_Foliage + ; [symbol_branch] - SymbolTree_Foliage + ; when [symbol_expected] = 0: + ; cf set when symbol not found or has no defined value + ; al = copy of symbol prediction flags before they were affected by this function + ; when [symbol_expected] = 1: + ; cf set when symbol not found + ; preserves: ecx, esi, edi + mov [symbol_branch],ebx + add ebx,sizeof.SymbolTree_Foliage + mov dl,[symbol_class] + scan_leaves: + mov al,[ebx+SymbolTree_Leaf.class] + cmp al,dl + je leaf_found + mov eax,[ebx+SymbolTree_Leaf.next] + test eax,eax + jz leaves_scanned + mov ebx,eax + jmp scan_leaves + leaf_found: + cmp [symbol_expected],0 + jne symbol_found + call get_available_value + jnc symbol_found + no_defined_symbol_found: + mov edx,[symbol_branch] + stc + retn + symbol_found: + mov edx,[symbol_branch] + clc + retn + leaves_scanned: + mov al,[symbol_required] + or al,[symbol_expected] + jnz attach_symbol_leaf + xor ebx,ebx + jmp no_defined_symbol_found + unregistered_name: + cmp [symbol_required],0 + je name_not_found + push ecx + lea ebx,[ebx+SymbolTree_Foliage.next] + jmp attach_foliage_branch + name_not_found: + xor ebx,ebx + xor edx,edx + stc + retn + unregistered_hash: + cmp [symbol_required],0 + je name_not_found + push ecx + if TREE_HEIGHT > 1 + expand_tree: + dec edi + jz attach_foliage_branch + mov ecx,sizeof.SymbolTree_Node + call create_tree_element + mov [ebx],eax + mov ebx,eax + mov eax,edx + and eax,(1 shl TREE_NODE_BITS)-1 + shr edx,TREE_NODE_BITS + lea ebx,[ebx+eax*4] + jmp expand_tree + end if + attach_foliage_branch: + mov ecx,sizeof.SymbolTree_Foliage + sizeof.SymbolTree_Leaf + call create_tree_element + mov [ebx],eax + mov [symbol_branch],eax + mov ebx,eax + pop ecx + mov eax,[symbol_root] + mov [ebx+SymbolTree_Foliage.root],eax + mov al,[name_kind] + mov [ebx+SymbolTree_Foliage.name_kind],al + mov [ebx+SymbolTree_Foliage.name_length],ecx + cmp al,NAME_ABSTRACT + je symbol_name_stored + mov edx,[name_token] + test edx,edx + jnz symbol_name_from_token + cmp [name_volatile],0 + je symbol_name_stored + call store_string + and [name_volatile],0 + jmp symbol_name_stored + symbol_name_from_token: + or [ebx+SymbolTree_Foliage.flags],FOLIAGE_WITH_TOKEN + mov esi,[edx] + add esi,4 + symbol_name_stored: + mov [ebx+SymbolTree_Foliage.name_data],esi + lea ebx,[ebx+sizeof.SymbolTree_Foliage] + jmp fill_new_symbol_leaf + attach_symbol_leaf: + push ecx + mov ecx,sizeof.SymbolTree_Leaf + call create_tree_element + mov [ebx+SymbolTree_Leaf.next],eax + mov ebx,eax + pop ecx + fill_new_symbol_leaf: + mov al,[symbol_class] + mov [ebx+SymbolTree_Leaf.class],al + mov edx,[symbol_branch] + cmp al,SYMCLASS_PARAMETER + jne namespace_flags_updated + cmp [name_kind],NAME_CASEINSENSITIVE + jne namespace_flags_updated + mov eax,[edx+SymbolTree_Foliage.root] + or [eax+SymbolTree_Root.attributes],SYMTREE_WITH_CASEINSENSITIVE_PARAMETERS + namespace_flags_updated: + mov [ebx+SymbolTree_Leaf.branch],edx + cmp [symbol_expected],0 + jne symbol_found + xor al,al + or [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED + jmp no_defined_symbol_found + scan_local_namespace: + add ebx,sizeof.SymbolTree_Root + if LOCAL_TREE_HEIGHT > 1 + mov edi,LOCAL_TREE_HEIGHT + follow_local_tree: + mov eax,edx + and eax,(1 shl LOCAL_TREE_NODE_BITS)-1 + shr edx,LOCAL_TREE_NODE_BITS + lea ebx,[ebx+eax*4] + else + and edx,(1 shl LOCAL_TREE_NODE_BITS)-1 + lea ebx,[ebx+edx*4] + end if + mov eax,[ebx] + test eax,eax + jz local_unregistered_hash + mov ebx,eax + if LOCAL_TREE_HEIGHT > 1 + dec edi + jnz follow_local_tree + end if + jmp scan_foliage_branches + local_unregistered_hash: + cmp [symbol_required],0 + je name_not_found + push ecx + if LOCAL_TREE_HEIGHT > 1 + expand_local_tree: + dec edi + jz attach_foliage_branch + mov ecx,sizeof.SymbolTree_LocalNode + call create_tree_element + mov [ebx],eax + mov ebx,eax + mov eax,edx + and eax,(1 shl LOCAL_TREE_NODE_BITS)-1 + shr edx,LOCAL_TREE_NODE_BITS + lea ebx,[ebx+eax*4] + jmp expand_local_tree + else + jmp attach_foliage_branch + end if + +get_abstract_symbol: +; in: +; eax:ecx = symbol identifier +; ebx - SymbolTree_Root, null for local scope +; dl = SYMCLASS_# +; out: +; ebx - SymbolTree_Leaf +; edx - SymbolTree_Foliage +; edi - SymbolTree_Root + mov [symbol_class],dl + test ebx,ebx + jnz scope_selected + mov ebx,[current_context.base_namespace] + scope_selected: + mov esi,eax + mov edx,FNV_OFFSET + mov [minor_identifier],ecx + mov ecx,4 + hash_major_identifier: + xor dl,al + imul edx,FNV_PRIME + shr eax,8 + loop hash_major_identifier + mov eax,[minor_identifier] + mov ecx,4 + hash_minor_identifier: + xor dl,al + imul edx,FNV_PRIME + shr eax,8 + loop hash_minor_identifier + mov ecx,[minor_identifier] + mov [name_kind],NAME_ABSTRACT + or [symbol_required],1 + or [symbol_expected],1 + call scan_namespace + mov edi,[symbol_root] + retn + +create_tree_element: +; in: ecx = length of element +; out: eax - pointer to allocated and zeroed memory +; preserves: ebx, ecx, edx, esi, edi + sub [tree_reserve_length],ecx + jc expand_tree_reserve + mov eax,[tree_reserve] + add [tree_reserve],ecx + retn + expand_tree_reserve: + push ecx edx edi + mov ecx,10000h + call malloc_fixed + mov edx,eax + xchg edx,[tree_blocks] + mov [eax],edx + lea edi,[eax+4] + sub ecx,4 + mov [tree_reserve],edi + mov [tree_reserve_length],ecx + mov edx,eax + xor eax,eax + shr ecx,2 + rep stosd + mov eax,edx + pop edi edx ecx + jmp create_tree_element + +store_string: +; in: esi - string, ecx = length +; out: esi - stored string +; preserves: ebx, ecx, edi + cmp ecx,[storage_free_space_length] + ja expand_storage + storage_ready: + push ecx edi + mov edi,[storage_free_space] + add [storage_free_space],ecx + sub [storage_free_space_length],ecx + move_to_storage: + mov eax,edi + shr ecx,1 + jnc movsb_ok + movsb + movsb_ok: + shr ecx,1 + jnc movsw_ok + movsw + movsw_ok: + rep movsd + mov esi,eax + pop edi ecx + retn + expand_storage: + cmp ecx,100h + jae store_long_string + push ecx + mov ecx,10000h + call malloc_fixed + mov edx,eax + xchg edx,[storage_blocks] + mov [eax],edx + add eax,4 + sub ecx,4 + mov [storage_free_space],eax + mov [storage_free_space_length],ecx + pop ecx + jmp storage_ready + store_long_string: + push ecx + add ecx,4 + call malloc_fixed + mov edx,[storage_blocks] + test edx,edx + jz long_first_string + mov ecx,eax + xchg ecx,[edx] + mov [eax],ecx + long_string_storage_ready: + add eax,4 + mov ecx,[esp] + push edi + mov edi,eax + jmp move_to_storage + long_first_string: + mov [storage_blocks],eax + mov [eax],edx + jmp long_string_storage_ready + +get_symbol_namespace: +; in: +; edx - SymbolTree_Foliage +; out: +; ebx - SymbolTree_Root of child namespace +; preserves: edx, esi, edi + mov ebx,[edx+SymbolTree_Foliage.child_namespace] + test ebx,ebx + jnz symbol_namespace_ok + mov ecx,sizeof.SymbolTree_Root + sizeof.SymbolTree_Node + call create_tree_element + mov [eax+SymbolTree_Root.parent_branch],edx + mov [edx+SymbolTree_Foliage.child_namespace],eax + mov ebx,eax + symbol_namespace_ok: + retn +get_local_namespace: +; same as get_symbol_namespace + mov ebx,[edx+SymbolTree_Foliage.child_namespace] + test ebx,ebx + jnz symbol_namespace_ok + mov ecx,sizeof.SymbolTree_Root + sizeof.SymbolTree_LocalNode + call create_tree_element + or [eax+SymbolTree_Root.attributes],SYMTREE_LOCAL + or [eax+SymbolTree_Root.flags],NAMESPACE_LOCAL + mov [edx+SymbolTree_Foliage.child_namespace],eax + mov ebx,eax + retn + +get_local_anchor: +; in: +; eax = instruction identifier +; ecx = context identifier +; out: +; edx - SymbolTree_Foliage where a local namespace can be anchored + xor ebx,ebx + mov dl,SYMCLASS_PARAMETER + call get_abstract_symbol + mov eax,[ebx+SymbolTree_Leaf.definition] + test eax,eax + jz create_anchor_counter + mov ecx,[current_pass] + cmp ecx,[eax+ValueDefinition.pass] + je increment_anchor_counter + mov [eax+ValueDefinition.pass],ecx + and [eax+ValueDefinition.value],0 + jmp increment_anchor_counter + create_anchor_counter: + mov ecx,sizeof.ValueDefinition + call create_tree_element + mov [ebx+SymbolTree_Leaf.definition],eax + inc [eax+ValueDefinition.reference_count] + mov [eax+ValueDefinition.type],VALTYPE_PLAIN + mov ecx,[current_pass] + mov [eax+ValueDefinition.pass],ecx + increment_anchor_counter: + mov ecx,[eax+ValueDefinition.value] + inc [eax+ValueDefinition.value] + jecxz local_anchor_ready + mov eax,ebx + xor ebx,ebx + mov dl,SYMCLASS_PARAMETER + call get_abstract_symbol + local_anchor_ready: + retn + +get_available_value: +; in: +; ebx - SymbolTree_Leaf +; out: +; cf set if symbol is not considered defined +; edx - ValueDefinition +; al = copy of symbol prediction flags before they were affected by this function +; preserves: ebx, ecx, esi, edi + mov edx,[ebx+SymbolTree_Leaf.definition] + test [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz get_variable_value + test edx,edx + jz symbol_predicted_undefined + mov al,[edx+ValueDefinition.flags] + test al,VAL_INTERNAL + jnz symbol_defined + not al + test al,VAL_IN_USE + VAL_NONRECURSIVE + jz symbol_undefined + mov eax,[current_pass] + sub eax,[edx+ValueDefinition.pass] + jz symbol_defined + cmp eax,1 + ja symbol_predicted_undefined + symbol_predicted_defined: + mov al,[ebx+SymbolTree_Leaf.flags] + or [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED + SYM_PREDICTED_DEFINED + ; clc + retn + symbol_defined: + mov al,[ebx+SymbolTree_Leaf.flags] + clc + retn + symbol_predicted_undefined: + mov al,[ebx+SymbolTree_Leaf.flags] + or al,SYM_PREDICTED + and al,not SYM_PREDICTED_DEFINED + xchg [ebx+SymbolTree_Leaf.flags],al + stc + retn + get_variable_value: + test edx,edx + jz symbol_undefined + inspect_definition: + test [edx+ValueDefinition.flags],VAL_INTERNAL + jnz symbol_defined + test [edx+ValueDefinition.flags],VAL_IN_USE + jnz try_previous_definition + mov eax,[current_pass] + cmp eax,[edx+ValueDefinition.pass] + je symbol_defined + cmp edx,[ebx+SymbolTree_Leaf.definition] + je retire_outdated_definition + try_previous_definition: + mov edx,[edx+ValueDefinition.previous] + test edx,edx + jnz inspect_definition + symbol_undefined: + mov al,[ebx+SymbolTree_Leaf.flags] + stc + retn + retire_outdated_definition: + mov eax,edx + dec [edx+ValueDefinition.reference_count] + xchg edx,[ebx+SymbolTree_Leaf.retired_definition] + xchg edx,[eax+ValueDefinition.previous] + mov [ebx+SymbolTree_Leaf.definition],edx + jmp get_variable_value + +mark_symbol_as_used: +; in: +; ebx - SymbolTree_Leaf +; edx - ValueDefinition, null when value is unavailable but used nonetheless +; preserves: ebx, ecx, edx, esi, edi +; note: +; normally setting SymbolTree_Leaf.last_use_pass is enough, but this function +; improves prediction quality of USED operator; + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + test edx,edx + jz mark_used_fallbacks + retn + mark_used_fallbacks: + push ebx edx + mark_fallback_neighbour: + mov edx,[ebx+SymbolTree_Leaf.fallback_neighbour] + test edx,edx + jz mark_fallback_parent + mov [edx+SymbolTree_Leaf.last_use_pass],eax + mark_fallback_parent: + mov ebx,[ebx+SymbolTree_Leaf.fallback_parent] + test ebx,ebx + jz used_fallbacks_marked + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + jmp mark_fallback_neighbour + used_fallbacks_marked: + pop edx ebx + retn + +use_available_value: +; same as get_available_value, but also includes operation of mark_symbol_as_used + mov eax,[current_pass] + mov [ebx+SymbolTree_Leaf.last_use_pass],eax + call get_available_value + jc use_unavailable_value + retn + use_unavailable_value: + call mark_used_fallbacks + stc + retn + +create_constant_value_definition: +; in: +; ebx - SymbolTree_Leaf +; out: +; edx - ValueDefinition possibly containing value to update, null if definition forbidden +; preserves: ebx, esi, edi + test [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz symbol_already_defined + or [ebx+SymbolTree_Leaf.flags],SYM_CONSTANT + mov eax,[ebx+SymbolTree_Leaf.definition] + test eax,eax + jz add_value_definition + test [eax+ValueDefinition.flags],VAL_INTERNAL + jnz symbol_already_defined + mov ecx,[eax+ValueDefinition.pass] + cmp ecx,[current_pass] + jne reset_value + symbol_already_defined: + mov edx,_conflicting_definition + call register_error + xor edx,edx + retn +update_value_definition: +; in: +; ebx - SymbolTree_Leaf +; out: +; edx - ValueDefinition possibly containing value to update, null if definition forbidden +; preserves: ebx, esi, edi + mov eax,[ebx+SymbolTree_Leaf.definition] + test eax,eax + jz add_value_definition + test [eax+ValueDefinition.flags],VAL_INTERNAL + jnz value_redefinition + mov ecx,[eax+ValueDefinition.pass] + cmp ecx,[current_pass] + jne reset_value + test [ebx+SymbolTree_Leaf.flags],SYM_CONSTANT or SYM_LINK + jnz constant_redefined + mov edx,eax + or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED + jz dynamic_value_definition_ready + and [ebx+SymbolTree_Leaf.flags],not SYM_PREDICTED + test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED_DEFINED + jz dynamic_value_definition_ready + or [next_pass_needed],1 + dynamic_value_definition_ready: + cmp [edx+ValueDefinition.reference_count],1 + ja dynamic_value_in_use + retn + dynamic_value_in_use: + mov eax,[edx+ValueDefinition.previous] + mov [ebx+SymbolTree_Leaf.definition],eax + dec [edx+ValueDefinition.reference_count] + mov eax,edx + xchg eax,[ebx+SymbolTree_Leaf.retired_definition] + mov [edx+ValueDefinition.previous],eax +create_value_definition: +; in: +; ebx - SymbolTree_Leaf +; out: +; edx - ValueDefinition possibly containing value to update, null if definition forbidden +; preserves: ebx, esi, edi + mov eax,[ebx+SymbolTree_Leaf.definition] + test eax,eax + jz add_value_definition + test [eax+ValueDefinition.flags],VAL_INTERNAL + jnz value_redefinition + mov ecx,[eax+ValueDefinition.pass] + cmp ecx,[current_pass] + je value_redefinition + reset_value: + test [ebx+SymbolTree_Leaf.flags],SYM_LINK + jnz reset_link_value + mov edx,[ebx+SymbolTree_Leaf.retired_definition] + retire_previous_values: + dec [eax+ValueDefinition.reference_count] + xchg edx,[eax+ValueDefinition.previous] + xchg eax,edx + test eax,eax + jz previous_values_retired + test [eax+ValueDefinition.flags],VAL_INTERNAL + jz retire_previous_values + previous_values_retired: + mov [ebx+SymbolTree_Leaf.definition],edx + xchg eax,[edx+ValueDefinition.previous] + mov [ebx+SymbolTree_Leaf.retired_definition],eax + cmp [edx+ValueDefinition.reference_count],0 + jne add_value_definition + inc [edx+ValueDefinition.reference_count] + test [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz reset_value_type + retn + reset_link_value: + and [ebx+SymbolTree_Leaf.flags],not (SYM_LINK or SYM_LINK_PREDICTED) + mov eax,[ebx+SymbolTree_Leaf.last_use_pass] + cmp eax,[current_pass] + jne reset_current_link_value + or [next_pass_needed],1 + reset_current_link_value: + xor eax,eax + xchg eax,[ebx+SymbolTree_Leaf.definition] + dec [eax+ValueDefinition.reference_count] + jnz reset_previous_link_value + test [eax+ValueDefinition.flags],VAL_DETACHED + jz reset_previous_link_value + mov ecx,eax + xchg eax,[retired_definition] + mov [ecx+ValueDefinition.previous],eax + reset_previous_link_value: + xor eax,eax + xchg eax,[ebx+SymbolTree_Leaf.retired_definition] + test eax,eax + jz add_value_definition + dec [eax+ValueDefinition.reference_count] + jnz add_value_definition + test [eax+ValueDefinition.flags],VAL_DETACHED + jz add_value_definition + mov ecx,eax + xchg eax,[retired_definition] + mov [ecx+ValueDefinition.previous],eax + jmp add_value_definition + constant_redefined: + mov edx,_conflicting_definition + call register_error + xor edx,edx + retn + value_redefinition: + cmp [eax+ValueDefinition.type],VALTYPE_ELEMENT + je constant_redefined + test [ebx+SymbolTree_Leaf.flags],SYM_CONSTANT or SYM_LINK + jnz constant_redefined + test [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz add_value_definition + or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED + jz add_value_definition + and [ebx+SymbolTree_Leaf.flags],not SYM_PREDICTED + test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED_DEFINED + jz add_value_definition + or [next_pass_needed],1 + add_value_definition: + lea ecx,[ebx+SymbolTree_Leaf.retired_definition] + retrieve_retired_value: + mov eax,[ecx] + test eax,eax + jz new_value_definition + cmp [eax+ValueDefinition.reference_count],0 + jne retired_value_immutable + inc [eax+ValueDefinition.reference_count] + mov edx,[eax+ValueDefinition.previous] + mov [ecx],edx + mov [eax+ValueDefinition.type],VALTYPE_RESERVED + jmp adopt_value_definition + retired_value_immutable: + lea ecx,[eax+ValueDefinition.previous] + jmp retrieve_retired_value + new_value_definition: + mov ecx,sizeof.ValueDefinition + call create_tree_element + mov ecx,eax + xchg ecx,[value_definition_chain] + mov [eax+ValueDefinition.interlink],ecx + assert VALTYPE_RESERVED = 0 + inc [eax+ValueDefinition.reference_count] + adopt_value_definition: + mov edx,eax + xchg eax,[ebx+SymbolTree_Leaf.definition] + mov [edx+ValueDefinition.previous],eax + test [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz reset_value_type + test eax,eax + jz value_definition_ready + mov ecx,eax + xchg ecx,[ebx+SymbolTree_Leaf.retired_definition] + xchg ecx,[eax+ValueDefinition.previous] + mov [edx+ValueDefinition.previous],ecx + ; test ecx,ecx + ; jnz internal_error + mov ecx,[eax+ValueDefinition.pass] + mov [edx+ValueDefinition.pass],ecx + mov cl,[eax+ValueDefinition.type] + mov [edx+ValueDefinition.type],cl + mov ecx,[eax+ValueDefinition.value_length] + mov [edx+ValueDefinition.value_length],ecx + jecxz value_definition_ready + push esi edi + mov esi,[eax+ValueDefinition.value] + mov edi,[edx+ValueDefinition.value] + cmp ecx,[edx+ValueDefinition.block_length] + jbe duplicate_value + push edx + cmp [edx+ValueDefinition.block_length],0 + je reallocate_for_duplicate + push ecx + xor eax,eax + xchg eax,[edx+ValueDefinition.value] + call mfree + pop ecx + reallocate_for_duplicate: + mov edi,ecx + call malloc + pop edx + mov [edx+ValueDefinition.value],eax + mov [edx+ValueDefinition.block_length],ecx + mov ecx,edi + mov edi,eax + duplicate_value: + rep movsb + pop edi esi + value_definition_ready: + retn + reset_value_type: + mov [edx+ValueDefinition.type],VALTYPE_RESERVED + retn + +remove_value_definition: +; in: +; ebx - SymbolTree_Leaf +; edx - ValueDefinition, null to remove the present value +; edi - SymbolTree_Leaf where to move the value, null for plain remove +; out: +; cf set if there was no value to remove +; when cf = 0: +; edx - ValueDefinition that got removed +; preserves: ebx, esi, edi + test [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz variable_ready + test [ebx+SymbolTree_Leaf.flags],SYM_CONSTANT or SYM_LINK + jnz cannot_apply_to_constant + or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED + jz variable_ready + and [ebx+SymbolTree_Leaf.flags],not SYM_PREDICTED + test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED_DEFINED + jz variable_ready + or [next_pass_needed],1 + variable_ready: + lea ecx,[ebx+SymbolTree_Leaf.definition] + test edx,edx + jnz find_definition_to_remove + mov edx,[ecx] + test edx,edx + jz no_definition_to_remove + test [edx+ValueDefinition.flags],VAL_INTERNAL + jnz no_definition_to_remove + cmp [edx+ValueDefinition.type],VALTYPE_RESERVED + je no_definition_to_remove + mov eax,[edx+ValueDefinition.pass] + cmp eax,[current_pass] + jne no_definition_to_remove + remove_definition: + mov eax,[edx+ValueDefinition.previous] + test edi,edi + jnz move_definition + mov [ecx],eax + mov eax,[ebx+SymbolTree_Leaf.retired_definition] + mov [edx+ValueDefinition.previous],eax + dec [edx+ValueDefinition.reference_count] + mov [ebx+SymbolTree_Leaf.retired_definition],edx + clc + retn + move_definition: + cmp edi,edx + je definition_moved + test [edi+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz append_moved_definition + test [edi+SymbolTree_Leaf.flags],SYM_CONSTANT or SYM_LINK + jnz cannot_apply_to_constant + or [edi+SymbolTree_Leaf.flags],SYM_VARIABLE + test [edi+SymbolTree_Leaf.flags],SYM_PREDICTED + jz append_moved_definition + and [ebx+SymbolTree_Leaf.flags],not SYM_PREDICTED + test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED_DEFINED + jz append_moved_definition + or [next_pass_needed],1 + append_moved_definition: + mov [ecx],eax + mov eax,[edi+SymbolTree_Leaf.definition] + mov [edx+ValueDefinition.previous],eax + mov [edi+SymbolTree_Leaf.definition],edx + definition_moved: + clc + retn + find_definition_to_remove: + mov eax,[ecx] + cmp eax,edx + je remove_definition + test eax,eax + jz no_definition_to_remove + lea ecx,[eax+ValueDefinition.previous] + jmp find_definition_to_remove + cannot_apply_to_constant: + mov edx,_cannot_apply_to_constant + call register_error + no_definition_to_remove: + stc + retn + +assign_value: +; in: +; ebx - SymbolTree_Leaf +; edx - ValueDefinition prepared to receive the new value +; esi - value +; ecx = length of value +; [value_type] = VALTYPE_# +; preserves: ebx, edx +; notes: +; with VALTYPE_PLAIN ecx must be zero and esi should contain the value directly +; if esi is null, requested length is allocated but not filled + and [edx+ValueDefinition.flags],0 + mov eax,[current_pass] + sub eax,[edx+ValueDefinition.pass] + add [edx+ValueDefinition.pass],eax + test [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz reuse_value_block + cmp eax,[current_pass] + je reuse_value_block + mov edi,[ebx+SymbolTree_Leaf.last_use_pass] + cmp edi,[current_pass] + jne reuse_value_block + cmp ecx,[edx+ValueDefinition.value_length] + je update_value + or [next_pass_needed],1 + reuse_value_block: + mov [edx+ValueDefinition.value_length],ecx + mov edi,[edx+ValueDefinition.value] + cmp ecx,[edx+ValueDefinition.block_length] + jbe write_value + push edx + push ecx + cmp [edx+ValueDefinition.block_length],0 + je new_value + xor eax,eax + xchg eax,[edx+ValueDefinition.value] + call mfree + new_value: + pop ecx + call malloc + pop edx + mov [edx+ValueDefinition.value],eax + mov [edx+ValueDefinition.block_length],ecx + mov edi,eax + write_value: + mov al,[value_type] + mov [edx+ValueDefinition.type],al + cmp al,VALTYPE_PLAIN + je write_plain_value + test esi,esi + jz value_written + mov ecx,[edx+ValueDefinition.value_length] + rep movsb + value_written: + retn + write_plain_value: + xchg esi,[edx+ValueDefinition.value] + cmp [edx+ValueDefinition.block_length],0 + je value_written + and [edx+ValueDefinition.block_length],0 + mov eax,esi + call mfree + jmp value_written + rewrite_value: + or [next_pass_needed],1 + jmp write_value + update_value: + mov edi,[edx+ValueDefinition.value] + cmp eax,1 + ja rewrite_value + mov al,[value_type] + cmp [edx+ValueDefinition.type],al + jne rewrite_value + jecxz value_written + test esi,esi + jz rewrite_value + cmp al,VALTYPE_SYMBOLIC + je update_symbolic_value + cmp al,VALTYPE_PLAIN + je update_plain_value + mov ecx,[edx+ValueDefinition.value_length] + repe cmpsb + je value_updated + inc ecx + dec esi + dec edi + or [next_pass_needed],1 + rep movsb + value_updated: + retn + update_symbolic_value: + mov ecx,[edx+ValueDefinition.value_length] + push edx + call compare_symbolic_values + pop edx + jecxz value_updated + value_changed: + rep movsb + changed_value_updated: + or [next_pass_needed],1 + retn + update_plain_value: + mov eax,esi + xchg eax,[edx+ValueDefinition.value] + cmp eax,esi + jne changed_value_updated + retn + +expand_value: +; in: +; edx - ValueDefinition +; ebx = number of additional zero bytes to append to the value +; preserves: ebx, edx, esi + mov eax,[edx+ValueDefinition.value_length] + mov edi,[edx+ValueDefinition.value] + add edi,eax + add eax,ebx + jc out_of_memory + cmp eax,[edx+ValueDefinition.block_length] + jbe append_zero_bytes + push eax + bsr ecx,eax + dec cl + shr eax,cl + inc eax + shl eax,cl + mov ecx,eax + pop eax + cmp ecx,eax + jbe out_of_memory + mov eax,[edx+ValueDefinition.value] + push edx + call realloc + pop edx + mov [edx+ValueDefinition.value],eax + mov [edx+ValueDefinition.block_length],ecx + mov edi,eax + add edi,[edx+ValueDefinition.value_length] + append_zero_bytes: + add [edx+ValueDefinition.value_length],ebx + xor al,al + mov ecx,ebx + rep stosb + retn + +update_value_link: +; in: +; ebx - SymbolTree_Leaf +; edx - ValueDefinition to link +; preserves: ebx, edx +; note: value must be from the current pass + mov eax,[ebx+SymbolTree_Leaf.definition] + test eax,eax + jz values_detached + mov ecx,[eax+ValueDefinition.pass] + cmp ecx,[current_pass] + je symbol_already_defined + test [ebx+SymbolTree_Leaf.flags],SYM_LINK + jnz update_established_link + detach_and_retire_values: + test eax,eax + jz values_detached + dec [eax+ValueDefinition.reference_count] + or [eax+ValueDefinition.flags],VAL_DETACHED + mov ecx,eax + xchg eax,[retired_definition] + xchg eax,[ecx+ValueDefinition.previous] + jmp detach_and_retire_values + values_detached: + mov [ebx+SymbolTree_Leaf.definition],eax + mov eax,[ebx+SymbolTree_Leaf.retired_definition] + detach_retired_values: + test eax,eax + jz retired_values_detached + or [eax+ValueDefinition.flags],VAL_DETACHED + mov ecx,eax + xchg eax,[retired_definition] + xchg eax,[ecx+ValueDefinition.previous] + jmp detach_retired_values + retired_values_detached: + mov [ebx+SymbolTree_Leaf.retired_definition],eax + or [ebx+SymbolTree_Leaf.flags],SYM_LINK + jmp link_new_value + update_established_link: + mov ecx,[current_pass] + cmp ecx,[ebx+SymbolTree_Leaf.last_use_pass] + jne link_new_value + or [ebx+SymbolTree_Leaf.flags],SYM_LINK_PREDICTED + link_new_value: + ; cmp ecx,[edx+ValueDefinition.pass] + ; jne internal_error + mov eax,edx + inc [eax+ValueDefinition.reference_count] + xchg eax,[ebx+SymbolTree_Leaf.definition] + xchg eax,[ebx+SymbolTree_Leaf.retired_definition] + test eax,eax + jz link_updated + dec [eax+ValueDefinition.reference_count] + jnz link_updated + test [eax+ValueDefinition.flags],VAL_DETACHED + jz link_updated + mov ecx,eax + xchg eax,[retired_definition] + mov [ecx+ValueDefinition.previous],eax + link_updated: + retn + +detect_mispredictions: +; in: ebx - SymbolTree_Root +; note: +; while it is looking for mispredicted definitions, it also prepares the tree for the next pass + mov edx,[tree_stack_base] + browse_from_root: + xor eax,eax + mov [ebx+SymbolTree_Root.current_label],eax + and [ebx+SymbolTree_Root.flags],not NAMESPACE_LABEL_FORWARDING + test [ebx+SymbolTree_Root.attributes],SYMTREE_LOCAL + jnz browse_local_tree + add ebx,sizeof.SymbolTree_Root + mov eax,[tree_stack_end] + sub eax,TREE_HEIGHT*8+16 + cmp edx,eax + jbe tree_stack_prepared + mov eax,[tree_stack_base] + sub edx,eax + mov ecx,[tree_stack_end] + sub ecx,eax + add ecx,TREE_HEIGHT*8+16 + push edx + call grow_stack + pop edx + add edx,eax + mov [tree_stack_base],eax + add eax,ecx + mov [tree_stack_end],eax + tree_stack_prepared: + mov ecx,TREE_HEIGHT + browse_node: + mov edi,ebx + dec cl + browse_branch: + cmp dword [edi],0 + je branch_browsed + test cl,cl + jnz deeper_node + mov esi,[edi] + browse_foliage: + mov eax,[esi+SymbolTree_Foliage.child_namespace] + test eax,eax + jz subtree_browsed + mov [edx],ebx + mov [edx+4],ecx + mov [edx+8],esi + mov [edx+12],edi + add edx,16 + mov ebx,eax + jmp browse_from_root + browse_local_tree: + add ebx,sizeof.SymbolTree_Root + mov eax,[tree_stack_end] + sub eax,LOCAL_TREE_HEIGHT*8+16 + cmp edx,eax + jbe local_tree_stack_prepared + mov eax,[tree_stack_base] + sub edx,eax + mov ecx,[tree_stack_end] + sub ecx,eax + add ecx,LOCAL_TREE_HEIGHT*8+16 + push edx + call grow_stack + pop edx + add edx,eax + mov [tree_stack_base],eax + add eax,ecx + mov [tree_stack_end],eax + local_tree_stack_prepared: + mov ecx,LOCAL_TREE_HEIGHT + 1 shl 8 + jmp browse_node + subtree_browsed: + mov eax,esi + add eax,sizeof.SymbolTree_Foliage + inspect_leaf: + test [eax+SymbolTree_Leaf.flags],SYM_LINK_PREDICTED + jz link_prediction_ok + push eax ecx edx esi edi + mov edx,[eax+SymbolTree_Leaf.definition] + mov ecx,[eax+SymbolTree_Leaf.retired_definition] + mov esi,dword [edx+ValueDefinition.type] + sub esi,dword [ecx+ValueDefinition.type] + test esi,0FFh + jnz link_value_mispredicted + mov esi,[ecx+ValueDefinition.value] + mov ecx,[ecx+ValueDefinition.value_length] + mov edi,[edx+ValueDefinition.value] + mov edx,[edx+ValueDefinition.value_length] + cmp ecx,edx + jne link_value_mispredicted + jecxz reset_link_prediction + repe cmpsb + je reset_link_prediction + link_value_mispredicted: + or [next_pass_needed],1 + reset_link_prediction: + and [eax+SymbolTree_Leaf.flags],not SYM_LINK_PREDICTED + pop edi esi edx ecx eax + link_prediction_ok: + test [eax+SymbolTree_Leaf.flags],SYM_VARIABLE + jnz inspect_next_leaf + and [eax+SymbolTree_Leaf.flags],not SYM_CONSTANT + test [eax+SymbolTree_Leaf.flags],SYM_PREDICTED or SYM_USAGE_PREDICTED + jz inspect_next_leaf + push edx + test [eax+SymbolTree_Leaf.flags],SYM_PREDICTED + jz definition_prediction_ok + mov edx,[eax+SymbolTree_Leaf.definition] + test edx,edx + jz detect_misprediction_of_undefined + test [edx+ValueDefinition.flags],VAL_INTERNAL + jnz detect_misprediction_of_defined + mov edx,[edx+ValueDefinition.pass] + cmp edx,[current_pass] + je detect_misprediction_of_defined + detect_misprediction_of_undefined: + test [eax+SymbolTree_Leaf.flags],SYM_PREDICTED_DEFINED + jz reset_prediction + or [next_pass_needed],1 + jmp reset_prediction + detect_misprediction_of_defined: + test [eax+SymbolTree_Leaf.flags],SYM_PREDICTED_DEFINED + jnz reset_prediction + or [next_pass_needed],1 + reset_prediction: + and [eax+SymbolTree_Leaf.flags],not SYM_PREDICTED + definition_prediction_ok: + test [eax+SymbolTree_Leaf.flags],SYM_USAGE_PREDICTED + jz usage_prediction_ok + mov edx,[eax+SymbolTree_Leaf.last_use_pass] + cmp edx,[current_pass] + je detect_misprediction_of_used + detect_misprediction_of_unused: + test [eax+SymbolTree_Leaf.flags],SYM_PREDICTED_USED + jz reset_usage_prediction + or [next_pass_needed],1 + jmp reset_usage_prediction + detect_misprediction_of_used: + test [eax+SymbolTree_Leaf.flags],SYM_PREDICTED_USED + jnz reset_usage_prediction + or [next_pass_needed],1 + reset_usage_prediction: + and [eax+SymbolTree_Leaf.flags],not SYM_USAGE_PREDICTED + usage_prediction_ok: + pop edx + jmp inspect_next_leaf + inspect_next_leaf: + mov eax,[eax+SymbolTree_Leaf.next] + test eax,eax + jnz inspect_leaf + mov esi,[esi+SymbolTree_Foliage.next] + test esi,esi + jnz browse_foliage + branch_browsed: + test ch,ch + jnz local_branch_browsed + add edi,4 + lea eax,[ebx+sizeof.SymbolTree_Node] + cmp edi,eax + jne browse_branch + inc cl + cmp cl,TREE_HEIGHT + je tree_browsed + sub edx,8 + mov ebx,[edx] + mov edi,[edx+4] + jmp branch_browsed + local_branch_browsed: + add edi,4 + lea eax,[ebx+sizeof.SymbolTree_LocalNode] + cmp edi,eax + jne browse_branch + inc cl + cmp cl,LOCAL_TREE_HEIGHT + je tree_browsed + sub edx,8 + mov ebx,[edx] + mov edi,[edx+4] + jmp local_branch_browsed + deeper_node: + mov [edx],ebx + mov [edx+4],edi + add edx,8 + mov ebx,[edi] + jmp browse_node + tree_browsed: + cmp edx,[tree_stack_base] + je complete_tree_browsed + sub edx,16 + mov ebx,[edx] + mov ecx,[edx+4] + mov esi,[edx+8] + mov edi,[edx+12] + jmp subtree_browsed + complete_tree_browsed: + retn diff --git a/toolchain/fasm2/source/tables.inc b/toolchain/fasm2/source/tables.inc new file mode 100644 index 0000000..ebb1222 --- /dev/null +++ b/toolchain/fasm2/source/tables.inc @@ -0,0 +1,649 @@ + +OPERATOR_PRECEDENCE_MASK = 3Fh +OPERATOR_UNARY = 40h +OPERATOR_RIGHT_ASSOCIATIVE = 80h + +SIZE_BYTE = 1 +SIZE_WORD = 2 +SIZE_DWORD = 4 +SIZE_PWORD = 6 +SIZE_QWORD = 8 +SIZE_TWORD = 10 +SIZE_DQWORD = 16 +SIZE_QQWORD = 32 +SIZE_DQQWORD = 64 + +PREPOSITION_AT = 0 +PREPOSITION_FROM = 1 +PREPOSITION_AS = 2 +PREPOSITION_DUP = 3 + +control_characters db 0,9,0Ah,0Dh,1Ah,20h +.count = $-control_characters + +syntactical_characters db '+-/*=<>()[]{}:?!,.|&~#`\;' +.count = $-syntactical_characters + +include_variable db 'INCLUDE',0 + +separating_operators: + + db '+',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,1 + OPERATOR_UNARY + dd calculate_to_number + + db '-',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,1 + OPERATOR_UNARY + dd calculate_neg + + db '+',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,1 + dd calculate_add + + db '-',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,1 + dd calculate_sub + + db '*',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,2 + dd calculate_mul + + db '/',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,2 + dd calculate_div + + db 0 + +symbols: + + db 3,'not',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,6 + OPERATOR_UNARY + dd calculate_not + + db 3,'mod',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,3 + dd calculate_mod + + db 3,'xor',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,4 + dd calculate_xor + + db 3,'and',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,4 + dd calculate_and + + db 2,'or',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,4 + dd calculate_or + + db 3,'shl',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,5 + dd calculate_shl + + db 3,'shr',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,5 + dd calculate_shr + + db 3,'bsf',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,6 + OPERATOR_UNARY + dd calculate_bsf + + db 3,'bsr',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,6 + OPERATOR_UNARY + dd calculate_bsr + + db 5,'bswap',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,5 + dd calculate_bswap + + db 7,'bappend',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,4 + dd calculate_bappend + + db 6,'string',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + OPERATOR_UNARY + dd calculate_to_string + + db 5,'float',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY + dd calculate_to_float + + db 5,'trunc',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY + dd extract_integer_part + + db 6,'sizeof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY + dd extract_size + + db 8,'lengthof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY + dd count_bytes + + db 10,'elementsof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY + dd count_elements + + db 7,'element',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,7 + dd extract_element + + db 5,'scale',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,7 + dd extract_scale + + db 8,'metadata',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,7 + dd extract_metadata + + db 9,'elementof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,8 + OPERATOR_RIGHT_ASSOCIATIVE + dd extract_element_reverse + + db 7,'scaleof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,8 + OPERATOR_RIGHT_ASSOCIATIVE + dd extract_scale_reverse + + db 10,'metadataof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,8 + OPERATOR_RIGHT_ASSOCIATIVE + dd extract_metadata_reverse + + db 7,'element',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd define_element + + db 3,'equ',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd define_symbolic_variable + + db 5,'reequ',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd redefine_symbolic_variable + + db 6,'define',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd define_raw_symbolic_variable + + db 8,'redefine',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd redefine_raw_symbolic_variable + + db 7,'restore',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_EXPRESSION + dd restore_variables + + db 9,'namespace',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd set_namespace + + db 7,'display',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd display_data + + db 3,'err',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd custom_error + + db 7,'include',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd include_source + + db 4,'eval',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd evaluate_string + + db 6,'assert',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd assert_condition + + db 7,'defined',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0 + dd check_if_defined + + db 4,'used',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0 + dd check_if_used + + db 8,'definite',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0 + dd check_if_defined_earlier + + db 6,'eqtype',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0 + dd check_if_type_equal + + db 2,'eq',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0 + dd check_if_value_equal + + db 10,'relativeto',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0 + dd check_if_relative + + db 2,'if',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd conditional_block + + db 5,'match',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd match_block + + db 6,'rmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd raw_match_block + + db 8,'rawmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd raw_match_block + + db 5,'while',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd conditionally_repeated_block + + db 6,'repeat',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd repeated_block + + db 7,'iterate',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd iterator_block + + db 4,'rept',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd repeated_block + + db 3,'irp',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd iterator_block + + db 4,'irpv',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd variable_iterator_block + + db 4,'indx',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd set_iterator_index + + db 5,'break',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd break_directive + + db 4,'else',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd else_directive + + db 3,'end',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_directive + + db 8,'postpone',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd postponed_block + + db 5,'macro',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd define_macro + + db 5,'struc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd define_struc + + db 3,'esc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd escape_directive + + db 5,'local',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd local_directive + + db 8,'outscope',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd outscope_directive + + db 5,'purge',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_INSTRUCTION + dd restore_variables + + db 7,'restruc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_STRUCTURE + dd restore_variables + + db 7,'mvmacro',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_INSTRUCTION + dd move_variable_values + + db 7,'mvstruc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_STRUCTURE + dd move_variable_values + + db 15,'calminstruction',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd define_calm_instruction + + db 14,'removecomments',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd choose_to_remove_comments + + db 14,'retaincomments',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd choose_to_retain_comments + + db 12,'combinelines',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd choose_to_combine_lines + + db 12,'isolatelines',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd choose_to_isolate_lines + + db 3,'org',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd set_base_address + + db 7,'section',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd begin_new_section + + db 10,'restartout',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd restart_output + + db 6,'format',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd format_directive + + db 4,'emit',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd define_data + + db 4,'emit',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd define_labeled_data + + db 3,'dbx',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd define_data + + db 3,'dbx',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd define_labeled_data + + db 2,'db',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_BYTE + dd define_data + + db 2,'db',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_BYTE + dd define_labeled_data + + db 2,'dw',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_WORD + dd define_data + + db 2,'dw',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_WORD + dd define_labeled_data + + db 2,'dd',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DWORD + dd define_data + + db 2,'dd',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DWORD + dd define_labeled_data + + db 2,'dp',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_PWORD + dd define_data + + db 2,'dp',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_PWORD + dd define_labeled_data + + db 2,'dq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QWORD + dd define_data + + db 2,'dq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QWORD + dd define_labeled_data + + db 2,'dt',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_TWORD + dd define_data + + db 2,'dt',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_TWORD + dd define_labeled_data + + db 3,'ddq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQWORD + dd define_data + + db 3,'ddq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQWORD + dd define_labeled_data + + db 3,'dqq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QQWORD + dd define_data + + db 3,'dqq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QQWORD + dd define_labeled_data + + db 4,'ddqq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQQWORD + dd define_data + + db 4,'ddqq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQQWORD + dd define_labeled_data + + db 2,'rb',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_BYTE + dd reserve_data + + db 2,'rb',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_BYTE + dd reserve_labeled_data + + db 2,'rw',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_WORD + dd reserve_data + + db 2,'rw',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_WORD + dd reserve_labeled_data + + db 2,'rd',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DWORD + dd reserve_data + + db 2,'rd',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DWORD + dd reserve_labeled_data + + db 2,'rp',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_PWORD + dd reserve_data + + db 2,'rp',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_PWORD + dd reserve_labeled_data + + db 2,'rq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QWORD + dd reserve_data + + db 2,'rq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QWORD + dd reserve_labeled_data + + db 2,'rt',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_TWORD + dd reserve_data + + db 2,'rt',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_TWORD + dd reserve_labeled_data + + db 3,'rdq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQWORD + dd reserve_data + + db 3,'rdq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQWORD + dd reserve_labeled_data + + db 3,'rqq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QQWORD + dd reserve_data + + db 3,'rqq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QQWORD + dd reserve_labeled_data + + db 4,'rdqq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQQWORD + dd reserve_data + + db 4,'rdqq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQQWORD + dd reserve_labeled_data + + db 4,'file',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd include_data + + db 4,'file',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd include_labeled_data + + db 1,'$',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd current_address_value + + db 2,'$$',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd base_address_value + + db 2,'$@',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd truncated_address_value + + db 2,'$%',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd current_position_value + + db 3,'$%%',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd truncated_position_value + + db 2,'%t',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd current_time_value + + db 8,'__time__',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd current_time_value + + db 10,'__source__',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd main_file_name_value + + db 8,'__file__',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd current_file_name_value + + db 8,'__line__',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0 + dd current_line_number_value + + db 4,'byte',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_BYTE + + db 4,'word',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_WORD + + db 5,'dword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_DWORD + + db 5,'pword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_PWORD + + db 5,'fword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_PWORD + + db 5,'qword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_QWORD + + db 5,'tword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_TWORD + + db 5,'tbyte',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_TWORD + + db 6,'dqword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_DQWORD + + db 5,'xword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_DQWORD + + db 6,'qqword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_QQWORD + + db 5,'yword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_QQWORD + + db 7,'dqqword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_DQQWORD + + db 5,'zword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0 + dd SIZE_DQQWORD + + db 5,'label',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd label_directive + + db 7,'virtual',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd virtual_block + + db 4,'load',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd load_value + + db 5,'store',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd store_value + + db 2,'at',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_PREPOSITION,VAL_INTERNAL,0 + dd PREPOSITION_AT + + db 4,'from',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_PREPOSITION,VAL_INTERNAL,0 + dd PREPOSITION_FROM + + db 2,'as',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_PREPOSITION,VAL_INTERNAL,0 + dd PREPOSITION_AS + + db 3,'dup',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_PREPOSITION,VAL_INTERNAL,0 + dd PREPOSITION_DUP + + db 0 + +db 3,'end' + + db 9,'namespace',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd end_namespace + + db 2,'if',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_conditional_block + + db 5,'match',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_match_block + + db 6,'rmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_raw_match_block + + db 8,'rawmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_raw_match_block + + db 5,'while',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_conditionally_repeated_block + + db 6,'repeat',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_repeated_block + + db 7,'iterate',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_iterator_block + + db 4,'rept',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_repeated_block + + db 3,'irp',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_iterator_block + + db 4,'irpv',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_variable_iterator_block + + db 8,'postpone',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_postponed_block + + db 5,'macro',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_macro + + db 5,'struc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd end_struc + + db 7,'virtual',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd end_virtual_block + + db 0 + +db 4,'else' + + db 2,'if',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd else_conditional_block + + db 5,'match',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd else_match_block + + db 6,'rmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd else_raw_match_block + + db 8,'rawmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd else_raw_match_block + + db 0 + +db 6,'format' + + db 6,'binary',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd format_binary + + db 0 + +db 15,'calminstruction' + + db 5,'local',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_local + + db 7,'arrange',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_arrange + + db 5,'match',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_match + + db 8,'assemble',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_assemble + + db 9,'transform',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_transform + + db 9,'stringify',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_stringify + + db 7,'publish',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_publish + + db 4,'take',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_take + + db 7,'compute',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_compute + + db 5,'check',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_check + + db 4,'emit',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_emit + + db 4,'load',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_load + + db 5,'store',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_store + + db 7,'display',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_display + + db 3,'err',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_err + + db 4,'jyes',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_jyes + + db 3,'jno',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_jno + + db 4,'jump',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_jump + + db 4,'call',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_call + + db 4,'exit',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_exit + + db 3,'end',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0 + dd alm_end + + db 15,'calminstruction',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + dd alm_end + +db 0 + +zero_value dd 0 + dd 0 + +singular_value dd 1 + db 1 + dd 0 + +subtraction_operator dd EXPR_OPERATOR,calculate_sub + dd 0 diff --git a/toolchain/fasm2/source/variables.inc b/toolchain/fasm2/source/variables.inc new file mode 100644 index 0000000..922a6ac --- /dev/null +++ b/toolchain/fasm2/source/variables.inc @@ -0,0 +1,314 @@ + +characters db 256 dup ? + +maximum_number_of_errors dd ? +maximum_depth_of_stack dd ? + +variables: + + temporary_value dd 4 dup ? + accumulator dd 3 dup ? + + source_file dd ? + + include_paths dd ? + + storage_blocks dd ? + storage_free_space dd ? + storage_free_space_length dd ? + + tree_blocks dd ? + tree_reserve dd ? + tree_reserve_length dd ? + + value_definition_chain dd ? + retired_definition dd ? + + file_source_cache dd ? + memory_source_cache dd ? + file_data_cache dd ? + + operator_table dd ? + root_namespace dd ? + root_parameter_namespace dd ? + local_parameter_namespace dd ? + interceptor_symbol dd ? + label_interceptor_symbol dd ? + other_interceptor_symbol dd ? + proxy_number dd ? + + source_context dd ? + source_context_maximum_length dd ? + current_pass dd ? + current_context RecognitionContext + local_namespace dd ? + parameter_namespace dd ? + + directives_stack dd ? + directives_stack_base dd ? + directives_stack_end dd ? + + current_counter dd ? + counters_stack_base dd ? + counters_stack_end dd ? + + first_error dd ? + + current_area dd ? + output_areas_list dd ? + output_areas_list_end dd ? + initial_output_area_entry dd ? + current_output_area_entry dd ? + prior_uninitialized_length dq ? + virtual_area dd ? + auxiliary_output_areas dd ? + void_symbol dd ? + + base_path dd ? + output_extension dd ? + output_extension_length dd ? + output_failures dd ? + + preprocessing_workspace Workspace + assembly_workspace Workspace + identifier_workspace Workspace + value_workspace Workspace + expression_workspace Workspace + calculation_workspace Workspace + auxiliary_workspace Workspace + + line_start dd ? + line_end dd ? + line_embeddings dd ? + line_embeddings_maximum_length dd ? + number_of_line_embeddings dd ? + preprocessed_context dd ? + line_context dd ? + embedded_context dd ? + number_of_enclosings dd ? + + recognition_context RecognitionContext + name_token dd ? + case_sensitive_hash dd ? + case_insensitive_hash dd ? + kept_symbol dd ? + current_symbol dd ? + tree_stack_base dd ? + tree_stack_end dd ? + symbol_root dd ? + symbol_branch dd ? + minor_identifier dd ? + + source_end dd ? + symbol_start dd ? + symbol_data dd ? + symbol_value_start dd ? + symbol_value_end dd ? + + interceptor dd ? + label_branch dd ? + label_leaf dd ? + label_interceptor dd ? + label_instruction_start dd ? + label_instruction_context dd ? + + display_buffer dd ? + display_buffer_length dd ? + display_data_length dd ? + + macro_buffer dd ? + macro_buffer_length dd ? + macro_leaf dd ? + macro_end_position dd ? + + constituent_symbol dd ? + constituent_value dd ? + constituent_whitespace dd ? + + alm_namespace dd ? + alm_adjusted_context RecognitionContext + calm_code_buffer Workspace + calm_code_cursor dd ? + calm_literals_buffer Workspace + calm_literals_cursor dd ? + calm_auxiliary_buffer Workspace + calm_auxiliary_cursor dd ? + calm_line_number dd ? + calm_instruction_number dd ? + calm_value dd ? + calm_literals dd ? + calm_source_pointer dd ? + calm_rollback_offset dd ? + + value_position dd ? + kept_value dd ? + converter_position dd ? + expression_position dd ? + expression_end dd ? + operator_stack dd ? + operator_stack_position dd ? + operator_stack_base dd ? + operator_stack_end dd ? + calculation_position dd ? + source_term dd ? + destination_term dd ? + temporary_terms dd ? + free_temporary_terms dd ? + temporary_floats dd ? + iterations dd ? + exponent dd ? + multiplier dd ? + divisor dd ? + long_dividend_term dd ? + long_divisor_term dd ? + long_divisor_length dd ? + division_temporary_terms dd ? + mantissa_tail dd ? + predicted_shift dd ? + subexpression_end dd ? + + condition_stack dd ? + condition_stack_base dd ? + condition_stack_end dd ? + initial_parentheses dd ? + comparator dd ? + outer_expression dd ? + + assembly_stack_base dd ? + assembly_stack_end dd ? + previous_symbol_end dd ? + further_whitespace dd ? + zero_digits dd ? + decimal_places dd ? + literal_exponent dd ? + update_function dd ? + argument_start dd ? + macro_parameters_context dd ? + new_local_namespace dd ? + file_name dd ? + string_end dd ? + message_end dd ? + data_area_symbol dd ? + data_area dd ? + data_offset dd ? + file_offset dq ? + data_length dd ? + local_path dd ? + + error_line_start dd ? + error_line_end dd ? + error_symbol dd ? + last_source_entry dd ? + last_file_source_entry dd ? + preprocessed_text_end dd ? + + source_text dd ? + source_text_length dd ? + tokenization_buffer dd ? + tokenization_buffer_length dd ? + buffer_end_offset dd ? + file_data dd ? + file_cache_pointer dd ? + + address_length dd ? + data_unit_length dd ? + uninitialized_length dq ? + + directive_block dd ? + number_of_iterations dd ? + number_of_parameters dd ? + number_of_values dd ? + parameter_index dd ? + value_index dd ? + value dd ? + value_length dd ? + metadata_length dd ? + sequence_header_cursor dd ? + sequence_header_length dd ? + expression_sequence_cursor dd ? + expression_sequence_end dd ? + context_boundary dd ? + whitespace_boundary dd ? + transforming_namespace dd ? + + pattern_start dd ? + pattern_end dd ? + matched_context dd ? + substitutions_end dd ? + stored_position dd ? + stored_substitution dd ? + stored_context dd ? + stored_pattern dd ? + brackets dd ? + + instruction_value dd ? + instruction_branch dd ? + instruction_body dd ? + + number_of_lines dd ? + + preprocessing_mode db ? + assembly_mode db ? + next_pass_needed db ? + shift_tracking db ? + + name_kind db ? + name_volatile db ? + symbol_class db ? + symbol_required db ? + symbol_expected db ? + kept_symbol_flags db ? + chosen_class db ? + expected_class db ? + symbol_definition db ? + symbol_independent db ? + recognizer_setting db ? + label_independent db ? + value_type db ? + waiting_for_digit db ? + literal_exponent_sign db ? + literal_fractional_part db ? + float_literal_status db ? + use_raw_values db ? + + last_token db ? + breakpoint_token db ? + current_constituent db ? + kept_value_in_workspace db ? + leave_opening_parentheses db ? + operator_argument_expected db ? + term_type db ? + bit_shift db ? + shift_overflow db ? + multiplier_sign db ? + high_bits_count db ? + first_sign db ? + second_sign db ? + comparator_priority db ? + result_type db ? + defined_element db ? + + source_context_affected db ? + raw_value db ? + substitution_active db ? + stored_substitution_activity db ? + unprocessed_matching db ? + whitespace_matching db ? + macro_definition_active db ? + macro_flags db ? + macro_greedy db ? + calm_definition_active db ? + + size_specified db ? + + message_volatile db ? + displayed_byte db ? + + alm_statement db ? + calm_result db ? + hidden_context db ? + contextless_processing db ? + +variables_end: + + trace_mode db ? diff --git a/toolchain/fasm2/source/version.inc b/toolchain/fasm2/source/version.inc new file mode 100644 index 0000000..213bb30 --- /dev/null +++ b/toolchain/fasm2/source/version.inc @@ -0,0 +1 @@ +VERSION equ "kl0e" \ No newline at end of file diff --git a/toolchain/fasm2/source/windows/dll/fasmg.asm b/toolchain/fasm2/source/windows/dll/fasmg.asm new file mode 100644 index 0000000..4958b10 --- /dev/null +++ b/toolchain/fasm2/source/windows/dll/fasmg.asm @@ -0,0 +1,255 @@ + + include 'win32a.inc' + +match ,{ + + include 'localptr.inc' + +} match -,{ +else + + include 'localptr.alm' + +end match +_ equ } + + format PE large NX DLL + entry DllEntryPoint + +include '../../version.inc' + +struct MEMORY_REGION + address dd ? + size dd ? +ends + +section '.text' code executable + + include '../../assembler.inc' + include '../../symbols.inc' + include '../../expressions.inc' + include '../../conditions.inc' + include '../../floats.inc' + include '../../directives.inc' + include '../../calm.inc' + include '../../errors.inc' + include '../../map.inc' + include '../../reader.inc' + include '../../output.inc' + include '../../console.inc' + + DllEntryPoint: + mov eax,1 + retn 12 + + fasmg_GetVersion: + mov eax,version_string + retn + + fasmg_Assemble: + + virtual at ebp - LOCAL_VARIABLES_SIZE + + LocalVariables: + + include '../../variables.inc' + + maximum_number_of_passes dd ? + + timestamp dq ? + systemtime SYSTEMTIME + filetime FILETIME + + memory dd ? + systmp dd ? + + rb (LocalVariables - $) and 11b + + LOCAL_VARIABLES_SIZE = $ - LocalVariables + + assert $ - ebp = 0 + + previous_frame dd ? + stored_edi dd ? + stored_esi dd ? + stored_ebx dd ? + return_address dd ? + + FunctionParameters: + + source_string dd ? + source_path dd ? + output_region dd ? + output_path dd ? + stdout dd ? + stderr dd ? + + FUNCTION_PARAMETERS_SIZE = $ - FunctionParameters + + end virtual + + push ebx esi edi + enter LOCAL_VARIABLES_SIZE,0 + + call system_init + + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1000 + mov [maximum_depth_of_stack],10000 + + xor al,al + call assembly_init + + assemble: + mov esi,[source_string] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + call assembly_shutdown + call system_shutdown + mov eax,-2 + leave + pop edi esi ebx + retn FUNCTION_PARAMETERS_SIZE + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + mov esi,[output_region] + test esi,esi + jz output_copied + call get_output_length + test edx,edx + jnz out_of_memory + mov [value_length],eax + xchg eax,[esi+MEMORY_REGION.size] + cmp [esi+MEMORY_REGION.address],0 + je new_region_for_output + cmp eax,[value_length] + jae copy_output + invoke VirtualAlloc,[esi+MEMORY_REGION.address],[esi+MEMORY_REGION.size],MEM_COMMIT,PAGE_READWRITE + test eax,eax + jnz copy_output + invoke VirtualFree,[esi+MEMORY_REGION.address],0,MEM_RELEASE + new_region_for_output: + invoke VirtualAlloc,0,[esi+MEMORY_REGION.size],MEM_COMMIT,PAGE_READWRITE + test eax,eax + jz out_of_memory + mov [esi+MEMORY_REGION.address],eax + copy_output: + mov edi,[esi+MEMORY_REGION.address] + xor eax,eax + mov dword [file_offset],eax + mov dword [file_offset+4],eax + call read_from_output + output_copied: + + mov ebx,[source_path] + mov edi,[output_path] + mov eax,ebx + or eax,edi + jz output_written + call write_output_file + jc write_failed + output_written: + + call assembly_shutdown + call system_shutdown + xor eax,eax + leave + pop edi esi ebx + retn FUNCTION_PARAMETERS_SIZE + + assembly_failed: + mov eax,[first_error] + xor ecx,ecx + count_errors: + inc ecx + mov eax,[eax+Error.next] + test eax,eax + jnz count_errors + push ecx + call show_errors + call assembly_shutdown + call system_shutdown + pop eax + leave + pop edi esi ebx + retn FUNCTION_PARAMETERS_SIZE + + write_failed: + call assembly_shutdown + call system_shutdown + mov eax,-3 + leave + pop edi esi ebx + retn FUNCTION_PARAMETERS_SIZE + + out_of_memory: + call assembly_shutdown + call system_shutdown + mov eax,-1 + leave + pop edi esi ebx + retn FUNCTION_PARAMETERS_SIZE + + include 'system.inc' + +section '.rdata' data readable + +data import + + library kernel32,'KERNEL32.DLL' + + import kernel32,\ + CloseHandle,'CloseHandle',\ + CreateFile,'CreateFileA',\ + ExitProcess,'ExitProcess',\ + GetCommandLine,'GetCommandLineA',\ + GetEnvironmentVariable,'GetEnvironmentVariableA',\ + GetStdHandle,'GetStdHandle',\ + GetSystemTime,'GetSystemTime',\ + GetTickCount,'GetTickCount',\ + HeapAlloc,'HeapAlloc',\ + HeapCreate,'HeapCreate',\ + HeapDestroy,'HeapDestroy',\ + HeapFree,'HeapFree',\ + HeapReAlloc,'HeapReAlloc',\ + HeapSize,'HeapSize',\ + VirtualAlloc,'VirtualAlloc',\ + VirtualFree,'VirtualFree',\ + ReadFile,'ReadFile',\ + SetFilePointer,'SetFilePointer',\ + SystemTimeToFileTime,'SystemTimeToFileTime',\ + WriteFile,'WriteFile',\ + GetLastError,'GetLastError' + +end data + +align 4 + +data export + + export 'FASMG.DLL',\ + fasmg_GetVersion,'fasmg_GetVersion',\ + fasmg_Assemble,'fasmg_Assemble' + +end data + + include '../../tables.inc' + include '../../messages.inc' + + version_string db VERSION,0 + +section '.reloc' fixups data readable discardable + \ No newline at end of file diff --git a/toolchain/fasm2/source/windows/dll/localptr.alm b/toolchain/fasm2/source/windows/dll/localptr.alm new file mode 100644 index 0000000..11996e5 --- /dev/null +++ b/toolchain/fasm2/source/windows/dll/localptr.alm @@ -0,0 +1,34 @@ + +calminstruction push? arg*& + local tmp, more + match =dword? arg, arg + jno regular + match tmp], arg + jyes regular + check arg relativeto ebp & arg - ebp + jno regular + arrange tmp, =push =eax + assemble tmp + arrange tmp, =lea =eax,[arg] + assemble tmp + arrange tmp, =xchg =eax,[=esp] + assemble tmp + exit + regular: + arrange tmp, =push arg + assemble tmp +end calminstruction + +calminstruction mov? dest*,src* + local tmp + match tmp], src + jyes regular + check src relativeto ebp & src - ebp + jno regular + arrange tmp, =lea dest,[src] + assemble tmp + exit + regular: + arrange tmp, =mov dest,src + assemble tmp +end calminstruction diff --git a/toolchain/fasm2/source/windows/dll/localptr.inc b/toolchain/fasm2/source/windows/dll/localptr.inc new file mode 100644 index 0000000..eaf63eb --- /dev/null +++ b/toolchain/fasm2/source/windows/dll/localptr.inc @@ -0,0 +1,28 @@ + +macro pushd arg +{ + if arg eqtype +ebp & arg relativeto ebp + if arg - ebp + push eax + lea eax,[arg] + xchg eax,[esp] + else + push ebp + end if + else if ~ arg eq + pushd arg + end if +} + +macro mov dest,src +{ + if src eqtype +ebp & src relativeto ebp + if src - ebp + lea dest,[src] + else + mov dest,ebp + end if + else + mov dest,src + end if +} diff --git a/toolchain/fasm2/source/windows/dll/system.inc b/toolchain/fasm2/source/windows/dll/system.inc new file mode 100644 index 0000000..d4c6d40 --- /dev/null +++ b/toolchain/fasm2/source/windows/dll/system.inc @@ -0,0 +1,214 @@ + +LINE_FEED equ 13,10 + +system_init: + invoke HeapCreate,0,20000h,0 + mov [memory],eax + test eax,eax + jz out_of_memory + invoke GetSystemTime,systemtime + invoke SystemTimeToFileTime,systemtime,filetime + mov ebx,[filetime.dwLowDateTime] + mov eax,[filetime.dwHighDateTime] + sub ebx,116444736000000000 and 0FFFFFFFFh + sbb eax,116444736000000000 shr 32 + xor edx,edx + mov ecx,10000000 + div ecx + mov dword [timestamp+4],eax + mov eax,ebx + div ecx + mov dword [timestamp],eax + retn + +system_shutdown: + cmp [memory],0 + je memory_released + invoke HeapDestroy,[memory] + memory_released: + retn + +malloc: +malloc_fixed: +malloc_growable: +; in: ecx = requested size +; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi +; note: +; use of malloc_fixed hints that block will be kept as is until the end of assembly +; use of malloc_growable hints that block is likely to be resized + invoke HeapAlloc,[memory],0,ecx + test eax,eax + jz out_of_memory + memory_allocated: + push eax + invoke HeapSize,[memory],0,eax + mov ecx,eax + pop eax + cmp ecx,-1 + je out_of_memory + retn +realloc: +; in: eax - memory block, ecx = requested size +; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi + invoke HeapReAlloc,[memory],0,eax,ecx + test eax,eax + jnz memory_allocated + jmp out_of_memory +mfree: +; in: eax - memory block +; out: cf set on error +; preserves: ebx, esi, edi +; note: eax may have value 0 or -1, it should be treated as invalid input then + test eax,eax + jz interface_error + cmp eax,-1 + je interface_error + invoke HeapFree,[memory],0,eax + test eax,eax + jz interface_error + clc + retn + interface_error: + stc + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + invoke CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0 + cmp eax,-1 + je interface_error + mov ebx,eax + clc + retn +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + invoke CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0 + cmp eax,-1 + je interface_error + mov ebx,eax + clc + retn +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ecx + invoke WriteFile,ebx,edx,ecx,systmp,0 + pop ecx + test eax,eax + jz interface_error + cmp ecx,[systmp] + jne interface_error + clc + retn +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ecx + invoke ReadFile,ebx,edx,ecx,systmp,0 + pop ecx + test eax,eax + jz interface_error + cmp ecx,[systmp] + jne interface_error + clc + retn +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + invoke CloseHandle,ebx + retn +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + movzx ecx,cl + mov [systmp],edx + invoke SetFilePointer,ebx,eax,systmp,ecx + cmp eax,-1 + jne lseek_ok + invoke GetLastError + test eax,eax + jnz interface_error + not eax + lseek_ok: + mov edx,[systmp] + clc + retn + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx + mov ebx,[stdout] + jmp write_string +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx + mov ebx,[stderr] + write_string: + test ebx,ebx + jz hidden_display + test ecx,ecx + jnz write_string_to_stdout + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stdout: + mov edx,esi + write_portion_to_stdout: + mov eax,51200 + cmp ecx,eax + jbe final_write_to_stdout + sub ecx,eax + add eax,edx + push eax ecx + invoke WriteFile,ebx,edx,51200,systmp,0 + pop ecx edx + jmp write_portion_to_stdout + final_write_to_stdout: + invoke WriteFile,ebx,edx,ecx,systmp,0 + hidden_display: + pop ebx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push ecx + invoke GetEnvironmentVariable,esi,edi,ecx + pop ecx + cmp eax,ecx + jae environment_variable_ready + mov byte [edi+eax],0 + environment_variable_ready: + inc eax + retn diff --git a/toolchain/fasm2/source/windows/fasmg.asm b/toolchain/fasm2/source/windows/fasmg.asm new file mode 100644 index 0000000..4ce969e --- /dev/null +++ b/toolchain/fasm2/source/windows/fasmg.asm @@ -0,0 +1,520 @@ + + include 'win32a.inc' + + format PE large NX console 4.0 + entry start + +include '../version.inc' + +PE.Settings.Stamp = +VERSION + +section '.text' code executable + + include 'system.inc' + + start: + + call system_init + + call get_arguments + mov bl,al + cmp [no_logo],0 + jne logo_ok + mov esi,_logo + xor ecx,ecx + call display_string + logo_ok: + test bl,bl + jnz display_usage_information + + xor al,al + movzx ecx,[verbosity_level] + jecxz init + or al,TRACE_ERROR_STACK + dec ecx + jz init + or al,TRACE_DISPLAY + init: + call assembly_init + + invoke GetTickCount + mov [timer],eax + + assemble: + mov esi,[initial_commands] + mov edx,[source_path] + call assembly_pass + jc assembly_done + + mov eax,[current_pass] + cmp eax,[maximum_number_of_passes] + jb assemble + + call show_display_data + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,_code_cannot_be_generated + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + jmp assembly_failed + + assembly_done: + + call show_display_data + + cmp [first_error],0 + jne assembly_failed + + cmp [no_logo],0 + jne summary_done + mov eax,[current_pass] + xor edx,edx + call itoa + call display_string + mov esi,_passes + cmp [current_pass],1 + jne display_passes_suffix + mov esi,_pass + display_passes_suffix: + xor ecx,ecx + call display_string + invoke GetTickCount + sub eax,[timer] + xor edx,edx + add eax,50 + mov ecx,1000 + div ecx + mov ebx,eax + mov eax,edx + xor edx,edx + mov ecx,100 + div ecx + mov [timer],eax + xchg eax,ebx + or ebx,eax + jz display_output_length + xor edx,edx + call itoa + call display_string + mov esi,_message_suffix + mov ecx,1 + call display_string + mov eax,[timer] + xor edx,edx + call itoa + call display_string + mov esi,_seconds + xor ecx,ecx + call display_string + display_output_length: + call get_output_length + push eax edx + call itoa + call display_string + pop edx eax + mov esi,_bytes + cmp eax,1 + jne display_bytes_suffix + test edx,edx + jnz display_bytes_suffix + mov esi,_byte + display_bytes_suffix: + xor ecx,ecx + call display_string + mov esi,_new_line + xor ecx,ecx + call display_string + summary_done: + + mov ebx,[source_path] + mov edi,[output_path] + call write_output_file + jc write_failed + + call assembly_shutdown + call system_shutdown + + invoke ExitProcess,0 + + assembly_failed: + + call show_errors + + call assembly_shutdown + call system_shutdown + + invoke ExitProcess,2 + + write_failed: + mov ebx,_write_failed + jmp fatal_error + + out_of_memory: + mov ebx,_out_of_memory + jmp fatal_error + + fatal_error: + + mov esi,_error_prefix + xor ecx,ecx + call display_error_string + mov esi,ebx + xor ecx,ecx + call display_error_string + mov esi,_message_suffix + xor ecx,ecx + call display_error_string + + call assembly_shutdown + call system_shutdown + + invoke ExitProcess,3 + + display_usage_information: + + mov esi,_usage + xor ecx,ecx + call display_string + + call system_shutdown + + invoke ExitProcess,1 + + get_arguments: + xor eax,eax + mov [initial_commands],eax + mov [source_path],eax + mov [output_path],eax + mov [no_logo],al + mov [verbosity_level],al + mov [maximum_number_of_passes],100 + mov [maximum_number_of_errors],1 + mov [maximum_depth_of_stack],10000 + invoke GetCommandLine + mov esi,eax + mov edi,eax + or ecx,-1 + xor al,al + repne scasb + sub edi,esi + mov ecx,edi + call malloc + mov edi,eax + get_argument: + xor ah,ah + read_character: + lodsb + test al,al + jz no_more_arguments + cmp al,22h + je switch_quote + cmp ax,20h + je end_argument + stosb + jmp read_character + end_argument: + xor al,al + stosb + find_next_argument: + mov al,[esi] + test al,al + jz no_more_arguments + cmp al,20h + jne next_argument_found + inc esi + jmp find_next_argument + switch_quote: + xor ah,1 + jmp read_character + next_argument_found: + cmp al,'-' + je get_option + cmp al,'/' + je get_option + cmp [source_path],0 + je get_source_path + cmp [output_path],0 + je get_output_path + error_in_arguments: + or al,-1 + retn + get_source_path: + mov [source_path],edi + jmp get_argument + get_output_path: + mov [output_path],edi + jmp get_argument + no_more_arguments: + cmp [source_path],0 + je error_in_arguments + xor al,al + stosb + retn + get_option: + inc esi + lodsb + cmp al,'e' + je set_errors_limit + cmp al,'E' + je set_errors_limit + cmp al,'i' + je insert_initial_command + cmp al,'I' + je insert_initial_command + cmp al,'p' + je set_passes_limit + cmp al,'P' + je set_passes_limit + cmp al,'r' + je set_recursion_limit + cmp al,'R' + je set_recursion_limit + cmp al,'v' + je set_verbose_mode + cmp al,'V' + je set_verbose_mode + cmp al,'n' + je set_no_logo + cmp al,'N' + jne error_in_arguments + set_no_logo: + or [no_logo],-1 + mov al,[esi] + cmp al,20h + je find_next_argument + test al,al + jnz error_in_arguments + jmp find_next_argument + set_verbose_mode: + call get_option_value + jc error_in_arguments + cmp edx,2 + ja error_in_arguments + mov [verbosity_level],dl + jmp find_next_argument + set_errors_limit: + call get_option_value + jc error_in_arguments + test edx,edx + jz error_in_arguments + mov [maximum_number_of_errors],edx + jmp find_next_argument + set_recursion_limit: + call get_option_value + jc error_in_arguments + test edx,edx + jz error_in_arguments + mov [maximum_depth_of_stack],edx + jmp find_next_argument + set_passes_limit: + call get_option_value + jc error_in_arguments + test edx,edx + jz error_in_arguments + mov [maximum_number_of_passes],edx + jmp find_next_argument + get_option_value: + xor eax,eax + mov edx,eax + find_option_value: + cmp byte [esi],20h + jne get_option_digit + inc esi + jmp find_option_value + get_option_digit: + lodsb + cmp al,20h + je option_value_ok + test al,al + jz option_value_ok + sub al,30h + jc invalid_option_value + cmp al,9 + ja invalid_option_value + imul edx,10 + jo invalid_option_value + add edx,eax + jc invalid_option_value + jmp get_option_digit + option_value_ok: + dec esi + clc + ret + invalid_option_value: + stc + ret + insert_initial_command: + push edi + find_command_segment: + cmp byte [esi],20h + jne command_segment_found + inc esi + jmp find_command_segment + command_segment_found: + xor ah,ah + cmp byte [esi],22h + jne measure_command_segment + inc esi + inc ah + measure_command_segment: + mov ebx,esi + scan_command_segment: + mov ecx,esi + mov al,[esi] + test al,al + jz command_segment_measured + cmp ax,20h + je command_segment_measured + cmp ax,22h + je command_segment_measured + inc esi + cmp al,22h + jne scan_command_segment + command_segment_measured: + sub ecx,ebx + mov edi,[initial_commands] + lea eax,[ecx+2] + test edi,edi + jz allocate_initial_commands_buffer + mov edx,[initial_commands_length] + add edi,edx + add eax,edx + cmp eax,[initial_commands_maximum_length] + ja grow_initial_commands_buffer + copy_initial_command: + xchg esi,ebx + rep movsb + mov esi,ebx + sub edi,[initial_commands] + mov [initial_commands_length],edi + mov al,[esi] + test al,al + jz initial_command_ready + cmp al,20h + jne command_segment_found + initial_command_ready: + mov edi,[initial_commands] + add edi,[initial_commands_length] + mov ax,0Ah + stosw + inc [initial_commands_length] + pop edi + jmp find_next_argument + allocate_initial_commands_buffer: + push ecx + mov ecx,eax + call malloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + pop ecx + jmp copy_initial_command + grow_initial_commands_buffer: + push ecx + mov ecx,eax + mov eax,[initial_commands] + call realloc + mov [initial_commands],eax + mov [initial_commands_maximum_length],ecx + mov edi,eax + add edi,[initial_commands_length] + pop ecx + jmp copy_initial_command + + include '../symbols.inc' + include '../assembler.inc' + include '../expressions.inc' + include '../conditions.inc' + include '../floats.inc' + include '../directives.inc' + include '../calm.inc' + include '../errors.inc' + include '../map.inc' + include '../reader.inc' + include '../output.inc' + include '../console.inc' + +section '.bss' readable writeable + + include '../variables.inc' + + source_path dd ? + output_path dd ? + maximum_number_of_passes dd ? + + initial_commands dd ? + initial_commands_length dd ? + initial_commands_maximum_length dd ? + + stdout dd ? + stderr dd ? + memory dd ? + timestamp dq ? + systemtime SYSTEMTIME + filetime FILETIME + systmp dd ? + + timer dd ? + verbosity_level db ? + no_logo db ? + +section '.rdata' data readable + +data import + + library kernel32,'KERNEL32.DLL' + + import kernel32,\ + CloseHandle,'CloseHandle',\ + CreateFile,'CreateFileA',\ + ExitProcess,'ExitProcess',\ + GetCommandLine,'GetCommandLineA',\ + GetEnvironmentVariable,'GetEnvironmentVariableA',\ + GetStdHandle,'GetStdHandle',\ + GetSystemTime,'GetSystemTime',\ + GetTickCount,'GetTickCount',\ + HeapAlloc,'HeapAlloc',\ + HeapCreate,'HeapCreate',\ + HeapDestroy,'HeapDestroy',\ + HeapFree,'HeapFree',\ + HeapReAlloc,'HeapReAlloc',\ + HeapSize,'HeapSize',\ + ReadFile,'ReadFile',\ + SetFilePointer,'SetFilePointer',\ + SystemTimeToFileTime,'SystemTimeToFileTime',\ + WriteFile,'WriteFile',\ + GetLastError,'GetLastError' + +end data + + _logo db 'flat assembler version g.',VERSION,13,10,0 + + _usage db 'Usage: fasmg source [output]',13,10 + db 'Optional settings:',13,10 + db ' -e limit Set the maximum number of displayed errors (default 1)',13,10 + db ' -p limit Set the maximum allowed number of passes (default 100)',13,10 + db ' -r limit Set the maximum depth of the stack (default 10000)',13,10 + db ' -v flag Enable or disable showing all lines from the stack (default 0)',13,10 + db ' -i command Insert instruction at the beginning of source',13,10 + db ' -n Do not show logo nor summary',13,10 + db 0 + + _pass db ' pass, ',0 + _passes db ' passes, ',0 + _dot db '.' + _seconds db ' seconds, ',0 + _byte db ' byte.',0 + _bytes db ' bytes.',0 + + _write_failed db 'failed to write the output file',0 + _out_of_memory db 'not enough memory to complete the assembly',0 + _code_cannot_be_generated db 'could not generate code within the allowed number of passes',0 + + include '../tables.inc' + include '../messages.inc' diff --git a/toolchain/fasm2/source/windows/system.inc b/toolchain/fasm2/source/windows/system.inc new file mode 100644 index 0000000..79d8c41 --- /dev/null +++ b/toolchain/fasm2/source/windows/system.inc @@ -0,0 +1,218 @@ + +LINE_FEED equ 13,10 + +system_init: + invoke GetStdHandle,STD_OUTPUT_HANDLE + mov [stdout],eax + invoke GetStdHandle,STD_ERROR_HANDLE + mov [stderr],eax + invoke HeapCreate,0,20000h,0 + mov [memory],eax + test eax,eax + jz out_of_memory + invoke GetSystemTime,systemtime + invoke SystemTimeToFileTime,systemtime,filetime + mov ebx,[filetime.dwLowDateTime] + mov eax,[filetime.dwHighDateTime] + sub ebx,116444736000000000 and 0FFFFFFFFh + sbb eax,116444736000000000 shr 32 + xor edx,edx + mov ecx,10000000 + div ecx + mov dword [timestamp+4],eax + mov eax,ebx + div ecx + mov dword [timestamp],eax + retn + +system_shutdown: + cmp [memory],0 + je memory_released + invoke HeapDestroy,[memory] + memory_released: + invoke CloseHandle,[stdout] + invoke CloseHandle,[stderr] + retn + +malloc: +malloc_fixed: +malloc_growable: +; in: ecx = requested size +; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi +; note: +; use of malloc_fixed hints that block will be kept as is until the end of assembly +; use of malloc_growable hints that block is likely to be resized + invoke HeapAlloc,[memory],0,ecx + test eax,eax + jz out_of_memory + memory_allocated: + push eax + invoke HeapSize,[memory],0,eax + mov ecx,eax + pop eax + cmp ecx,-1 + je out_of_memory + retn +realloc: +; in: eax - memory block, ecx = requested size +; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return) +; preserves: ebx, esi, edi + invoke HeapReAlloc,[memory],0,eax,ecx + test eax,eax + jnz memory_allocated + jmp out_of_memory +mfree: +; in: eax - memory block +; out: cf set on error +; preserves: ebx, esi, edi +; note: eax may have value 0 or -1, it should be treated as invalid input then + test eax,eax + jz interface_error + cmp eax,-1 + je interface_error + invoke HeapFree,[memory],0,eax + test eax,eax + jz interface_error + clc + retn + interface_error: + stc + retn + +open: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + invoke CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0 + cmp eax,-1 + je interface_error + mov ebx,eax + clc + retn +create: +; in: edx - path to file +; out: ebx = file handle, cf set on error +; preserves: esi, edi + invoke CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0 + cmp eax,-1 + je interface_error + mov ebx,eax + clc + retn +write: +; in: ebx = file handle, edx - data, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ecx + invoke WriteFile,ebx,edx,ecx,systmp,0 + pop ecx + test eax,eax + jz interface_error + cmp ecx,[systmp] + jne interface_error + clc + retn +read: +; in: ebx = file handle, edx - buffer, ecx = number of bytes +; out: cf set on error +; preserves: ebx, esi, edi + push ecx + invoke ReadFile,ebx,edx,ecx,systmp,0 + pop ecx + test eax,eax + jz interface_error + cmp ecx,[systmp] + jne interface_error + clc + retn +close: +; in: ebx = file handle +; preserves: ebx, esi, edi + invoke CloseHandle,ebx + retn +lseek: +; in: ebx = file handle, cl = method, edx:eax = offset +; out: edx:eax = new offset from the beginning of file, cf set on error +; preserves: ebx, esi, edi + movzx ecx,cl + mov [systmp],edx + invoke SetFilePointer,ebx,eax,systmp,ecx + cmp eax,-1 + jne lseek_ok + invoke GetLastError + test eax,eax + jnz interface_error + not eax + lseek_ok: + mov edx,[systmp] + clc + retn + +get_timestamp: +; out: edx:eax = timestamp +; preserves: ebx, ecx, esi, edi +; note: during the passes of a single assembly this function should always return the same value + mov eax,dword [timestamp] + mov edx,dword [timestamp+4] + retn + +display_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx + mov ebx,[stdout] + jmp write_string +display_error_string: +; in: +; esi - string +; ecx = string length, zero for ASCIIZ string +; preserves: ebx, esi + push ebx + mov ebx,[stderr] + write_string: + test ecx,ecx + jnz write_string_to_stdout + xor al,al + mov edi,esi + or ecx,-1 + repne scasb + neg ecx + sub ecx,2 + write_string_to_stdout: + mov edx,esi + write_portion_to_stdout: + mov eax,51200 + cmp ecx,eax + jbe final_write_to_stdout + sub ecx,eax + add eax,edx + push eax ecx + invoke WriteFile,ebx,edx,51200,systmp,0 + pop ecx edx + jmp write_portion_to_stdout + final_write_to_stdout: + invoke WriteFile,ebx,edx,ecx,systmp,0 + pop ebx + retn + +get_environment_variable: +; in: +; esi - name +; edi - buffer for value +; ecx = size of buffer +; out: +; eax = length of value +; preserves: ebx, esi, edi + push ecx + invoke GetEnvironmentVariable,esi,edi,ecx + pop ecx + cmp eax,ecx + jae environment_variable_ready + mov byte [edi+eax],0 + environment_variable_ready: + inc eax + retn +