├── example ├── CMakeLists.txt └── variables.cpp ├── asm_test ├── CMakeLists.txt ├── main.cpp └── .gitignore ├── library.properties ├── License.txt ├── .gitignore ├── stk_stasm.cpp ├── README.md.bak ├── stasm.pro ├── README.md └── stk_stasm.h /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(example) 2 | cmake_minimum_required(VERSION 2.8) 3 | aux_source_directory(. SRC_LIST) 4 | add_executable(${PROJECT_NAME} ${SRC_LIST}) 5 | 6 | -------------------------------------------------------------------------------- /asm_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(asm_test) 2 | cmake_minimum_required(VERSION 2.8) 3 | aux_source_directory(. SRC_LIST) 4 | add_executable(${PROJECT_NAME} ${SRC_LIST}) 5 | 6 | -------------------------------------------------------------------------------- /asm_test/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Hello World!" << endl; 8 | return 0; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Stasinek's Easy ASM 2 | version=1.0.0 3 | author=SSTSOFT 4 | maintainer=Stanley 5 | sentence=Library to make GCC/GAS inline assembly remind Micsoroft Visual Studio approach, to be pleasure not torture 6 | paragraph=Library is using preprocessor, to format __asm { mov eax,ebx; } into something like this __stasm(code, mov eax,ebx; ) 7 | category=Utility 8 | url=https://github.com/stasinek/stasm 9 | architectures=* 10 | depends= 11 | -------------------------------------------------------------------------------- /example/variables.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | __stasm_x86[0] = 12; // input data A 9 | __stasm_x86[1] = 13; // input data, static variable, directly available to __stasm, and protected by atomic lock, unlock! 10 | __stasm(x86,code, 11 | mov esi, __stasm_x86; 12 | mov eax,[esi+0]; 13 | mov ebx,[esi+4]; 14 | imul eax,ebx; 15 | mov edi, __stasm_x86; 16 | mov [edi+8],eax; 17 | ); 18 | int another_c_variable = __stasm_x86[2]; 19 | 20 | cout << "Hello World!" << endl; 21 | cout << __stasm_x86[0] << "*" << __stasm_x86[1] << "=" << __stasm_x86[2] << endl; 22 | assert(__stasm_x86[2]==12*13); 23 | cout << "Success!" << endl; 24 | return 0; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /asm_test/.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | *~ 5 | *.autosave 6 | *.a 7 | *.core 8 | *.moc 9 | *.o 10 | *.obj 11 | *.orig 12 | *.rej 13 | *.so 14 | *.so.* 15 | *_pch.h.cpp 16 | *_resource.rc 17 | *.qm 18 | .#* 19 | *.*# 20 | core 21 | !core/ 22 | tags 23 | .DS_Store 24 | *.debug 25 | Makefile* 26 | *.prl 27 | *.app 28 | moc_*.cpp 29 | ui_*.h 30 | qrc_*.cpp 31 | Thumbs.db 32 | *.res 33 | *.rc 34 | /.qmake.cache 35 | /.qmake.stash 36 | 37 | # qtcreator generated files 38 | *.pro.user* 39 | 40 | # xemacs temporary files 41 | *.flc 42 | 43 | # Vim temporary files 44 | .*.swp 45 | 46 | # Visual Studio generated files 47 | *.ib_pdb_index 48 | *.idb 49 | *.ilk 50 | *.pdb 51 | *.sln 52 | *.suo 53 | *.vcproj 54 | *vcproj.*.*.user 55 | *.ncb 56 | *.sdf 57 | *.opensdf 58 | *.vcxproj 59 | *vcxproj.* 60 | 61 | # MinGW generated files 62 | *.Debug 63 | *.Release 64 | 65 | # Python byte code 66 | *.pyc 67 | 68 | # Binaries 69 | # -------- 70 | *.dll 71 | *.exe 72 | 73 | 74 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | /* Copyright(C) Stanislaw Stasiak, sstoft@wp.pl <2002-2015> All rights reserved. 2 | * 3 | * Redistribution and use in source and binary forms, with or without 4 | * modification, are permitted provided that the following conditions 5 | * are met: 6 | * 1. Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * 2. Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * 3. Redistributions in any form must be accompanied by information on 12 | * how to obtain complete source code and any 13 | * accompanying software that uses any part of it. 14 | * The source code must either be included in the distribution 15 | * or be available for no more than the cost of distribution plus 16 | * a nominal fee, and must be freely redistributable under reasonable 17 | * conditions. For an executable file, complete source code means 18 | * the source code for all modules it contains. It does not include 19 | * source code for modules or files that typically accompany the major 20 | * components of operating system on which the executable file runs. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | */ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Map files 2 | *.mbr 3 | *.tds 4 | *.map 5 | *.sdf 6 | *.pdb 7 | *.idb 8 | # Precompiled headers 9 | *.il 10 | *.ii 11 | *.ilk 12 | *.ilb 13 | *.ils 14 | *.ilc 15 | *.ild 16 | *.ilf 17 | *.idb 18 | *.pch 19 | *.gch 20 | *.ipch 21 | # Auto generated files 22 | *.Release 23 | *.Debug 24 | *.cache 25 | # Editor's IDE backups 26 | *.bak 27 | *.~* 28 | *.#* 29 | *.err 30 | *.drc 31 | # LOGS 32 | *.stat 33 | *.log 34 | *.tlog 35 | # Compiled TARGETS 36 | *.obj 37 | *.a 38 | *.o 39 | *.s 40 | *.lib 41 | *.exe 42 | *.dll 43 | *.res 44 | # IDE's output directories 45 | debug/* 46 | realese/* 47 | Qt_*-Release/* 48 | Qt_*-Debug/* 49 | # Prerequisites 50 | *.d 51 | # Compiled Object files 52 | *.slo 53 | *.lo 54 | # Compiled Dynamic libraries 55 | *.so 56 | *.dylib 57 | # Fortran module files 58 | *.mod 59 | *.smod 60 | # Compiled Static libraries 61 | *.lai 62 | *.la 63 | # Executables 64 | *.out 65 | *.app 66 | # Object files 67 | *.ko 68 | *.elf 69 | # Linker output 70 | *.map 71 | *.exp 72 | # Libraries 73 | # Shared objects (inc. Windows DLLs) 74 | *.so.* 75 | *.i*86 76 | *.x86_64 77 | *.hex 78 | # Debug files 79 | *.dSYM/ 80 | *.su 81 | # Kernel Module Compile Results 82 | *.mod* 83 | *.cmd 84 | .tmp_versions/ 85 | modules.order 86 | Module.symvers 87 | Mkfile.old 88 | dkms.conf 89 | CMakeCache.txt 90 | CMakeFiles 91 | CMakeScripts 92 | Testing 93 | cmake_install.cmake 94 | install_manifest.txt 95 | compile_commands.json 96 | CTestTestfile.cmake 97 | # Delphi compiler-generated binaries (safe to delete) 98 | *.bpl 99 | *.bpi 100 | *.dcp 101 | *.apk 102 | *.dres 103 | *.rsm 104 | *.dcu 105 | *.ocx 106 | # Delphi autogenerated files (duplicated info) 107 | *.cfg 108 | *.hpp 109 | *Resource.rc 110 | # Delphi local files (user-specific info) 111 | *.local 112 | *.identcache 113 | *.projdata 114 | *.tvsconfig 115 | *.dsk 116 | # Delphi history and backups 117 | __history/ 118 | __recovery/ 119 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 120 | # C++ objects and libs 121 | # Qt-es 122 | object_script.*.Release 123 | object_script.*.Debug 124 | *_plugin_import.cpp 125 | /.qmake.cache 126 | /.qmake.stash 127 | *.pro.user 128 | *.pro.user.* 129 | *.qbs.user 130 | *.qbs.user.* 131 | *.moc 132 | moc_*.cpp 133 | moc_*.h 134 | qrc_*.cpp 135 | *.qmlc 136 | *.jsc 137 | *build-* 138 | # Qt unit tests 139 | target_wrapper.* 140 | # QtCreator 141 | *.autosave 142 | # QtCreator Qml 143 | *.qmlproject.user 144 | *.qmlproject.user.* 145 | # QtCreator CMake 146 | CMakeLists.txt.user* 147 | # Windows thumbnail cache files 148 | Thumbs.db 149 | ehthumbs.db 150 | ehthumbs_vista.db 151 | # Dump file 152 | *.stackdump 153 | # Folder config file 154 | [Dd]esktop.ini 155 | *.mbr 156 | */Desktop_*/* 157 | */build_*/* 158 | Qt_*/* 159 | /LLVM_*/* 160 | *.tlog 161 | *.err 162 | Makefile 163 | Makefile.win 164 | # MEGA Sync 165 | *.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].* 166 | * ([0-9]).* 167 | -------------------------------------------------------------------------------- /stk_stasm.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // ------ Stanislaw Stasiak = "sstsoft@2001-2015r"--------------------------- 3 | //--------------------------------------------------------------------------- 4 | #include "stk_stasm.h" 5 | //--------------------------------------------------------------------------- 6 | // Stasm is only for GCC compatible inline asembler 7 | #if defined( __GNUC__) || defined(__CLANG__) 8 | //--------------------------------------------------------------------------- 9 | // __STASM_DECLARE_SHARE_STACK Template 10 | //--------------------------------------------------------------------------- 11 | #define __STASM_DECLARE_SHARE_STACK(mode_name,data_type) \ 12 | uint8_t __stasm_##mode_name##_max asm("__stasm_"#mode_name"_max") =__STASM_MAX_PARARELL; \ 13 | data_type __stasm_##mode_name##_stack[__STASM_MAX_PARARELL+1][__STASM_STACK_SIZE] asm("__stasm_"#mode_name"_stack"); \ 14 | data_type *__stasm_##mode_name asm("__stasm_"#mode_name) = (data_type*)(__stasm_##mode_name##_stack[__stasm_##mode_name##_max]); 15 | //--------------------------------------------------------------------------- 16 | #if defined(__x86_64__) || defined(__i386__) 17 | // AMD/Intel 32 or 64 bits 18 | // ^^ We assume x87 is present since 486/Pentium era by default 19 | #define __X87__ 20 | __STASM_DECLARE_SHARE_STACK(x86,uint32_t) 21 | // #error 22 | __STASM_DECLARE_SHARE_STACK(eax,uint32_t) 23 | __STASM_DECLARE_SHARE_STACK(ebx,uint32_t) 24 | __STASM_DECLARE_SHARE_STACK(ecx,uint32_t) 25 | __STASM_DECLARE_SHARE_STACK(edx,uint32_t) 26 | __STASM_DECLARE_SHARE_STACK(esi,uint32_t) 27 | __STASM_DECLARE_SHARE_STACK(edi,uint32_t) 28 | #ifdef __x86_64__ 29 | __STASM_DECLARE_SHARE_STACK(x64,uint64_t) 30 | __STASM_DECLARE_SHARE_STACK(rax,uint64_t) 31 | __STASM_DECLARE_SHARE_STACK(rbx,uint64_t) 32 | __STASM_DECLARE_SHARE_STACK(rcx,uint64_t) 33 | __STASM_DECLARE_SHARE_STACK(rdx,uint64_t) 34 | __STASM_DECLARE_SHARE_STACK(rsi,uint64_t) 35 | __STASM_DECLARE_SHARE_STACK(rdi,uint64_t) 36 | __STASM_DECLARE_SHARE_STACK(x64r08,uint64_t) 37 | __STASM_DECLARE_SHARE_STACK(x64r09,uint64_t) 38 | __STASM_DECLARE_SHARE_STACK(x64rxx,uint64_t) 39 | // TODO: Make sure __SSE__ to be defined if __x86_64__ is present 40 | // To declare necessary placeholders for FPU/XMM registers push/pop states 41 | #endif 42 | //--------------------------------------------------------------------------- 43 | #ifdef __X87__ 44 | __STASM_DECLARE_SHARE_STACK(x87,double) 45 | // In addition we declare FPU state save placeholder 46 | __STASM_STRUCT_FNSAVE __stasm_fnsaved_stack[__STASM_MAX_PARARELL+1] asm("__stasm_fnsaved_stack"); 47 | #endif 48 | //--------------------------------------------------------------------------- 49 | #ifdef __MMX__ 50 | __STASM_DECLARE_SHARE_STACK(mmx,__m64) 51 | // We DON'T need to declare FPU state since MMX/FPU shares same thing ^^ 52 | #if !defined(__X87__) 53 | __STASM_STRUCT_FNSAVE __stasm_fnsaved_stack[__STASM_MAX_PARARELL+1] asm("__stasm_fnsaved_stack"); 54 | #endif 55 | #endif 56 | //--------------------------------------------------------------------------- 57 | #ifdef __SSE__ 58 | __STASM_DECLARE_SHARE_STACK(sse1,__m128) 59 | // In addition we declare FPU state save placeholder 60 | // ASM: fxsaved 61 | __STASM_STRUCT_FXSAVE __stasm_fxsaved_stack[__STASM_MAX_PARARELL+1] asm("__stasm_fxsaved_stack"); 62 | #endif 63 | //--------------------------------------------------------------------------- 64 | #ifdef __SSE2__ 65 | __STASM_DECLARE_SHARE_STACK(sse2,__m128d) 66 | #if !defined(__SSE__) 67 | // If SSE was not declared, we have to make FPU xstate enlarged placeholder as well 68 | // ASM: fxsaved 69 | __STASM_STRUCT_FXSAVE __stasm_fxsaved_stack[__STASM_MAX_PARARELL+1] asm("__stasm_fxsaved_stack"); 70 | #endif 71 | #endif 72 | //--------------------------------------------------------------------------- 73 | #ifdef __SSE3__ 74 | __STASM_DECLARE_SHARE_STACK(sse3,__m128i) 75 | #if !defined(__SSE__) and !defined(__SSE2__) 76 | // If SSE was not declared, we have to make FPU xstate enlarged placeholder as well 77 | // ASM: fxsaved 78 | __STASM_STRUCT_FXSAVE __stasm_fxsaved_stack[__STASM_MAX_PARARELL+1] asm("__stasm_fxsaved_stack"); 79 | #endif 80 | //--------------------------------------------------------------------------- 81 | #endif 82 | #if defined(__SSE4A__)\ 83 | or defined(__SSE41__)\ 84 | or defined(__SSE42__) 85 | __STASM_DECLARE_SHARE_STACK(sse4,__m128i) 86 | #if !defined(__SSE__) and !defined(__SSE2__) and !defined(__SSE3__) 87 | // If SSE was not declared, we have to make FPU xstate enlarged placeholder as well 88 | // ASM: fxsaved 89 | __STASM_STRUCT_FXSAVE __stasm_fxsaved_stack[__STASM_MAX_PARARELL+1] asm("__stasm_fxsaved_stack"); 90 | #endif 91 | #endif 92 | //--------------------------------------------------------------------------- 93 | #ifdef __AVX__ 94 | __STASM_DECLARE_SHARE_STACK(avx,__m256) 95 | // For AVX we must declare even bigger placeholder for FPU state almost 8kB of data! 96 | // ASM: xsaved 97 | __STASM_STRUCT_XSAVE __stasm_axsaved_stack[__STASM_MAX_PARARELL+1] asm("__stasm_axsaved_stack*"); 98 | #endif 99 | //--------------------------------------------------------------------------- 100 | size_t __stasm_stack[__STASM_STACK_SIZE]; 101 | //--------------------------------------------------------------------------- 102 | #endif 103 | #endif 104 | -------------------------------------------------------------------------------- /README.md.bak: -------------------------------------------------------------------------------- 1 | # stasm 2 | 3 | Hi, my name is Stanley. 4 | First of all this are my first steps using GitHub(and Git also), Those are my first steps since many years in C, and also english is not my primary language. 5 | So please forgive me if im doing it wrong. Help me if You can and want to. 6 | 7 | This repo is mainly working but still alpha version of GCC inline asm volatile("":::) replacement using C preprocessor. 8 | Replaceent by: 9 | ``` 10 | __stasm(lot of options and clobber list, 11 | code(word where code starts), 12 | then literal code without "" 13 | ) 14 | ``` 15 | Thats all. 16 | As You can see, simplest form of inline assembly could be: 17 | ``` 18 | __stasm(push eax; xor eax,eax; ret;) 19 | ``` 20 | Or if you will debug it: 21 | ``` 22 | __stasm(push eax\n and so on...) 23 | ``` 24 | 25 | With __stasm You can simple copy-paste from Visual Studio asm {} block. It also simplify work a little using options. 26 | The big options are: 27 | ``` 28 | x86, eax, ebx, ecx, edx, esi, edi, x87, x64,x64r89, x64rxx, mmx, sse, sse2, sse3, sse4, avx, aes 29 | ``` 30 | You could write one of them or all of them to some magic happen. 31 | If you do this, preproccessor will warn you to add -mmx, -msse option into GCC commmand line. 32 | The preprocessor would include headers with data types(mmx,sse), it will add clobbers into asm() clobber list; 33 | The option is to add individial registers eax,ebx etc.. or all of particular registers group: 34 | x86 means all x86 registers, x64r89 means only r8+r9, x64rxx means all r10-r15. 35 | Those simple options affect only clobber list passed into gcc asm(); passing individual or all registers. 36 | If you don't want to affect GCC but must save them before use you must add magical word "save": 37 | "save,register_name" and then macro would generate "push register" "pop register" pair before and after your code block. 38 | This would not break GCC optimisation for local variables but simple push them and pop from stack when your code is done. 39 | If you want fnsave,fxsave,xsave simply save,x87,save,sse,save,avx and stasm would do it for you. 40 | There is also magical option "dim", then after comma you write "+g", global variable name then comma again so instead of: unnamed variable %1, you could write "mov you_named_in_C,eax; 41 | Extended syntax using "dim's" is not working for two or more variables. 42 | This need to be fixed. 43 | 44 | #Due the GCC bugs... 45 | ` 46 | Again invalidated by bugzilla guys macro is not as useful and intuitive as could be. 47 | [Ticket number: 65897](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65897) 48 | [Ticket number: 65898](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65898) 49 | ` 50 | Dim has no chance working well with GCC without -masm=intel in compiler command line options. 51 | For now it is very cool in Clang inline asm() and it was working well without problems...until I broke something. 52 | For working in GCC i have created global variables and Semaphores(mutexes) as temporary feature. 53 | And so You should not use dim's but static "stacks" named: 54 | s_x86,s_x87 etc. in size of 1 cache line 64 bytes. 55 | ` 56 | Anyway, this macro helped me to switch from Borland C++ 6 inline asm {} into QT Creator + MinGW 57 | Mutexes/semaphores(counting from MAX_PARARELL to 0) were created for multithread safety. 58 | You could use them in up to MAX_PARARELL=12 threads(recrusion) because of semaphore/mutex switcher. 59 | Global variables are for easy exchange data. 60 | Anybody should avoid globals im working to avoid them but bugzilla is not helping me so i must for now. 61 | This is not good idea(makes asm opposite to program speedup) but it works. 62 | This is not way it should be but it's very easy create inline assembly for people who used to Microsoft/Borland asm {} 63 | For me it was only way to start working with code from many many years ago. 64 | ` 65 | 66 | How it works? Instead of writing: 67 | ``` 68 | asm("blabla %bla,bla\n\ 69 | someother bla,bla\n 70 | " : input : output or whatever : registers used : goto labels); 71 | ``` 72 | You could easly write(for example): 73 | ``` 74 | s_x86[0] = 13; // input data 75 | __stasm(x86,code, 76 | mov esi, s_x86; 77 | mov eax,[esi]; 78 | imul eax,3; 79 | mov edi,s_x86; 80 | inc edi; 81 | mob [edi],ecx; 82 | ); 83 | ``` 84 | And then int variable = s_x86[1]; 85 | You could say, it's dumb, silly, useless.. 86 | GCC has such great feature "+r", there is not many changes except "", 87 | In GCC code could be only 1 line: imul %1,3; GCC would create mov eax,[ebs-8]; or whatever.. 88 | Yeah You right, You got me, but for me it was the only way to switch from something like that: 89 | ``` 90 | int __stdcall somefunc(int variable){ 91 | asm { 92 | mov eax,variable; 93 | imul eax,3; 94 | mov variable,eax; 95 | } 96 | return variable; 97 | } 98 | ``` 99 | Into previously presented, by just copy-paste blocks of asm code and adapt into gcc much more easly. 100 | You may say, should copy them into ".s"" files, "offline" asembly or into NASM, YASM,FASM 101 | Of course. So I did it in QT Creator by modifying makefile and adding compiler for .asm 102 | And then realized that GAS is better and created some .s files, and then realised... i don't want to learn linker nameing convention. 103 | I don't want to change whole C code into asm, then line by line when i switch from 32bit version of apps change function prequels. 104 | Let C compiler do this for me. 105 | So decided to do stasm macro. Yust for fun and learn C preprocessor features. 106 | When i done it, I have decided that I will never, ever learn GCC dumb inline assembly. Promise! 107 | Clang has experimental support for asm {} so.. there is a hope i wont be forced to it anymore. 108 | GCC asembly has been done wrong. Not for human beings let's forget about. 109 | I know it's "+r","r" faster better.. blabla.. 110 | But it's not intuitive. I like WinAVR, i want to make asembly for ARM instead of GCC used to IAR Embadded. 111 | BCC32 is very old, Pelles C is only C compiler.. Clang is not working with Qt Creator so.. 112 | 113 | ## Here it is, as it is. 114 | Maybe you could make it better, so give me a sign. 115 | I don't know what im done wrong with dim's - why it's not working. 116 | It worked but suddenly i have make some mistake? 117 | Help me if you can. 118 | Cheers. -------------------------------------------------------------------------------- /stasm.pro: -------------------------------------------------------------------------------- 1 | # 2 | # Qmake Qt5.5.1 file last modified 2018.5, Windows MSC2010,MinGW4.92,LLVM3.7 builds tester 3 | # 4 | DEFINES += BUILD_STK_LIBRARY 5 | # ------------------------------------------------------------- 6 | # CONFIG: LIBRARY: STATIC, DLL OR EXE: TESTING.APP 7 | # ------------------------------------------------------------- 8 | contains(DEFINES, BUILD_STASM_LIBRARY) { 9 | message("TARGET stasm.DLL") 10 | message($$DEFINES) 11 | TARGET = stasm 12 | TEMPLATE = lib 13 | # CONFIG += staticlib 14 | CONFIG += embed_manifest_dll 15 | CONFIG += dll 16 | CONFIG -= warn_on 17 | CONFIG += warn_off 18 | } 19 | else { 20 | message("TARGET Example application stasm.exe") 21 | TARGET = stasm_example 22 | TEMPLATE = app 23 | CONFIG += console 24 | CONFIG += embed_manifest_exe 25 | CONFIG -= warn_on 26 | CONFIG += warn_off 27 | } 28 | # ------------------------------------------------------------- 29 | CONFIG += precompiled_header 30 | # ------------------------------------------------------------- 31 | # MESSAGE ABOUT TARGET 32 | # ------------------------------------------------------------- 33 | message(QMAKESPEC:$$QMAKESPEC) 34 | message(CONFIG:$$CONFIG) 35 | 36 | contains(TEMPLATE, dll) { 37 | contains(CONFIG, dll) { 38 | message($$TARGET".dll") 39 | } 40 | contains(CONFIG, static) { 41 | message("lib"{$$TARGET}".lib") 42 | } 43 | } 44 | # ------------------------------------------------------------- 45 | # MORE CONFIG 46 | # ------------------------------------------------------------- 47 | QT -= core gui 48 | CONFIG -= qt 49 | CONFIG += precompile_header 50 | #CONFIG -= static 51 | CONFIG += warn_on 52 | CONFIG += exceptions 53 | CONFIG += c++11 54 | contains(QMAKE_COMPILER_DEFINES,_MSC_VER) { 55 | # ------------------------------------------------------------- 56 | # Microsoft Visual C++ 57 | # ------------------------------------------------------------- 58 | message("Using MSVC Microsoft Compiler QMAKE_FLAGS") 59 | QMAKE_CXXFLAGS -= /W1 60 | QMAKE_CXXFLAGS -= /W2 61 | QMAKE_CXXFLAGS -= /W3 62 | QMAKE_CXXFLAGS -= /W4 63 | QMAKE_CXXFLAGS_RELEASE += /w 64 | QMAKE_CXXFLAGS_DEBUG += /W0 65 | QMAKE_CXXFLAGS_RELEASE += /arch:SSE2 66 | } else { 67 | contains(QMAKE_COMPILER_DEFINES,__clang__) { 68 | # ------------------------------------------------------------- 69 | # LLVM - Clang 70 | # ------------------------------------------------------------- 71 | message("Using LLVM Clang Compiler QMAKE_FLAGS") 72 | 73 | WARNINGS_LLVM += -Wextra 74 | WARNINGS_LLVM += -Wunknown-pragmas -Wundef 75 | WARNINGS_LLVM += -Wold-style-cast 76 | WARNINGS_LLVM += -Wdisabled-optimization -Wstrict-overflow=4 77 | WARNINGS_LLVM += -Weffc++ #-Wuseless-cast 78 | WARNINGS_LLVM += -Winit-self -Wpointer-arith 79 | WARNINGS_LLVM += -Wlogical-op 80 | WARNINGS_LLVM += -Wunsafe-loop-optimizations -Wno-error=unsafe-loop-optimizations 81 | WARNINGS_LLVM += -Wno-write-strings -Wno-multichar 82 | WARNINGS_LLVM += -Wno-ignored-attributes 83 | 84 | NO_WARNINGS_LLVM += -Wno-write-strings -Wno-multichar 85 | NO_WARNINGS_LLVM += -Wno-unused-variable -Wno-unused-parameter -Wno-unused-value -Wno-unused-label 86 | NO_WARNINGS_LLVM += -Wno-unused-but-set-variable 87 | NO_WARNINGS_LLVM += -Wattributes -Winline 88 | NO_WARNINGS_LLVM += -Wunknown-pragmas 89 | NO_WARNINGS_LLVM += -Wno-ignored-attributes 90 | NO_WARNINGS_LLVM += -Wattributes -Winline -Wshadow -Wall 91 | #NO_WARNINGS_LLVM += -fverbose-asm 92 | #NO_WARNINGS_LLVM += -fstrict-aliasing 93 | #NO_WARNINGS_LLVM += -dD 94 | #NO_WARNINGS_LLVM += -g 95 | NO_WARNINGS_LLVM += -std=gnu++0x -pthread 96 | NO_WARNINGS_LLVM += -Qunused-arguments -Wno-error=unused-command-line-argument-hard-error-in-future 97 | 98 | FLAGS_LLVM += -fno-use-linker-plugin 99 | FLAGS_LLVM += -malign-double 100 | FLAGS_LLVM += -momit-leaf-frame-pointer 101 | FLAGS_LLVM += -fwrapv 102 | FLAGS_LLVM += -funroll-loops 103 | FLAGS_LLVM += -m32 -mfpmath=sse -flto -O3 104 | FLAGS_LLVM += -mpreferred-stack-boundary=8 105 | FLAGS_LLVM += -mmmx -msse -msse2 106 | FLAGS_LLVM -= -fno-keep-inline-dllexport 107 | FLAGS_LLVM -= -finline-small-functions 108 | #FLAGS_LLVM -= -pipe 109 | #FLAGS_LLVM += -save-temps 110 | 111 | # C++ FLAGS 112 | QMAKE_CXXFLAGS += $$FLAGS_LLVM 113 | QMAKE_CXXFLAGS_RELEASE += $$NO_WARNINGS_LLVM 114 | QMAKE_CXXFLAGS_DEBUG += $$WARNINGS_LLVM 115 | QMAKE_CXXFLAGS += clang++ 116 | 117 | # Pure C FLAGS 118 | QMAKE_CFLAGS += $$FLAGS_LLVM 119 | QMAKE_CFLAGS_RELEASE += $$NO_WARNINGS_LLVM 120 | QMAKE_CFLAGS_DEBUG += $$WARNINGS_LLVM 121 | QMAKE_CFLAGS += clang 122 | 123 | # Linker FLAGS 124 | QMAKE_LFLAGS += -Qunused-arguments -Wno-error=unused-command-line-argument-hard-error-in-future 125 | QMAKE_LFLAGS -= -mthreads 126 | } else { 127 | contains(QMAKE_COMPILER_DEFINES,__GNUC__) { 128 | # ------------------------------------------------------------- 129 | # MINGW / GCC 130 | # ------------------------------------------------------------- 131 | message("Using MinGW/GCC QMAKE_FLAGS") 132 | 133 | WARNINGS_GNU += -Wextra 134 | WARNINGS_GNU += -Wunknown-pragmas -Wundef 135 | WARNINGS_GNU += -Wold-style-cast 136 | WARNINGS_GNU += -Wdisabled-optimization -Wstrict-overflow=4 137 | WARNINGS_GNU += -Weffc++ #-Wuseless-cast 138 | WARNINGS_GNU += -Winit-self -Wpointer-arith 139 | WARNINGS_GNU += -Wlogical-op 140 | WARNINGS_GNU += -Wunsafe-loop-optimizations -Wno-error=unsafe-loop-optimizations 141 | WARNINGS_GNU += -Wno-write-strings -Wno-multichar 142 | 143 | NO_WARNINGS_GNU += -Wno-write-strings -Wno-multichar 144 | NO_WARNINGS_GNU += -Wno-unused-variable -Wno-unused-parameter -Wno-unused-value -Wno-unused-label 145 | NO_WARNINGS_GNU += -Wno-unused-but-set-variable 146 | NO_WARNINGS_GNU += -Wattributes -Winline 147 | NO_WARNINGS_GNU += -Wunknown-pragmas 148 | NO_WARNINGS_GNU += -Wattributes -Winline -Wshadow -Wall 149 | #NO_WARNINGS_GNU += -fverbose-asm 150 | #NO_WARNINGS_GNU += -fstrict-aliasing 151 | #NO_WARNINGS_GNU += -dD 152 | #NO_WARNINGS_GNU += -g 153 | NO_WARNINGS_GNU += -pthread 154 | 155 | FLAGS_GNU += -fno-use-linker-plugin 156 | FLAGS_GNU += -malign-double 157 | FLAGS_GNU += -momit-leaf-frame-pointer 158 | FLAGS_GNU += -fwrapv 159 | FLAGS_GNU += -funroll-loops 160 | FLAGS_GNU += -m32 -mfpmath=sse -flto -O3 161 | FLAGS_GNU += -mpreferred-stack-boundary=8 162 | FLAGS_GNU += -mmmx -msse -msse2 163 | FLAGS_GNU += -save-temps 164 | 165 | QMAKE_CXXFLAGS_DEBUG += $$FLAGS_GNU $$WARNINGS_GNU -std=gnu++0x 166 | QMAKE_CXXFLAGS_RELEASE += $$FLAGS_GNU $$NO_WARNINGS_GNU -std=gnu++0x 167 | QMAKE_CXXFLAGS_DEBUG -= -pipe 168 | QMAKE_CXXFLAGS_RELEASE -= -pipe 169 | 170 | QMAKE_CFLAGS_DEBUG += $$FLAGS_GNU $$WARNINGS_GNU 171 | QMAKE_CFLAGS_RELEASE += $$FLAGS_GNU $$NO_WARNINGS_GNU 172 | QMAKE_CFLAGS_DEBUG -= -pipe 173 | QMAKE_CFLAGS_RELEASE -= -pipe 174 | }}} 175 | # ------------------------------------------------------------- 176 | # 177 | # Common section SOURCES, HEADERS, OTHER FILES 178 | # 179 | # ------------------------------------------------------------- 180 | SOURCES += \ 181 | example/variables.cpp\ 182 | stk_stasm.cpp 183 | # ------------------------------------------------------------- 184 | # 185 | # Both GCC and LLVM 186 | # 187 | # ------------------------------------------------------------- 188 | contains(QMAKE_COMPILER_DEFINES,__clang__) { 189 | message("LLVM GAS Assembler SOURCES") 190 | SOURCES+= 191 | # gas.s 192 | } else { 193 | contains(QMAKE_COMPILER_DEFINES,__GNUC__) { 194 | message("GNUC GAS Asembler SOURCES") 195 | SOURCES+= 196 | # gas.s 197 | } else { 198 | contains(QMAKE_COMPILER_DEFINES,_MSC_VER) { 199 | message("Microsoft Visual C++ MASM SOURCES") 200 | SOURCES+= 201 | # gas.s 202 | }}} 203 | # ------------------------------------------------------------- 204 | #PRECOMPILED_HEADER += stk_MAIN.h 205 | HEADERS += \ 206 | stk_stasm.h 207 | # ------------------------------------------------------------- 208 | # QT GUI 209 | # ------------------------------------------------------------- 210 | contains(DEFINES, QT_GUI) { 211 | message("QT5 GUI specific SOURCE") 212 | CONFIG += 213 | SOURCES += 214 | HEADERS += 215 | FORMS += 216 | RESOURCES += 217 | } 218 | # ------------------------------------------------------------- 219 | contains(DEFINES, _MSC_VER) { 220 | message("LINKER Microsoft Visual C++ LIBS") 221 | # LIBS += vcomp.lib 222 | LIBS += crypt32.lib 223 | LIBS += kernel32.lib shell32.lib gdi32.lib 224 | LIBS += user32.lib uuid.lib 225 | LIBS += wsock32.lib ws2_32.lib 226 | LIBS += winmm.lib 227 | LIBS += ole32.lib oleaut32.lib 228 | LIBS -= gomp.lib 229 | contains(DEFINES, QT_GUI) { 230 | LIBS += QtCored.lib 231 | } 232 | } else { 233 | contains(QMAKE_COMPILER_DEFINES,__clang__) { 234 | message("LLVM LIBS") 235 | LIBS += crypt32.lib 236 | LIBS += kernel32.lib shell32.lib gdi32.lib 237 | LIBS += user32.lib uuid.lib 238 | LIBS += wsock32.lib ws2_32.lib 239 | LIBS += winmm.lib 240 | LIBS += ole32.lib oleaut32.lib 241 | LIBS -= gomp.lib 242 | contains(DEFINES, QT_GUI) { 243 | LIBS += QtCored.lib 244 | } 245 | } else { 246 | contains(QMAKE_COMPILER_DEFINES,__GNUC__) { 247 | message("GNUC LIBS") 248 | LIBS += -lkernel32 249 | LIBS += -lgdi32 -lcomctl32 -lshell32 -luser32 -luserenv 250 | LIBS += -lws2_32 -lwsock32 251 | LIBS += -lwinmm -limm32 252 | LIBS += -lole32 -loleaut32 253 | LIBS += -ladvapi32 254 | LIBS += -lcrypt32 -uiid 255 | LIBS += -lgomp 256 | contains(DEFINES, QT_GUI) { 257 | LIBS += QtCored.a 258 | } 259 | } 260 | }} 261 | # ------------------------------------------------------------- 262 | win32: { 263 | message("Windows RC Resource Files RC_FILE") 264 | ## RC_FILE = stk_stasm.rc 265 | #-manifest file.manifest 266 | } 267 | OTHER_FILES += 268 | DISTFILES += test.txt 269 | # ------------------------------------------------------------- 270 | message("QMAKE FINISH") 271 | # ------------------------------------------------------------- 272 | # External ASM .s compiler 273 | # ------------------------------------------------------------- 274 | #QMAKE_CFLAGS_RELEASE += rtti_off stl_off exceptions_off 275 | #QMAKE_CXXFLAGS += -save-temps 276 | #QMAKE_CXXFLAGS += -fverbose-asm 277 | #QMAKE_CXXFLAGS -= -pipe 278 | #moc.depend_command = g++ -E -M ${QMAKE_FILE_NAME} | sed "s,^.*: ,," 279 | #NASM.output = ${QMAKE_FILE_BASE}_asm.o 280 | #NASM.commands = c:/nasm/nasm -f elf -g -F dwarf --prefix ${PWD}${QMAKE_FILE_NAME} -o ${PWD}/${QMAKE_FILE_OUT} 281 | #NASM.input = ASM_SOURCES 282 | #YASM.output = ${QMAKE_FILE_BASE}_asm.o 283 | #YASM.commands = c:/YASM/YASM -f elf -g dwarf2 -w -o ${QMAKE_FILE_OUT} ${PWD}${QMAKE_FILE_NAME} 284 | #YASM.input = ASM_SOURCES 285 | #FASM.output = ${QMAKE_FILE_BASE}_asm.o 286 | #FASM.commands = c:/fasm/fasm ${PWD}${QMAKE_FILE_NAME} ${QMAKE_FILE_OUT} 287 | #FASM.input = ASM_SOURCES 288 | #QMAKE_EXTRA_COMPILERS += YASM 289 | #ASM_SOURCES += ../STK/cpu/stk_cpu_nasm.asm 290 | 291 | 292 | #postlink.target = .buildfile 293 | #postlink.commands = dlltool -z --output-def,exported.def -l $$postlink.target 294 | #QMAKE_EXTRA_TARGETS += postlink 295 | #QMAKE_POST_LINK += postlink 296 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # __stasm(...) 2 | ### The inline assembly wrapper for GCC and Clang C/C++ compiler. Made for human beings. 3 | 4 | Hi, my name is Stanley. First of all, this are my first steps using GitHub(and Git also) and also first steps in C++ since many years. Plus english is not my primary language. So i can't guarantee even the readme to be usefull. 5 | 6 | Actually this easy-peasy macro tool is daily working with MinGW 4.9 and Clang3.7 (windows and linux gcc) can work with any compiler that have simmilar inline asembly syntax as GCC. Just get it import .c file to your project makefile and include .h to any unit you want use asembly then use the macros __stasm() instead asm(""). It's working for targeting all x386, x86-64 processors with all of those MMX,3Dnow, SSE, AVX extensions. Could work with ARM (this was made but wasn't tested). Could work also with any other processor and it need to be adapted exclusivly one by one. This would be done in future. 7 | 8 | I need mention this is still alpha version of "wrapper" for asm volatile("":::); i wanted to have. Wanted to have using just C preprocessor, without need for any special meta compilers or something like that. Just pure C preprocessor capable for __VA_ARGS__, glue ## and #. Macros has ability to make inline assembly, a lot easier and intuitive for any C programmer that wanted to learn asembly without painfull GCC/GAS AT&T style. Could be usefull for testing and debuging the code. Then after testing you can copy-paste a whole functional block into prepared extern "C" function, obscuficate blocks with specific calling conventions and let it compile by any external asembler such as GAS, FASM, YASM, NASM. With stasm you can copy, copy-back the code without many effort. Stasm inline assembly could be as easy as in Visual Studio or Borland __asm {} with Intel specific syntax: 9 | 10 | ~~~{.cpp} 11 | __stasm( 12 | mov eax,0x00000001; 13 | xor ecx,ecx; 14 | cpuid; 15 | mov ecx,0x00000001; 16 | shl ecx,27; 17 | and ecx,edx; 18 | xor eax,eax; 19 | xor edx,edx; 20 | 21 | test ecx,ecx; 22 | jz tsc_exit; 23 | mov eax,1; 24 | cpuid; 25 | jmp tsc_intel_measure; 26 | tsc_amd_measure:\n 27 | sfence; 28 | rdtsc; 29 | 30 | tsc_intel_measure:\n 31 | sfence; 32 | rdtsc; 33 | 34 | tsc_exit:\n 35 | mov edi,s_x86; 36 | mov [edi+0],eax; 37 | mov [edi+4],edx; 38 | ) 39 | ~~~ 40 | If you want to debug(make traps for specific line) instead C styled line separator ';' (actually comment separator in GAS) you must put code for next line '\n': 41 | 42 | ~~~{.cpp} 43 | __stasm( 44 | ... \n 45 | mov [edi+0],eax \n 46 | ) 47 | ~~~ 48 | 49 | With __stasm You can copy-paste code from and to Visual Studio, Borland asm {} block. Stasm can also simplify work with processor multimedia extensions registers and simplify using of local variables that is painfull in GCC inline asm. Stasm can simplify it by using special words written just before actual code. The options are: 50 | 51 | ~~~{.asm} 52 | save,var,label,x86, eax, ebx, ecx, edx, esi, edi, x87, x64, x64r89, x64rxx, mmx, sse, sse2, sse3, sse4, avx, aes 53 | ~~~ 54 | 55 | You could write one of them or all of them altogether (sepparated with comma) just before your asm code begins remembering only to add "code" word before actual asembly. That's it - magic would happen automaticaly. If you write, a single "mmx" for example, macro will automatically generate warn message for you to add -mmx option into GCC commmand line and will automatically include headers needed for C to exchange data types speciffic to MMX. Will also add special clobbers into asm() clobber list. Will create additional static variables needed for painless data sharing - migration from Microsoft C compiler to GCC. For example "x86" means all x86 registers that userspace program can reach would be added to clobbers, x64r89 means r8+r9, x64rxx means all from r10 to r15. But you can write just one of them. Intuitive as defining local variables in C functions. Opposite to GCC inline where those are defined at end. 56 | 57 | Because those simple words written just as i have listed are affecting so called "clobbers" GCC could know what registers you want to use so will not put local variables onto them. If you don't want to affect GCC compilation process that potentially slows down the C code part. You can tell __stasm to save them for you on the stac in way simmilar for calling a C function. Hidden from your attencion. It can be done by adding magical word "save" before those register names i had mentioned as an additional sub option: "save,register_name" instead "register_name". It would make "push register" "pop register" pair in your code or even fnsave,fsave,xsave pair before and after your code block. (lot of kB without need to learn how much data is needed - i had done it for you!) This stack way would not break GCC optimisation for local variables, and you can forget to push them and pop from stack just in the same way as in MSVC and Borland C asm {}. 58 | 59 | If you want fnsave,fxsave,xsave state of FPU, SSE, AVX register state made by C code you just have to write: save,x87,save,sse,save,avx and even dont bother memory assignment or variable to hold it. 60 | 61 | ##But that's not whole magic: Variables. 62 | 63 | As you may know GCC inline asembly code can't reach local variables directly by it's name. It's not simple as in Microsoft _asm{} block. It's harder mostly because asm(""); block is almost blindly passed by GCC to GAS .s as string just before the end of C compilation process. Rather than bidirectional analizer GCC is simply copy-paster. In addition because of linker nameing conventions (underscore added to variable names), namespaces, classes it's even more complicated. That's why even special GCC extended inline options for getting access to static variables is vary painfull. Of course with stasm i had resolved this problem it a little :) 64 | 65 | There is magical spell for variables: "var". If you put this before a variable name (separated by comma from "var") Instead of using: unnamed variable "%1" in asembly code, you could write intuitive "mov you_named_in_C, eax; 66 | 67 | ### But there is limitation: 68 | Extended syntax using "var's" and "save" is currently not working for two or more variables. 69 | This need to be fixed if it's can be fixed? In another attempt i will try create additional macros named: 70 | ~~~ 71 | use(...), save(...), var(...), label(...) 72 | ~~~ 73 | For now options had to be separated by comma 'var,"+r",var_name,save,eax,code', with additional macros can form something like this: 74 | ~~~ 75 | c_goto_label: 76 | scanf("Please write a number bigger than 0: %d",c_var_name); 77 | stasm(save(eax,ebx,ecx),var(+r,c_var_name),label(c_goto_label),code( 78 | mov eax,c_var_name; 79 | jnz c_goto_label; 80 | )) 81 | ~~~ 82 | ##GAS limitations and differences to asm{} 83 | 84 | As you can see there is additional "+r" word before sub option "var". You need to inform how GAS should thread name you provided. Details about it can be found in GAS extended syntax manual. https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html 85 | You need to remember at least "+r" because is adequate to most common global/local variable [EBP-some_unique_number] or [ESP-some_other_number]. The code written as: 'lea esi,c_variable' to variable defined as +r will always move variable address, to ESI not it's value whatever it's value or pointer. Oposite to Borland C and MSVC by with is detected automatically. To retrive variable you need to: mov eax,[esi]; 86 | 87 | Why is that? Names for local variables passed to inline asembly are replaced by [register-some values] in simmilar way as printf("mov %s,%s","[register1]","[register2]"); That's why also this Microsoft trick: mov eax,[ponter+index]; won't work because it will produce code that looks like this: [[register-index]+index]. Witch is wrong cant be undestanded by GAS. No AGU operations can't be done by those imported c_variable. It can be used only to import values from C code. 88 | 89 | #Another bad information. Due the GCC bugs... 90 | ` 91 | Again invalidated by bugzilla guys macro is not as useful and intuitive as could be. 92 | [Ticket number: 65897](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65897) 93 | [Ticket number: 65898](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65898) 94 | ` 95 | Var has no chance working well with GCC without -masm=intel in compiler command line options. All because AT&T % 96 | But it is working well in Clang inline asm() without passing any additional options to compiler, and it was tested to without problems... I was just like holy-grall for me when i tested it. Asembly just as it should be local variables visible to inline asembler. To get this working in GCC (share data between C code and asm) i have created global variables protected by locking mechanism(for multithreading safety) as temporary feature. It is currently only one used by me for now. 97 | 98 | Meantime you should not use var's but use static share "stacks", created automaticly for you as you type x86,x87 options to stasm. Those variables would be named: s_x86, s_x87 created at minimum size of 1 cache line 64 bytes. Also because of that exchanged buffers can be shared by separated stasm block. The type of those variables seen from C code is automatically definied adequate to type of extension you will declare to use: registers 8,16,32 bytes wide. Literally arrays of variables in number of 8,16,32 of them. It's not too much RAM and adequate to common number: 8,16,32 of XMM registers - don't you think?;) 99 | 100 | In actual form macro sucesfully helped me to switch from obsolete Borland C++ 6 inline asm {} into QT Creator + MinGW. Change usles asembly code into C code step by step. Move some code to external .s file compiled as it should be.. This is not ultimate answer just, a easy tool to make GNU GAS human friendly. 101 | 102 | #Static? What about multithreading? 103 | 104 | Static and global variables are bad for many reasons even in single threaded program(cache miss). In multithreaded should be always protected by locks,unlock mechanism. Anyway i think there are some advantage over local variables for couple reasons. Common data generates less code/data size so can easly fit in cache. (in other words: cache hit probability will increases) Althought locking mechanism makes the oposite to what asm inline asembly is made for. But anyway locking semaphores(counting from MAX_PARARELL to 0) were created for multithread safety and it works! You could safety use __stasm inline in up to MAX_PARARELL=12 threads. The biggest disadventage you should know is that it can create synchronizing barier for you multithreaded code. And it is very risky.. specially in recrusion ;) Think about this. This is important! 105 | 106 | Althoug global variables are for easy exchange data. Im working to avoid them. Bugzilla is not helping me do what i want to do just now, so i must use them... This is not good idea(makes asm opposite to program speedup) but it just works for GCC. Clang don't need them at all because local variables are working well. 107 | 108 | Actually in GCC inline asembly it's copy-pasted by GCC onto the GAS compiler stage. GAS has nothing to do with inline asembly i don't blame it for bugs. But it's a part of GNU GCC and it's not for human beings. I hope someone will change this then stasm would work as charm without static globals. 109 | 110 | ~~~{.cpp} 111 | asm("i hate gas universalism fuck %gnu\n" 112 | "some other hatres words\n" 113 | : input : output or whatever i hate that : registers hate to be used : goto shitty labels); 114 | ~~~ 115 | 116 | With globals you could easly write(for weird example): 117 | 118 | ~~~{.asm} 119 | s_x86[0] = 13; // input my lovely number for test 120 | __stasm(x86,code, 121 | mov esi, s_x86; 122 | mov eax,[esi]; 123 | imul eax,3; 124 | mov edi, s_x86; 125 | add edi, 4; 126 | mov [edi],eax; 127 | ); 128 | int another_c_variable = s_x86[1]; 129 | assert(s_x86[1]==3*13); 130 | ~~~ 131 | 132 | You may say: Using common GCC inliner the generated could be only 1 liner: imul %1,3; GCC would create mov eax,[ebs-8]; or whatever.. it would be a lot faster and have much more sense. 133 | Yeah You right, You got me, but for me it was the only way for painless migration from something like that(althought it's stupit): 134 | 135 | ~~~{.cpp} 136 | int __stdcall somefunc(int variable){ 137 | __asm { 138 | mov eax,variable; 139 | imul eax,3; 140 | mov variable,eax; 141 | } 142 | return variable; 143 | } 144 | ~~~ 145 | 146 | Into previously presented form, by just copy-paste blocks of asm code. You may say, I should copy them into ".s" files, "offline" asembly. Learn great GCC manual or one of many asms compilers: NASM,YASM,FASM. 147 | Of course. I did at first attempt in QT Creator by modifying qmakefile: 148 | 149 | ~~~{.pro} 150 | #NASM.output = ${QMAKE_FILE_BASE}_asm.o 151 | #NASM.commands = c:/nasm/nasm -f elf -g -F dwarf --prefix ${PWD}${QMAKE_FILE_NAME} -o ${PWD}/${QMAKE_FILE_OUT} 152 | #NASM.input = ASM_SOURCES 153 | #YASM.output = ${QMAKE_FILE_BASE}_asm.o 154 | #YASM.commands = c:/YASM/YASM -f elf -g dwarf2 -w -o ${QMAKE_FILE_OUT} ${PWD}${QMAKE_FILE_NAME} 155 | #YASM.input = ASM_SOURCES 156 | #FASM.output = ${QMAKE_FILE_BASE}_asm.o 157 | #FASM.commands = c:/fasm/fasm ${PWD}${QMAKE_FILE_NAME} ${QMAKE_FILE_OUT} 158 | #FASM.input = ASM_SOURCES 159 | #QMAKE_EXTRA_COMPILERS += YASM 160 | #ASM_SOURCES += ../../../x86_libraries/SSTSOFT/cpu/tsoft_cpuid_nasm.asm\ 161 | #ASM_SOURCES += ../../../x86_libraries/SSTSOFT/mem/tsoft_mem32_nasm.asm\ 162 | #ASM_SOURCES += ../../../x86_libraries/SSTSOFT/text/tsoft_cstr_nasm.asm\ 163 | #ASM_SOURCES += ../../../x86_libraries/SSTSOFT/time/tsoft_time_nasm.asm 164 | ~~~ 165 | 166 | I had done it because if you want to compile .s file by GAS you need add GCC option to make stage files. So external asembler is much more usefull. When i tried to utilize them then i had realized that whatever asembler is. I don't want to learn linker nameing convention at all, change all C functions into extern "C". I don't want to learn macro languages so nice as in FASM/Fresh IDE - C is one of them for christ sake! I don't want to change whole C code into asm whatever great ASM compiler wouuld be. I don't want to use __buildin, __instrict or whatever it's called. I want just use sometimes test an pure inline asembly fragments. Mostly because i love to code in C, even if it's stupud and feel how processor works by using asm! I love to code! It makes me think how processor works how it can be speeded up after all learn how to write better C code or algorithms. Plus in embedded world it's very usefull specially to adapt some asm code into C program. Probably i will soon adapt __stasm to AVR8 microcontrollers. 167 | 168 | Before __stasm was made i had started to ask myself: Why create external files when i can use #ifdefs for x86, x86-64,ARM and compile single C file without so much files? Why i should learn linker nameing conventions, line by line modifying __calling conventions? Let C compiler do this for me magically. I wanted GNU to bring my asm{} simplicity and freedom! But instead of that GNU guys makes the oposite. I know why - this is much more universal, faster, better. But however it is I have decided that I will never, ever, learn GCC dumb inline assembly. No other human should. I Hate GCC since my first attempt in WinAVR. It was awful experience. Actually GCC style had destroyed Atmel Studio and Embarcadero RAD's 169 | 170 | Hopefully Clang has experimental support for asm {} so.. there is a hope i wont be forced to it anymore. I know there are "+r","r" faster better ways.. But it's not intuitive as it could be. BCC32 is very old, Pelles C is only C compiler.. Clang is not working well with Qt Creator, Windows SDK with MSVC Windows SDK is Windows only so.. __stasm was the only way to focus on different aspects of code than fighting against AT&T. Rather than hateres. 171 | 172 | ## Here it is, as it is. 173 | 174 | Maybe you could make it better, so give me a sign. 175 | I don't know what im done wrong with vars(actually "dim" i wil change that in .cpp further). 176 | It worked like a charm but suddenly i have make some mistake? Sadly it was before GIT repo created 177 | Help me if you can to bring it back. 178 | Cheers. 179 | 180 | #License 181 | 182 | Just as Linus Torvalds does i think GPL3 license is wrong, but GPL2 is problematic also, public could be best but i want to be forgeted as an original author of this concepr. The copyright license for __stasm is Berkley Standard Distribution clause 2 license: 183 | 184 | ~~~{.txt} 185 | Copyright (c) 2015, Stanisław Stasiak 186 | sstsoft.pl 187 | All rights reserved. 188 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 189 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 190 | 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. 191 | 192 | 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 COPYRIGHT HOLDER 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. 193 | ~~~ 194 | 195 | Write me an github message if you liked it. ;) 196 | Feel free to commit. 197 | You should also check my incbin repo.. another trick (not mine concept) in this case GAS can be very is usefull :) 198 | -------------------------------------------------------------------------------- /stk_stasm.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | #ifndef __stk_stasm_h__ 3 | #define __stk_stasm_h__ 4 | #pragma once 5 | //--------------------------------------------------------------------------- 6 | #include "./../stk_main.h" 7 | //--------------------------------------------------------------------------- 8 | //If you don't want stasm warnings uncomment this define: 9 | //#define __STASM_DO_NOT_WARN__ 10 | //Define your CPU cache if it's non convencional. 11 | #ifndef __STASM_CPU_CACHE_LINE_SIZE 12 | #define __STASM_CPU_CACHE_LINE_SIZE 64 13 | #endif 14 | //--------------------------------------------------------------------------- 15 | //Define your favorite syntax and size of CPU cache if it's non convencional. 16 | #ifndef __STASM_INLINE_SYNTAX 17 | #define __STASM_INLINE_SYNTAX "\n.intel_syntax noprefix\n" 18 | #endif 19 | //--------------------------------------------------------------------------- 20 | // Be careful specialy with recurence and potential deadlock(barier) using threads! 21 | // I think nothing bad will happen if there would not be more than 12 calls & function in where first called copy is waiting for 13 copy to end... 22 | // Otherwise 33 would wait for first 32 to relese semaphore and 32 would be waiting for 33 up to infinity.. 23 | // When called functions uses __stasm are independent to each other there will be "only" barier for another one. 24 | // Then nothing bad would happen, and can be even milions of them in pararell but only 32 would start execution at the same time. 25 | // Sometimes this limit could be even usefull i think? Your fork bomb would not choke OS? :) 26 | #ifndef __STASM_MAX_PARARELL 27 | #define __STASM_MAX_PARARELL 64 28 | #endif 29 | //--------------------------------------------------------------------------- 30 | // TODO: __STASM_STACK_SIZE AUTO determined to be exacly number of MMX,SSE,SSE2,SSE3,SSE4,AVX registers count on processor 31 | // It means how many registers mine data exchange structure (between GCC and GAS) will fit. Ex. 8 on x86 means 16xEAX's = 64B 32 | // Or 8xMMX = 64B to be exact one cache line. 33 | #ifndef __STASM_STACK_SIZE 34 | #if defined(__x86_64__) 35 | #define __STASM_STACK_SIZE 8 // 8x = 8 bytes 64 bit = 64 bytes a cache line on most x86-64 CPU's 36 | #else 37 | #define __STASM_STACK_SIZE 16 // 16x = 4 bytes 32 bit = 64 bytes a cache line on most CPUs 38 | #endif 39 | #endif 40 | //--------------------------------------------------------------------------- 41 | // Put some warnings to compiler, depending what compiler you use currently. If you use multiple ones, you would be able to detect wherever STASM was/should be called 42 | // If not, warnings reminds you to review code and hide __stasm() blocks conditionaly to replace with something else. 43 | #if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__MSVC__) || defined(__POCC__) 44 | 45 | #if !defined(asm) && !defined(asm_warned) 46 | #define asm_warned 47 | #pragma message("NOTE: This compiler doesn't support GCC asm(\"\":::) any inline asembler, directive ::asm(variable_name) will expand to nothing") 48 | #endif 49 | #if !defined(__attribute__) && !defined(attribute_warned) 50 | #define attribute_warned 51 | #pragma message("NOTE: This compiler doesnt support GCC __attribute__() macro, you must use different data packing directives, will expand to nothing") 52 | #endif 53 | #ifndef __attribute__ 54 | #define __attribute__(var) 55 | #endif 56 | #ifndef asm 57 | #define asm(var) 58 | #endif 59 | #ifndef __asm__ 60 | #define __asm__(var) 61 | #endif 62 | #ifndef volatile 63 | #define volatile(var) 64 | #endif 65 | #ifndef __volatile__ 66 | #define __volatile__(var) 67 | #endif 68 | // It's possible to direct convert stasm into inline assembler builtin MS, Borland, Pelees C Compiler Collection 69 | // Because why to even use STASM then? 70 | // So let's do this! 71 | #define __stasm(var) __asm { var } 72 | #define stasm(var) __asm { var } 73 | // TODO: the only problem, for direct conversion are codewords passed to stasm macro: "code,save,x86,mmx" so on so forth.. 74 | // Those will be missing! 75 | // But don't worry too much, got you covered, will let all other asm's("") to be converted into nothing 76 | // Borland and MSVC will do conversion of local variables automatically, chances are, all statically created variables will be available in asm {} anyway! 77 | //--------------------------------------------------------------------------- 78 | // This is what inspired me to make stasm at first place: 79 | // BTW: VARGS for older C99 compiler are defined here, could be usefull in WATCOM, GCC2(HaikuOS) or Borland compiler. 80 | // If you use modern MSVC, LLVM, GCC compiler this part is not for you. 81 | //--------------------------------------------------------------------------- 82 | /* Borland C++ compiler */ 83 | #if defined(__BORLANDC__) 84 | 85 | //--------------------------------------------------------------------------- 86 | /* OpenWatcom C++ compiler */ 87 | #elif defined(__WATCOMC__) 88 | 89 | //--------------------------------------------------------------------------- 90 | /* Microsoft C/C++-compatible compiler */ 91 | #elif defined(__MSVC__) 92 | 93 | //--------------------------------------------------------------------------- 94 | /* All other compilers with no __VA_ARGS__ support, lets make this feature anyway */ 95 | #else 96 | #define VA_ARGS_EVAL(_1, _2, _3, _4, _5, N, ...) N 97 | #define VA_ARGS(...) VA_ARGS_EVAL(__VA_ARGS__, 5, 4, 3, 2, 1) 98 | 99 | #define IF_ELVIS_EVAL_HELPER(count, ...) IF_ELVIS_##count(__VA_ARGS__) 100 | #define IF_ELVIS_EVAL(count, ...) IF_ELVIS_EVAL_HELPER(count, __VA_ARGS__) 101 | #define IF_ELVIS(...) IF_ELVIS_EVAL(VA_ARGS(__VA_ARGS__), __VA_ARGS__) 102 | #define IF_ELVIS_1(__a) if (__a!=NULL)) 103 | #define IF_ELVIS_2(__a,__b) if (__a!=NULL) if (__a.__b!=NULL) 104 | #define IF_ELVIS_3(__a,__b,__c) if ((a!=NULL ? a.b!= NULL : false) ? a.b.c!=NULL : false) 105 | #define IF_ELVIS_4(__a,__b,__c,__d) if (((a!=NULL ? a.b!= NULL : false) ? a.b.c!=NULL : false) ? a.b.c.d!=NULL : false) 106 | #define IF_ELVIS_5(__a,__b,__c,__d,__e) if ((((a!=NULL ? a.b!= NULL : false) ? a.b.c!=NULL : false) ? a.b.c.d!=NULL : false) ? a.b.c.d.e!=NULL : false) 107 | #endif 108 | // BEGIN, START Here is main part of library, for compilers doesnt not support asm {} 109 | // 110 | #elif defined (__GNUC__) || defined(__MINGW__) || defined(__CLANG__) || defined(__llvm__) 111 | // ************************************************************************** 112 | // 113 | // HERE IS WHERE IT ALL BEGINS; FOR GCC, CLANG 114 | // 115 | // ************************************************************************** 116 | 117 | extern int __stdcall _asm(const char *, ...); 118 | 119 | //#pragma GCC system_header 120 | //#pragma GCC diagnostic ignored "-Wno-variadic-macros" 121 | //#pragma GCC diagnostic ignored "-Wpedantic" 122 | #pragma GCC diagnostic push 123 | #if defined(__CLANG__) || defined(__llvm__) 124 | #pragma clang diagnostic push 125 | #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 126 | #endif 127 | #if defined(__x86_64__) 128 | /* GCC-compatible compiler, targeting x86/x86-64 */ 129 | #endif 130 | #if defined(__ARM_NEON__) 131 | /* GCC-compatible compiler, targeting ARM with NEON */ 132 | #include 133 | #endif 134 | #if defined(__IWMMXT__) 135 | /* GCC-compatible compiler, targeting ARM with WMMX */ 136 | #include 137 | #endif 138 | #if defined(__xlC__) && (defined(__VEC__) || defined(__ALTIVEC__)) 139 | /* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */ 140 | #include 141 | #endif 142 | #if defined(__SPE__) 143 | /* GCC-compatible compiler, targeting PowerPC with SPE */ 144 | #include 145 | #endif 146 | // Depending on GCC/GAS command line switches, fix GCC/GAS BUG's of copy pasting asm("") blocks in different syntax than chosen by command line 147 | #ifdef __INLINE_INTEL__ 148 | #define __GCC_INLINE_SYNTAX "\n.intel_syntax noprefix\n" 149 | #else 150 | #define __GCC_INLINE_SYNTAX "\n.att_syntax\n" 151 | #endif 152 | //--------------------------------------------------------------------------- 153 | // Typical typedefs for SAVE(PUSH/POP) structures and includes for FPU & SIMD extensions 154 | // FPU x87 template for typedef 155 | //--------------------------------------------------------------------------- 156 | #pragma pack(push, 1) 157 | #define __STASM_TEMPLATE_FNSAVE_X87 \ 158 | uint16_t FCW; /* Control Word */ \ 159 | uint16_t reserved1; \ 160 | uint16_t FSW; /* Status Word */ \ 161 | uint16_t reserved2; \ 162 | uint16_t FTW; /* TAG Word */ \ 163 | uint16_t reserved3; \ 164 | union { \ 165 | /*64 BIT */ \ 166 | struct { \ 167 | uint64_t RIP; /* Instruction Pointer */ \ 168 | uint64_t RDP; /* Data Pointer */ \ 169 | }; \ 170 | /*32 BIT */ \ 171 | struct { \ 172 | uint32_t FIP; /* IP Offset */ \ 173 | uint16_t FCS; /* IP Selector */ \ 174 | uint16_t FOP; /* Last Opcode */ \ 175 | uint32_t FDP; /* Operand Offset */ \ 176 | uint16_t FDS; /* Operand Selector */ \ 177 | }; \ 178 | }; 179 | //--------------------------------------------------------------------------- 180 | // FPU x87 STK_IMPEXP 181 | //--------------------------------------------------------------------------- 182 | struct __STASM_STRUCT_STX_MMX { 183 | uint64_t VAL; 184 | uint16_t EXP; 185 | }; 186 | extern STK_IMPEXP struct __STASM_STRUCT_FNSAVE { 187 | __STASM_TEMPLATE_FNSAVE_X87 188 | struct __STASM_STRUCT_STX_MMX 189 | ST0,ST1,ST2,ST3,ST4,ST5,ST6,ST7; 190 | } __attribute__((packed,aligned (16))) __stasm_fnsave[__STASM_MAX_PARARELL+1]; 191 | //--------------------------------------------------------------------------- 192 | // SSE typedef template 193 | //--------------------------------------------------------------------------- 194 | struct __STASM_STRUCT_XMM { 195 | union { 196 | uint8_t B[16]; /* perfect for ASCII */ 197 | uint16_t W[8]; /* UTF16 */ 198 | uint32_t I[4]; float F[4]; /* 3D Vector */ 199 | uint64_t Q[2]; /* 2 MMX */ 200 | double D[2]; 201 | }; 202 | }; 203 | #define __STASM_TEMPLATE_FXSAVE_SSE \ 204 | uint16_t FCW; /* Control Word */ \ 205 | uint16_t FSW; /* Status Word */ \ 206 | uint16_t FTW; /* TAG Word */ \ 207 | uint16_t FOP; /* Last Opcode */ \ 208 | union { \ 209 | struct { /*64 BIT */ \ 210 | uint64_t RIP; /* Instruction Pointer */ \ 211 | uint64_t RDP; /* Data Pointer */ \ 212 | }; \ 213 | struct { /*32 BIT */ \ 214 | uint32_t FIP; /* IP Offset */ \ 215 | uint16_t FCS; /* IP Selector */ \ 216 | uint16_t reserved1; \ 217 | uint32_t FDP; /* Operand Offset */ \ 218 | uint16_t FDS; /* Operand Selector */ \ 219 | uint16_t reserved2; \ 220 | }; \ 221 | }; \ 222 | uint32_t MXCR; /* SSE status */ \ 223 | uint32_t MXCR_MASK; \ 224 | struct __STASM_STRUCT_STX_MMX \ 225 | ST0,ST1,ST2,ST3,ST4,ST5,ST6,ST7; \ 226 | struct __STASM_STRUCT_XMM \ 227 | XMM0,XMM1,XMM2,XMM3,XMM4,XMM5,XMM6,XMM7, \ 228 | XMM8,XMM9,XMM10,XMM11,XMM12,XMM13,XMM14,XMM15; \ 229 | /* FILL UNUSED 4kB RESERVED */ \ 230 | uint32_t reserved3[(464 - 416) / sizeof(uint32_t)]; \ 231 | /* FILL UNUSED 4kB */ \ 232 | uint32_t user[(512 - 464) / sizeof(uint32_t)]; 233 | //--------------------------------------------------------------------------- 234 | // SSE STK_IMPEXP 235 | //--------------------------------------------------------------------------- 236 | extern STK_IMPEXP struct __STASM_STRUCT_FXSAVE { 237 | __STASM_TEMPLATE_FXSAVE_SSE 238 | } __attribute__((packed,aligned (16))) __stasm_fxsave[__STASM_MAX_PARARELL+1]; 239 | //--------------------------------------------------------------------------- 240 | // AVX STK_IMPEXP 241 | //--------------------------------------------------------------------------- 242 | extern STK_IMPEXP struct __STASM_STRUCT_XSAVE { 243 | __STASM_TEMPLATE_FXSAVE_SSE 244 | union { 245 | uint64_t PAD[64]; /* align 64 */ 246 | struct { 247 | uint64_t XSTATE_BV; 248 | uint64_t XSTATE_COMP_BV; 249 | uint64_t RESERVED[6]; 250 | } __attribute__((packed)) HDR; 251 | }; 252 | struct __YMM { 253 | union { 254 | uint8_t BYTE[16]; /* perfect for ASCII */ 255 | uint16_t W[8]; /* UTF16 */ 256 | uint32_t I[4]; float F[4]; /* 3D Vector */ 257 | uint64_t Q[2]; /* 2 MMX */ 258 | double D[2]; 259 | }; 260 | } YMM0,YMM1,YMM2,YMM3,YMM4,YMM5,YMM6,YMM7,YMM8,YMM9,YMM10,YMM11,YMM12,YMM13,YMM14,YMM15; 261 | struct __ZMML { 262 | uint8_t BYTE[32]; // 256 bit 263 | } __attribute__((packed)) ZMML[16]; 264 | struct __ZMMH { 265 | uint8_t BYTE[32]; // 256 bit 266 | } __attribute__((packed)) ZMMH[16]; 267 | //uint8_t reserved5[8192 - 512 - 64 - 32*32 - 32*32]; 268 | } __attribute__ ((packed, aligned (64))) __stasm_xsave[__STASM_MAX_PARARELL+1]; 269 | //--------------------------------------------------------------------------- 270 | // UNIVERSAL stack for common pointer type 271 | // Should be big enought that one of each fits separate cache lines for it's own CPU core! 272 | //--------------------------------------------------------------------------- 273 | extern STK_IMPEXP size_t __stasm_stack[__STASM_STACK_SIZE] __attribute__ ((aligned (sizeof(size_t)))); 274 | //--------------------------------------------------------------------------- 275 | #pragma pack(pop) 276 | //--------------------------------------------------------------------------- 277 | #define __STASM_SHARE_STACK_CLEAR(mode_name, data_type) \ 278 | for (uint32_t __stasm_##mode_name##_thread = 0;__stasm_##mode_name##_thread <=__STASM_MAX_PARARELL;__stasm_##mode_name##_t++) \ 279 | for (uint32_t __stasm_##mode_name##_i = 0;__stasm_##mode_name##_i < __STASM_STACK_SIZE; __stasm_##mode_name##_c++) \ 280 | __stasm_##mode_name##_stack[__stasm_##mode_name##_thread][__stasm_##mode_name##_i] = 0; 281 | //--------------------------------------------------------------------------- 282 | #define __STASM_SHARE_STACK_DEFINE(mode_name, data_type) \ 283 | extern uint8_t __stasm_##mode_name##_max asm("__stasm_"#mode_name"_max"); \ 284 | extern data_type *__stasm_##mode_name asm("__stasm_"#mode_name); \ 285 | extern data_type (__stasm_##mode_name##_stack)[__STASM_MAX_PARARELL+1][__STASM_STACK_SIZE] asm("__stasm_"#mode_name"_stack") __attribute__ ((aligned (sizeof(data_type)))); 286 | //--------------------------------------------------------------------------- 287 | // For __stdcall, __cdecl, __fastcall for naked C functions: the "code" trigger word, must be defined before "save"! 288 | // Because code also must be placed after "load" block not before it, and it's part of "code" in hidden way for programmer. 289 | // If you want to avoid time consuming process push, pops to be called for all registers use save with care. 290 | //--------------------------------------------------------------------------- 291 | #define __stasm_s_head(prologue,mode,...) prologue __stasm_s_##mode(__VA_ARGS__) 292 | #define __stasm_t_head(prologue,mode,...) __stasm_t_##mode(__VA_ARGS__) 293 | #define __stasm_l_head(prologue,mode,...) __stasm_l_##mode(__VA_ARGS__) 294 | #define __stasm_x_head(prologue,mode,...) __stasm_x_##mode(__VA_ARGS__) 295 | #define __stasm_o_head(prologue,mode,...) __stasm_o_##mode(__VA_ARGS__) 296 | #define __stasm_i_head(prologue,mode,...) __stasm_i_##mode(__VA_ARGS__) 297 | #define __stasm_r_head(prologue,mode,...) __stasm_r_##mode(__VA_ARGS__) 298 | 299 | // NEXT: Obviously stack POP's must be declared in reverse order than prologue PUSHes, therefore epilog it's in X block, 300 | // i/o/r blocks are reseved for GAS clobbers, there is no code there, only variables. 301 | 302 | #define __stasm_s_back(epilog,mode,...) __stasm_s_##mode(__VA_ARGS__) 303 | #define __stasm_t_back(epilog,mode,...) __stasm_t_##mode(__VA_ARGS__) 304 | #define __stasm_l_back(epilog,mode,...) __stasm_l_##mode(__VA_ARGS__) 305 | #define __stasm_x_back(epilog,mode,...) __stasm_x_##mode(__VA_ARGS__) epilog 306 | #define __stasm_o_back(epilog,mode,...) __stasm_o_##mode(__VA_ARGS__) 307 | #define __stasm_i_back(epilog,mode,...) __stasm_i_##mode(__VA_ARGS__) 308 | #define __stasm_r_back(epilog,mode,...) __stasm_r_##mode(__VA_ARGS__) 309 | //--------------------------------------------------------------------------- 310 | // Shared memory piece is defined here only because of macro limitation, without them there would be "," added by preprocessor after variables, 311 | // So I put some text never used as variable in real, just to solve preprocessor limitations. 312 | // It could be used for common, static defined variable for all asm's() blocks(profiling, debug?), there is place for static code and vars in there ;) 313 | // Enable EFLAGS modification to be passed from GAS to GCC ("cc" in block r) ALWAYS! 314 | // It's for safe programming rather super-duper-speed. FLAGS to be always passed to influence C++ code from ASM block. 315 | //--------------------------------------------------------------------------- 316 | #define __stasm_s_code(...) 317 | #define __stasm_t_code(...) #__VA_ARGS__ 318 | #define __stasm_l_code(...) 319 | #define __stasm_x_code(...) 320 | #define __stasm_o_code(...) "=g" (__stasm_stack) 321 | #define __stasm_i_code(...) "g" (__stasm_stack) 322 | #define __stasm_r_code(...) "cc" 323 | //--------------------------------------------------------------------------- 324 | // Macros for var_i special word, predefined as read variable (tell GCC it's to be read so could be even register name) 325 | //--------------------------------------------------------------------------- 326 | #define __stasm_s_var_i(as,varname,mode,...) __stasm_s_##mode(__VA_ARGS__) 327 | #define __stasm_t_var_i(as,varname,mode,...) __stasm_t_##mode(__VA_ARGS__) 328 | #define __stasm_l_var_i(as,varname,mode,...) __stasm_l_##mode(__VA_ARGS__) 329 | #define __stasm_x_var_i(as,varname,mode,...) __stasm_x_##mode(__VA_ARGS__) 330 | #define __stasm_o_var_i(as,varname,mode,...) __stasm_o_##mode(__VA_ARGS__) 331 | #define __stasm_i_var_i(as,varname,mode,...) [varname] as (varname), __stasm_i_##mode(__VA_ARGS__) 332 | #define __stasm_r_var_i(as,varname,mode,...) __stasm_r_##mode(__VA_ARGS__) 333 | //--------------------------------------------------------------------------- 334 | // Macros for var_o special word, predefined as output variable (tell GCC it will be written) 335 | //--------------------------------------------------------------------------- 336 | #define __stasm_s_var_o(as,varname,mode,...) __stasm_s_##mode(__VA_ARGS__) 337 | #define __stasm_t_var_o(as,varname,mode,...) __stasm_t_##mode(__VA_ARGS__) 338 | #define __stasm_l_var_o(as,varname,mode,...) __stasm_l_##mode(__VA_ARGS__) 339 | #define __stasm_x_var_o(as,varname,mode,...) __stasm_x_##mode(__VA_ARGS__) 340 | #define __stasm_o_var_o(as,varname,mode,...) [varname] as (varname), __stasm_o_##mode(__VA_ARGS__) 341 | #define __stasm_i_var_o(as,varname,mode,...) __stasm_i_##mode(__VA_ARGS__) 342 | #define __stasm_r_var_o(as,varname,mode,...) __stasm_r_##mode(__VA_ARGS__) 343 | //--------------------------------------------------------------------------- 344 | // Specify macros for var_c special word, const value(must be #defined with same name in C): 345 | //--------------------------------------------------------------------------- 346 | #define __stasm_s_var_c(constname,mode,...) __stasm_s_##mode(__VA_ARGS__) 347 | #define __stasm_t_var_c(constname,mode,...) __stasm_t_##mode(__VA_ARGS__) 348 | #define __stasm_l_var_c(constname,mode,...) __stasm_l_##mode(__VA_ARGS__) 349 | #define __stasm_x_var_c(constname,mode,...) __stasm_x_##mode(__VA_ARGS__) 350 | #define __stasm_o_var_c(constname,mode,...) __stasm_o_##mode(__VA_ARGS__) 351 | #define __stasm_i_var_c(constname,mode,...) [constname] "n" (constname), __stasm_i_##mode(__VA_ARGS__) 352 | #define __stasm_r_var_c(constname,mode,...) __stasm_r_##mode(__VA_ARGS__) 353 | //--------------------------------------------------------------------------- 354 | // Specify any read-write variable(lvalue) in single definition: 355 | //--------------------------------------------------------------------------- 356 | #define __stasm_s_var(as,varname,mode,...) __stasm_s_##mode(__VA_ARGS__) 357 | #define __stasm_t_var(as,varname,mode,...) __stasm_t_##mode(__VA_ARGS__) 358 | #define __stasm_l_var(as,varname,mode,...) __stasm_l_##mode(__VA_ARGS__) 359 | #define __stasm_x_var(as,varname,mode,...) __stasm_x_##mode(__VA_ARGS__) 360 | #define __stasm_o_var(as,varname,mode,...) [varname] as (varname), __stasm_o_##mode(__VA_ARGS__) 361 | #define __stasm_i_var(as,varname,mode,...) "0" (varname), __stasm_i_##mode(__VA_ARGS__) 362 | #define __stasm_r_var(as,varname,mode,...) __stasm_r_##mode(__VA_ARGS__) 363 | //--------------------------------------------------------------------------- 364 | // Place for other simmilar macros "special word" ex. var_m, var_p etc. 365 | // I will make i hope with name simmilar to GAS/GCC inline asembler manual for variable types 366 | //--------------------------------------------------------------------------- 367 | // "tell" could be implemented for any processor x86, ARM, PowerPC so you could write eax,ebx,ecx without save stack or use special data structures for exchange it's values 368 | // You could use word "tell" and register name after for all unknown to stasm register names 369 | // This could be usefull for unknown platform(PowerPC, MIPS etc.) could be only way __stasm to access GCC clobbers 370 | // Its the safer way that guarantee thread savety, recurence safety, maybe i shoud change default option to something like "static" "exchange"? 371 | //--------------------------------------------------------------------------- 372 | #define __stasm_s_tell(reg,mode,...) __stasm_s_##mode(__VA_ARGS__) 373 | #define __stasm_t_tell(reg,mode,...) __stasm_t_##mode(__VA_ARGS__) 374 | #define __stasm_l_tell(reg,mode,...) __stasm_l_##mode(__VA_ARGS__) 375 | #define __stasm_x_tell(reg,mode,...) __stasm_x_##mode(__VA_ARGS__) 376 | #define __stasm_o_tell(reg,mode,...) __stasm_o_##mode(__VA_ARGS__) 377 | #define __stasm_i_tell(reg,mode,...) __stasm_i_##mode(__VA_ARGS__) 378 | #define __stasm_r_tell(reg,mode,...) #reg, __stasm_r_##mode(__VA_ARGS__) 379 | //--------------------------------------------------------------------------- 380 | // Save registers ex, on stack, save fpu state, save mmx state and pop it out at end 381 | // Invoke push command automatically 382 | //--------------------------------------------------------------------------- 383 | #define __stasm_s_save(what,mode,...) __stasm_save_##what(__VA_ARGS__) "\n" __stasm_s_##mode(__VA_ARGS__) 384 | #define __stasm_t_save(what,mode,...) __stasm_t_##mode(__VA_ARGS__) 385 | //--------------------------------------------------------------------------- 386 | // Auto invoke pop but, keep in mind that it must be in reverse order than push 387 | //--------------------------------------------------------------------------- 388 | #define __stasm_l_save(what,mode,...) __stasm_l_##mode(__VA_ARGS__) "\n" __stasm_load_##what(__VA_ARGS__) 389 | #define __stasm_x_save(what,mode,...) __stasm_x_##mode(__VA_ARGS__) 390 | #define __stasm_o_save(what,mode,...) __stasm_o_##mode(__VA_ARGS__) 391 | #define __stasm_i_save(what,mode,...) __stasm_i_##mode(__VA_ARGS__) 392 | #define __stasm_r_save(what,mode,...) __stasm_r_##mode(__VA_ARGS__) 393 | 394 | //--------------------------------------------------------------------------- 395 | 396 | #ifdef __ARM__ 397 | // Actually not fully implemented, should i put r0-r7 registers on the stack? ;) 398 | // or even more? 399 | // Because of stupid GCC inline assembly in WinAPR, Atmel Studio i had never ever wanted to learn ARM 400 | #define __stasm_save_arm "push ???\n" 401 | #define __stasm_load_arm "push ???\n" 402 | 403 | __STASM_SHARE_STACK_DEFINE(arm,uint32_t) 404 | #define __TINIT_ARM(mode,...) \ 405 | __stasm_arm_max = __STASM_MAX_PARARELL; \ 406 | __stasm_arm = __stasm_arm_stack[__stasm_arm_max]; \ 407 | __TINITSTACK(arm) \ 408 | __TINIT_##mode(__VA_ARGS__) 409 | //--------------------------------------------------------------------------- 410 | #define __stasm_s_arm(mode,...) \ 411 | __stasm_s_##mode(__VA_ARGS__) 412 | #define __stasm_t_arm(mode,...) \ 413 | __stasm_t_##mode(__VA_ARGS__) 414 | #define __stasm_l_arm(mode,...) \ 415 | __stasm_l_##mode(__VA_ARGS__) 416 | #define __stasm_x_arm(mode,...) \ 417 | __stasm_x_##mode(__VA_ARGS__) 418 | #define __stasm_o_arm(mode,...) \ 419 | __stasm_o_##mode(__VA_ARGS__) 420 | #define __stasm_i_arm(mode,...) \ 421 | __stasm_i_##mode(__VA_ARGS__) 422 | #define __stasm_r_arm(mode,...) \ 423 | "r0","r1","r2","r3","r4","r5","r6","r7", \ 424 | __stasm_r_##mode(__VA_ARGS__) 425 | 426 | #endif 427 | //--------------------------------------------------------------------------- 428 | // Adapters for macros and real asembly code 429 | //--------------------------------------------------------------------------- 430 | #if defined(__x86_64__) | defined(__i386__) 431 | #define __stasm_save_eax "push eax\n" 432 | #define __stasm_save_ebx "push ebx\n" 433 | #define __stasm_save_ecx "push ecx\n" 434 | #define __stasm_save_edx "push edx\n" 435 | #define __stasm_save_esi "push esi\n" 436 | #define __stasm_save_edi "push edi\n" 437 | #define __stasm_save_x86 __stasm_save_eax\ 438 | __stasm_save_ebx\ 439 | __stasm_save_ecx\ 440 | __stasm_save_edx\ 441 | __stasm_save_esi\ 442 | __stasm_save_edi 443 | #define __stasm_save_x87 "fsave _m_fsaved\n" 444 | #define __stasm_save_rax "push rax\n" 445 | #define __stasm_save_rbx "push rbx\n" 446 | #define __stasm_save_rcx "push rcx\n" 447 | #define __stasm_save_rdx "push rdx\n" 448 | #define __stasm_save_rsi "push rsi\n" 449 | #define __stasm_save_rdi "push rdi\n" 450 | #define __stasm_save_x64r8 "push r8\n\n" 451 | #define __stasm_save_x64r9 "push r9\n" 452 | #define __stasm_save_x64rxx "push r10\n push r11\n push r12\n push r13\n push r14\n push r15\n" 453 | #define __stasm_save_x64 __stasm_save_rax\ 454 | __stasm_save_rbx\ 455 | __stasm_save_rcx\ 456 | __stasm_save_rdx\ 457 | __stasm_save_rsi\ 458 | __stasm_save_rdi\ 459 | __stasm_save_x64r8 __stasm_save_x64r9 __stasm_save_x64rxx 460 | #define __stasm_save_mmx "fxsave _m_fxsaved\n" 461 | #define __stasm_save_sse "fxsave _m_fxsaved\n" 462 | #define __stasm_save_avx "xsave _m_axsaved\n" 463 | 464 | // **********//*********** 465 | 466 | #define __stasm_load_eax "pop eax\n" 467 | #define __stasm_load_ebx "pop ebx\n" 468 | #define __stasm_load_ecx "pop ecx\n" 469 | #define __stasm_load_edx "pop edx\n" 470 | #define __stasm_load_esi "pop esi\n" 471 | #define __stasm_load_edi "pop edi\n" 472 | #define __stasm_load_x86 __stasm_save_edi\ 473 | __stasm_save_esi\ 474 | __stasm_save_edx\ 475 | __stasm_save_ecx\ 476 | __stasm_save_ebx\ 477 | __stasm_save_eax 478 | #define __stasm_load_x87 "frstor _m_fsaved\n" 479 | #define __stasm_load_rax "pop rax\n" 480 | #define __stasm_load_rbx "pop rbx\n" 481 | #define __stasm_load_rcx "pop rcx\n" 482 | #define __stasm_load_rdx "pop rdx\n" 483 | #define __stasm_load_rsi "pop rsi\n" 484 | #define __stasm_load_rdi "pop rdi\n" 485 | #define __stasm_load_x64r8 "pop r8\n" 486 | #define __stasm_load_x64r9 "pop r9\n" 487 | #define __stasm_load_x64rxx "pop r15\n push r14\n push r13\n push r12\n push r11\n push r10\n" 488 | #define __stasm_load_x64 __stasm_save_x64rxx __stasm_save_x64r9 __stasm_save_x64r8\ 489 | __stasm_save_rdi\ 490 | __stasm_save_rsi\ 491 | __stasm_save_rdx\ 492 | __stasm_save_rcx\ 493 | __stasm_save_rbx\ 494 | __stasm_save_rax 495 | #define __stasm_load_mmx "fxrstor _m_fxsaved\n" 496 | #define __stasm_load_sse "fxrstor _m_fxsaved\n" 497 | #define __stasm_load_avx "xrstor _m_axsaved\n" 498 | //--------------------------------------------------------------------------- 499 | __STASM_SHARE_STACK_DEFINE(x86,uint32_t) 500 | #define __TINIT_x86(mode,...) \ 501 | __stasm_x86_max = __STASM_MAX_PARARELL; \ 502 | __stasm_x86 = __stasm_x86_stack[__stasm_x86_max]; \ 503 | __STASM_SHARE_STACK_CLEAR(x86,uint32_t) \ 504 | __TINIT_##mode(__VA_ARGS__) 505 | //--------------------------------------------------------------------------- 506 | #define __stasm_s_x86(mode,...) \ 507 | __stasm_s_##mode(__VA_ARGS__) 508 | #define __stasm_t_x86(mode,...) \ 509 | __stasm_t_##mode(__VA_ARGS__) 510 | #define __stasm_l_x86(mode,...) \ 511 | __stasm_l_##mode(__VA_ARGS__) 512 | #define __stasm_x_x86(mode,...) \ 513 | __stasm_x_##mode(__VA_ARGS__) 514 | #define __stasm_o_x86(mode,...) \ 515 | __stasm_o_##mode(__VA_ARGS__) 516 | #define __stasm_i_x86(mode,...) \ 517 | __stasm_i_##mode(__VA_ARGS__) 518 | #define __stasm_r_x86(mode,...) \ 519 | "eax", "ebx", "ecx", "edx", "esi", "edi", \ 520 | __stasm_r_##mode(__VA_ARGS__) 521 | //--------------------------------------------------------------------------- 522 | __STASM_SHARE_STACK_DEFINE(eax,uint32_t) 523 | #define __TINIT_eax(mode,...) \ 524 | __stasm_eax_max = __STASM_MAX_PARARELL; \ 525 | __stasm_eax = __stasm_eax_stack[__stasm_eax_max]; \ 526 | __STASM_SHARE_STACK_CLEAR(eax,uint32_t) \ 527 | __TINIT_##mode(__VA_ARGS__) 528 | //--------------------------------------------------------------------------- 529 | #define __stasm_s_eax(mode,...) \ 530 | __stasm_s_##mode(__VA_ARGS__) 531 | #define __stasm_t_eax(mode,...) \ 532 | __stasm_t_##mode(__VA_ARGS__) 533 | #define __stasm_l_eax(mode,...) \ 534 | __stasm_l_##mode(__VA_ARGS__) 535 | #define __stasm_x_eax(mode,...) \ 536 | __stasm_x_##mode(__VA_ARGS__) 537 | #define __stasm_o_eax(mode,...) \ 538 | __stasm_o_##mode(__VA_ARGS__) 539 | #define __stasm_i_eax(mode,...) \ 540 | __stasm_i_##mode(__VA_ARGS__) 541 | #define __stasm_r_eax(mode,...) \ 542 | "eax", \ 543 | __stasm_r_##mode(__VA_ARGS__) 544 | //--------------------------------------------------------------------------- 545 | __STASM_SHARE_STACK_DEFINE(ebx,uint32_t) 546 | #define __TINIT_ebx(mode,...) \ 547 | __stasm_ebx_max = __STASM_MAX_PARARELL; \ 548 | __stasm_ebx = __stasm_ebx_stack[__stasm_ebx_max]; \ 549 | __STASM_SHARE_STACK_CLEAR(ebx,uint32_t) \ 550 | __TINIT_##mode(__VA_ARGS__) 551 | //--------------------------------------------------------------------------- 552 | #define __stasm_s_ebx(mode,...) \ 553 | __stasm_s_##mode(__VA_ARGS__) 554 | #define __stasm_t_ebx(mode,...) \ 555 | __stasm_t_##mode(__VA_ARGS__) 556 | #define __stasm_l_ebx(mode,...) \ 557 | __stasm_l_##mode(__VA_ARGS__) 558 | #define __stasm_x_ebx(mode,...) \ 559 | __stasm_x_##mode(__VA_ARGS__) 560 | #define __stasm_o_ebx(mode,...) \ 561 | __stasm_o_##mode(__VA_ARGS__) 562 | #define __stasm_i_ebx(mode,...) \ 563 | __stasm_i_##mode(__VA_ARGS__) 564 | #define __stasm_r_ebx(mode,...) \ 565 | "ebx", \ 566 | __stasm_r_##mode(__VA_ARGS__) 567 | //--------------------------------------------------------------------------- 568 | __STASM_SHARE_STACK_DEFINE(ecx,uint32_t) 569 | #define __TINIT_ecx(mode,...) \ 570 | __stasm_ecx_max = __STASM_MAX_PARARELL; \ 571 | __stasm_ecx = __stasm_ecx_stack[__stasm_ecx_max]; \ 572 | __STASM_SHARE_STACK_CLEAR(ecx,uint32_t) \ 573 | __TINIT_##mode(__VA_ARGS__) 574 | //--------------------------------------------------------------------------- 575 | #define __stasm_s_ecx(mode,...) \ 576 | __stasm_s_##mode(__VA_ARGS__) 577 | #define __stasm_t_ecx(mode,...) \ 578 | __stasm_t_##mode(__VA_ARGS__) 579 | #define __stasm_l_ecx(mode,...) \ 580 | __stasm_l_##mode(__VA_ARGS__) 581 | #define __stasm_x_ecx(mode,...) \ 582 | __stasm_x_##mode(__VA_ARGS__) 583 | #define __stasm_o_ecx(mode,...) \ 584 | __stasm_o_##mode(__VA_ARGS__) 585 | #define __stasm_i_ecx(mode,...) \ 586 | __stasm_i_##mode(__VA_ARGS__) 587 | #define __stasm_r_ecx(mode,...) \ 588 | "ecx", \ 589 | __stasm_r_##mode(__VA_ARGS__) 590 | //--------------------------------------------------------------------------- 591 | __STASM_SHARE_STACK_DEFINE(edx,uint32_t) 592 | #define __TINIT_edx(mode,...) \ 593 | __stasm_edx_max = __STASM_MAX_PARARELL; \ 594 | __stasm_edx = __stasm_edx_stack[__stasm_edx_max]; \ 595 | __STASM_SHARE_STACK_CLEAR(edx,uint32_t) \ 596 | __TINIT_##mode(__VA_ARGS__) 597 | //--------------------------------------------------------------------------- 598 | #define __stasm_s_edx(mode,...) \ 599 | __stasm_s_##mode(__VA_ARGS__) 600 | #define __stasm_t_edx(mode,...) \ 601 | __stasm_t_##mode(__VA_ARGS__) 602 | #define __stasm_l_edx(mode,...) \ 603 | __stasm_l_##mode(__VA_ARGS__) 604 | #define __stasm_x_edx(mode,...) \ 605 | __stasm_x_##mode(__VA_ARGS__) 606 | #define __stasm_o_edx(mode,...) \ 607 | __stasm_o_##mode(__VA_ARGS__) 608 | #define __stasm_i_edx(mode,...) \ 609 | __stasm_i_##mode(__VA_ARGS__) 610 | #define __stasm_r_edx(mode,...) \ 611 | "edx", \ 612 | __stasm_r_##mode(__VA_ARGS__) 613 | //--------------------------------------------------------------------------- 614 | __STASM_SHARE_STACK_DEFINE(esi,uint32_t) 615 | //--------------------------------------------------------------------------- 616 | #define __TINIT_esi(mode,...) \ 617 | __stasm_esi_max = __STASM_MAX_PARARELL; \ 618 | __stasm_esi = __stasm_esi_stack[__stasm_esi_max]; \ 619 | __STASM_SHARE_STACK_CLEAR(esi,uint32_t) \ 620 | __TINIT_##mode(__VA_ARGS__) 621 | #define __stasm_s_esi(mode,...) \ 622 | __stasm_s_##mode(__VA_ARGS__) 623 | #define __stasm_t_esi(mode,...) \ 624 | __stasm_t_##mode(__VA_ARGS__) 625 | #define __stasm_l_esi(mode,...) \ 626 | __stasm_l_##mode(__VA_ARGS__) 627 | #define __stasm_x_esi(mode,...) \ 628 | __stasm_x_##mode(__VA_ARGS__) 629 | #define __stasm_o_esi(mode,...) \ 630 | __stasm_o_##mode(__VA_ARGS__) 631 | #define __stasm_i_esi(mode,...) \ 632 | __stasm_i_##mode(__VA_ARGS__) 633 | #define __stasm_r_esi(mode,...) \ 634 | "esi", \ 635 | __stasm_r_##mode(__VA_ARGS__) 636 | //--------------------------------------------------------------------------- 637 | __STASM_SHARE_STACK_DEFINE(edi,uint32_t) 638 | //--------------------------------------------------------------------------- 639 | #define __TINIT_edi(mode,...) \ 640 | __stasm_edi_max = __STASM_MAX_PARARELL; \ 641 | __stasm_edi = __stasm_edi_stack[__stasm_edi_max]; \ 642 | __STASM_SHARE_STACK_CLEAR(edi,uint32_t) \ 643 | __TINIT_##mode(__VA_ARGS__) 644 | //--------------------------------------------------------------------------- 645 | #define __stasm_s_edi(mode,...) \ 646 | __stasm_s_##mode(__VA_ARGS__) 647 | #define __stasm_t_edi(mode,...) \ 648 | __stasm_t_##mode(__VA_ARGS__) 649 | #define __stasm_l_edi(mode,...) \ 650 | __stasm_l_##mode(__VA_ARGS__) 651 | #define __stasm_x_edi(mode,...) \ 652 | __stasm_x_##mode(__VA_ARGS__) 653 | #define __stasm_o_edi(mode,...) \ 654 | __stasm_o_##mode(__VA_ARGS__) 655 | #define __stasm_i_edi(mode,...) \ 656 | __stasm_i_##mode(__VA_ARGS__) 657 | #define __stasm_r_edi(mode,...) \ 658 | "edi", \ 659 | __stasm_r_##mode(__VA_ARGS__) 660 | //--------------------------------------------------------------------------- 661 | __STASM_SHARE_STACK_DEFINE(x87,double) 662 | //--------------------------------------------------------------------------- 663 | #define __TINIT_x87(mode,...) \ 664 | __stasm_x87_max = __STASM_MAX_PARARELL; \ 665 | __stasm_x87 = __stasm_x87_stack[__stasm_x87_max]; \ 666 | __STASM_SHARE_STACK_CLEAR(x87,double) \ 667 | __TINIT_##mode(__VA_ARGS__) 668 | //--------------------------------------------------------------------------- 669 | #define __stasm_s_x87(mode,...) \ 670 | __stasm_s_##mode(__VA_ARGS__) 671 | #define __stasm_t_x87(mode,...) \ 672 | __stasm_t_##mode(__VA_ARGS__) 673 | #define __stasm_l_x87(mode,...) \ 674 | __stasm_l_##mode(__VA_ARGS__) 675 | #define __stasm_x_x87(mode,...) \ 676 | __stasm_x_##mode(__VA_ARGS__) 677 | #define __stasm_o_x87(mode,...) \ 678 | __stasm_o_##mode(__VA_ARGS__) 679 | #define __stasm_i_x87(mode,...) \ 680 | __stasm_i_##mode(__VA_ARGS__) 681 | #define __stasm_r_x87(mode,...) \ 682 | "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", \ 683 | __stasm_r_##mode(__VA_ARGS__) 684 | //--------------------------------------------------------------------------- 685 | // END OF SUBSTANCIAL x86 + x87 686 | //--------------------------------------------------------------------------- 687 | #if defined(__x86_64__) 688 | #if !defined(__STASM_DO_NOT_WARN__) & !defined(x64_warned) 689 | #define x64_warned 690 | #warning "It seems that your CPU has got 64bit, make sure to add compiler option "-m64" to use 64bit mode" 691 | #endif 692 | __STASM_SHARE_STACK_DEFINE(rax,uint64_t) 693 | #define __TINIT_rax(mode,...) \ 694 | __stasm_rax_max = __STASM_MAX_PARARELL; \ 695 | __stasm_rax = __stasm_rax_stack[__stasm_rax_max]; \ 696 | __STASM_SHARE_STACK_CLEAR(rax,uint64_t) \ 697 | __TINIT_##mode(__VA_ARGS__) 698 | //--------------------------------------------------------------------------- 699 | #define __stasm_s_rax(mode,...) \ 700 | __stasm_s_##mode(__VA_ARGS__) 701 | #define __stasm_t_rax(mode,...) \ 702 | __stasm_t_##mode(__VA_ARGS__) 703 | #define __stasm_l_rax(mode,...) \ 704 | __stasm_l_##mode(__VA_ARGS__) 705 | #define __stasm_x_rax(mode,...) \ 706 | __stasm_x_##mode(__VA_ARGS__) 707 | #define __stasm_o_rax(mode,...) \ 708 | __stasm_o_##mode(__VA_ARGS__) 709 | #define __stasm_i_rax(mode,...) \ 710 | __stasm_i_##mode(__VA_ARGS__) 711 | #define __stasm_r_rax(mode,...) \ 712 | "rax", \ 713 | __stasm_r_##mode(__VA_ARGS__) 714 | //--------------------------------------------------------------------------- 715 | __STASM_SHARE_STACK_DEFINE(rbx,uint64_t) 716 | #define __TINIT_rbx(mode,...) \ 717 | __stasm_rbx_max = __STASM_MAX_PARARELL; \ 718 | __stasm_rbx = __stasm_rbx_stack[__stasm_rbx_max]; \ 719 | __STASM_SHARE_STACK_CLEAR(rbx,uint64_t) \ 720 | __TINIT_##mode(__VA_ARGS__) 721 | //--------------------------------------------------------------------------- 722 | #define __stasm_s_rbx(mode,...) \ 723 | __stasm_s_##mode(__VA_ARGS__) 724 | #define __stasm_t_rbx(mode,...) \ 725 | __stasm_t_##mode(__VA_ARGS__) 726 | #define __stasm_l_rbx(mode,...) \ 727 | __stasm_l_##mode(__VA_ARGS__) 728 | #define __stasm_x_rbx(mode,...) \ 729 | __stasm_x_##mode(__VA_ARGS__) 730 | #define __stasm_o_rbx(mode,...) \ 731 | __stasm_o_##mode(__VA_ARGS__) 732 | #define __stasm_i_rbx(mode,...) \ 733 | __stasm_i_##mode(__VA_ARGS__) 734 | #define __stasm_r_rbx(mode,...) \ 735 | "rbx", \ 736 | __stasm_r_##mode(__VA_ARGS__) 737 | //--------------------------------------------------------------------------- 738 | __STASM_SHARE_STACK_DEFINE(rcx,uint64_t) 739 | #define __TINIT_rcx(mode,...) \ 740 | __stasm_rcx_max = __STASM_MAX_PARARELL; \ 741 | __stasm_rcx = __stasm_rcx_stack[__stasm_rcx_max]; \ 742 | __STASM_SHARE_STACK_CLEAR(rcx,uint64_t) \ 743 | __TINIT_##mode(__VA_ARGS__) 744 | //--------------------------------------------------------------------------- 745 | #define __stasm_s_rcx(mode,...) \ 746 | __stasm_s_##mode(__VA_ARGS__) 747 | #define __stasm_t_rcx(mode,...) \ 748 | __stasm_t_##mode(__VA_ARGS__) 749 | #define __stasm_l_rcx(mode,...) \ 750 | __stasm_l_##mode(__VA_ARGS__) 751 | #define __stasm_x_rcx(mode,...) \ 752 | __stasm_x_##mode(__VA_ARGS__) 753 | #define __stasm_o_rcx(mode,...) \ 754 | __stasm_o_##mode(__VA_ARGS__) 755 | #define __stasm_i_rcx(mode,...) \ 756 | __stasm_i_##mode(__VA_ARGS__) 757 | #define __stasm_r_rcx(mode,...) \ 758 | "rcx", \ 759 | __stasm_r_##mode(__VA_ARGS__) 760 | //--------------------------------------------------------------------------- 761 | __STASM_SHARE_STACK_DEFINE(rdx,uint64_t) 762 | #define __TINIT_rdx(mode,...) \ 763 | __stasm_rdx_max = __STASM_MAX_PARARELL; \ 764 | __stasm_rdx = __stasm_rdx_stack[__stasm_rdx_max]; \ 765 | __STASM_SHARE_STACK_CLEAR(rdx,uint64_t) \ 766 | __TINIT_##mode(__VA_ARGS__) 767 | //--------------------------------------------------------------------------- 768 | #define __stasm_s_rdx(mode,...) \ 769 | __stasm_s_##mode(__VA_ARGS__) 770 | #define __stasm_t_rdx(mode,...) \ 771 | __stasm_t_##mode(__VA_ARGS__) 772 | #define __stasm_l_rdx(mode,...) \ 773 | __stasm_l_##mode(__VA_ARGS__) 774 | #define __stasm_x_rdx(mode,...) \ 775 | __stasm_x_##mode(__VA_ARGS__) 776 | #define __stasm_o_rdx(mode,...) \ 777 | __stasm_o_##mode(__VA_ARGS__) 778 | #define __stasm_i_rdx(mode,...) \ 779 | __stasm_i_##mode(__VA_ARGS__) 780 | #define __stasm_r_rdx(mode,...) \ 781 | "rdx", \ 782 | __stasm_r_##mode(__VA_ARGS__) 783 | //--------------------------------------------------------------------------- 784 | __STASM_SHARE_STACK_DEFINE(rsi,uint64_t) 785 | //--------------------------------------------------------------------------- 786 | #define __TINIT_rsi(mode,...) \ 787 | __stasm_rsi_max = __STASM_MAX_PARARELL; \ 788 | __stasm_rsi = __stasm_rsi_stack[__stasm_rsi_max]; \ 789 | __STASM_SHARE_STACK_CLEAR(rsi,uint64_t) \ 790 | __TINIT_##mode(__VA_ARGS__) 791 | #define __stasm_s_rsi(mode,...) \ 792 | __stasm_s_##mode(__VA_ARGS__) 793 | #define __stasm_t_rsi(mode,...) \ 794 | __stasm_t_##mode(__VA_ARGS__) 795 | #define __stasm_l_rsi(mode,...) \ 796 | __stasm_l_##mode(__VA_ARGS__) 797 | #define __stasm_x_rsi(mode,...) \ 798 | __stasm_x_##mode(__VA_ARGS__) 799 | #define __stasm_o_rsi(mode,...) \ 800 | __stasm_o_##mode(__VA_ARGS__) 801 | #define __stasm_i_rsi(mode,...) \ 802 | __stasm_i_##mode(__VA_ARGS__) 803 | #define __stasm_r_rsi(mode,...) \ 804 | "rsi", \ 805 | __stasm_r_##mode(__VA_ARGS__) 806 | //--------------------------------------------------------------------------- 807 | __STASM_SHARE_STACK_DEFINE(rdi,uint64_t) 808 | //--------------------------------------------------------------------------- 809 | #define __TINIT_rdi(mode,...) \ 810 | __stasm_rdi_max = __STASM_MAX_PARARELL; \ 811 | __stasm_rdi = __stasm_rdi_stack[__stasm_rdi_max]; \ 812 | __STASM_SHARE_STACK_CLEAR(rdi,uint64_t) \ 813 | __TINIT_##mode(__VA_ARGS__) 814 | //--------------------------------------------------------------------------- 815 | #define __stasm_s_rdi(mode,...) \ 816 | __stasm_s_##mode(__VA_ARGS__) 817 | #define __stasm_t_rdi(mode,...) \ 818 | __stasm_t_##mode(__VA_ARGS__) 819 | #define __stasm_l_rdi(mode,...) \ 820 | __stasm_l_##mode(__VA_ARGS__) 821 | #define __stasm_x_rdi(mode,...) \ 822 | __stasm_x_##mode(__VA_ARGS__) 823 | #define __stasm_o_rdi(mode,...) \ 824 | __stasm_o_##mode(__VA_ARGS__) 825 | #define __stasm_i_rdi(mode,...) \ 826 | __stasm_i_##mode(__VA_ARGS__) 827 | #define __stasm_r_rdi(mode,...) \ 828 | "rdi", \ 829 | __stasm_r_##mode(__VA_ARGS__) 830 | //--------------------------------------------------------------------------- 831 | __STASM_SHARE_STACK_DEFINE(x64,uint64_t) 832 | //--------------------------------------------------------------------------- 833 | #define __TINIT_x64(mode,...) \ 834 | __stasm_x64 = __STASM_MAX_PARARELL; \ 835 | __stasm_x64 = __stasm_x64_stack[__stasm_x64_max]; \ 836 | __STASM_SHARE_STACK_CLEAR(x64,uint64_t) \ 837 | __TINIT_##mode(__VA_ARGS__) 838 | //--------------------------------------------------------------------------- 839 | #define __stasm_s_x64(mode,...) \ 840 | __stasm_s_##mode(__VA_ARGS__) 841 | #define __stasm_t_x64(mode,...) \ 842 | __stasm_t_##mode(__VA_ARGS__) 843 | #define __stasm_l_x64(mode,...) \ 844 | __stasm_l_##mode(__VA_ARGS__) 845 | #define __stasm_x_x64(mode,...) \ 846 | __stasm_x_##mode(__VA_ARGS__) 847 | #define __stasm_o_x64(mode,...) \ 848 | __stasm_o_##mode(__VA_ARGS__) 849 | #define __stasm_i_x64(mode,...) \ 850 | __stasm_i_##mode(__VA_ARGS__) 851 | #define __stasm_r_x64(mode,...) \ 852 | "rax", "rbx", "rcx", "rdx", "rsi", "rdi", \ 853 | __stasm_r_##mode(__VA_ARGS__) 854 | //--------------------------------------------------------------------------- 855 | __STASM_SHARE_STACK_DEFINE(x64r08,uint64_t) 856 | //--------------------------------------------------------------------------- 857 | #define __TINIT_x64r08(mode,...) \ 858 | __stasm_x64r08_max = __STASM_MAX_PARARELL; \ 859 | __stasm_x64r08 = __stasm_x64r08_stack[__stasm_x64r08_max]; \ 860 | __STASM_SHARE_STACK_CLEAR(x64r08,uint64_t) \ 861 | __TINIT_##mode(__VA_ARGS__) 862 | #define __stasm_s_x64r08(mode,...) `\ 863 | __stasm_s_##mode(__VA_ARGS__) 864 | #define __stasm_t_x64r08(mode,...) `\ 865 | __stasm_t_##mode(__VA_ARGS__) 866 | #define __stasm_l_x64r08(mode,...) `\ 867 | __stasm_l_##mode(__VA_ARGS__) 868 | #define __stasm_x_x64r08(mode,...) `\ 869 | __stasm_x_##mode(__VA_ARGS__) 870 | #define __stasm_o_x64r08(mode,...) `\ 871 | __stasm_o_##mode(__VA_ARGS__) 872 | #define __stasm_i_x64r08(mode,...) `\ 873 | __stasm_i_##mode(__VA_ARGS__) 874 | #define __stasm_r_x64r08(mode,...) `\ 875 | "r8lb","r8hb","r8w","r8d","r8", `\ 876 | __stasm_r_##mode(__VA_ARGS__) 877 | //--------------------------------------------------------------------------- 878 | __STASM_SHARE_STACK_DEFINE(x64r09,uint64_t) 879 | //--------------------------------------------------------------------------- 880 | #define __TINIT_x64r09(mode,...) \ 881 | __stasm_x64r09_max = __STASM_MAX_PARARELL; \ 882 | __stasm_x64r09 = __stasm_x64r09_stack[__stasm_x64r09_max]; \ 883 | __STASM_SHARE_STACK_CLEAR(x64r09,uint64_t) \ 884 | __TINIT_##mode(__VA_ARGS__) 885 | #define __stasm_s_x64r09(mode,...) \ 886 | __stasm_s_##mode(__VA_ARGS__) 887 | #define __stasm_t_x64r09(mode,...) \ 888 | __stasm_t_##mode(__VA_ARGS__) 889 | #define __stasm_l_x64r09(mode,...) \ 890 | __stasm_l_##mode(__VA_ARGS__) 891 | #define __stasm_x_x64r09(mode,...) \ 892 | __stasm_x_##mode(__VA_ARGS__) 893 | #define __stasm_o_x64r09(mode,...) \ 894 | __stasm_o_##mode(__VA_ARGS__) 895 | #define __stasm_i_x64r09(mode,...) \ 896 | __stasm_i_##mode(__VA_ARGS__) 897 | #define __stasm_r_x64r09(mode,...) \ 898 | "r9lb","r9hb","r9w","r9d","r9", \ 899 | __stasm_r_##mode(__VA_ARGS__) 900 | //--------------------------------------------------------------------------- 901 | __STASM_SHARE_STACK_DEFINE(x64rxx,uint64_t) 902 | //--------------------------------------------------------------------------- 903 | #define __TINIT_x64rxx(mode,...) \ 904 | __stasm_x64rxx_max = __STASM_MAX_PARARELL; \ 905 | __stasm_x64rxx = __stasm_x64rx_stack[__stasm_x64xx_max]; \ 906 | __STASM_SHARE_STACK_CLEAR(x64rxx,uint64_t) \ 907 | __TINIT_##mode(__VA_ARGS__) 908 | #define __stasm_s_x64rxx(mode,...) \ 909 | __stasm_s_##mode(__VA_ARGS__) 910 | #define __stasm_t_x64rxx(mode,...) \ 911 | __stasm_t_##mode(__VA_ARGS__) 912 | #define __stasm_l_x64rxx(mode,...) \ 913 | __stasm_l_##mode(__VA_ARGS__) 914 | #define __stasm_x_x64rxx(mode,...) \ 915 | __stasm_x_##mode(__VA_ARGS__) 916 | #define __stasm_o_x64rxx(mode,...) \ 917 | __stasm_o_##mode(__VA_ARGS__) 918 | #define __stasm_i_x64rxx(mode,...) \ 919 | __stasm_i_##mode(__VA_ARGS__) 920 | #define __stasm_r_x64rxx(mode,...) \ 921 | "r10lb","r10hb","r10w","r10d","r10", \ 922 | "r11lb","r11hb","r11w","r11d","r11", \ 923 | "r12lb","r12hb","r12w","r12d","r12", \ 924 | "r13lb","r13hb","r13w","r13d","r13", \ 925 | "r14lb","r14hb","r14w","r14d","r14", \ 926 | "r15lb","r15hb","r15w","r15d","r15", \ 927 | __stasm_r_##mode(__VA_ARGS__) 928 | #endif 929 | //--------------------------------------------------------------------------- 930 | #ifdef __MMX__ 931 | #if !defined(__STASM_DO_NOT_WARN__) & !defined(mmx_warned) 932 | #define mmx_warned 933 | #warning "It seems that your CPU has got MMX, make sure to add compiler option "-mmmx" then you can use __stasm::mmx" 934 | #endif 935 | #include 936 | //--------------------------------------------------------------------------- 937 | __STASM_SHARE_STACK_DEFINE(mmx,__m64) 938 | //--------------------------------------------------------------------------- 939 | #define __TINIT_mmx(mode,...) \ 940 | __stasm_mmx_max = __STASM_MAX_PARARELL; \ 941 | __stasm_mmx = __stasm_mmx_stack[__stasm_mmx_max]; \ 942 | __STASM_SHARE_STACK_CLEAR(mmx,__m64) \ 943 | __TINIT_##mode(__VA_ARGS__) 944 | #define __stasm_s_mmx(mode,...) \ 945 | __stasm_s_##mode(__VA_ARGS__) 946 | #define __stasm_t_mmx(mode,...) \ 947 | __stasm_t_##mode(__VA_ARGS__) 948 | #define __stasm_l_mmx(mode,...) \ 949 | __stasm_l_##mode(__VA_ARGS__) 950 | #define __stasm_x_mmx(mode,...) \ 951 | "emms\n" \ 952 | __stasm_x_##mode(__VA_ARGS__) 953 | #define __stasm_o_mmx(mode,...) \ 954 | __stasm_o_##mode(__VA_ARGS__) 955 | #define __stasm_i_mmx(mode,...) \ 956 | __stasm_i_##mode(__VA_ARGS__) 957 | #define __stasm_r_mmx(mode,...) \ 958 | "mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7", \ 959 | __stasm_r_##mode(__VA_ARGS__) 960 | #endif 961 | //--------------------------------------------------------------------------- 962 | #ifdef __SSE__ 963 | #if !defined(__STASM_DO_NOT_WARN__) & !defined(sse_warned) 964 | #define sse_warned 965 | #warning "It seems that your CPU has got SSE, make sure to add compiler option "-msse" then you can use __stasm::sse" 966 | #endif 967 | #include 968 | //--------------------------------------------------------------------------- 969 | __STASM_SHARE_STACK_DEFINE(sse,__m128) 970 | //--------------------------------------------------------------------------- 971 | #define __TINIT_sse(mode,...) \ 972 | __stasm_sse_max = __STASM_MAX_PARARELL; \ 973 | __stasm_sse = __stasm_sse_stack[__stasm_sse_max]; \ 974 | __STASM_SHARE_STACK_CLEAR(sse,__m128) \ 975 | __TINIT_##mode(__VA_ARGS__) 976 | #define __stasm_s_sse(mode,...) \ 977 | __stasm_s_##mode(__VA_ARGS__) 978 | #define __stasm_t_sse(mode,...) \ 979 | __stasm_t_##mode(__VA_ARGS__) 980 | #define __stasm_l_sse(mode,...) \ 981 | __stasm_l_##mode(__VA_ARGS__) 982 | #define __stasm_x_sse(mode,...) \ 983 | "emms\n" \ 984 | __stasm_x_##mode(__VA_ARGS__) 985 | #define __stasm_o_sse(mode,...) \ 986 | __stasm_o_##mode(__VA_ARGS__) 987 | #define __stasm_i_sse(mode,...) \ 988 | __stasm_i_##mode(__VA_ARGS__) 989 | #define __stasm_r_sse(mode,...) \ 990 | "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7", \ 991 | __stasm_r_##mode(__VA_ARGS__) 992 | #endif 993 | //--------------------------------------------------------------------------- 994 | #if defined(__SSE2__) 995 | #if !defined(__STASM_DO_NOT_WARN__) & !defined(sse2_warned) 996 | #define sse2_warned 997 | #warning "It seems that your CPU has got SSE2, make sure to add compiler option "-msse2" then you can use __stasm::sse2" 998 | #endif 999 | #include 1000 | //--------------------------------------------------------------------------- 1001 | __STASM_SHARE_STACK_DEFINE(sse2,__m128d) 1002 | //--------------------------------------------------------------------------- 1003 | #define __TINIT_sse2(mode,...) \ 1004 | __stasm_sse2_max = __STASM_MAX_PARARELL; \ 1005 | __stasm_sse2 = __stasm_sse2_stack[__stasm_sse2_max]; \ 1006 | __STASM_SHARE_STACK_CLEAR(sse2,__m128d) \ 1007 | __TINIT_##mode(__VA_ARGS__) 1008 | #define __stasm_s_sse2(mode,...) \ 1009 | __stasm_s_##mode(__VA_ARGS__) 1010 | #define __stasm_t_sse2(mode,...) \ 1011 | __stasm_t_##mode(__VA_ARGS__) 1012 | #define __stasm_l_sse2(mode,...) \ 1013 | __stasm_l_##mode(__VA_ARGS__) 1014 | #define __stasm_x_sse2(mode,...) \ 1015 | "emms\n" \ 1016 | __stasm_x_##mode(__VA_ARGS__) 1017 | #define __stasm_o_sse2(mode,...)\ 1018 | __stasm_o_##mode(__VA_ARGS__) 1019 | #define __stasm_i_sse2(mode,...) \ 1020 | __stasm_i_##mode(__VA_ARGS__) 1021 | #define __stasm_r_sse2(mode,...) \ 1022 | "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7", \ 1023 | __stasm_r_##mode(__VA_ARGS__) 1024 | #endif 1025 | 1026 | #if defined(__SSE3__) || defined(__SSEE3__) 1027 | #if !defined(__STASM_DO_NOT_WARN__) & !defined(sse3_warned) 1028 | #define sse3_warned 1029 | #warning "It seems that your CPU has got SSE3, make sure to add compiler option "-msse3" then you can use __stasm::sse3" 1030 | #endif 1031 | #include 1032 | #ifdef __SSEE3__ 1033 | #include 1034 | #endif 1035 | //--------------------------------------------------------------------------- 1036 | __STASM_SHARE_STACK_DEFINE(sse3,__m128i) 1037 | //--------------------------------------------------------------------------- 1038 | #define __TINIT_sse3(mode,...) \ 1039 | __stasm_sse3_max = __STASM_MAX_PARARELL; \ 1040 | __stasm_sse3 = __stasm_sse3_stack[__stasm_sse3_max]; \ 1041 | __STASM_SHARE_STACK_CLEAR(sse3,__m128i) \ 1042 | __TINIT_##mode(__VA_ARGS__) 1043 | #define __stasm_s_sse3(mode,...) \ 1044 | __stasm_s_##mode(__VA_ARGS__) 1045 | #define __stasm_t_sse3(mode,...) \ 1046 | __stasm_t_##mode(__VA_ARGS__) 1047 | #define __stasm_l_sse3(mode,...) \ 1048 | __stasm_l_##mode(__VA_ARGS__) 1049 | #define __stasm_x_sse3(mode,...) \ 1050 | "emms\n" \ 1051 | __stasm_x_##mode(__VA_ARGS__) 1052 | #define __stasm_o_sse3(mode,...) \ 1053 | __stasm_o_##mode(__VA_ARGS__) 1054 | #define __stasm_i_sse3(mode,...) \ 1055 | __stasm_i_##mode(__VA_ARGS__) 1056 | #define __stasm_r_sse3(mode,...) \ 1057 | "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7", \ 1058 | __stasm_r_##mode(__VA_ARGS__) 1059 | #endif 1060 | 1061 | #if defined(__SSE4A__) || defined(__SSE41__) || defined(__SSE42__) 1062 | #ifdef __SSE4A__ 1063 | #include 1064 | #endif 1065 | #ifdef __SSE41__ 1066 | #include 1067 | #endif 1068 | #ifdef __SSE42__ 1069 | #include 1070 | #endif 1071 | //--------------------------------------------------------------------------- 1072 | __STASM_SHARE_STACK_DEFINE(sse4,__m128i) 1073 | //--------------------------------------------------------------------------- 1074 | #define __TINIT_sse4(mode,...) \ 1075 | __stasm_sse4_max = __STASM_MAX_PARARELL; \ 1076 | __stasm_sse4 = __stasm_sse4_stack[__stasm_sse4_max]; \ 1077 | __STASM_SHARE_STACK_CLEAR(sse4,__m128i) \ 1078 | __TINIT_##mode(__VA_ARGS__) 1079 | #define __stasm_s_sse4(mode,...) \ 1080 | __stasm_s_##mode(__VA_ARGS__) 1081 | #define __stasm_t_sse4(mode,...) \ 1082 | __stasm_t_##mode(__VA_ARGS__) 1083 | #define __stasm_l_sse4(mode,...) \ 1084 | __stasm_l_##mode(__VA_ARGS__) 1085 | #define __stasm_x_sse4(mode,...) \ 1086 | "emms\n" \ 1087 | __stasm_x_##mode(__VA_ARGS__) 1088 | #define __stasm_o_sse4(mode,...) \ 1089 | __stasm_o_##mode(__VA_ARGS__) 1090 | #define __stasm_i_sse4(mode,...) \ 1091 | __stasm_i_##mode(__VA_ARGS__) 1092 | #if !defined(__x86_64__) 1093 | #define __stasm_r_sse4(mode,...) \ 1094 | "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7", \ 1095 | __stasm_r_##mode(__VA_ARGS__) 1096 | #else 1097 | #define __stasm_r_sse4(mode,...) \ 1098 | "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7", \ 1099 | "xmm8","xmm9","xmm10","xmm11","xmm12","xmm13","xmm14","xmm15", \ 1100 | __stasm_r_##mode(__VA_ARGS__) 1101 | #endif 1102 | #endif 1103 | //--------------------------------------------------------------------------- 1104 | #ifdef __AVX__ 1105 | #if !defined(__STASM_DO_NOT_WARN__) & !defined(avx_warned) 1106 | #define avx_warned 1107 | #warning "It seems that your CPU has got AVX, make sure to add compiler option "-mavx" then you can use __stasm::avx" 1108 | #endif 1109 | #include 1110 | //--------------------------------------------------------------------------- 1111 | __STASM_SHARE_STACK_DEFINE(avx,__m256) 1112 | //--------------------------------------------------------------------------- 1113 | #define __TINIT_avx(mode,...) \ 1114 | __stasm_avx_max = __STASM_MAX_PARARELL; \ 1115 | __stasm_avx = __stasm_avx_stack[__stasm_avx_max]; \ 1116 | __STASM_SHARE_STACK_CLEAR(avx,__m256) \ 1117 | __TINIT_##mode(__VA_ARGS__) 1118 | #define __stasm_s_avx(mode,...) \ 1119 | __stasm_s_##mode(__VA_ARGS__) 1120 | #define __stasm_t_avx(mode,...) \ 1121 | __stasm_t_##mode(__VA_ARGS__) 1122 | #define __stasm_l_avx(mode,...) \ 1123 | __stasm_l_##mode(__VA_ARGS__) 1124 | #define __stasm_x_avx(mode,...) \ 1125 | "emms\n" \ 1126 | __stasm_x_##mode(__VA_ARGS__) 1127 | #define __stasm_o_avx(mode,...) \ 1128 | __stasm_o_##mode(__VA_ARGS__) 1129 | #define __stasm_i_avx(mode,...) \ 1130 | __stasm_i_##mode(__VA_ARGS__) 1131 | #if !defined(__x86_64__) 1132 | #define __stasm_r_avx(...) \ 1133 | "ymm0","ymm1","ymm2","ymm3","ymm4","ymm5","ymm6","ymm7", \ 1134 | __stasm_r_##mode(__VA_ARGS__) 1135 | #else 1136 | #define __stasm_r_avx(...) \ 1137 | "ymm0","ymm1","ymm2","ymm3","ymm4","ymm5","ymm6","ymm7", \ 1138 | "ymm8","ymm9","ymm10","ymm11","ymm12","ymm13","ymm14","ymm15", \ 1139 | __stasm_r_##mode(__VA_ARGS__) 1140 | #endif 1141 | #endif 1142 | //--------------------------------------------------------------------------- 1143 | #ifdef __AES__ 1144 | #if !defined(__STASM_DO_NOT_WARN__) & !defined(aes_warned) 1145 | #define aes_warned 1146 | #warning "It seems that your CPU has got AES, make sure to add compiler option "-maes" then you can use __stasm::aes" 1147 | #endif 1148 | #include 1149 | //--------------------------------------------------------------------------- 1150 | __STASM_SHARE_STACK_DEFINE(aes,__m256) 1151 | //--------------------------------------------------------------------------- 1152 | #define __TINIT_aes(mode,...) \ 1153 | __stasm_aes_max = __STASM_MAX_PARARELL; \ 1154 | __stasm_aes = __stasm_aes_stack[__stasm_aes_max]; \ 1155 | __STASM_SHARE_STACK_CLEAR(aes,__m256) \ 1156 | __TINIT_##mode(__VA_ARGS__) 1157 | #define __stasm_s_aes(mode,...) \ 1158 | __stasm_s_##mode(__VA_ARGS__) 1159 | #define __stasm_t_aes(mode,...) \ 1160 | __stasm_t_##mode(__VA_ARGS__) 1161 | #define __stasm_l_aes(mode,...) \ 1162 | __stasm_l_##mode(__VA_ARGS__) 1163 | #define __stasm_x_aes(mode,...) \ 1164 | __stasm_x_##mode(__VA_ARGS__) 1165 | #define __stasm_o_aes(mode,...) \ 1166 | __stasm_o_##mode(__VA_ARGS__) 1167 | #define __stasm_i_aes(mode,...) \ 1168 | __stasm_i_##mode(__VA_ARGS__) 1169 | #define __stasm_r_aes(...) \ 1170 | __stasm_r_##mode(__VA_ARGS__) 1171 | #endif 1172 | //--------------------------------------------------------------------------- 1173 | #endif 1174 | //--------------------------------------------------------------------------- 1175 | #define __TINIT(mode,...) __TINIT_##mode(__VA_ARGS__) 1176 | //--------------------------------------------------------------------------- 1177 | #define __TLOCK(mode) \ 1178 | while (__stasm_##mode##_max==0) stk::time::wait_us(1); \ 1179 | __stasm_##mode =(__stasm_##mode##_stack[__stasm_##mode##_max--]); 1180 | //--------------------------------------------------------------------------- 1181 | #define __TUNLOCK(mode) \ 1182 | __stasm_##mode =(__stasm_##mode##_stack[++__stasm_##mode##_max]); 1183 | //--------------------------------------------------------------------------- 1184 | #define __stasm(mode,...) \ 1185 | __asm__ __volatile__( \ 1186 | __STASM_INLINE_SYNTAX \ 1187 | __stasm_s_##mode(__VA_ARGS__) "\n" \ 1188 | __stasm_t_##mode(__VA_ARGS__) "\n" \ 1189 | __stasm_l_##mode(__VA_ARGS__) "\n" \ 1190 | __stasm_x_##mode(__VA_ARGS__) "\n" \ 1191 | __GCC_INLINE_SYNTAX \ 1192 | : __stasm_o_##mode(__VA_ARGS__) \ 1193 | : __stasm_i_##mode(__VA_ARGS__) \ 1194 | : __stasm_r_##mode(__VA_ARGS__) \ 1195 | ); 1196 | //--------------------------------------------------------------------------- 1197 | #define __stasmex(mode,...) \ 1198 | __asm__ __volatile__(__STASM_INLINE_SYNTAX \ 1199 | __stasm_s_##mode(__VA_ARGS__) "\n" \ 1200 | __stasm_t_##mode(__VA_ARGS__) "\n" \ 1201 | __stasm_l_##mode(__VA_ARGS__) "\n" \ 1202 | __stasm_x_##mode(__VA_ARGS__) "\n" \ 1203 | __GCC_INLINE_SYNTAX 1204 | //--------------------------------------------------------------------------- 1205 | #define __stasmex_i(var) \ 1206 | : [var] "r" (&var) 1207 | //--------------------------------------------------------------------------- 1208 | #define __stasmex_o(var) \ 1209 | : [var] "=r" (&var) 1210 | //--------------------------------------------------------------------------- 1211 | #define __stasmex_v(...) \ 1212 | : __VA_ARGS__ 1213 | //--------------------------------------------------------------------------- 1214 | #define __stasmex_code(...) \ 1215 | : __VA_ARGS__ 1216 | //--------------------------------------------------------------------------- 1217 | #define __stasmex_auto(mode,...) \ 1218 | __stasm_r_##mode(__VA_ARGS__) 1219 | //--------------------------------------------------------------------------- 1220 | #define __stasm_ex_end \ 1221 | ); 1222 | //--------------------------------------------------------------------------- 1223 | #pragma GCC diagnostic pop 1224 | #endif 1225 | //--------------------------------------------------------------------------- 1226 | #endif 1227 | //--------------------------------------------------------------------------- 1228 | 1229 | --------------------------------------------------------------------------------