예제 #1
0
static void emit_register_mode(const arch_register_t *reg,
                               x86_insn_size_t size)
{
	if (reg->cls == &amd64_reg_classes[CLASS_amd64_xmm]) {
		emit_register(reg);
	} else {
		emit_register_sized(reg, size);
	}
}
void SourceAssembler::emit_instruction(const char* format, va_list arguments) {
  // Due to a peculiarity in the Microsoft SourceAssembler we have to
  // make a special case out of jumps and calls. Try figuring out if
  // it's either of them.
  const bool jump_or_call = (strncmp(format, "jmp", 3) == 0) || (strncmp(format, "call", 4) == 0);
  const bool loop = (strncmp(format, "loop", 4) == 0);
  const bool is_int3 = (strncmp(format, "int 3", 5) == 0);
  const bool has_cl = (strlen(format) > 10 && strncmp(format+10, "cl", 2) == 0);
if (!GenerateGNUCode) {
  bool has_externals = emit_externals(format, arguments);
  emit("\t");
  if (GenerateInlineAsm)
    emit("__asm ");
  while (*format) {
    if (*format == '%') {
      format++;
      
      // Parse the size specifier.
      OperandSize size = long_operand;
      switch (*format) {
      case 't' : size = very_very_long_operand; format++; break;
      case 'v' : size = very_long_operand; format++;      break;
      case 'l' : size = long_operand; format++;           break;
      case 'w' : size = word_operand; format++;           break;
      case 'b' : size = byte_operand; format++;           break;
      }

      switch (*format) {
      case 'c' : { // Constant
        const Constant* cst = va_arg(arguments, const Constant *);
        if (!cst->is_immediate() && !jump_or_call) {
          emit("offset ");
        }
        emit_constant(*cst);
        break;
      }
      case 'a' : { // Address. 
        const Address* adr = va_arg(arguments, const Address *);
        emit_address(*adr, size);
        break; 
      }
      case 'r' : { // Register.
        const Register* reg = va_arg(arguments, const Register *);
        emit_register(*reg, size);
        break;
      }
      }  
    } else {
예제 #3
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);
}