static bool try_swap_inputs(ir_node *node) { /* commutative operation, just switch the inputs */ if (is_commutative(node)) { assert(get_amd64_attr_const(node)->op_mode == AMD64_OP_REG_REG); /* TODO: support Cmp input swapping */ ir_node *in0 = get_irn_n(node, 0); ir_node *in1 = get_irn_n(node, 1); set_irn_n(node, 0, in1); set_irn_n(node, 1, in0); return true; } return false; }
/** * Emit a Compare with conditional branch. */ static void emit_amd64_Jcc(const ir_node *irn) { const ir_node *proj_true = NULL; const ir_node *proj_false = NULL; const ir_node *block; const ir_node *next_block; const char *suffix; const amd64_attr_t *attr = get_amd64_attr_const(irn); ir_relation relation = attr->ext.relation; ir_node *op1 = get_irn_n(irn, 0); const amd64_attr_t *cmp_attr = get_amd64_attr_const(op1); bool is_signed = !cmp_attr->data.cmp_unsigned; assert(is_amd64_Cmp(op1)); foreach_out_edge(irn, edge) { ir_node *proj = get_edge_src_irn(edge); long nr = get_Proj_proj(proj); if (nr == pn_Cond_true) { proj_true = proj; } else { proj_false = proj; } }
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); }