865 lines
30 KiB
C++
865 lines
30 KiB
C++
#pragma once
|
|
|
|
//{
|
|
alwaysinline auto clc() { emit.byte(0xf8); }
|
|
alwaysinline auto cmc() { emit.byte(0xf5); }
|
|
alwaysinline auto lahf() { emit.byte(0x9f); }
|
|
alwaysinline auto sahf() { emit.byte(0x9e); }
|
|
alwaysinline auto stc() { emit.byte(0xf9); }
|
|
alwaysinline auto ret() { emit.byte(0xc3); }
|
|
|
|
//call imm32
|
|
alwaysinline auto call(imm32 it) {
|
|
emit.byte(0xe8);
|
|
emit.dword(it.data);
|
|
}
|
|
|
|
//jmp imm32
|
|
alwaysinline auto jmp(imm32 it) {
|
|
emit.byte(0xe9);
|
|
emit.dword(it.data);
|
|
}
|
|
|
|
//call reg64
|
|
alwaysinline auto call(reg64 rt) {
|
|
emit.rex(0, 0, 0, rt & 8);
|
|
emit.byte(0xff);
|
|
emit.modrm(3, 2, rt & 7);
|
|
}
|
|
|
|
//lea reg64,[reg64+imm8]
|
|
alwaysinline auto lea(reg64 rt, dis8 ds) {
|
|
emit.rex(1, rt & 8, 0, ds.reg & 8);
|
|
emit.byte(0x8d);
|
|
emit.modrm(1, rt & 7, ds.reg & 7);
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4);
|
|
emit.byte(ds.imm);
|
|
}
|
|
|
|
//lea reg64,[reg64+imm32]
|
|
alwaysinline auto lea(reg64 rt, dis32 ds) {
|
|
emit.rex(1, rt & 8, 0, ds.reg & 8);
|
|
emit.byte(0x8d);
|
|
emit.modrm(2, rt & 7, ds.reg & 7);
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4);
|
|
emit.dword(ds.imm);
|
|
}
|
|
|
|
//mov reg8,imm8
|
|
alwaysinline auto mov(reg8 rt, imm8 is) {
|
|
emit.rex(0, 0, 0, rt & 8);
|
|
emit.byte(0xb0 | rt & 7);
|
|
emit.byte(is.data);
|
|
}
|
|
|
|
//mov reg32,imm32
|
|
alwaysinline auto mov(reg32 rt, imm32 is) {
|
|
emit.rex(0, 0, 0, rt & 8);
|
|
emit.byte(0xb8 | rt & 7);
|
|
emit.dword(is.data);
|
|
}
|
|
|
|
//mov reg64,imm32
|
|
alwaysinline auto mov(reg64 rt, imm32 is) {
|
|
emit.rex(1, 0, 0, rt & 8);
|
|
emit.byte(0xc7);
|
|
emit.modrm(3, 0, rt & 7);
|
|
emit.dword(is.data);
|
|
}
|
|
|
|
//mov reg64,imm64
|
|
alwaysinline auto mov(reg64 rt, imm64 is) {
|
|
emit.rex(1, 0, 0, rt & 8);
|
|
emit.byte(0xb8 | rt & 7);
|
|
emit.qword(is.data);
|
|
}
|
|
|
|
//mov reg8,[mem64]
|
|
alwaysinline auto mov(reg8 rt, mem64 ps) {
|
|
if(unlikely(rt != al)) throw;
|
|
emit.byte(0xa0);
|
|
emit.qword(ps.data);
|
|
}
|
|
|
|
//mov reg16,[mem64]
|
|
alwaysinline auto mov(reg16 rt, mem64 ps) {
|
|
if(unlikely(rt != ax)) throw;
|
|
emit.byte(0x66, 0xa1);
|
|
emit.qword(ps.data);
|
|
}
|
|
|
|
//mov reg32,[mem64]
|
|
alwaysinline auto mov(reg32 rt, mem64 ps) {
|
|
if(unlikely(rt != eax)) throw;
|
|
emit.byte(0xa1);
|
|
emit.qword(ps.data);
|
|
}
|
|
|
|
//mov reg64,[mem64]
|
|
alwaysinline auto mov(reg64 rt, mem64 ps) {
|
|
if(unlikely(rt != rax)) throw;
|
|
emit.rex(1, 0, 0, 0);
|
|
emit.byte(0xa1);
|
|
emit.qword(ps.data);
|
|
}
|
|
|
|
//mov [mem64],reg8
|
|
alwaysinline auto mov(mem64 pt, reg8 rs) {
|
|
if(unlikely(rs != al)) throw;
|
|
emit.byte(0xa2);
|
|
emit.qword(pt.data);
|
|
}
|
|
|
|
//mov [mem64+imm8],imm8
|
|
alwaysinline auto movb(dis8 dt, imm8 is) {
|
|
emit.rex(0, 0, 0, dt.reg & 8);
|
|
emit.byte(0xc6);
|
|
emit.modrm(1, 0, dt.reg & 7);
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4);
|
|
emit.byte(dt.imm);
|
|
emit.byte(is.data);
|
|
}
|
|
|
|
//mov [mem64],reg16
|
|
alwaysinline auto mov(mem64 pt, reg16 rs) {
|
|
if(unlikely(rs != ax)) throw;
|
|
emit.byte(0x66, 0xa3);
|
|
emit.qword(pt.data);
|
|
}
|
|
|
|
//mov [mem64],reg32
|
|
alwaysinline auto mov(mem64 pt, reg32 rs) {
|
|
if(unlikely(rs != eax)) throw;
|
|
emit.byte(0xa3);
|
|
emit.qword(pt.data);
|
|
}
|
|
|
|
//mov [mem64],reg64
|
|
alwaysinline auto mov(mem64 pt, reg64 rs) {
|
|
if(unlikely(rs != rax)) throw;
|
|
emit.rex(1, 0, 0, 0);
|
|
emit.byte(0xa3);
|
|
emit.qword(pt.data);
|
|
}
|
|
|
|
//op reg8,[reg64]
|
|
#define op(code) \
|
|
emit.rex(0, rt & 8, 0, ds.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(0, rt & 7, ds.reg & 7); \
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4);
|
|
alwaysinline auto adc(reg8 rt, dis ds) { op(0x12); }
|
|
alwaysinline auto add(reg8 rt, dis ds) { op(0x02); }
|
|
alwaysinline auto and_(reg8 rt, dis ds) { op(0x22); }
|
|
alwaysinline auto cmp(reg8 rt, dis ds) { op(0x3a); }
|
|
alwaysinline auto mov(reg8 rt, dis ds) { op(0x8a); }
|
|
alwaysinline auto or_(reg8 rt, dis ds) { op(0x0a); }
|
|
alwaysinline auto sbb(reg8 rt, dis ds) { op(0x1a); }
|
|
alwaysinline auto sub(reg8 rt, dis ds) { op(0x2a); }
|
|
alwaysinline auto xor_(reg8 rt, dis ds) { op(0x32); }
|
|
#undef op
|
|
|
|
//op reg8,[reg64+imm8]
|
|
#define op(code) \
|
|
emit.rex(0, rt & 8, 0, ds.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(1, rt & 7, ds.reg & 7); \
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.byte(ds.imm);
|
|
alwaysinline auto adc(reg8 rt, dis8 ds) { op(0x12); }
|
|
alwaysinline auto add(reg8 rt, dis8 ds) { op(0x02); }
|
|
alwaysinline auto and_(reg8 rt, dis8 ds) { op(0x22); }
|
|
alwaysinline auto cmp(reg8 rt, dis8 ds) { op(0x3a); }
|
|
alwaysinline auto mov(reg8 rt, dis8 ds) { op(0x8a); }
|
|
alwaysinline auto or_(reg8 rt, dis8 ds) { op(0x0a); }
|
|
alwaysinline auto sbb(reg8 rt, dis8 ds) { op(0x1a); }
|
|
alwaysinline auto sub(reg8 rt, dis8 ds) { op(0x2a); }
|
|
alwaysinline auto xor_(reg8 rt, dis8 ds) { op(0x32); }
|
|
#undef op
|
|
|
|
//op reg32,[reg64]
|
|
#define op(code) \
|
|
emit.rex(0, rt & 8, 0, ds.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(0, rt & 7, ds.reg & 7); \
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4);
|
|
alwaysinline auto adc(reg32 rt, dis ds) { op(0x13); }
|
|
alwaysinline auto add(reg32 rt, dis ds) { op(0x03); }
|
|
alwaysinline auto and_(reg32 rt, dis ds) { op(0x23); }
|
|
alwaysinline auto cmp(reg32 rt, dis ds) { op(0x3b); }
|
|
alwaysinline auto mov(reg32 rt, dis ds) { op(0x8b); }
|
|
alwaysinline auto or_(reg32 rt, dis ds) { op(0x0b); }
|
|
alwaysinline auto sbb(reg32 rt, dis ds) { op(0x1b); }
|
|
alwaysinline auto sub(reg32 rt, dis ds) { op(0x2b); }
|
|
alwaysinline auto xor_(reg32 rt, dis ds) { op(0x33); }
|
|
#undef op
|
|
|
|
//op reg32,[reg64+imm8]
|
|
#define op(code) \
|
|
emit.rex(0, rt & 8, 0, ds.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(1, rt & 7, ds.reg & 7); \
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.byte(ds.imm);
|
|
alwaysinline auto adc(reg32 rt, dis8 ds) { op(0x13); }
|
|
alwaysinline auto add(reg32 rt, dis8 ds) { op(0x03); }
|
|
alwaysinline auto and_(reg32 rt, dis8 ds) { op(0x23); }
|
|
alwaysinline auto cmp(reg32 rt, dis8 ds) { op(0x3b); }
|
|
alwaysinline auto mov(reg32 rt, dis8 ds) { op(0x8b); }
|
|
alwaysinline auto or_(reg32 rt, dis8 ds) { op(0x0b); }
|
|
alwaysinline auto sbb(reg32 rt, dis8 ds) { op(0x1b); }
|
|
alwaysinline auto sub(reg32 rt, dis8 ds) { op(0x2b); }
|
|
alwaysinline auto xor_(reg32 rt, dis8 ds) { op(0x33); }
|
|
#undef op
|
|
|
|
//op reg64,[reg64]
|
|
#define op(code) \
|
|
emit.rex(1, rt & 8, 0, ds.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(0, rt & 7, ds.reg & 7); \
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4);
|
|
alwaysinline auto adc(reg64 rt, dis ds) { op(0x13); }
|
|
alwaysinline auto add(reg64 rt, dis ds) { op(0x03); }
|
|
alwaysinline auto and_(reg64 rt, dis ds) { op(0x23); }
|
|
alwaysinline auto cmp(reg64 rt, dis ds) { op(0x3b); }
|
|
alwaysinline auto mov(reg64 rt, dis ds) { op(0x8b); }
|
|
alwaysinline auto or_(reg64 rt, dis ds) { op(0x0b); }
|
|
alwaysinline auto sbb(reg64 rt, dis ds) { op(0x1b); }
|
|
alwaysinline auto sub(reg64 rt, dis ds) { op(0x2b); }
|
|
alwaysinline auto xor_(reg64 rt, dis ds) { op(0x33); }
|
|
#undef op
|
|
|
|
//op reg64,[reg64+imm8]
|
|
#define op(code) \
|
|
emit.rex(1, rt & 8, 0, ds.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(1, rt & 7, ds.reg & 7); \
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.byte(ds.imm);
|
|
alwaysinline auto adc(reg64 rt, dis8 ds) { op(0x13); }
|
|
alwaysinline auto add(reg64 rt, dis8 ds) { op(0x03); }
|
|
alwaysinline auto and_(reg64 rt, dis8 ds) { op(0x23); }
|
|
alwaysinline auto cmp(reg64 rt, dis8 ds) { op(0x3b); }
|
|
alwaysinline auto mov(reg64 rt, dis8 ds) { op(0x8b); }
|
|
alwaysinline auto or_(reg64 rt, dis8 ds) { op(0x0b); }
|
|
alwaysinline auto sbb(reg64 rt, dis8 ds) { op(0x1b); }
|
|
alwaysinline auto sub(reg64 rt, dis8 ds) { op(0x2b); }
|
|
alwaysinline auto xor_(reg64 rt, dis8 ds) { op(0x33); }
|
|
#undef op
|
|
|
|
//op reg64,[reg64+imm32]
|
|
#define op(code) \
|
|
emit.rex(1, rt & 8, 0, ds.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(2, rt & 7, ds.reg & 7); \
|
|
if(ds.reg == rsp || ds.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.dword(ds.imm);
|
|
alwaysinline auto adc(reg64 rt, dis32 ds) { op(0x13); }
|
|
alwaysinline auto add(reg64 rt, dis32 ds) { op(0x03); }
|
|
alwaysinline auto and_(reg64 rt, dis32 ds) { op(0x23); }
|
|
alwaysinline auto cmp(reg64 rt, dis32 ds) { op(0x3b); }
|
|
alwaysinline auto mov(reg64 rt, dis32 ds) { op(0x8b); }
|
|
alwaysinline auto or_(reg64 rt, dis32 ds) { op(0x0b); }
|
|
alwaysinline auto sbb(reg64 rt, dis32 ds) { op(0x1b); }
|
|
alwaysinline auto sub(reg64 rt, dis32 ds) { op(0x2b); }
|
|
alwaysinline auto xor_(reg64 rt, dis32 ds) { op(0x33); }
|
|
#undef op
|
|
|
|
//op [reg64+imm8],reg8
|
|
#define op(code) \
|
|
emit.rex(0, rs & 8, 0, dt.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(1, rs & 7, dt.reg & 7); \
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.byte(dt.imm);
|
|
alwaysinline auto adc(dis8 dt, reg8 rs) { op(0x10); }
|
|
alwaysinline auto add(dis8 dt, reg8 rs) { op(0x00); }
|
|
alwaysinline auto and_(dis8 dt, reg8 rs) { op(0x20); }
|
|
alwaysinline auto cmp(dis8 dt, reg8 rs) { op(0x38); }
|
|
alwaysinline auto mov(dis8 dt, reg8 rs) { op(0x88); }
|
|
alwaysinline auto or_(dis8 dt, reg8 rs) { op(0x08); }
|
|
alwaysinline auto sbb(dis8 dt, reg8 rs) { op(0x18); }
|
|
alwaysinline auto sub(dis8 dt, reg8 rs) { op(0x28); }
|
|
alwaysinline auto xor_(dis8 dt, reg8 rs) { op(0x30); }
|
|
#undef op
|
|
|
|
//op reg64,imm32
|
|
#define op(group) \
|
|
emit.rex(1, 0, 0, rt & 8); \
|
|
emit.byte(0x81); \
|
|
emit.modrm(3, group, rt & 7); \
|
|
emit.dword(is.data);
|
|
alwaysinline auto add(reg64 rt, imm32 is) { op(0); }
|
|
alwaysinline auto or_(reg64 rt, imm32 is) { op(1); }
|
|
alwaysinline auto adc(reg64 rt, imm32 is) { op(2); }
|
|
alwaysinline auto sbb(reg64 rt, imm32 is) { op(3); }
|
|
alwaysinline auto and_(reg64 rt, imm32 is) { op(4); }
|
|
alwaysinline auto sub(reg64 rt, imm32 is) { op(5); }
|
|
alwaysinline auto xor_(reg64 rt, imm32 is) { op(6); }
|
|
alwaysinline auto cmp(reg64 rt, imm32 is) { op(7); }
|
|
#undef op
|
|
|
|
//op.d [reg64+imm8],imm8
|
|
#define op(group) \
|
|
emit.rex(0, 0, 0, dt.reg & 8); \
|
|
emit.byte(0x83); \
|
|
emit.modrm(1, group, dt.reg & 7); \
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.byte(dt.imm); \
|
|
emit.byte(is.data);
|
|
alwaysinline auto addd(dis8 dt, imm8 is) { op(0); }
|
|
alwaysinline auto ord (dis8 dt, imm8 is) { op(1); }
|
|
alwaysinline auto adcd(dis8 dt, imm8 is) { op(2); }
|
|
alwaysinline auto sbbd(dis8 dt, imm8 is) { op(3); }
|
|
alwaysinline auto andd(dis8 dt, imm8 is) { op(4); }
|
|
alwaysinline auto subd(dis8 dt, imm8 is) { op(5); }
|
|
alwaysinline auto xord(dis8 dt, imm8 is) { op(6); }
|
|
alwaysinline auto cmpd(dis8 dt, imm8 is) { op(7); }
|
|
#undef op
|
|
|
|
//op [reg64],reg32
|
|
#define op(code) \
|
|
emit.rex(0, rs & 8, 0, dt.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(0, rs & 7, dt.reg & 7); \
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4);
|
|
alwaysinline auto adc(dis dt, reg32 rs) { op(0x11); }
|
|
alwaysinline auto add(dis dt, reg32 rs) { op(0x01); }
|
|
alwaysinline auto and_(dis dt, reg32 rs) { op(0x21); }
|
|
alwaysinline auto cmp(dis dt, reg32 rs) { op(0x39); }
|
|
alwaysinline auto mov(dis dt, reg32 rs) { op(0x89); }
|
|
alwaysinline auto or_(dis dt, reg32 rs) { op(0x09); }
|
|
alwaysinline auto sbb(dis dt, reg32 rs) { op(0x19); }
|
|
alwaysinline auto sub(dis dt, reg32 rs) { op(0x29); }
|
|
alwaysinline auto xor_(dis dt, reg32 rs) { op(0x31); }
|
|
#undef op
|
|
|
|
//op [reg64+imm8],reg32
|
|
#define op(code) \
|
|
emit.rex(0, rs & 8, 0, dt.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(1, rs & 7, dt.reg & 7); \
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.byte(dt.imm);
|
|
alwaysinline auto adc(dis8 dt, reg32 rs) { op(0x11); }
|
|
alwaysinline auto add(dis8 dt, reg32 rs) { op(0x01); }
|
|
alwaysinline auto and_(dis8 dt, reg32 rs) { op(0x21); }
|
|
alwaysinline auto cmp(dis8 dt, reg32 rs) { op(0x39); }
|
|
alwaysinline auto mov(dis8 dt, reg32 rs) { op(0x89); }
|
|
alwaysinline auto or_(dis8 dt, reg32 rs) { op(0x09); }
|
|
alwaysinline auto sbb(dis8 dt, reg32 rs) { op(0x19); }
|
|
alwaysinline auto sub(dis8 dt, reg32 rs) { op(0x29); }
|
|
alwaysinline auto xor_(dis8 dt, reg32 rs) { op(0x31); }
|
|
#undef op
|
|
|
|
//op [reg64],reg64
|
|
#define op(code) \
|
|
emit.rex(0, rs & 8, 0, dt.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(0, rs & 7, dt.reg & 7); \
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4);
|
|
alwaysinline auto adc(dis dt, reg64 rs) { op(0x11); }
|
|
alwaysinline auto add(dis dt, reg64 rs) { op(0x01); }
|
|
alwaysinline auto and_(dis dt, reg64 rs) { op(0x21); }
|
|
alwaysinline auto cmp(dis dt, reg64 rs) { op(0x39); }
|
|
alwaysinline auto mov(dis dt, reg64 rs) { op(0x89); }
|
|
alwaysinline auto or_(dis dt, reg64 rs) { op(0x09); }
|
|
alwaysinline auto sbb(dis dt, reg64 rs) { op(0x19); }
|
|
alwaysinline auto sub(dis dt, reg64 rs) { op(0x29); }
|
|
alwaysinline auto xor_(dis dt, reg64 rs) { op(0x31); }
|
|
#undef op
|
|
|
|
//op [reg64+imm8],reg64
|
|
#define op(code) \
|
|
emit.rex(1, rs & 8, 0, dt.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(1, rs & 7, dt.reg & 7); \
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.byte(dt.imm);
|
|
alwaysinline auto adc(dis8 dt, reg64 rs) { op(0x11); }
|
|
alwaysinline auto add(dis8 dt, reg64 rs) { op(0x01); }
|
|
alwaysinline auto and_(dis8 dt, reg64 rs) { op(0x21); }
|
|
alwaysinline auto cmp(dis8 dt, reg64 rs) { op(0x39); }
|
|
alwaysinline auto mov(dis8 dt, reg64 rs) { op(0x89); }
|
|
alwaysinline auto or_(dis8 dt, reg64 rs) { op(0x09); }
|
|
alwaysinline auto sbb(dis8 dt, reg64 rs) { op(0x19); }
|
|
alwaysinline auto sub(dis8 dt, reg64 rs) { op(0x29); }
|
|
alwaysinline auto xor_(dis8 dt, reg64 rs) { op(0x31); }
|
|
#undef op
|
|
|
|
//op [reg64+imm32],reg64
|
|
#define op(code) \
|
|
emit.rex(1, rs & 8, 0, dt.reg & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(2, rs & 7, dt.reg & 7); \
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4); \
|
|
emit.dword(dt.imm);
|
|
alwaysinline auto adc(dis32 dt, reg64 rs) { op(0x11); }
|
|
alwaysinline auto add(dis32 dt, reg64 rs) { op(0x01); }
|
|
alwaysinline auto and_(dis32 dt, reg64 rs) { op(0x21); }
|
|
alwaysinline auto cmp(dis32 dt, reg64 rs) { op(0x39); }
|
|
alwaysinline auto mov(dis32 dt, reg64 rs) { op(0x89); }
|
|
alwaysinline auto or_(dis32 dt, reg64 rs) { op(0x09); }
|
|
alwaysinline auto sbb(dis32 dt, reg64 rs) { op(0x19); }
|
|
alwaysinline auto sub(dis32 dt, reg64 rs) { op(0x29); }
|
|
alwaysinline auto xor_(dis32 dt, reg64 rs) { op(0x31); }
|
|
#undef op
|
|
|
|
//op reg32,reg8
|
|
#define op(code) \
|
|
emit.rex(0, rt & 8, 0, rs & 8); \
|
|
emit.byte(0x0f, code); \
|
|
emit.modrm(3, rt & 7, rs & 7);
|
|
alwaysinline auto movsx(reg32 rt, reg8 rs) { op(0xbe); }
|
|
alwaysinline auto movzx(reg32 rt, reg8 rs) { op(0xb6); }
|
|
#undef op
|
|
|
|
//op reg32,reg16
|
|
#define op(code) \
|
|
emit.rex(0, rt & 8, 0, rs & 8); \
|
|
emit.byte(0x0f, code); \
|
|
emit.modrm(3, rt & 7, rs & 7);
|
|
alwaysinline auto movsx(reg32 rt, reg16 rs) { op(0xbf); }
|
|
alwaysinline auto movzx(reg32 rt, reg16 rs) { op(0xb7); }
|
|
#undef op
|
|
|
|
alwaysinline auto movsxd(reg64 rt, reg32 rs) {
|
|
emit.rex(1, rt & 8, 0, rs & 8);
|
|
emit.byte(0x63);
|
|
emit.modrm(3, rt & 7, rs & 7);
|
|
}
|
|
|
|
//incd [reg64+imm8]
|
|
alwaysinline auto incd(dis8 dt) {
|
|
emit.rex(0, 0, 0, dt.reg & 8);
|
|
emit.byte(0xff);
|
|
emit.modrm(1, 0, dt.reg & 7);
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4);
|
|
emit.byte(dt.imm);
|
|
}
|
|
|
|
//decd [reg64+imm8]
|
|
alwaysinline auto decd(dis8 dt) {
|
|
emit.rex(0, 0, 0, dt.reg & 8);
|
|
emit.byte(0xff);
|
|
emit.modrm(1, 1, dt.reg & 7);
|
|
if(dt.reg == rsp || dt.reg == r12) emit.sib(0, 4, 4);
|
|
emit.byte(dt.imm);
|
|
}
|
|
|
|
//inc reg32
|
|
alwaysinline auto inc(reg32 rt) {
|
|
emit.rex(0, 0, 0, rt & 8);
|
|
emit.byte(0xff);
|
|
emit.modrm(3, 0, rt & 7);
|
|
}
|
|
|
|
//dec reg32
|
|
alwaysinline auto dec(reg32 rt) {
|
|
emit.rex(0, 0, 0, rt & 8);
|
|
emit.byte(0xff);
|
|
emit.modrm(3, 1, rt & 7);
|
|
}
|
|
|
|
//inc reg64
|
|
alwaysinline auto inc(reg64 rt) {
|
|
emit.rex(1, 0, 0, rt & 8);
|
|
emit.byte(0xff);
|
|
emit.modrm(3, 0, rt & 7);
|
|
}
|
|
|
|
//dec reg64
|
|
alwaysinline auto dec(reg64 rt) {
|
|
emit.rex(1, 0, 0, rt & 8);
|
|
emit.byte(0xff);
|
|
emit.modrm(3, 1, rt & 7);
|
|
}
|
|
|
|
#define op(code) \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0xd0); \
|
|
emit.modrm(3, code, rt & 7);
|
|
alwaysinline auto rol(reg8 rt) { op(0); }
|
|
alwaysinline auto ror(reg8 rt) { op(1); }
|
|
alwaysinline auto rcl(reg8 rt) { op(2); }
|
|
alwaysinline auto rcr(reg8 rt) { op(3); }
|
|
alwaysinline auto shl(reg8 rt) { op(4); }
|
|
alwaysinline auto shr(reg8 rt) { op(5); }
|
|
alwaysinline auto sal(reg8 rt) { op(6); }
|
|
alwaysinline auto sar(reg8 rt) { op(7); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0xd1); \
|
|
emit.modrm(3, code, rt & 7);
|
|
alwaysinline auto rol(reg32 rt) { op(0); }
|
|
alwaysinline auto ror(reg32 rt) { op(1); }
|
|
alwaysinline auto rcl(reg32 rt) { op(2); }
|
|
alwaysinline auto rcr(reg32 rt) { op(3); }
|
|
alwaysinline auto shl(reg32 rt) { op(4); }
|
|
alwaysinline auto shr(reg32 rt) { op(5); }
|
|
alwaysinline auto sal(reg32 rt) { op(6); }
|
|
alwaysinline auto sar(reg32 rt) { op(7); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0xc1); \
|
|
emit.modrm(3, code, rt & 7); \
|
|
emit.byte(is.data);
|
|
alwaysinline auto rol(reg32 rt, imm8 is) { op(0); }
|
|
alwaysinline auto ror(reg32 rt, imm8 is) { op(1); }
|
|
alwaysinline auto rcl(reg32 rt, imm8 is) { op(2); }
|
|
alwaysinline auto rcr(reg32 rt, imm8 is) { op(3); }
|
|
alwaysinline auto shl(reg32 rt, imm8 is) { op(4); }
|
|
alwaysinline auto shr(reg32 rt, imm8 is) { op(5); }
|
|
alwaysinline auto sal(reg32 rt, imm8 is) { op(6); }
|
|
alwaysinline auto sar(reg32 rt, imm8 is) { op(7); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
if(unlikely(rs != cl)) throw; \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0xd3); \
|
|
emit.modrm(3, code, rt & 7);
|
|
alwaysinline auto rol(reg32 rt, reg8 rs) { op(0); }
|
|
alwaysinline auto ror(reg32 rt, reg8 rs) { op(1); }
|
|
alwaysinline auto rcl(reg32 rt, reg8 rs) { op(2); }
|
|
alwaysinline auto rcr(reg32 rt, reg8 rs) { op(3); }
|
|
alwaysinline auto shl(reg32 rt, reg8 rs) { op(4); }
|
|
alwaysinline auto shr(reg32 rt, reg8 rs) { op(5); }
|
|
alwaysinline auto sal(reg32 rt, reg8 rs) { op(6); }
|
|
alwaysinline auto sar(reg32 rt, reg8 rs) { op(7); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(1, 0, 0, rt & 8); \
|
|
emit.byte(0xc1); \
|
|
emit.modrm(3, code, rt & 7); \
|
|
emit.byte(is.data);
|
|
alwaysinline auto rol(reg64 rt, imm8 is) { op(0); }
|
|
alwaysinline auto ror(reg64 rt, imm8 is) { op(1); }
|
|
alwaysinline auto rcl(reg64 rt, imm8 is) { op(2); }
|
|
alwaysinline auto rcr(reg64 rt, imm8 is) { op(3); }
|
|
alwaysinline auto shl(reg64 rt, imm8 is) { op(4); }
|
|
alwaysinline auto shr(reg64 rt, imm8 is) { op(5); }
|
|
alwaysinline auto sal(reg64 rt, imm8 is) { op(6); }
|
|
alwaysinline auto sar(reg64 rt, imm8 is) { op(7); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
if(unlikely(rs != cl)) throw; \
|
|
emit.rex(1, 0, 0, rt & 8); \
|
|
emit.byte(0xd3); \
|
|
emit.modrm(3, code, rt & 7);
|
|
alwaysinline auto rol(reg64 rt, reg8 rs) { op(0); }
|
|
alwaysinline auto ror(reg64 rt, reg8 rs) { op(1); }
|
|
alwaysinline auto rcl(reg64 rt, reg8 rs) { op(2); }
|
|
alwaysinline auto rcr(reg64 rt, reg8 rs) { op(3); }
|
|
alwaysinline auto shl(reg64 rt, reg8 rs) { op(4); }
|
|
alwaysinline auto shr(reg64 rt, reg8 rs) { op(5); }
|
|
alwaysinline auto sal(reg64 rt, reg8 rs) { op(6); }
|
|
alwaysinline auto sar(reg64 rt, reg8 rs) { op(7); }
|
|
#undef op
|
|
|
|
//push reg
|
|
alwaysinline auto push(reg64 rt) {
|
|
emit.rex(0, 0, 0, rt & 8);
|
|
emit.byte(0x50 | rt & 7);
|
|
}
|
|
|
|
//pop reg
|
|
alwaysinline auto pop(reg64 rt) {
|
|
emit.rex(0, 0, 0, rt & 8);
|
|
emit.byte(0x58 | rt & 7);
|
|
}
|
|
|
|
#define op(code) \
|
|
emit.rex(0, rs & 8, 0, rt & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(3, rs & 7, rt & 7);
|
|
alwaysinline auto adc (reg8 rt, reg8 rs) { op(0x10); }
|
|
alwaysinline auto add (reg8 rt, reg8 rs) { op(0x00); }
|
|
alwaysinline auto and_(reg8 rt, reg8 rs) { op(0x20); }
|
|
alwaysinline auto cmp (reg8 rt, reg8 rs) { op(0x38); }
|
|
alwaysinline auto mov (reg8 rt, reg8 rs) { op(0x88); }
|
|
alwaysinline auto or_ (reg8 rt, reg8 rs) { op(0x08); }
|
|
alwaysinline auto sbb (reg8 rt, reg8 rs) { op(0x18); }
|
|
alwaysinline auto sub (reg8 rt, reg8 rs) { op(0x28); }
|
|
alwaysinline auto test(reg8 rt, reg8 rs) { op(0x84); }
|
|
alwaysinline auto xor_(reg8 rt, reg8 rs) { op(0x30); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.byte(0x66); \
|
|
emit.rex(0, rs & 8, 0, rt & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(3, rs & 7, rt & 7);
|
|
alwaysinline auto adc (reg16 rt, reg16 rs) { op(0x11); }
|
|
alwaysinline auto add (reg16 rt, reg16 rs) { op(0x01); }
|
|
alwaysinline auto and_(reg16 rt, reg16 rs) { op(0x21); }
|
|
alwaysinline auto cmp (reg16 rt, reg16 rs) { op(0x39); }
|
|
alwaysinline auto mov (reg16 rt, reg16 rs) { op(0x89); }
|
|
alwaysinline auto or_ (reg16 rt, reg16 rs) { op(0x09); }
|
|
alwaysinline auto sbb (reg16 rt, reg16 rs) { op(0x19); }
|
|
alwaysinline auto sub (reg16 rt, reg16 rs) { op(0x29); }
|
|
alwaysinline auto test(reg16 rt, reg16 rs) { op(0x85); }
|
|
alwaysinline auto xor_(reg16 rt, reg16 rs) { op(0x31); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(0, rs & 8, 0, rt & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(3, rs & 7, rt & 7);
|
|
alwaysinline auto adc (reg32 rt, reg32 rs) { op(0x11); }
|
|
alwaysinline auto add (reg32 rt, reg32 rs) { op(0x01); }
|
|
alwaysinline auto and_(reg32 rt, reg32 rs) { op(0x21); }
|
|
alwaysinline auto cmp (reg32 rt, reg32 rs) { op(0x39); }
|
|
alwaysinline auto mov (reg32 rt, reg32 rs) { op(0x89); }
|
|
alwaysinline auto or_ (reg32 rt, reg32 rs) { op(0x09); }
|
|
alwaysinline auto sbb (reg32 rt, reg32 rs) { op(0x19); }
|
|
alwaysinline auto sub (reg32 rt, reg32 rs) { op(0x29); }
|
|
alwaysinline auto test(reg32 rt, reg32 rs) { op(0x85); }
|
|
alwaysinline auto xor_(reg32 rt, reg32 rs) { op(0x31); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(1, rs & 8, 0, rt & 8); \
|
|
emit.byte(code); \
|
|
emit.modrm(3, rs & 7, rt & 7);
|
|
alwaysinline auto adc (reg64 rt, reg64 rs) { op(0x11); }
|
|
alwaysinline auto add (reg64 rt, reg64 rs) { op(0x01); }
|
|
alwaysinline auto and_(reg64 rt, reg64 rs) { op(0x21); }
|
|
alwaysinline auto cmp (reg64 rt, reg64 rs) { op(0x39); }
|
|
alwaysinline auto mov (reg64 rt, reg64 rs) { op(0x89); }
|
|
alwaysinline auto or_ (reg64 rt, reg64 rs) { op(0x09); }
|
|
alwaysinline auto sbb (reg64 rt, reg64 rs) { op(0x19); }
|
|
alwaysinline auto sub (reg64 rt, reg64 rs) { op(0x29); }
|
|
alwaysinline auto test(reg64 rt, reg64 rs) { op(0x85); }
|
|
alwaysinline auto xor_(reg64 rt, reg64 rs) { op(0x31); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0x83); \
|
|
emit.modrm(3, code, rt & 7); \
|
|
emit.byte(is.data);
|
|
alwaysinline auto adc(reg32 rt, imm8 is) { op(2); }
|
|
alwaysinline auto add(reg32 rt, imm8 is) { op(0); }
|
|
alwaysinline auto and_(reg32 rt, imm8 is) { op(4); }
|
|
alwaysinline auto cmp(reg32 rt, imm8 is) { op(7); }
|
|
alwaysinline auto or_(reg32 rt, imm8 is) { op(1); }
|
|
alwaysinline auto sbb(reg32 rt, imm8 is) { op(3); }
|
|
alwaysinline auto sub(reg32 rt, imm8 is) { op(5); }
|
|
alwaysinline auto xor_(reg32 rt, imm8 is) { op(6); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(1, 0, 0, rt & 8); \
|
|
emit.byte(0x83); \
|
|
emit.modrm(3, code, rt & 7); \
|
|
emit.byte(is.data);
|
|
alwaysinline auto adc(reg64 rt, imm8 is) { op(2); }
|
|
alwaysinline auto add(reg64 rt, imm8 is) { op(0); }
|
|
alwaysinline auto and_(reg64 rt, imm8 is) { op(4); }
|
|
alwaysinline auto cmp(reg64 rt, imm8 is) { op(7); }
|
|
alwaysinline auto or_(reg64 rt, imm8 is) { op(1); }
|
|
alwaysinline auto sbb(reg64 rt, imm8 is) { op(3); }
|
|
alwaysinline auto sub(reg64 rt, imm8 is) { op(5); }
|
|
alwaysinline auto xor_(reg64 rt, imm8 is) { op(6); }
|
|
#undef op
|
|
|
|
#define op(code, group) \
|
|
if(rt == al) { \
|
|
emit.byte(code); \
|
|
emit.byte(is.data); \
|
|
} else { \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0x80); \
|
|
emit.modrm(3, group, rt & 7); \
|
|
emit.byte(is.data); \
|
|
}
|
|
alwaysinline auto adc(reg8 rt, imm8 is) { op(0x14, 2); }
|
|
alwaysinline auto add(reg8 rt, imm8 is) { op(0x04, 0); }
|
|
alwaysinline auto and_(reg8 rt, imm8 is) { op(0x24, 4); }
|
|
alwaysinline auto cmp(reg8 rt, imm8 is) { op(0x3c, 7); }
|
|
alwaysinline auto or_(reg8 rt, imm8 is) { op(0x0c, 1); }
|
|
alwaysinline auto sbb(reg8 rt, imm8 is) { op(0x1c, 3); }
|
|
alwaysinline auto sub(reg8 rt, imm8 is) { op(0x2c, 5); }
|
|
alwaysinline auto xor_(reg8 rt, imm8 is) { op(0x34, 6); }
|
|
#undef op
|
|
|
|
#define op(code, group) \
|
|
if(rt == eax) { \
|
|
emit.byte(code); \
|
|
emit.dword(is.data); \
|
|
} else { \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0x81); \
|
|
emit.modrm(3, group, rt & 7); \
|
|
emit.dword(is.data); \
|
|
}
|
|
alwaysinline auto adc(reg32 rt, imm32 is) { op(0x15, 2); }
|
|
alwaysinline auto add(reg32 rt, imm32 is) { op(0x05, 0); }
|
|
alwaysinline auto and_(reg32 rt, imm32 is) { op(0x25, 4); }
|
|
alwaysinline auto cmp(reg32 rt, imm32 is) { op(0x3d, 7); }
|
|
alwaysinline auto or_(reg32 rt, imm32 is) { op(0x0d, 1); }
|
|
alwaysinline auto sbb(reg32 rt, imm32 is) { op(0x1d, 3); }
|
|
alwaysinline auto sub(reg32 rt, imm32 is) { op(0x2d, 5); }
|
|
alwaysinline auto xor_(reg32 rt, imm32 is) { op(0x35, 6); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0xf7); \
|
|
emit.modrm(3, code, rt & 7);
|
|
alwaysinline auto not_(reg32 rt) { op(2); }
|
|
alwaysinline auto neg (reg32 rt) { op(3); }
|
|
alwaysinline auto mul (reg32 rt) { op(4); }
|
|
alwaysinline auto imul(reg32 rt) { op(5); }
|
|
alwaysinline auto div (reg32 rt) { op(6); }
|
|
alwaysinline auto idiv(reg32 rt) { op(7); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.rex(1, 0, 0, rt & 8); \
|
|
emit.byte(0xf7); \
|
|
emit.modrm(3, code, rt & 7);
|
|
alwaysinline auto not_(reg64 rt) { op(2); }
|
|
alwaysinline auto neg (reg64 rt) { op(3); }
|
|
alwaysinline auto mul (reg64 rt) { op(4); }
|
|
alwaysinline auto imul(reg64 rt) { op(5); }
|
|
alwaysinline auto div (reg64 rt) { op(6); }
|
|
alwaysinline auto idiv(reg64 rt) { op(7); }
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.byte(code); \
|
|
emit.byte(it.data);
|
|
#define r imm8 it{resolve(l, 1, 1)}
|
|
alwaysinline auto jmp (imm8 it) { op(0xeb); }
|
|
alwaysinline auto jmp8(label l) { r; op(0xeb); }
|
|
alwaysinline auto jnz (imm8 it) { op(0x75); }
|
|
alwaysinline auto jnz8(label l) { r; op(0x75); }
|
|
alwaysinline auto jz (imm8 it) { op(0x74); }
|
|
alwaysinline auto jz8 (label l) { r; op(0x74); }
|
|
#undef r
|
|
#undef op
|
|
|
|
#define op(code) \
|
|
emit.byte(0x0f); \
|
|
emit.byte(code); \
|
|
emit.dword(it.data);
|
|
#define r imm32 it{resolve(l, 2, 4)}
|
|
alwaysinline auto jnz(imm32 it) { op(0x85); }
|
|
alwaysinline auto jnz(label l) { r; op(0x85); }
|
|
alwaysinline auto jz (imm32 it) { op(0x84); }
|
|
alwaysinline auto jz (label l) { r; op(0x84); }
|
|
#undef r
|
|
#undef op
|
|
|
|
//op reg8
|
|
#define op(code) \
|
|
emit.rex(0, 0, 0, rt & 8); \
|
|
emit.byte(0x0f); \
|
|
emit.byte(code); \
|
|
emit.modrm(3, 0, rt & 7);
|
|
alwaysinline auto seta (reg8 rt) { op(0x97); }
|
|
alwaysinline auto setbe(reg8 rt) { op(0x96); }
|
|
alwaysinline auto setb (reg8 rt) { op(0x92); }
|
|
alwaysinline auto setc (reg8 rt) { op(0x92); }
|
|
alwaysinline auto setg (reg8 rt) { op(0x9f); }
|
|
alwaysinline auto setge(reg8 rt) { op(0x9d); }
|
|
alwaysinline auto setl (reg8 rt) { op(0x9c); }
|
|
alwaysinline auto setle(reg8 rt) { op(0x9e); }
|
|
alwaysinline auto setnc(reg8 rt) { op(0x93); }
|
|
alwaysinline auto setno(reg8 rt) { op(0x91); }
|
|
alwaysinline auto setnp(reg8 rt) { op(0x9b); }
|
|
alwaysinline auto setns(reg8 rt) { op(0x99); }
|
|
alwaysinline auto setnz(reg8 rt) { op(0x95); }
|
|
alwaysinline auto seto (reg8 rt) { op(0x90); }
|
|
alwaysinline auto setp (reg8 rt) { op(0x9a); }
|
|
alwaysinline auto sets (reg8 rt) { op(0x98); }
|
|
alwaysinline auto setz (reg8 rt) { op(0x94); }
|
|
#undef op
|
|
|
|
//op [reg64]
|
|
#define op(code) \
|
|
emit.rex(0, 0, 0, dt.reg & 8); \
|
|
emit.byte(0x0f); \
|
|
emit.byte(code); \
|
|
if(dt.reg == rsp || dt.reg == r12) { \
|
|
emit.modrm(0, 0, dt.reg & 7); \
|
|
emit.sib(0, 4, 4); \
|
|
} else if(dt.reg == rbp || dt.reg == r13) { \
|
|
emit.modrm(1, 0, dt.reg & 7); \
|
|
emit.byte(0x00); \
|
|
} else { \
|
|
emit.modrm(0, 0, dt.reg & 7); \
|
|
}
|
|
alwaysinline auto seta (dis dt) { op(0x97); }
|
|
alwaysinline auto setbe(dis dt) { op(0x96); }
|
|
alwaysinline auto setb (dis dt) { op(0x92); }
|
|
alwaysinline auto setc (dis dt) { op(0x92); }
|
|
alwaysinline auto setg (dis dt) { op(0x9f); }
|
|
alwaysinline auto setge(dis dt) { op(0x9d); }
|
|
alwaysinline auto setl (dis dt) { op(0x9c); }
|
|
alwaysinline auto setle(dis dt) { op(0x9e); }
|
|
alwaysinline auto setnc(dis dt) { op(0x93); }
|
|
alwaysinline auto setno(dis dt) { op(0x91); }
|
|
alwaysinline auto setnp(dis dt) { op(0x9b); }
|
|
alwaysinline auto setns(dis dt) { op(0x99); }
|
|
alwaysinline auto setnz(dis dt) { op(0x95); }
|
|
alwaysinline auto seto (dis dt) { op(0x90); }
|
|
alwaysinline auto setp (dis dt) { op(0x9a); }
|
|
alwaysinline auto sets (dis dt) { op(0x98); }
|
|
alwaysinline auto setz (dis dt) { op(0x94); }
|
|
#undef op
|
|
|
|
//op [reg64+imm8]
|
|
#define op(code) \
|
|
emit.rex(0, 0, 0, dt.reg & 8); \
|
|
emit.byte(0x0f); \
|
|
emit.byte(code); \
|
|
emit.modrm(1, 0, dt.reg & 7); \
|
|
if(dt.reg == rsp || dt.reg == r12) { \
|
|
emit.sib(0, 4, 4); \
|
|
} \
|
|
emit.byte(dt.imm);
|
|
alwaysinline auto seta (dis8 dt) { op(0x97); }
|
|
alwaysinline auto setbe(dis8 dt) { op(0x96); }
|
|
alwaysinline auto setb (dis8 dt) { op(0x92); }
|
|
alwaysinline auto setc (dis8 dt) { op(0x92); }
|
|
alwaysinline auto setg (dis8 dt) { op(0x9f); }
|
|
alwaysinline auto setge(dis8 dt) { op(0x9d); }
|
|
alwaysinline auto setl (dis8 dt) { op(0x9c); }
|
|
alwaysinline auto setle(dis8 dt) { op(0x9e); }
|
|
alwaysinline auto setnc(dis8 dt) { op(0x93); }
|
|
alwaysinline auto setno(dis8 dt) { op(0x91); }
|
|
alwaysinline auto setnp(dis8 dt) { op(0x9b); }
|
|
alwaysinline auto setns(dis8 dt) { op(0x99); }
|
|
alwaysinline auto setnz(dis8 dt) { op(0x95); }
|
|
alwaysinline auto seto (dis8 dt) { op(0x90); }
|
|
alwaysinline auto setp (dis8 dt) { op(0x9a); }
|
|
alwaysinline auto sets (dis8 dt) { op(0x98); }
|
|
alwaysinline auto setz (dis8 dt) { op(0x94); }
|
|
#undef op
|
|
|
|
//call imm64 (pseudo-op)
|
|
alwaysinline auto call(imm64 target, reg64 scratch) {
|
|
s64 dist = distance(target.data) - 5;
|
|
if(dist < INT32_MIN || dist > INT32_MAX) {
|
|
mov(scratch, target);
|
|
call(scratch);
|
|
} else {
|
|
call(imm32{dist});
|
|
}
|
|
}
|
|
|
|
//jmp label (pseudo-op)
|
|
alwaysinline auto jmp(label l) {
|
|
jmp(imm32{resolve(l, 1, 4)});
|
|
}
|
|
//};
|