X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fbe%2Fia32%2Fia32_emitter.c;h=34c75bb322cc186d66808e197a9f8525c1bd0406;hb=d0bb153368997acebe0339c165bec2ec3235581b;hp=088ef5141602a6de9f12b0f8176c50fad939485a;hpb=ff4acf5218ebcb851bb04d2cc4181b456833d5d8;p=libfirm diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 088ef5141..34c75bb32 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -23,9 +23,7 @@ * @author Christian Wuerdig, Matthias Braun * @version $Id$ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include @@ -68,7 +66,6 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) #define SNPRINTF_BUF_LEN 128 -static const arch_env_t *arch_env; static const ia32_isa_t *isa; static ia32_code_gen_t *cg; static int do_pic; @@ -129,7 +126,7 @@ static const arch_register_t *get_in_reg(const ir_node *irn, int pos) in register we need. */ op = get_irn_n(irn, pos); - reg = arch_get_irn_register(arch_env, op); + reg = arch_get_irn_register(op); assert(reg && "no in register found"); @@ -138,10 +135,7 @@ static const arch_register_t *get_in_reg(const ir_node *irn, int pos) /* in case of unknown register: just return a valid register */ if (reg == &ia32_gp_regs[REG_GP_UKNWN]) { - const arch_register_req_t *req; - - /* ask for the requirements */ - req = arch_get_register_req(arch_env, irn, pos); + const arch_register_req_t *req = arch_get_register_req(irn, pos); if (arch_register_req_is(req, limited)) { /* in case of limited requirements: get the first allowed register */ @@ -171,7 +165,7 @@ static const arch_register_t *get_out_reg(const ir_node *irn, int pos) if (get_irn_mode(irn) != mode_T) { assert(pos == 0); - reg = arch_get_irn_register(arch_env, irn); + reg = arch_get_irn_register(irn); } else if (is_ia32_irn(irn)) { reg = get_ia32_out_reg(irn, pos); } else { @@ -181,7 +175,7 @@ static const arch_register_t *get_out_reg(const ir_node *irn, int pos) proj = get_edge_src_irn(edge); assert(is_Proj(proj) && "non-Proj from mode_T node"); if (get_Proj_proj(proj) == pos) { - reg = arch_get_irn_register(arch_env, proj); + reg = arch_get_irn_register(proj); break; } } @@ -255,7 +249,52 @@ void ia32_emit_source_register(const ir_node *node, int pos) emit_register(reg, NULL); } -static void emit_ia32_Immediate(const ir_node *node); +static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust) +{ + ident *id; + + set_entity_backend_marked(entity, 1); + id = get_entity_ld_ident(entity); + be_emit_ident(id); + + if (get_entity_owner(entity) == get_tls_type()) { + if (get_entity_visibility(entity) == visibility_external_allocated) { + be_emit_cstring("@INDNTPOFF"); + } else { + be_emit_cstring("@NTPOFF"); + } + } + + if (!no_pic_adjust && do_pic) { + /* TODO: only do this when necessary */ + be_emit_char('-'); + be_emit_string(pic_base_label); + } +} + +static void emit_ia32_Immediate_no_prefix(const ir_node *node) +{ + const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node); + + if (attr->symconst != NULL) { + if (attr->sc_sign) + be_emit_char('-'); + ia32_emit_entity(attr->symconst, 0); + } + if (attr->symconst == NULL || attr->offset != 0) { + if (attr->symconst != NULL) { + be_emit_irprintf("%+d", attr->offset); + } else { + be_emit_irprintf("0x%X", attr->offset); + } + } +} + +static void emit_ia32_Immediate(const ir_node *node) +{ + be_emit_char('$'); + emit_ia32_Immediate_no_prefix(node); +} void ia32_emit_8bit_source_register_or_immediate(const ir_node *node, int pos) { @@ -476,6 +515,11 @@ static void ia32_emit_cmp_suffix(int pnc) be_emit_string(str); } +typedef enum ia32_emit_mod_t { + EMIT_RESPECT_LS = 1U << 0, + EMIT_ALTERNATE_AM = 1U << 1 +} ia32_emit_mod_t; + /** * fmt parameter output * ---- ---------------------- --------------------------------------------- @@ -495,6 +539,7 @@ static void ia32_emit_cmp_suffix(int pnc) * * x starts at 0 * # modifier for %ASx, %D and %S uses ls mode of node to alter register width + * * modifier does not prefix immediates with $, but AM with * */ static void ia32_emitf(const ir_node *node, const char *fmt, ...) { @@ -502,8 +547,8 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) va_start(ap, fmt); for (;;) { - const char *start = fmt; - const ir_mode *mode = NULL; + const char *start = fmt; + ia32_emit_mod_t mod = 0; while (*fmt != '%' && *fmt != '\n' && *fmt != '\0') ++fmt; @@ -523,8 +568,13 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) break; ++fmt; + if (*fmt == '*') { + mod |= EMIT_ALTERNATE_AM; + ++fmt; + } + if (*fmt == '#') { - mode = get_ia32_ls_mode(node); + mod |= EMIT_RESPECT_LS; ++fmt; } @@ -536,11 +586,15 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) case 'A': { switch (*fmt++) { case 'M': + if (mod & EMIT_ALTERNATE_AM) + be_emit_char('*'); ia32_emit_am(node); break; case 'R': { const arch_register_t *reg = va_arg(ap, const arch_register_t*); + if (mod & EMIT_ALTERNATE_AM) + be_emit_char('*'); if (get_ia32_op_type(node) == ia32_AddrModeS) { ia32_emit_am(node); } else { @@ -551,6 +605,8 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) case 'S': if (get_ia32_op_type(node) == ia32_AddrModeS) { + if (mod & EMIT_ALTERNATE_AM) + be_emit_char('*'); ia32_emit_am(node); ++fmt; } else { @@ -573,12 +629,14 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...) pos = *fmt++ - '0'; reg = get_out_reg(node, pos); - emit_register(reg, mode); + emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL); break; } case 'I': - emit_ia32_Immediate(node); + if (!(mod & EMIT_ALTERNATE_AM)) + be_emit_char('$'); + emit_ia32_Immediate_no_prefix(node); break; case 'L': @@ -613,10 +671,16 @@ emit_S: pos = *fmt++ - '0'; in = get_irn_n(node, pos); if (is_ia32_Immediate(in)) { - emit_ia32_Immediate(in); + if (!(mod & EMIT_ALTERNATE_AM)) + be_emit_char('$'); + emit_ia32_Immediate_no_prefix(in); } else { - const arch_register_t *reg = get_in_reg(node, pos); - emit_register(reg, mode); + const arch_register_t *reg; + + if (mod & EMIT_ALTERNATE_AM) + be_emit_char('*'); + reg = get_in_reg(node, pos); + emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL); } break; } @@ -698,29 +762,6 @@ void ia32_emit_unop(const ir_node *node, int pos) ia32_emitf(node, fmt); } -static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust) -{ - ident *id; - - set_entity_backend_marked(entity, 1); - id = get_entity_ld_ident(entity); - be_emit_ident(id); - - if (get_entity_owner(entity) == get_tls_type()) { - if (get_entity_visibility(entity) == visibility_external_allocated) { - be_emit_cstring("@INDNTPOFF"); - } else { - be_emit_cstring("@NTPOFF"); - } - } - - if (!no_pic_adjust && do_pic) { - /* TODO: only do this when necessary */ - be_emit_char('-'); - be_emit_string(pic_base_label); - } -} - /** * Emits address mode. */ @@ -1024,17 +1065,15 @@ static void emit_ia32_CMov(const ir_node *node) { const ia32_attr_t *attr = get_ia32_attr_const(node); int ins_permuted = attr->data.ins_permuted; - const arch_register_t *out = arch_get_irn_register(arch_env, node); + const arch_register_t *out = arch_get_irn_register(node); pn_Cmp pnc = get_ia32_condcode(node); const arch_register_t *in_true; const arch_register_t *in_false; pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc); - in_true = arch_get_irn_register(arch_env, - get_irn_n(node, n_ia32_CMov_val_true)); - in_false = arch_get_irn_register(arch_env, - get_irn_n(node, n_ia32_CMov_val_false)); + in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_true)); + in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_false)); /* should be same constraint fullfilled? */ if (out == in_false) { @@ -1215,25 +1254,6 @@ static void emit_Jmp(const ir_node *node) } } -static void emit_ia32_Immediate(const ir_node *node) -{ - const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node); - - be_emit_char('$'); - if (attr->symconst != NULL) { - if (attr->sc_sign) - be_emit_char('-'); - ia32_emit_entity(attr->symconst, 0); - } - if (attr->symconst == NULL || attr->offset != 0) { - if (attr->symconst != NULL) { - be_emit_irprintf("%+d", attr->offset); - } else { - be_emit_irprintf("0x%X", attr->offset); - } - } -} - /** * Emit an inline assembler operand. * @@ -1511,7 +1531,7 @@ static void emit_ia32_Conv_I2I(const ir_node *node) if (signed_mode && smaller_bits == 16 && &ia32_gp_regs[REG_EAX] == get_out_reg(node, 0) && - &ia32_gp_regs[REG_EAX] == arch_get_irn_register(arch_env, get_irn_n(node, n_ia32_unary_op))) { + &ia32_gp_regs[REG_EAX] == arch_get_irn_register(get_irn_n(node, n_ia32_unary_op))) { /* argument and result are both in EAX and signedness is ok: use the * smaller cwtl opcode */ ia32_emitf(node, "\tcwtl\n"); @@ -1521,6 +1541,16 @@ static void emit_ia32_Conv_I2I(const ir_node *node) } } +/** + * Emits a call + */ +static void emit_ia32_Call(const ir_node *node) +{ + /* Special case: Call must not have its immediates prefixed by $, instead + * address mode is prefixed by *. */ + ia32_emitf(node, "\tcall %*AS3\n"); +} + /******************************************* * _ _ @@ -1532,24 +1562,6 @@ static void emit_ia32_Conv_I2I(const ir_node *node) * *******************************************/ -/** - * Emits a backend call - */ -static void emit_be_Call(const ir_node *node) -{ - ir_entity *ent = be_Call_get_entity(node); - - be_emit_cstring("\tcall "); - if (ent) { - ia32_emit_entity(ent, 1); - } else { - const arch_register_t *reg = get_in_reg(node, be_pos_Call_ptr); - be_emit_char('*'); - emit_register(reg, NULL); - } - be_emit_finish_line_gas(node); -} - /** * Emits code to increase stack pointer. */ @@ -1572,8 +1584,8 @@ static void emit_be_IncSP(const ir_node *node) */ static void Copy_emitter(const ir_node *node, const ir_node *op) { - const arch_register_t *in = arch_get_irn_register(arch_env, op); - const arch_register_t *out = arch_get_irn_register(arch_env, node); + const arch_register_t *in = arch_get_irn_register(op); + const arch_register_t *out = arch_get_irn_register(node); if (in == out) { return; @@ -1609,8 +1621,8 @@ static void emit_be_Perm(const ir_node *node) const arch_register_t *in0, *in1; const arch_register_class_t *cls0, *cls1; - in0 = arch_get_irn_register(arch_env, get_irn_n(node, 0)); - in1 = arch_get_irn_register(arch_env, get_irn_n(node, 1)); + in0 = arch_get_irn_register(get_irn_n(node, 0)); + in1 = arch_get_irn_register(get_irn_n(node, 1)); cls0 = arch_register_get_class(in0); cls1 = arch_register_get_class(in1); @@ -1792,38 +1804,37 @@ static void ia32_register_emitters(void) ia32_register_spec_emitters(); /* other ia32 emitter functions */ + IA32_EMIT2(Conv_I2I8Bit, Conv_I2I); IA32_EMIT(Asm); IA32_EMIT(CMov); - IA32_EMIT(IMul); - IA32_EMIT(SwitchJmp); - IA32_EMIT(CopyB); - IA32_EMIT(CopyB_i); - IA32_EMIT(Conv_I2FP); - IA32_EMIT(Conv_FP2I); + IA32_EMIT(Call); + IA32_EMIT(Const); IA32_EMIT(Conv_FP2FP); + IA32_EMIT(Conv_FP2I); + IA32_EMIT(Conv_I2FP); IA32_EMIT(Conv_I2I); - IA32_EMIT2(Conv_I2I8Bit, Conv_I2I); - IA32_EMIT(Const); + IA32_EMIT(CopyB); + IA32_EMIT(CopyB_i); + IA32_EMIT(GetEIP); + IA32_EMIT(IMul); + IA32_EMIT(Jcc); IA32_EMIT(LdTls); IA32_EMIT(Minus64Bit); - IA32_EMIT(Jcc); - IA32_EMIT(GetEIP); + IA32_EMIT(SwitchJmp); /* benode emitter */ - BE_EMIT(Call); - BE_EMIT(IncSP); BE_EMIT(Copy); BE_EMIT(CopyKeep); + BE_EMIT(IncSP); BE_EMIT(Perm); BE_EMIT(Return); - BE_IGN(RegParams); BE_IGN(Barrier); BE_IGN(Keep); + BE_IGN(RegParams); /* firm emitter */ EMIT(Jmp); - IGN(Proj); IGN(Phi); IGN(Start); @@ -2097,8 +2108,7 @@ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg) int i, n; cg = ia32_cg; - isa = (const ia32_isa_t*) cg->arch_env; - arch_env = cg->arch_env; + isa = cg->isa; do_pic = cg->birg->main_env->options->pic; ia32_register_emitters();