Skip to content

Instantly share code, notes, and snippets.

@nkurz

nkurz/asm.h Secret

Created July 31, 2013 03:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nkurz/66254dce614b077e51eb to your computer and use it in GitHub Desktop.
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.
#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