-
-
Save nkurz/66254dce614b077e51eb to your computer and use it in GitHub Desktop.
Thought to be working for GCC and ICC, but I just did some cleanup and might have done something silly. Also might be bugs in the register specifications for some uses. But should work well enough to get started.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#define ASM_REGISTER(decl, reg, args...) register decl __asm(#reg) args | |
#define ASM_LINE(command) "\n\t" command | |
#define ASM_BLOCK(args...) __asm volatile(args) | |
#define ASM_LEA_ADD_BASE(ptr, base) \ | |
ASM_BLOCK(ASM_LINE("lea (%0, %1, %c2), %0") : \ | |
/* writes %0 */ "+r" (ptr) : \ | |
/* reads %1 */ "r" (base), \ | |
/* reads %2 */ "i" (sizeof(*ptr))); | |
#define ASM_LEA_ADD_BASE_MUL(ptr, base, mul) \ | |
ASM_BLOCK(ASM_LINE("lea (%0, %1, %c2), %0") : \ | |
/* writes %0 */ "+r" (ptr) : \ | |
/* reads %1 */ "r" (base), \ | |
/* reads %2 */ "i" (mul)); | |
#define ASM_LEA_ADD_BYTES(ptr, bytes) \ | |
ASM_BLOCK(ASM_LINE("lea %c1(%0), %0") : \ | |
/* reads/writes %0 */ "+r" (ptr) : \ | |
/* reads %1 */ "i" (bytes)); | |
#define ASM_POPCOUNT(count, src) \ | |
ASM_BLOCK(ASM_LINE("popcnt %1, %0") : \ | |
/* writes %0 */ "=r" (count) : \ | |
/* reads %1 */ "rm" (src)); | |
#define ASM_MOVE_BYTE(dest, src) \ | |
ASM_BLOCK(ASM_LINE("movzx %1, %0") : \ | |
/* writes %0 */ "=r" (dest) : \ | |
/* reads %1 */ "irm" (src)); | |
#define ASM_COPY(dest, src) \ | |
ASM_BLOCK(ASM_LINE("mov %1, %0") : \ | |
/* writes %0 */ "=r" (dest) : \ | |
/* reads %1 */ "irm" (src)); | |
#define ASM_AND(dest, src) \ | |
ASM_BLOCK(ASM_LINE("and %1, %0") : \ | |
/* reads/writes %0 */ "+r" (dest) : \ | |
/* reads %1 */ "irm" (src)); | |
#define ASM_AND_BASE_OFFSET_INDEX_MUL(dest, base, offset, index, mul) \ | |
ASM_BLOCK(ASM_LINE("and %c2(%1, %3, %c4), %0") : \ | |
/* writes %0 */ "=r" (dest) : \ | |
/* reads %1 */ "r" (base), \ | |
/* reads %2 */ "i" (offset), \ | |
/* reads %3 */ "r" (index), \ | |
/* reads %4 */ "i" (mul)); | |
#define ASM_LOAD_BASE_OFFSET_INDEX_MUL(dest, base, offset, index, mul) \ | |
ASM_BLOCK(ASM_LINE("mov %c2(%1, %3, %c4), %0") : \ | |
/* writes %0 */ "=r" (dest) : \ | |
/* reads %1 */ "r" (base), \ | |
/* reads %2 */ "i" (offset), \ | |
/* reads %3 */ "r" (index), \ | |
/* reads %4 */ "i" (mul)); | |
// NOTE: cmova/cmovb are one cycle slower than cmovg/cmovl | |
#define ASM_ADD_CMOV(var, add, cmp1, cmp2, cmov) { \ | |
typeof(var) _new = var + add; \ | |
ASM_BLOCK(ASM_LINE("cmp %2, %1") \ | |
ASM_LINE(#cmov " %3, %0") : \ | |
/* writes %0 */ "+r" (var) : \ | |
/* reads %1 */ "ri" (cmp1), \ | |
/* reads %2 */ "rm" (cmp2), \ | |
/* reads %3 */ "r" (_new) : \ | |
/* clobbers */ "cc"); \ | |
} | |
#define ASM_CALL_ARRAY(array, offset) \ | |
ASM_BLOCK(ASM_LINE("call *(%0, %1, %c2)") : \ | |
/* no writes */ : \ | |
/* reads %0 */ "r" (array), \ | |
/* reads %1 */ "r" (offset), \ | |
/* reads %2 */ "i" (sizeof(*array))); | |
#define ASM_CALL_FUNC(func) \ | |
ASM_BLOCK(ASM_LINE("call %P0") : \ | |
/* no writes */ : \ | |
/* reads %0 */ "i" (func)) | |
#define ASM_USING_VAR(var) \ | |
ASM_BLOCK( /* no action */ "# pretend to read and write %0" : \ | |
/* no real writes */ "+r" (var) : \ | |
/* no real reads */ ) | |
#define ASM_USING_XMM(xmm) \ | |
ASM_BLOCK( /* no action */ "# pretend to read and write %0" : \ | |
/* no real writes */ "+x" (xmm) : \ | |
/* no real reads */ ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment