<commit_before>#ifndef ASSEMBLER_X86_64_CPP_DNNNABGU
#define ASSEMBLER_X86_64_CPP_DNNNABGU

#include "x86_64-Assembler.h"

namespace snow {
namespace x86_64 {
	byte Assembler::rex_for_operands(const Register& reg, const Register& rm) {
		int flags = rex_for_operands(0, rm) | REX_WIDE_OPERAND;
		if (reg.extended())
			flags |= REX_EXTEND_REG;
		return flags;
	}
	
	byte Assembler::rex_for_operands(const Register& reg, const Address& rm) {
		int flags = rex_for_operands(reg, rm.reg());
		if (rm.wide())
			flags |= REX_WIDE_OPERAND;
		return flags;
	}
	
	byte Assembler::rex_for_operands(const Register& reg, const SIB& sib) {
		return rex_for_operands(0, reg) | rex_for_operands(0, sib);
	}
	
	byte Assembler::rex_for_operands(int, const Register& rm) {
		int flags = NO_REX;
		if (rm.extended())
			flags |= REX_EXTEND_RM;
		return flags;
	}
	
	byte Assembler::rex_for_operands(int, const Address& rm) {
		int flags = rex_for_operands(0, rm.reg());
		if (rm.wide())
			flags |= REX_WIDE_OPERAND;
		return flags;
	}
	
	byte Assembler::rex_for_operands(int, const SIB& sib) {
		int flags = NO_REX;
		if (sib.base().extended())
			flags |= REX_EXTEND_SIB_BASE;
		if (sib.index().extended())
			flags |= REX_EXTEND_SIB_INDEX;
		if (sib.wide())
			flags |= REX_WIDE_OPERAND;
		return flags;
	}
	
	Assembler::RM_MODE Assembler::mod_for_displacement(int32_t displacement) {
		if (displacement == 0)
			return RM_ADDRESS;
		else if ((int)(char)displacement == displacement)
			return RM_ADDRESS_DISP8;
		else
			return RM_ADDRESS_DISP32;
	}
	
	Assembler::RM_MODE Assembler::mod_for_address(const Address& addr) {
		RM_MODE mod = mod_for_displacement(addr.offset());
		if (mod == RM_ADDRESS && addr.reg() == rbp) {
			return RM_ADDRESS_DISP32;
		}
		return mod;
	}
	
	void Assembler::emit_opcodes(byte* ptr) {
		while (*ptr != (byte)'\x00') {
			emit(*ptr++);
		}
	}
	
	void Assembler::emit_immediate(const Immediate& imm, size_t bytes) {
		int64_t value = imm.data();
		byte* data = reinterpret_cast<byte*>(&value);
		for (size_t i = 0; i < bytes; ++i) {
			emit(data[i]);
		}
	}
	
	void Assembler::emit_sib(const SIB& sib) {
		byte scale = sib.scale() << 6 & 0xc0;
		byte index = sib.index().code() << 3 & 0x38;
		byte base = sib.base().code() & 0x07;
		emit(scale | index | base);
	}
	
	void Assembler::emit_operands(byte mod, byte reg, byte rm) {
		// masking to ensure that nothing spills over
		mod = (mod << 6) & 0xc0;
		reg = (reg << 3) & 0x38;
		rm &= 0x07;
		emit(mod | reg | rm);
	}
	
	void Assembler::emit_operands(byte opcode_ext, const Register& rm) {
		emit_operands(RM_REGISTER, opcode_ext, rm.code());
	}
	
	void Assembler::emit_operands(const Register& reg, const Register& rm) {
		if (rm == rsp)
			error("(x86_64 asm) Cannot use %rsp as target operand.");
		emit_operands(RM_REGISTER, reg.code(), rm.code());
	}
	
	void Assembler::emit_operands(byte opcode_ext, const Address& rm) {
		if (rm.reg() == rsp)
			error("(x86_64 asm) Cannot use %rsp as memory operand.");
		emit_operands(mod_for_address(rm), opcode_ext, rm.reg().code());
		emit_displacement(rm.offset());
	}
	
	void Assembler::emit_operands(const Register& reg, const Address& rm) {
		if (rm.reg() == rsp)
			error("(x86_64 asm) Cannot use %rsp as memory operand.");
		emit_operands(mod_for_address(rm), reg.code(), rm.reg().code());
		emit_displacement(rm.offset());
	}
	
	void Assembler::emit_operands(byte opcode_ext, const SIB& sib) {
		emit_operands(mod_for_displacement(sib.offset()), opcode_ext, 4);
		emit_sib(sib);
		emit_displacement(sib.offset());
	}
	
	void Assembler::emit_operands(const Register& reg, const SIB& sib) {
		emit_operands(mod_for_displacement(sib.offset()), reg.code(), 4);
		emit_sib(sib);
		emit_displacement(sib.offset());
	}
	
