Beispiel #1
0
static void amd64_emit_insn_mode_suffix(amd64_insn_mode_t mode)
{
	char c;
	switch (mode) {
	case INSN_MODE_8:  c = 'b'; break;
	case INSN_MODE_16: c = 'w'; break;
	case INSN_MODE_32: c = 'l'; break;
	case INSN_MODE_64: c = 'q'; break;
	default:
		panic("invalid insn mode");
	}
	be_emit_char(c);
}
Beispiel #2
0
static void amd64_emit_mode_suffix(const ir_mode *mode)
{
	assert(mode_is_int(mode) || mode_is_reference(mode));
	char c;
	switch (get_mode_size_bits(mode)) {
	case 8:  c = 'b'; break;
	case 16: c = 'w'; break;
	case 32: c = 'l'; break;
	case 64: c = 'q'; break;
	default:
		panic("Can't output mode_suffix for %+F", mode);
	}
	be_emit_char(c);
}
Beispiel #3
0
static void emit_register_mode(const arch_register_t *reg, const ir_mode *mode)
{
	const char *name;
	switch (get_mode_size_bits(mode)) {
	case 8:  name = get_8bit_name(reg);  break;
	case 16: name = get_16bit_name(reg); break;
	case 32: name = get_32bit_name(reg); break;
	case 64: name = reg->name;           break;
	default:
		panic("invalid mode");
	}
	be_emit_char('%');
	be_emit_string(name);
}
Beispiel #4
0
static void emit_register_insn_mode(const arch_register_t *reg,
                                    amd64_insn_mode_t mode)
{
	const char *name;
	switch (mode) {
	case INSN_MODE_8:  name = get_8bit_name(reg);  break;
	case INSN_MODE_16: name = get_16bit_name(reg); break;
	case INSN_MODE_32: name = get_32bit_name(reg); break;
	case INSN_MODE_64: name = reg->name;           break;
	default:
		panic("invalid mode");
	}
	be_emit_char('%');
	be_emit_string(name);
}
Beispiel #5
0
void be_emit_finish_line_gas(const ir_node *node)
{
	if (node && be_options.verbose_asm) {
		be_emit_pad_comment();
		dbg_info   *const dbg = get_irn_dbg_info(node);
		src_loc_t   const loc = ir_retrieve_dbg_info(dbg);
		char const *const fmt =
			!loc.file       ? "/* %+F */\n"       :
			loc.line   == 0 ? "/* %+F %s */\n"    :
			loc.column == 0 ? "/* %+F %s:%u */\n" :
			/*             */ "/* %+F %s:%u:%u */\n";
		be_emit_irprintf(fmt, node, loc.file, loc.line, loc.column);
	} else {
		be_emit_char('\n');
	}
	be_emit_write_line();
}
Beispiel #6
0
void amd64_emitf(ir_node const *const node, char const *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);

	be_emit_char('\t');
	for (;;) {
		char const *start = fmt;

		while (*fmt != '%' && *fmt != '\n' && *fmt != '\0')
			++fmt;
		if (fmt != start) {
			be_emit_string_len(start, fmt - start);
		}

		if (*fmt == '\n') {
			be_emit_char('\n');
			be_emit_write_line();
			be_emit_char('\t');
			++fmt;
			continue;
		}

		if (*fmt == '\0')
			break;

		++fmt;
		amd64_emit_mod_t mod = EMIT_NONE;
		for (;;) {
			switch (*fmt) {
			case '#': mod |= EMIT_RESPECT_LS;  break;
			case '^': mod |= EMIT_IGNORE_MODE; break;
			default:
				goto end_of_mods;
			}
			++fmt;
		}
end_of_mods:

		switch (*fmt++) {
			arch_register_t const *reg;

			case '%':
				be_emit_char('%');
				break;

			case 'C': {
				amd64_attr_t const *const attr = get_amd64_attr_const(node);
				/* FIXME: %d is a hack... we must emit 64bit constants, or sign
				 * extended 32bit constants... */
				be_emit_irprintf("$%d", attr->ext.imm_value);
				break;
			}

			case 'D':
				if (*fmt < '0' || '9' <= *fmt)
					goto unknown;
				reg = arch_get_irn_register_out(node, *fmt++ - '0');
				goto emit_R;

			case 'E': {
				ir_entity const *const ent = va_arg(ap, ir_entity const*);
				be_gas_emit_entity(ent);
				break;
			}

			case 'L': {
				ir_node *const block = get_cfop_target_block(node);
				be_gas_emit_block_name(block);
				break;
			}

			case 'O': {
				amd64_SymConst_attr_t const *const attr = get_amd64_SymConst_attr_const(node);
				if (attr->fp_offset)
					be_emit_irprintf("%d", attr->fp_offset);
				break;
			}

			case 'R':
				reg = va_arg(ap, arch_register_t const*);
emit_R:
				if (mod & EMIT_IGNORE_MODE) {
					emit_register(reg);
				} else {
					amd64_attr_t const *const attr = get_amd64_attr_const(node);
					if (mod & EMIT_RESPECT_LS) {
						emit_register_mode(reg, attr->ls_mode);
					} else {
						emit_register_insn_mode(reg, attr->data.insn_mode);
					}
				}
				break;

			case 'S': {
				int pos;
				if ('0' <= *fmt && *fmt <= '9') {
					pos = *fmt++ - '0';
				} else {
					goto unknown;
				}
				reg = arch_get_irn_register_in(node, pos);
				goto emit_R;
			}

			case 'M': {
				amd64_attr_t const *const attr = get_amd64_attr_const(node);
				if (mod & EMIT_RESPECT_LS) {
					amd64_emit_mode_suffix(attr->ls_mode);
				} else {
					amd64_emit_insn_mode_suffix(attr->data.insn_mode);
				}
				break;
			}

			case 'd': {
				int const num = va_arg(ap, int);
				be_emit_irprintf("%d", num);
				break;
			}

			case 's': {
				char const *const str = va_arg(ap, char const*);
				be_emit_string(str);
				break;
			}

			case 'u': {
				unsigned const num = va_arg(ap, unsigned);
				be_emit_irprintf("%u", num);
				break;
			}

			case 'c': {
				amd64_attr_t const *const attr = get_amd64_attr_const(node);
				ir_mode                  *mode = attr->ls_mode;
				if (get_mode_size_bits(mode) == 64)
					break;
				if (get_mode_size_bits(mode) == 32 && !mode_is_signed(mode)
				 && attr->data.insn_mode == INSN_MODE_32)
					break;
				be_emit_char(mode_is_signed(mode) ? 's' : 'z');
				amd64_emit_mode_suffix(mode);
				break;
			}

			default:
unknown:
				panic("unknown format conversion");
		}
	}

	be_emit_finish_line_gas(node);
	va_end(ap);
}
Beispiel #7
0
static void emit_register(const arch_register_t *reg)
{
	be_emit_char('%');
	be_emit_string(reg->name);
}
Beispiel #8
0
static void amd64_emit_x87_size_suffix(x86_insn_size_t const size)
{
	be_emit_char(get_x87_size_suffix(size));
}
Beispiel #9
0
static void amd64_emit_am(const ir_node *const node, bool indirect_star)
{
	const amd64_addr_attr_t *const attr = get_amd64_addr_attr_const(node);

	switch ((amd64_op_mode_t)attr->base.op_mode) {
	case AMD64_OP_REG_IMM: {
		const amd64_binop_addr_attr_t *const binop_attr
			= (const amd64_binop_addr_attr_t*)attr;
		be_emit_char('$');
		x86_emit_imm32(&binop_attr->u.immediate);
		be_emit_cstring(", ");
		goto emit_addr_reg;
	}
	case AMD64_OP_REG_REG: {
		const arch_register_t *reg1 = arch_get_irn_register_in(node, 1);
		emit_register_mode(reg1, attr->base.size);
		be_emit_cstring(", ");
		goto emit_addr_reg;
	}
	case AMD64_OP_REG_ADDR: {
		const amd64_binop_addr_attr_t *const binop_attr
			= (const amd64_binop_addr_attr_t*)attr;
		x86_emit_addr(node, &attr->addr);
		be_emit_cstring(", ");
		const arch_register_t *reg
			= arch_get_irn_register_in(node, binop_attr->u.reg_input);
		emit_register_mode(reg, binop_attr->base.base.size);
		return;
	}
	case AMD64_OP_ADDR_IMM: {
		const amd64_binop_addr_attr_t *const binop_attr
			= (const amd64_binop_addr_attr_t*)attr;
		be_emit_char('$');
		x86_emit_imm32(&binop_attr->u.immediate);
		be_emit_cstring(", ");
		goto emit_addr;
	}
	case AMD64_OP_ADDR:
	case AMD64_OP_X87_ADDR_REG:
		if (indirect_star)
			be_emit_char('*');
		goto emit_addr;
	case AMD64_OP_ADDR_REG: {
		amd64_binop_addr_attr_t const *const binop_attr = (amd64_binop_addr_attr_t const*)attr;
		arch_register_t const *const reg = arch_get_irn_register_in(node, binop_attr->u.reg_input);
		emit_register_mode(reg, binop_attr->base.base.size);
		be_emit_cstring(", ");
emit_addr:
		x86_emit_addr(node, &attr->addr);
		return;
	}
	case AMD64_OP_REG: {
		if (indirect_star)
			be_emit_char('*');
emit_addr_reg:
		assert(attr->addr.variant == X86_ADDR_REG);
		arch_register_t const *const reg
			= arch_get_irn_register_in(node, attr->addr.base_input);
		emit_register_mode(reg, attr->base.size);
		return;
	}
	case AMD64_OP_IMM32:
		x86_emit_imm32(&attr->addr.immediate);
		return;

	case AMD64_OP_X87:
		return;
	case AMD64_OP_IMM64:
	case AMD64_OP_NONE:
	case AMD64_OP_SHIFT_REG:
	case AMD64_OP_SHIFT_IMM:
	case AMD64_OP_CC:
		break;
	}
	panic("invalid op_mode");
}
Beispiel #10
0
static void emit_register_sized(const arch_register_t *reg,
                                const x86_insn_size_t size)
{
	be_emit_char('%');
	be_emit_string(get_register_name_mode(reg, size));
}