void Assembler::movsd(XMMRegister src, Indirect dest) { int rex = 0; int src_idx = src.regnum; int dest_idx = dest.base.regnum; if (src_idx >= 8) { rex |= REX_R; src_idx -= 8; } if (dest_idx >= 8) { trap(); rex |= REX_B; dest_idx -= 8; } emitByte(0xf2); if (rex) emitRex(rex); emitByte(0x0f); emitByte(0x11); bool needssib = (dest_idx == 0b100); int mode = getModeFromOffset(dest.offset, dest_idx); emitModRM(mode, src_idx, dest_idx); if (needssib) emitSIB(0b00, 0b100, dest_idx); if (mode == 0b01) { emitByte(dest.offset); } else if (mode == 0b10) { emitInt(dest.offset, 4); } }
void Assembler::incl(Indirect mem) { int src_idx = mem.base.regnum; int rex = 0; if (src_idx >= 8) { rex |= REX_B; src_idx -= 8; } assert(src_idx >= 0 && src_idx < 8); bool needssib = (src_idx == 0b100); if (rex) emitRex(rex); emitByte(0xff); assert(-0x80 <= mem.offset && mem.offset < 0x80); if (mem.offset == 0) { emitModRM(0b00, 0, src_idx); if (needssib) emitSIB(0b00, 0b100, src_idx); } else { emitModRM(0b01, 0, src_idx); if (needssib) emitSIB(0b00, 0b100, src_idx); emitByte(mem.offset); } }
void Assembler::movq(Immediate src, Indirect dest) { int64_t src_val = src.val; assert(fitsInto<int32_t>(src_val)); int rex = REX_W; int dest_idx = dest.base.regnum; if (dest_idx >= 8) { rex |= REX_B; dest_idx -= 8; } emitRex(rex); emitByte(0xc7); bool needssib = (dest_idx == 0b100); int mode = getModeFromOffset(dest.offset, dest_idx); emitModRM(mode, 0, dest_idx); if (needssib) emitSIB(0b00, 0b100, dest_idx); if (mode == 0b01) { emitByte(dest.offset); } else if (mode == 0b10) { emitInt(dest.offset, 4); } emitInt(src_val, 4); }
void Assembler::mov(Register src, Indirect dest) { int rex = REX_W; int src_idx = src.regnum; int dest_idx = dest.base.regnum; assert(src_idx != dest_idx && "while valid this is almost certainly a register allocator bug"); if (src_idx >= 8) { rex |= REX_R; src_idx -= 8; } if (dest_idx >= 8) { rex |= REX_B; dest_idx -= 8; } emitRex(rex); emitByte(0x89); bool needssib = (dest_idx == 0b100); int mode = getModeFromOffset(dest.offset, dest_idx); emitModRM(mode, src_idx, dest_idx); if (needssib) emitSIB(0b00, 0b100, dest_idx); if (mode == 0b01) { emitByte(dest.offset); } else if (mode == 0b10) { emitInt(dest.offset, 4); } }
static void emitMOVZX_EAX_WORD( int off ) // movzx eax,off[ecx] { emitByte( 0x0f ); emitByte( 0xb7 ); emitByte( 0x41 ); emitByte( off ); }
void Assembler::decq(Immediate imm) { emitByte(0x48); emitByte(0xff); emitByte(0x0c); emitByte(0x25); emitInt(imm.val, 4); }
void Assembler::cmp(Indirect mem, Register reg) { int mem_idx = mem.base.regnum; int reg_idx = reg.regnum; int rex = REX_W; if (mem_idx >= 8) { rex |= REX_B; mem_idx -= 8; } if (reg_idx >= 8) { rex |= REX_R; reg_idx -= 8; } assert(mem_idx >= 0 && mem_idx < 8); assert(reg_idx >= 0 && reg_idx < 8); emitRex(rex); emitByte(0x3B); if (mem.offset == 0) { emitModRM(0b00, reg_idx, mem_idx); } else if (-0x80 <= mem.offset && mem.offset < 0x80) { emitModRM(0b01, reg_idx, mem_idx); emitByte(mem.offset); } else { assert(fitsInto<int32_t>(mem.offset)); emitModRM(0b10, reg_idx, mem_idx); emitInt(mem.offset, 4); } }
void Assembler::emitArith(Immediate imm, Register r, int opcode) { // assert(r != RSP && "This breaks unwinding, please don't use."); int64_t amount = imm.val; RELEASE_ASSERT((-1L << 31) <= amount && amount < (1L << 31) - 1, ""); assert(0 <= opcode && opcode < 8); int rex = REX_W; int reg_idx = r.regnum; if (reg_idx >= 8) { rex |= REX_B; reg_idx -= 8; } emitRex(rex); if (-0x80 <= amount && amount < 0x80) { emitByte(0x83); emitModRM(0b11, opcode, reg_idx); emitByte(amount); } else { emitByte(0x81); emitModRM(0b11, opcode, reg_idx); emitInt(amount, 4); } }
void Assembler::cmp(Indirect mem, Immediate imm) { int64_t val = imm.val; assert((-1L << 31) <= val && val < (1L << 31) - 1); int src_idx = mem.base.regnum; int rex = REX_W; if (src_idx >= 8) { rex |= REX_B; src_idx -= 8; } assert(src_idx >= 0 && src_idx < 8); emitRex(rex); emitByte(0x81); assert(-0x80 <= mem.offset && mem.offset < 0x80); if (mem.offset == 0) { emitModRM(0b00, 7, src_idx); } else { emitModRM(0b01, 7, src_idx); emitByte(mem.offset); } emitInt(val, 4); }
void Assembler::lea(Indirect mem, Register reg) { int mem_idx = mem.base.regnum; int reg_idx = reg.regnum; int rex = REX_W; if (mem_idx >= 8) { rex |= REX_B; mem_idx -= 8; } if (reg_idx >= 8) { rex |= REX_R; reg_idx -= 8; } assert(mem_idx >= 0 && mem_idx < 8); assert(reg_idx >= 0 && reg_idx < 8); emitRex(rex); emitByte(0x8D); bool needssib = (mem_idx == 0b100); int mode = getModeFromOffset(mem.offset, mem_idx); emitModRM(mode, reg_idx, mem_idx); if (needssib) emitSIB(0b00, 0b100, mem_idx); if (mode == 0b01) { emitByte(mem.offset); } else if (mode == 0b10) { assert(fitsInto<int32_t>(mem.offset)); emitInt(mem.offset, 4); } }
void Assembler::emitArith(Immediate imm, Register r, int opcode, MovType type) { // assert(r != RSP && "This breaks unwinding, please don't use."); int64_t amount = imm.val; RELEASE_ASSERT(fitsInto<int32_t>(amount), ""); assert(0 <= opcode && opcode < 8); assert(type == MovType::Q || type == MovType::L); int rex = type == MovType::Q ? REX_W : 0; int reg_idx = r.regnum; if (reg_idx >= 8) { rex |= REX_B; reg_idx -= 8; } if (rex) emitRex(rex); if (-0x80 <= amount && amount < 0x80) { emitByte(0x83); emitModRM(0b11, opcode, reg_idx); emitByte(amount); } else { emitByte(0x81); emitModRM(0b11, opcode, reg_idx); emitInt(amount, 4); } }
void Assembler::callq(Register r) { assert(r == R11 && "untested"); emitRex(REX_B); emitByte(0xff); emitByte(0xd3); }
static void emitWord( unsigned short word ) { char hi,lo; hi = word >> 8; lo = word & 0xff; emitByte( lo ); emitByte( hi ); }
void actionsDir1(opcodeTableEntryType *opcode, int numberOfOperands, valueType **evaluatedOperands) { #define ZERO_PAGE_ADDRESS_BIT 0x00 #define NON_ZERO_PAGE_ADDRESS_BIT 0x08 if(class==EXPRESSION_OPND && isByteAddress(operand) && isDefined(operand)){ emitByte(binary | ZERO_PAGE_ADDRESS_BIT); emitByte(address); } else if (wordCheck(address)) {
void Assembler::jmp(JumpDestination dest) { assert(dest.type == JumpDestination::FROM_START); int offset = dest.offset - (addr - start_addr) - 2; if (offset >= -0x80 && offset < 0x80) { emitByte(0xeb); emitByte(offset); } else { offset -= 3; emitByte(0xe9); emitInt(offset, 4); } }
/* * emitCode - generate callback code for a specified argument list */ static int emitCode( int argcnt, int bytecnt, char *array, DWORD fn, int is_cdecl ) { int i; int offset; emitOffset = 0; emitMOV_EBX_const( fn ); // 32-bit callback routine /* * emit code to push parms from 16-bit stack onto 32-bit stack */ offset = bytecnt + 6; if( is_cdecl ) { i = argcnt-1; } else { i = 0; } while( argcnt > 0 ) { if( array[i] == CB_DWORD ) { offset -= 4; emitMOV_EAX_DWORD( offset ); } else { offset -= 2; emitMOVZX_EAX_WORD( offset ); } emitByte( PUSH_EAX ); if( is_cdecl ) { i--; } else { i++; } --argcnt; } emitByte( PUSH_ES ); emitByte( POP_DS ); emitByte( PUSH_CS ); emitCALL_EBX(); if( is_cdecl ) { emitADD_ESP_const( bytecnt ); emitMOV_DL_const( 0 ); } else { emitMOV_DL_const( bytecnt ); } emitByte( RET ); return( emitOffset ); } /* emitCode */
void Assembler::set_cond(Register reg, ConditionCode condition) { int reg_idx = reg.regnum; assert(0 <= reg_idx && reg_idx < 8); int rex = 0; // Have to emit a blank REX when accessing RSP/RBP/RDI/RSI, // since without it this instruction will refer to ah/bh/ch/dh. if (reg_idx >= 4 || rex) emitRex(rex); emitByte(0x0f); emitByte(0x90 + condition); emitModRM(0b11, 0, reg_idx); }
void process_org() { int64_t new_address; NextToken(); new_address = expr(); if (!rel_out) { if (segment==bssseg || segment==tlsseg) { bss_address = new_address; sections[segment].address = new_address; } else { if (first_org && segment==codeseg) { code_address = new_address; start_address = new_address; sections[0].address = new_address; first_org = 0; } else { while(sections[0].address < new_address) emitByte(0x00); } } } ScanToEOL(); }
void Assembler::jmp(Indirect dest) { int reg_idx = dest.base.regnum; assert(reg_idx >= 0 && reg_idx < 8 && "not yet implemented"); emitByte(0xFF); if (dest.offset == 0) { emitModRM(0b00, 0b100, reg_idx); } else if (-0x80 <= dest.offset && dest.offset < 0x80) { emitModRM(0b01, 0b100, reg_idx); emitByte(dest.offset); } else { assert((-1L << 31) <= dest.offset && dest.offset < (1L << 31) - 1); emitModRM(0b10, 0b100, reg_idx); emitInt(dest.offset, 4); } }
void process_fill() { char sz = 'b'; int64_t count; int64_t val; int64_t nn; if (*inptr=='.') { inptr++; if (strchr("bchwBCHW",*inptr)) { sz = tolower(*inptr); inptr++; } else printf("Illegal fill size.\r\n"); } SkipSpaces(); NextToken(); count = expr(); prevToken(); need(','); NextToken(); val = expr(); prevToken(); for (nn = 0; nn < count; nn++) switch(sz) { case 'b': emitByte(val); break; case 'c': emitChar(val); break; case 'h': emitHalf(val); break; case 'w': emitWord(val); break; } }
void Assembler::movsd(Indirect src, XMMRegister dest) { int rex = 0; int src_idx = src.base.regnum; int dest_idx = dest.regnum; if (src_idx >= 8) { trap(); rex |= REX_R; src_idx -= 8; } if (dest_idx >= 8) { trap(); rex |= REX_B; dest_idx -= 8; } emitByte(0xf2); if (rex) emitRex(rex); emitByte(0x0f); emitByte(0x10); bool needssib = (src_idx == 0b100); int mode; if (src.offset == 0) mode = 0b00; else if (-0x80 <= src.offset && src.offset < 0x80) mode = 0b01; else mode = 0b10; emitModRM(mode, dest_idx, src_idx); if (needssib) emitSIB(0b00, 0b100, src_idx); if (mode == 0b01) { emitByte(src.offset); } else if (mode == 0b10) { emitInt(src.offset, 4); } }
void Assembler::clear_reg(Register reg) { int reg_idx = reg.regnum; // we don't need to generate a REX_W because 32bit instructions will clear the upper 32bits. if (reg_idx >= 8) { emitRex(REX_R | REX_B); reg_idx -= 8; } emitByte(0x31); emitModRM(0b11, reg_idx, reg_idx); }
void Assembler::emitInt(int64_t n, int bytes) { assert(bytes > 0 && bytes <= 8); if (bytes < 8) assert((-1L << (8 * bytes - 1)) <= n && n <= ((1L << (8 * bytes - 1)) - 1)); for (int i = 0; i < bytes; i++) { emitByte(n & 0xff); n >>= 8; } ASSERT(n == 0 || n == -1, "%ld", n); }
void Violet::Generator::assemble() { emitByte(RETURN); for(int i = 0; i < this->scopes.size(); i++) { (this->scopes[i])->locals.reserve( (this->scopes[i])->local_bytes.size() ); } }
void Assembler::emitUInt(uint64_t n, int bytes) { assert(bytes > 0 && bytes <= 8); if (bytes < 8) assert(n < ((1UL << (8 * bytes)))); for (int i = 0; i < bytes; i++) { emitByte(n & 0xff); n >>= 8; } ASSERT(n == 0, "%lu", n); }
void ByteData::emitOpcode (opcode _opcode) { int opcodeLength = _opcode.size(); opcode::iterator opcode_it = _opcode.begin(); for (int i = 0; i < opcodeLength; i++) { emitByte (*opcode_it); ++opcode_it; } }
void process_db() { int64_t val; SkipSpaces(); //NextToken(); while(token!=tk_eol) { SkipSpaces(); if (*inptr=='\n') break; if (*inptr=='"') { inptr++; while (*inptr!='"') { if (*inptr=='\\') { inptr++; switch(*inptr) { case '\\': emitByte('\\'); inptr++; break; case 'r': emitByte(0x13); inptr++; break; case 'n': emitByte(0x0A); inptr++; break; case 'b': emitByte('\b'); inptr++; break; case '"': emitByte('"'); inptr++; break; default: inptr++; break; } } else { emitByte(*inptr); inptr++; } } inptr++; } else if (*inptr=='\'') { inptr++; emitByte(*inptr); inptr++; if (*inptr!='\'') { printf("Missing ' in character constant.\r\n"); } } else { NextToken(); val = expr(); emitByte(val & 255); prevToken(); } SkipSpaces(); if (*inptr!=',') break; inptr++; } ScanToEOL(); }
void Assembler::jmp_cond(JumpDestination dest, ConditionCode condition) { bool unlikely = false; assert(dest.type == JumpDestination::FROM_START); int offset = dest.offset - (addr - start_addr) - 2; if (unlikely) offset--; if (offset >= -0x80 && offset < 0x80) { if (unlikely) emitByte(0x2e); emitByte(0x70 | condition); emitByte(offset); } else { offset -= 4; if (unlikely) emitByte(0x2e); emitByte(0x0f); emitByte(0x80 | condition); emitInt(offset, 4); } }
void Assembler::movq(Immediate src, Indirect dest) { int64_t src_val = src.val; assert((-1L << 31) <= src_val && src_val < (1L << 31) - 1); int rex = REX_W; int dest_idx = dest.base.regnum; if (dest_idx >= 8) { rex |= REX_B; dest_idx -= 8; } emitRex(rex); emitByte(0xc7); bool needssib = (dest_idx == 0b100); int mode; if (dest.offset == 0) mode = 0b00; else if (-0x80 <= dest.offset && dest.offset < 0x80) mode = 0b01; else mode = 0b10; emitModRM(mode, 0, dest_idx); if (needssib) emitSIB(0b00, 0b100, dest_idx); if (mode == 0b01) { emitByte(dest.offset); } else if (mode == 0b10) { emitInt(dest.offset, 4); } emitInt(src_val, 4); }
void Assembler::mov(Immediate val, Register dest) { int rex = REX_W; int dest_idx = dest.regnum; if (dest_idx >= 8) { rex |= REX_B; dest_idx -= 8; } emitRex(rex); emitByte(0xb8 + dest_idx); emitInt(val.val, 8); }