secret
Created

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.

  • Download Gist
asm.h
C
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 */ )

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.