	void Assembler::emit_displacement(int32_t displacement) {
		switch (mod_for_displacement(displacement)) {
			case RM_ADDRESS_DISP8:
				emit(displacement);
				break;
			case RM_ADDRESS_DISP32:
				emit_immediate(Immediate(displacement), 4);
			default:
				break;
		}
	}
	
	void Assembler::emit_label_ref(const RefPtr<Label>& label) {
		if (label->bound()) {
			int offset = label->offset() - (this->offset() + 4);
			byte* _offset = reinterpret_cast<byte*>(&offset);
			for (int i = 0; i < 4; ++i) {
				emit(_offset[i]);
			}
		} else {
			m_UnboundLabelReferences.push_back(UnboundLabelReference(label, offset(), 4));
			for (int i = 0; i < 4; ++i) {
				emit(0x00);
			}
		}
	}

	void Assembler::add(const Immediate& src, const Register& dst) {
		emit_instr(0x81, 0, dst, REX_WIDE_OPERAND);
		emit_immediate(src);
	}
	
	void Assembler::add(const Immediate& src, const Address& dst) {
		emit_instr(0x81, 0, dst);
		emit_immediate(src);
	}
	
	void Assembler::add(const Register& src, const Register& dst) {
		emit_instr(0x01, src, dst, REX_WIDE_OPERAND);
	}
	
	void Assembler::add(const Register& src, const Address& dst) {
		emit_instr(0x01, src, dst);
	}

	void Assembler::add(const Address& src, const Register& dst) {
		emit_instr(0x03, dst, src, REX_WIDE_OPERAND);
	}
	
	void Assembler::bin_and(const Immediate& src, const Register& dst) {
		emit_instr(0x81, 4, dst);
		emit_immediate(src);
	}
	
	void Assembler::bin_and(const Immediate& src, const Address& dst) {
		emit_instr(0x81, 4, dst);
		emit_immediate(src);
	}
	
	void Assembler::bin_and(const Register& src, const Register& dst) {
		emit_instr(0x21, src, dst);
	}
	
	void Assembler::bin_and(const Register& src, const Address& dst) {
		emit_instr(0x21, src, dst);
	}

	void Assembler::bin_and(const Address& src, const Register& dst) {
		emit_instr(0x23, dst, src);
	}
	
	void Assembler::bswap(const Register& reg) {
		emit_rex(rex_for_operands(0, reg));
		emit(0x0f);
		emit(0xc8 + reg.code());
	}
	
	void Assembler::call(const Immediate& rel32off) {
		emit(0xe8);
		emit_immediate(rel32off, 4);
	}
	
	void Assembler::call(const Register& reg) {
		emit_instr(0xff, 2, reg);
	}
	
	void Assembler::call(const Address& addr) {
		emit_instr(0xff, 2, addr);
	}
	
	void Assembler::call(const Linker::Symbol& symb) {
		if (symb.external()) {
			mov(Immediate((int64_t)symb.address()), rax);
			call(rax);
		} else {
			call(Immediate(symb.offset() - (offset() + 5)));
		}
	}
	
	void Assembler::call(const std::string& symb) {
		#ifdef PIC
		mov(0, rbx);
		m_SymbolReferences.push_back(Linker::Info(symb, offset() - 8, 8));
		call(rbx);
		#else
		call(Immediate((int64_t)0));
		m_SymbolReferences.push_back(Linker::Info(symb, offset() - 4, 4, true, -4));
		#endif
	}
	
	void Assembler::call_far(const Address& addr) {
		emit_instr(0xff, 3, addr);
	}
	
	void Assembler::cmov(Condition cc, const Register& src, const Register& dst) {
		byte opcodes[2];
		opcodes[0] = 0x0f;
		opcodes[1] = 0x40 + cc;
		emit_instr(opcodes, dst, src);
	}
	
	void Assembler::cmov(Condition cc, const Address& src, const Register& dst) {
		byte opcodes[2];
		opcodes[0] = 0x0f;
		opcodes[1] = 0x40 + cc;
		emit_instr(opcodes, dst, src);
	}
	
	void Assembler::cmp(const Immediate& left, const Register& right, bool single_byte) {
		emit_instr(single_byte ? 0x80 : 0x81, 7, right);
		emit_immediate(left, single_byte ? 1 : 4);
	}
	
