X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_emitter.c;h=e5c46b707f70c271ce28f38d8f4b8c02fba58934;hb=d4bbab11371a9c68aa2a716eaa7589b82a28691e;hp=56a93111237192f41325ed6ac87a980978810d53;hpb=c99aaa20c33a6f767ab26489f4bb8e2b2711a749;p=libfirm diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 56a931112..e5c46b707 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -129,7 +129,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 +138,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 +168,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 +178,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 +252,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 +518,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 +542,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 +550,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 +571,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 +589,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 +608,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 +632,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 +674,14 @@ 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 { + if (mod & EMIT_ALTERNATE_AM) + be_emit_char('*'); const arch_register_t *reg = get_in_reg(node, pos); - emit_register(reg, mode); + emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL); } break; } @@ -698,29 +763,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 +1066,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 +1255,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 +1532,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 +1542,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 +1563,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 +1585,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 +1622,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); @@ -1795,6 +1808,7 @@ static void ia32_register_emitters(void) IA32_EMIT2(Conv_I2I8Bit, Conv_I2I); IA32_EMIT(Asm); IA32_EMIT(CMov); + IA32_EMIT(Call); IA32_EMIT(Const); IA32_EMIT(Conv_FP2FP); IA32_EMIT(Conv_FP2I); @@ -1810,7 +1824,6 @@ static void ia32_register_emitters(void) IA32_EMIT(SwitchJmp); /* benode emitter */ - BE_EMIT(Call); BE_EMIT(Copy); BE_EMIT(CopyKeep); BE_EMIT(IncSP); @@ -1824,7 +1837,6 @@ static void ia32_register_emitters(void) /* firm emitter */ EMIT(Jmp); IGN(Phi); - IGN(Proj); IGN(Start); #undef BE_EMIT