nkurz / asm.h secret
Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

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.

View asm.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#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
Something went wrong with that request. Please try again.