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); }
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); }
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); }
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); }
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(); }
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); }
static void emit_register(const arch_register_t *reg) { be_emit_char('%'); be_emit_string(reg->name); }
static void amd64_emit_x87_size_suffix(x86_insn_size_t const size) { be_emit_char(get_x87_size_suffix(size)); }
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"); }
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)); }