	void Assembler::cmp(const Register& left, const Register& right, bool single_byte) {
		emit_instr(single_byte ? 0x38 : 0x39, right, left, REX_WIDE_OPERAND);<commit_msg>x86-64: always use PIC for internal code. Non-PIC was causing problems -- probably a linker bug, but might also be because the code segments were too far apart (> 2^32)<commit_after>#ifndef ASSEMBLER_X86_64_CPP_DNNNABGU
#define ASSEMBLER_X86_64_CPP_DNNNABGU

#include "x86_64-Assembler.h"

namespace snow {
namespace x86_64 {
	byte Assembler::rex_for_operands(const Register& reg, const Register& rm) {
		int flags = rex_for_operands(0, rm) | REX_WIDE_OPERAND;
		if (reg.extended())
			flags |= REX_EXTEND_REG;
		return flags;
	}
	
	byte Assembler::rex_for_operands(const Register& reg, const Address& rm) {
		int flags = rex_for_operands(reg, rm.reg());
		if (rm.wide())
			flags |= REX_WIDE_OPERAND;
		return flags;
	}
	
	byte Assembler::rex_for_operands(const Register& reg, const SIB& sib) {
		return rex_for_operands(0, reg) | rex_for_operands(0, sib);
	}
	
	byte Assembler::rex_for_operands(int, const Register& rm) {
		int flags = NO_REX;
		if (rm.extended())
			flags |= REX_EXTEND_RM;
		return flags;
	}
	
	byte Assembler::rex_for_operands(int, const Address& rm) {
		int flags = rex_for_operands(0, rm.reg());
		if (rm.wide())
			flags |= REX_WIDE_OPERAND;
		return flags;
	}
	
	byte Assembler::rex_for_operands(int, const SIB& sib) {
		int flags = NO_REX;
		if (sib.base().extended())
			flags |= REX_EXTEND_SIB_BASE;
		if (sib.index().extended())
			flags |= REX_EXTEND_SIB_INDEX;
		if (sib.wide())
			flags |= REX_WIDE_OPERAND;
		return flags;
	}
	
	Assembler::RM_MODE Assembler::mod_for_displacement(int32_t displacement) {
		if (displacement == 0)
			return RM_ADDRESS;
		else if ((int)(char)displacement == displacement)
			return RM_ADDRESS_DISP8;
		else
			return RM_ADDRESS_DISP32;
	}
	
	Assembler::RM_MODE Assembler::mod_for_address(const Address& addr) {
		RM_MODE mod = mod_for_displacement(addr.offset());
		if (mod == RM_ADDRESS && addr.reg() == rbp) {
			return RM_ADDRESS_DISP32;
		}
		return mod;
	}
	
	void Assembler::emit_opcodes(byte* ptr) {
		while (*ptr != (byte)'\x00') {
			emit(*ptr++);
		}
	}
	
	void Assembler::emit_immediate(const Immediate& imm, size_t bytes) {
		int64_t value = imm.data();
		byte* data = reinterpret_cast<byte*>(&value);
		for (size_t i = 0; i < bytes; ++i) {
			emit(data[i]);
		}
	}
	
	void Assembler::emit_sib(const SIB& sib) {
		byte scale = sib.scale() << 6 & 0xc0;
		byte index = sib.index().code() << 3 & 0x38;
		byte base = sib.base().code() & 0x07;
		emit(scale | index | base);
	}
	
	void Assembler::emit_operands(byte mod, byte reg, byte rm) {
		// masking to ensure that nothing spills over
		mod = (mod << 6) & 0xc0;
		reg = (reg << 3) & 0x38;
		rm &= 0x07;
		emit(mod | reg | rm);
	}
	
	void Assembler::emit_operands(byte opcode_ext, const Register& rm) {
		emit_operands(RM_REGISTER, opcode_ext, rm.code());
	}
	
	void Assembler::emit_operands(const Register& reg, const Register& rm) {
		if (rm == rsp)
			error("(x86_64 asm) Cannot use %rsp as target operand.");
		emit_operands(RM_REGISTER, reg.code(), rm.code());
	}
	
	void Assembler::emit_operands(byte opcode_ext, const Address& rm) {
		if (rm.reg() == rsp)
			error("(x86_64 asm) Cannot use %rsp as memory operand.");
		emit_operands(mod_for_address(rm), opcode_ext, rm.reg().code());
		emit_displacement(rm.offset());
	}
	
	void Assembler::emit_operands(const Register& reg, const Address& rm) {
		if (rm.reg() == rsp)
			error("(x86_64 asm) Cannot use %rsp as memory operand.");
		emit_operands(mod_for_address(rm), reg.code(), rm.reg().code());
		emit_displacement(rm.offset());
	}
	
	void Assembler::emit_operands(byte opcode_ext, const SIB& sib) {
		emit_operands(mod_for_displacement(sib.offset()), opcode_ext, 4);
		emit_sib(sib);
		emit_displacement(sib.offset());
	}
	
	void Assembler::emit_operands(const Register& reg, const SIB& sib) {
		emit_operands(mod_for_displacement(sib.offset()), reg.code(), 4);
		emit_sib(sib);
		emit_displacement(sib.offset());
	}
	
	void Assembler::emit_displacement(int32_t displacement) {
		switch (mod_for_displacement(displacement)) {
			case RM_ADDRESS_DISP8:
				emit(displacement);
				break;
			case RM_ADDRESS_DISP32:
				emit_immediate(Immediate(displacement), 4);
			default:
				break;
		}
	}
	
	void Assembler::emit_label_ref(const RefPtr<Label>& label) {
		if (label->bound()) {
			int offset = label->offset() - (this->offset() + 4);
			byte* _offset = reinterpret_cast<byte*>(&offset);
			for (int i = 0; i < 4; ++i) {
				emit(_offset[i]);
			}
		} else {
			m_UnboundLabelReferences.push_back(UnboundLabelReference(label, offset(), 4));
			for (int i = 0; i < 4; ++i) {
				emit(0x00);
			}
		}
	}

	void Assembler::add(const Immediate& src, const Register& dst) {
		emit_instr(0x81, 0, dst, REX_WIDE_OPERAND);
		emit_immediate(src);
	}
	
	void Assembler::add(const Immediate& src, const Address& dst) {
		emit_instr(0x81, 0, dst);
		emit_immediate(src);
	}
	
	void Assembler::add(const Register& src, const Register& dst) {
		emit_instr(0x01, src, dst, REX_WIDE_OPERAND);
	}
	
	void Assembler::add(const Register& src, const Address& dst) {
		emit_instr(0x01, src, dst);
	}

	void Assembler::add(const Address& src, const Register& dst) {
		emit_instr(0x03, dst, src, REX_WIDE_OPERAND);
	}
	
	void Assembler::bin_and(const Immediate& src, const Register& dst) {
		emit_instr(0x81, 4, dst);
		emit_immediate(src);
	}
	
	void Assembler::bin_and(const Immediate& src, const Address& dst) {
		emit_instr(0x81, 4, dst);
		emit_immediate(src);
	}
	
	void Assembler::bin_and(const Register& src, const Register& dst) {
		emit_instr(0x21, src, dst);
	}
	
	void Assembler::bin_and(const Register& src, const Address& dst) {
		emit_instr(0x21, src, dst);
	}

	void Assembler::bin_and(const Address& src, const Register& dst) {
		emit_instr(0x23, dst, src);
	}
	
	void Assembler::bswap(const Register& reg) {
		emit_rex(rex_for_operands(0, reg));
		emit(0x0f);
		emit(0xc8 + reg.code());
	}
	
	void Assembler::call(const Immediate& rel32off) {
		emit(0xe8);
		emit_immediate(rel32off, 4);
	}
	
	void Assembler::call(const Register& reg) {
		emit_instr(0xff, 2, reg);
	}
	
	void Assembler::call(const Address& addr) {
		emit_instr(0xff, 2, addr);
	}
	
	void Assembler::call(const Linker::Symbol& symb) {
		if (symb.external()) {
			mov(Immediate((int64_t)symb.address()), rax);
			call(rax);
		} else {
			call(Immediate(symb.offset() - (offset() + 5)));
		}
	}
	
	void Assembler::call(const std::string& symb) {
		//#ifdef PIC
		mov(0, rbx);
		m_SymbolReferences.push_back(Linker::Info(symb, offset() - 8, 8));
		call(rbx);
		//#else
		//call(Immediate((int64_t)0));
		//m_SymbolReferences.push_back(Linker::Info(symb, offset() - 4, 4, true, -4));
		//#endif
	}
	
	void Assembler::call_far(const Address& addr) {
		emit_instr(0xff, 3, addr);
	}
	
	void Assembler::cmov(Condition cc, const Register& src, const Register& dst) {
		byte opcodes[2];
		opcodes[0] = 0x0f;
		opcodes[1] = 0x40 + cc;
		emit_instr(opcodes, dst, src);
	}
	
	void Assembler::cmov(Condition cc, const Address& src, const Register& dst) {
		byte opcodes[2];
		opcodes[0] = 0x0f;
		opcodes[1] = 0x40 + cc;
		emit_instr(opcodes, dst, src);
	}
	
	void Assembler::cmp(const Immediate& left, const Register& right, bool single_byte) {
		emit_instr(single_byte ? 0x80 : 0x81, 7, right);
		emit_immediate(left, single_byte ? 1 : 4);
	}
	
	void Assembler::cmp(const Register& left, const Register& right, bool single_byte) {
		emit_instr(single_byte ? 0x38 : 0x39, right, left, REX_WIDE_OPERAND);
{'fraction_non_alphanumeric': 0.14796438523754502, 'fraction_numerical': 0.024536124515734385, 'mean_word_length': 4.46379502413665, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3505866', 'n_tokens_mistral': 6474, 'n_tokens_neox': 5716, 'n_words': 1254}