int x86_jmp_forward( struct x86_function *p) { DUMP(); emit_1ub(p, 0xe9); emit_1i(p, 0); return x86_get_label(p); }
void x86_jcc( struct x86_function *p, enum x86_cc cc, int label ) { int offset = label - (x86_get_label(p) + 2); DUMP_I(cc); if (offset < 0) { /*assert(p->csr - p->store > -offset);*/ if (p->csr - p->store <= -offset) { /* probably out of memory (using the error_overflow buffer) */ return; } } if (offset <= 127 && offset >= -128) { emit_1ub(p, 0x70 + cc); emit_1b(p, (char) offset); } else { offset = label - (x86_get_label(p) + 6); emit_2ub(p, 0x0f, 0x80 + cc); emit_1i(p, offset); } }
/* Always use a 32bit offset for forward jumps: */ unsigned char *x86_jcc_forward( struct x86_function *p, enum x86_cc cc ) { emit_2ub(p, 0x0f, 0x80 + cc); emit_1i(p, 0); return x86_get_label(p); }
void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ) { DUMP_RI( dst, imm ); assert(dst.file == file_REG32); assert(dst.mod == mod_REG); emit_1ub(p, 0xb8 + dst.idx); emit_1i(p, imm); }
/* Always use a 32bit offset for forward jumps: */ int x86_jcc_forward( struct x86_function *p, enum x86_cc cc ) { DUMP_I(cc); emit_2ub(p, 0x0f, 0x80 + cc); emit_1i(p, 0); return x86_get_label(p); }
void x86_push_imm32( struct x86_function *p, int imm32 ) { DUMP_I( imm32 ); emit_1ub(p, 0x68); emit_1i(p, imm32); p->stack_offset += 4; }
void x86_mov_imm( struct x86_function *p, struct x86_reg dst, int imm ) { DUMP_RI( dst, imm ); if(dst.mod == mod_REG) x86_mov_reg_imm(p, dst, imm); else { emit_1ub(p, 0xc7); emit_modrm_noreg(p, 0, dst); emit_1i(p, imm); } }
void x86_jcc( struct x86_function *p, enum x86_cc cc, unsigned char *label ) { int offset = label - (x86_get_label(p) + 2); if (offset <= 127 && offset >= -128) { emit_1ub(p, 0x70 + cc); emit_1b(p, (char) offset); } else { offset = label - (x86_get_label(p) + 6); emit_2ub(p, 0x0f, 0x80 + cc); emit_1i(p, offset); } }
/** * Immediate group 1 instructions. */ static INLINE void x86_group1_imm( struct x86_function *p, unsigned op, struct x86_reg dst, int imm ) { assert(dst.file == file_REG32); assert(dst.mod == mod_REG); if(-0x80 <= imm && imm < 0x80) { emit_1ub(p, 0x83); emit_modrm_noreg(p, op, dst); emit_1b(p, (char)imm); } else { emit_1ub(p, 0x81); emit_modrm_noreg(p, op, dst); emit_1i(p, imm); } }
/* Build a modRM byte + possible displacement. No treatment of SIB * indexing. BZZT - no way to encode an absolute address. * * This is the "/r" field in the x86 manuals... */ static void emit_modrm( struct x86_function *p, struct x86_reg reg, struct x86_reg regmem ) { unsigned char val = 0; assert(reg.mod == mod_REG); /* TODO: support extended x86-64 registers */ assert(reg.idx < 8); assert(regmem.idx < 8); val |= regmem.mod << 6; /* mod field */ val |= reg.idx << 3; /* reg field */ val |= regmem.idx; /* r/m field */ emit_1ub(p, val); /* Oh-oh we've stumbled into the SIB thing. */ if (regmem.file == file_REG32 && regmem.idx == reg_SP && regmem.mod != mod_REG) { emit_1ub(p, 0x24); /* simplistic! */ } switch (regmem.mod) { case mod_REG: case mod_INDIRECT: break; case mod_DISP8: emit_1b(p, (char) regmem.disp); break; case mod_DISP32: emit_1i(p, regmem.disp); break; default: assert(0); break; } }
void x86_jmp( struct x86_function *p, int label) { DUMP_I( label ); emit_1ub(p, 0xe9); emit_1i(p, label - x86_get_label(p) - 4); }
/* michal: * Temporary. As I need immediate operands, and dont want to mess with the codegen, * I load the immediate into general purpose register and use it. */ void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ) { assert(dst.mod == mod_REG); emit_1ub(p, 0xb8 + dst.idx); emit_1i(p, imm); }
/* This doesn't work once we start reallocating & copying the * generated code on buffer fills, because the call is relative to the * current pc. */ void x86_call( struct x86_function *p, void (*label)()) { emit_1ub(p, 0xe8); emit_1i(p, cptr(label) - x86_get_label(p) - 4); }
void x86_jmp( struct x86_function *p, unsigned char *label) { emit_1ub(p, 0xe9); emit_1i(p, label - x86_get_label(p) - 4); }
unsigned char *x86_call_forward( struct x86_function *p) { emit_1ub(p, 0xe8); emit_1i(p, 0); return x86_get_label(p); }