2 * This is the main ia32 firm backend driver.
3 * @author Christian Wuerdig
20 #include <libcore/lc_opts.h>
21 #include <libcore/lc_opts_enum.h>
22 #endif /* WITH_LIBCORE */
24 #include "pseudo_irg.h"
28 #include "iredges_t.h"
36 #include "../beabi.h" /* the general register allocator interface */
37 #include "../benode_t.h"
38 #include "../belower.h"
39 #include "../besched_t.h"
41 #include "bearch_ia32_t.h"
43 #include "ia32_new_nodes.h" /* ia32 nodes interface */
44 #include "gen_ia32_regalloc_if.h" /* the generated interface (register type and class defenitions) */
45 #include "ia32_gen_decls.h" /* interface declaration emitter */
46 #include "ia32_transform.h"
47 #include "ia32_emitter.h"
48 #include "ia32_map_regs.h"
49 #include "ia32_optimize.h"
51 #include "ia32_dbg_stat.h"
52 #include "ia32_finish.h"
53 #include "ia32_util.h"
55 #define DEBUG_MODULE "firm.be.ia32.isa"
58 static set *cur_reg_set = NULL;
61 #define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
63 /* Creates the unique per irg GP NoReg node. */
64 ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
65 return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_GP_NOREG]);
68 /* Creates the unique per irg FP NoReg node. */
69 ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
70 return be_abi_get_callee_save_irn(cg->birg->abi,
71 USE_SSE2(cg) ? &ia32_xmm_regs[REG_XMM_NOREG] : &ia32_vfp_regs[REG_VFP_NOREG]);
74 /**************************************************
77 * _ __ ___ __ _ __ _| | | ___ ___ _| |_
78 * | '__/ _ \/ _` | / _` | | |/ _ \ / __| | | _|
79 * | | | __/ (_| | | (_| | | | (_) | (__ | | |
80 * |_| \___|\__, | \__,_|_|_|\___/ \___| |_|_|
83 **************************************************/
85 static ir_node *my_skip_proj(const ir_node *n) {
93 * Return register requirements for an ia32 node.
94 * If the node returns a tuple (mode_T) then the proj's
95 * will be asked for this information.
97 static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
98 const ia32_irn_ops_t *ops = self;
99 const ia32_register_req_t *irn_req;
100 long node_pos = pos == -1 ? 0 : pos;
101 ir_mode *mode = is_Block(irn) ? NULL : get_irn_mode(irn);
102 FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
104 if (is_Block(irn) || mode == mode_M || mode == mode_X) {
105 DBG((mod, LEVEL_1, "ignoring Block, mode_M, mode_X node %+F\n", irn));
109 if (mode == mode_T && pos < 0) {
110 DBG((mod, LEVEL_1, "ignoring request OUT requirements for node %+F\n", irn));
114 DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
118 node_pos = ia32_translate_proj_pos(irn);
124 irn = my_skip_proj(irn);
126 DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
129 if (is_ia32_irn(irn)) {
131 irn_req = get_ia32_in_req(irn, pos);
134 irn_req = get_ia32_out_req(irn, node_pos);
137 DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
139 memcpy(req, &(irn_req->req), sizeof(*req));
141 if (arch_register_req_is(&(irn_req->req), should_be_same)) {
142 assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
143 req->other_same = get_irn_n(irn, irn_req->same_pos);
146 if (arch_register_req_is(&(irn_req->req), should_be_different)) {
147 assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
148 req->other_different = get_irn_n(irn, irn_req->different_pos);
152 /* treat Unknowns like Const with default requirements */
153 if (is_Unknown(irn)) {
154 DB((mod, LEVEL_1, "returning UKNWN reqs for %+F\n", irn));
155 if (mode_is_float(mode)) {
156 if (USE_SSE2(ops->cg))
157 memcpy(req, &(ia32_default_req_ia32_xmm_xmm_UKNWN), sizeof(*req));
159 memcpy(req, &(ia32_default_req_ia32_vfp_vfp_UKNWN), sizeof(*req));
161 else if (mode_is_int(mode) || mode_is_reference(mode))
162 memcpy(req, &(ia32_default_req_ia32_gp_gp_UKNWN), sizeof(*req));
163 else if (mode == mode_T || mode == mode_M) {
164 DBG((mod, LEVEL_1, "ignoring Unknown node %+F\n", irn));
168 assert(0 && "unsupported Unknown-Mode");
171 DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
179 static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
181 const ia32_irn_ops_t *ops = self;
183 if (get_irn_mode(irn) == mode_X) {
187 DBG((ops->cg->mod, LEVEL_1, "ia32 assigned register %s to node %+F\n", reg->name, irn));
190 pos = ia32_translate_proj_pos(irn);
191 irn = my_skip_proj(irn);
194 if (is_ia32_irn(irn)) {
195 const arch_register_t **slots;
197 slots = get_ia32_slots(irn);
201 ia32_set_firm_reg(irn, reg, cur_reg_set);
205 static const arch_register_t *ia32_get_irn_reg(const void *self, const ir_node *irn) {
207 const arch_register_t *reg = NULL;
211 if (get_irn_mode(irn) == mode_X) {
215 pos = ia32_translate_proj_pos(irn);
216 irn = my_skip_proj(irn);
219 if (is_ia32_irn(irn)) {
220 const arch_register_t **slots;
221 slots = get_ia32_slots(irn);
225 reg = ia32_get_firm_reg(irn, cur_reg_set);
231 static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
232 irn = my_skip_proj(irn);
234 return arch_irn_class_branch;
235 else if (is_ia32_Cnst(irn))
236 return arch_irn_class_const;
237 else if (is_ia32_Ld(irn))
238 return arch_irn_class_load;
239 else if (is_ia32_St(irn) || is_ia32_Store8Bit(irn))
240 return arch_irn_class_store;
241 else if (is_ia32_irn(irn))
242 return arch_irn_class_normal;
247 static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
248 irn = my_skip_proj(irn);
249 if (is_ia32_irn(irn))
250 return get_ia32_flags(irn);
253 return arch_irn_flags_ignore;
258 static entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
259 return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
262 static void ia32_set_stack_bias(const void *self, ir_node *irn, int bias) {
264 const ia32_irn_ops_t *ops = self;
266 if (get_ia32_frame_ent(irn)) {
267 ia32_am_flavour_t am_flav = get_ia32_am_flavour(irn);
269 DBG((ops->cg->mod, LEVEL_1, "stack biased %+F with %d\n", irn, bias));
270 snprintf(buf, sizeof(buf), "%d", bias);
272 if (get_ia32_op_type(irn) == ia32_Normal) {
273 set_ia32_cnst(irn, buf);
276 add_ia32_am_offs(irn, buf);
278 set_ia32_am_flavour(irn, am_flav);
284 be_abi_call_flags_bits_t flags;
285 const arch_isa_t *isa;
286 const arch_env_t *aenv;
290 static void *ia32_abi_init(const be_abi_call_t *call, const arch_env_t *aenv, ir_graph *irg)
292 ia32_abi_env_t *env = xmalloc(sizeof(env[0]));
293 be_abi_call_flags_t fl = be_abi_call_get_flags(call);
294 env->flags = fl.bits;
297 env->isa = aenv->isa;
302 * Put all registers which are saved by the prologue/epilogue in a set.
304 * @param self The callback object.
305 * @param s The result set.
307 static void ia32_abi_dont_save_regs(void *self, pset *s)
309 ia32_abi_env_t *env = self;
310 if(env->flags.try_omit_fp)
311 pset_insert_ptr(s, env->isa->bp);
315 * Generate the routine prologue.
317 * @param self The callback object.
318 * @param mem A pointer to the mem node. Update this if you define new memory.
319 * @param reg_map A map mapping all callee_save/ignore/parameter registers to their defining nodes.
321 * @return The register which shall be used as a stack frame base.
323 * All nodes which define registers in @p reg_map must keep @p reg_map current.
325 static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
327 ia32_abi_env_t *env = self;
329 if (!env->flags.try_omit_fp) {
330 int reg_size = get_mode_size_bytes(env->isa->bp->reg_class->mode);
331 ir_node *bl = get_irg_start_block(env->irg);
332 ir_node *curr_sp = be_abi_reg_map_get(reg_map, env->isa->sp);
333 ir_node *curr_bp = be_abi_reg_map_get(reg_map, env->isa->bp);
337 push = new_rd_ia32_Push(NULL, env->irg, bl, curr_sp, curr_bp, *mem);
338 curr_sp = new_r_Proj(env->irg, bl, push, get_irn_mode(curr_sp), pn_ia32_Push_stack);
339 *mem = new_r_Proj(env->irg, bl, push, mode_M, pn_ia32_Push_M);
341 /* the push must have SP out register */
342 arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
343 set_ia32_flags(push, arch_irn_flags_ignore);
345 /* move esp to ebp */
346 curr_bp = be_new_Copy(env->isa->bp->reg_class, env->irg, bl, curr_sp);
347 be_set_constr_single_reg(curr_bp, BE_OUT_POS(0), env->isa->bp);
348 arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
349 be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_ignore);
351 /* beware: the copy must be done before any other sp use */
352 curr_sp = be_new_CopyKeep_single(env->isa->sp->reg_class, env->irg, bl, curr_sp, curr_bp, get_irn_mode(curr_sp));
353 be_set_constr_single_reg(curr_sp, BE_OUT_POS(0), env->isa->sp);
354 arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
355 be_node_set_flags(curr_sp, BE_OUT_POS(0), arch_irn_flags_ignore);
357 be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
358 be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
367 * Generate the routine epilogue.
368 * @param self The callback object.
369 * @param bl The block for the epilog
370 * @param mem A pointer to the mem node. Update this if you define new memory.
371 * @param reg_map A map mapping all callee_save/ignore/parameter registers to their defining nodes.
372 * @return The register which shall be used as a stack frame base.
374 * All nodes which define registers in @p reg_map must keep @p reg_map current.
376 static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
378 ia32_abi_env_t *env = self;
379 ir_node *curr_sp = be_abi_reg_map_get(reg_map, env->isa->sp);
380 ir_node *curr_bp = be_abi_reg_map_get(reg_map, env->isa->bp);
382 if (env->flags.try_omit_fp) {
383 /* simply remove the stack frame here */
384 curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, *mem, BE_STACK_FRAME_SIZE, be_stack_dir_shrink);
387 const ia32_isa_t *isa = (ia32_isa_t *)env->isa;
388 ir_mode *mode_bp = env->isa->bp->reg_class->mode;
389 int reg_size = get_mode_size_bytes(env->isa->bp->reg_class->mode);
391 /* gcc always emits a leave at the end of a routine */
392 if (1 || ARCH_AMD(isa->opt_arch)) {
396 leave = new_rd_ia32_Leave(NULL, env->irg, bl, curr_sp, *mem);
397 set_ia32_flags(leave, arch_irn_flags_ignore);
398 curr_bp = new_r_Proj(current_ir_graph, bl, leave, mode_bp, pn_ia32_Leave_frame);
399 curr_sp = new_r_Proj(current_ir_graph, bl, leave, get_irn_mode(curr_sp), pn_ia32_Leave_stack);
400 *mem = new_r_Proj(current_ir_graph, bl, leave, mode_M, pn_ia32_Leave_M);
405 /* copy ebp to esp */
406 curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
409 pop = new_rd_ia32_Pop(NULL, env->irg, bl, curr_sp, *mem);
410 set_ia32_flags(pop, arch_irn_flags_ignore);
411 curr_bp = new_r_Proj(current_ir_graph, bl, pop, mode_bp, pn_ia32_Pop_res);
412 curr_sp = new_r_Proj(current_ir_graph, bl, pop, get_irn_mode(curr_sp), pn_ia32_Pop_stack);
413 *mem = new_r_Proj(current_ir_graph, bl, pop, mode_M, pn_ia32_Pop_M);
415 arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
416 arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
419 be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
420 be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
424 * Produces the type which sits between the stack args and the locals on the stack.
425 * it will contain the return address and space to store the old base pointer.
426 * @return The Firm type modeling the ABI between type.
428 static ir_type *ia32_abi_get_between_type(void *self)
430 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
431 static ir_type *omit_fp_between_type = NULL;
432 static ir_type *between_type = NULL;
434 ia32_abi_env_t *env = self;
436 if ( !between_type) {
438 entity *ret_addr_ent;
439 entity *omit_fp_ret_addr_ent;
441 ir_type *old_bp_type = new_type_primitive(IDENT("bp"), mode_P);
442 ir_type *ret_addr_type = new_type_primitive(IDENT("return_addr"), mode_P);
444 between_type = new_type_struct(IDENT("ia32_between_type"));
445 old_bp_ent = new_entity(between_type, IDENT("old_bp"), old_bp_type);
446 ret_addr_ent = new_entity(between_type, IDENT("ret_addr"), ret_addr_type);
448 set_entity_offset_bytes(old_bp_ent, 0);
449 set_entity_offset_bytes(ret_addr_ent, get_type_size_bytes(old_bp_type));
450 set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
451 set_type_state(between_type, layout_fixed);
453 omit_fp_between_type = new_type_struct(IDENT("ia32_between_type_omit_fp"));
454 omit_fp_ret_addr_ent = new_entity(omit_fp_between_type, IDENT("ret_addr"), ret_addr_type);
456 set_entity_offset_bytes(omit_fp_ret_addr_ent, 0);
457 set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type));
458 set_type_state(omit_fp_between_type, layout_fixed);
461 return env->flags.try_omit_fp ? omit_fp_between_type : between_type;
466 * Get the estimated cycle count for @p irn.
468 * @param self The this pointer.
469 * @param irn The node.
471 * @return The estimated cycle count for this operation
473 static int ia32_get_op_estimated_cost(const void *self, const ir_node *irn)
476 switch (get_ia32_irn_opcode(irn)) {
478 case iro_ia32_DivMod:
483 case iro_ia32_l_Load:
493 case iro_ia32_xStore:
494 case iro_ia32_l_Store:
496 case iro_ia32_Store8Bit:
504 case iro_ia32_l_MulS:
517 * Returns the inverse operation if @p irn, recalculating the argument at position @p i.
519 * @param irn The original operation
520 * @param i Index of the argument we want the inverse operation to yield
521 * @param inverse struct to be filled with the resulting inverse op
522 * @param obstack The obstack to use for allocation of the returned nodes array
523 * @return The inverse operation or NULL if operation invertible
525 static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obst) {
528 ir_node *block, *noreg, *nomem;
531 /* we cannot invert non-ia32 irns */
532 if (! is_ia32_irn(irn))
535 /* operand must always be a real operand (not base, index or mem) */
536 if (i != 2 && i != 3)
539 /* we don't invert address mode operations */
540 if (get_ia32_op_type(irn) != ia32_Normal)
543 irg = get_irn_irg(irn);
544 block = get_nodes_block(irn);
545 mode = get_ia32_res_mode(irn);
546 noreg = get_irn_n(irn, 0);
547 nomem = new_r_NoMem(irg);
549 /* initialize structure */
550 inverse->nodes = obstack_alloc(obst, 2 * sizeof(inverse->nodes[0]));
554 switch (get_ia32_irn_opcode(irn)) {
556 if (get_ia32_immop_type(irn) == ia32_ImmConst) {
557 /* we have an add with a const here */
558 /* invers == add with negated const */
559 inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
560 pnc = pn_ia32_Add_res;
562 copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
563 set_ia32_Immop_tarval(inverse->nodes[0], tarval_neg(get_ia32_Immop_tarval(irn)));
564 set_ia32_commutative(inverse->nodes[0]);
566 else if (get_ia32_immop_type(irn) == ia32_ImmSymConst) {
567 /* we have an add with a symconst here */
568 /* invers == sub with const */
569 inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
570 pnc = pn_ia32_Sub_res;
572 copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
575 /* normal add: inverse == sub */
576 ir_node *proj = ia32_get_res_proj(irn);
579 inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, proj, get_irn_n(irn, i ^ 1), nomem);
580 pnc = pn_ia32_Sub_res;
585 if (get_ia32_immop_type(irn) != ia32_ImmNone) {
586 /* we have a sub with a const/symconst here */
587 /* invers == add with this const */
588 inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
589 pnc = pn_ia32_Add_res;
590 inverse->costs += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
591 copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
595 ir_node *proj = ia32_get_res_proj(irn);
599 inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, proj, get_irn_n(irn, 3), nomem);
602 inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, get_irn_n(irn, 2), proj, nomem);
604 pnc = pn_ia32_Sub_res;
609 if (get_ia32_immop_type(irn) != ia32_ImmNone) {
610 /* xor with const: inverse = xor */
611 inverse->nodes[0] = new_rd_ia32_Eor(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
612 pnc = pn_ia32_Eor_res;
613 inverse->costs += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
614 copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
618 inverse->nodes[0] = new_rd_ia32_Eor(NULL, irg, block, noreg, noreg, (ir_node *)irn, get_irn_n(irn, i), nomem);
619 pnc = pn_ia32_Eor_res;
624 ir_node *proj = ia32_get_res_proj(irn);
627 inverse->nodes[0] = new_rd_ia32_Not(NULL, irg, block, noreg, noreg, proj, nomem);
628 pnc = pn_ia32_Not_res;
632 case iro_ia32_Minus: {
633 ir_node *proj = ia32_get_res_proj(irn);
636 inverse->nodes[0] = new_rd_ia32_Minus(NULL, irg, block, noreg, noreg, proj, nomem);
637 pnc = pn_ia32_Minus_res;
642 /* inverse operation not supported */
646 set_ia32_res_mode(inverse->nodes[0], mode);
647 inverse->nodes[1] = new_r_Proj(irg, block, inverse->nodes[0], mode, pnc);
653 * Check if irn can load it's operand at position i from memory (source addressmode).
654 * @param self Pointer to irn ops itself
655 * @param irn The irn to be checked
656 * @param i The operands position
657 * @return Non-Zero if operand can be loaded
659 static int ia32_possible_memory_operand(const void *self, const ir_node *irn, unsigned int i) {
660 if (! is_ia32_irn(irn) || /* must be an ia32 irn */
661 get_irn_arity(irn) != 5 || /* must be a binary operation */
662 get_ia32_op_type(irn) != ia32_Normal || /* must not already be a addressmode irn */
663 ! (get_ia32_am_support(irn) & ia32_am_Source) || /* must be capable of source addressmode */
664 (i != 2 && i != 3) || /* a "real" operand position must be requested */
665 (i == 2 && ! is_ia32_commutative(irn)) || /* if first operand requested irn must be commutative */
666 is_ia32_use_frame(irn)) /* must not already use frame */
672 static void ia32_perform_memory_operand(const void *self, ir_node *irn, ir_node *reload, unsigned int i) {
673 assert(ia32_possible_memory_operand(self, irn, i) && "Cannot perform memory operand change");
674 assert(get_nodes_block(reload) == get_nodes_block(irn) && "Reload must be in same block as irn.");
676 if (get_irn_n_edges(reload) > 1)
680 ir_node *tmp = get_irn_n(irn, 3);
681 set_irn_n(irn, 3, get_irn_n(irn, 2));
682 set_irn_n(irn, 2, tmp);
685 set_ia32_am_support(irn, ia32_am_Source);
686 set_ia32_op_type(irn, ia32_AddrModeS);
687 set_ia32_am_flavour(irn, ia32_B);
688 set_ia32_ls_mode(irn, get_irn_mode(reload));
689 set_ia32_frame_ent(irn, be_get_frame_entity(reload));
690 set_ia32_use_frame(irn);
692 set_irn_n(irn, 0, be_get_Reload_frame(reload));
693 set_irn_n(irn, 4, be_get_Reload_mem(reload));
696 Input at position one is index register, which is NoReg.
697 We would need cg object to get a real noreg, but we cannot
700 set_irn_n(irn, 3, get_irn_n(irn, 1));
702 DBG_OPT_AM_S(reload, irn);
705 static const be_abi_callbacks_t ia32_abi_callbacks = {
708 ia32_abi_get_between_type,
709 ia32_abi_dont_save_regs,
714 /* fill register allocator interface */
716 static const arch_irn_ops_if_t ia32_irn_ops_if = {
717 ia32_get_irn_reg_req,
722 ia32_get_frame_entity,
725 ia32_get_op_estimated_cost,
726 ia32_possible_memory_operand,
727 ia32_perform_memory_operand,
730 ia32_irn_ops_t ia32_irn_ops = {
737 /**************************************************
740 * ___ ___ __| | ___ __ _ ___ _ __ _| |_
741 * / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \ | | _|
742 * | (_| (_) | (_| | __/ (_| | __/ | | | | | |
743 * \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
746 **************************************************/
749 * Transforms the standard firm graph into
752 static void ia32_prepare_graph(void *self) {
753 ia32_code_gen_t *cg = self;
754 dom_front_info_t *dom;
755 DEBUG_ONLY(firm_dbg_module_t *old_mod = cg->mod;)
757 FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
759 /* 1st: transform constants and psi condition trees */
760 ia32_pre_transform_phase(cg);
762 /* 2nd: transform all remaining nodes */
763 ia32_register_transformers();
764 dom = be_compute_dominance_frontiers(cg->irg);
765 irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_node, cg);
766 be_free_dominance_frontiers(dom);
769 be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
771 /* 3rd: optimize address mode */
772 FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.am");
773 ia32_optimize_addressmode(cg);
776 be_dump(cg->irg, "-am", dump_ir_block_graph_sched);
778 DEBUG_ONLY(cg->mod = old_mod;)
782 * Dummy functions for hooks we don't need but which must be filled.
784 static void ia32_before_sched(void *self) {
787 static void remove_unused_nodes(ir_node *irn, bitset_t *already_visited) {
795 mode = get_irn_mode(irn);
797 /* check if we already saw this node or the node has more than one user */
798 if (bitset_contains_irn(already_visited, irn) || get_irn_n_edges(irn) > 1)
801 /* mark irn visited */
802 bitset_add_irn(already_visited, irn);
804 /* non-Tuple nodes with one user: ok, return */
805 if (get_irn_n_edges(irn) >= 1 && mode != mode_T)
808 /* tuple node has one user which is not the mem proj-> ok */
809 if (mode == mode_T && get_irn_n_edges(irn) == 1) {
810 mem_proj = ia32_get_proj_for_mode(irn, mode_M);
815 for (i = get_irn_arity(irn) - 1; i >= 0; i--) {
816 ir_node *pred = get_irn_n(irn, i);
818 /* do not follow memory edges or we will accidentally remove stores */
819 if (is_Proj(pred) && get_irn_mode(pred) == mode_M)
822 set_irn_n(irn, i, new_Bad());
825 The current node is about to be removed: if the predecessor
826 has only this node as user, it need to be removed as well.
828 if (get_irn_n_edges(pred) <= 1)
829 remove_unused_nodes(pred, already_visited);
832 if (sched_is_scheduled(irn))
836 static void remove_unused_loads_walker(ir_node *irn, void *env) {
837 bitset_t *already_visited = env;
838 if (is_ia32_Ld(irn) && ! bitset_contains_irn(already_visited, irn))
839 remove_unused_nodes(irn, env);
843 * Called before the register allocator.
844 * Calculate a block schedule here. We need it for the x87
845 * simulator and the emitter.
847 static void ia32_before_ra(void *self) {
848 ia32_code_gen_t *cg = self;
849 bitset_t *already_visited = bitset_irg_malloc(cg->irg);
851 cg->blk_sched = sched_create_block_schedule(cg->irg);
855 There are sometimes unused loads, only pinned by memory.
856 We need to remove those Loads and all other nodes which won't be used
857 after removing the Load from schedule.
859 irg_walk_graph(cg->irg, remove_unused_loads_walker, NULL, already_visited);
860 bitset_free(already_visited);
865 * Transforms a be node into a Load.
867 static void transform_to_Load(ia32_transform_env_t *env) {
868 ir_node *irn = env->irn;
869 entity *ent = be_get_frame_entity(irn);
870 ir_mode *mode = env->mode;
871 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
872 ir_node *nomem = new_rd_NoMem(env->irg);
873 ir_node *sched_point = NULL;
874 ir_node *ptr = get_irn_n(irn, 0);
875 ir_node *mem = be_is_Reload(irn) ? get_irn_n(irn, 1) : nomem;
876 ir_node *new_op, *proj;
877 const arch_register_t *reg;
879 if (sched_is_scheduled(irn)) {
880 sched_point = sched_prev(irn);
883 if (mode_is_float(mode)) {
884 if (USE_SSE2(env->cg))
885 new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, mem);
887 new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
890 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem);
893 set_ia32_am_support(new_op, ia32_am_Source);
894 set_ia32_op_type(new_op, ia32_AddrModeS);
895 set_ia32_am_flavour(new_op, ia32_B);
896 set_ia32_ls_mode(new_op, mode);
897 set_ia32_frame_ent(new_op, ent);
898 set_ia32_use_frame(new_op);
900 DBG_OPT_RELOAD2LD(irn, new_op);
902 proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, pn_Load_res);
905 sched_add_after(sched_point, new_op);
906 sched_add_after(new_op, proj);
911 /* copy the register from the old node to the new Load */
912 reg = arch_get_irn_register(env->cg->arch_env, irn);
913 arch_set_irn_register(env->cg->arch_env, new_op, reg);
915 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, irn));
921 * Transforms a be node into a Store.
923 static void transform_to_Store(ia32_transform_env_t *env) {
924 ir_node *irn = env->irn;
925 entity *ent = be_get_frame_entity(irn);
926 ir_mode *mode = env->mode;
927 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
928 ir_node *nomem = new_rd_NoMem(env->irg);
929 ir_node *ptr = get_irn_n(irn, 0);
930 ir_node *val = get_irn_n(irn, 1);
931 ir_node *new_op, *proj;
932 ir_node *sched_point = NULL;
934 if (sched_is_scheduled(irn)) {
935 sched_point = sched_prev(irn);
938 if (mode_is_float(mode)) {
939 if (USE_SSE2(env->cg))
940 new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
942 new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
944 else if (get_mode_size_bits(mode) == 8) {
945 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
948 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
951 set_ia32_am_support(new_op, ia32_am_Dest);
952 set_ia32_op_type(new_op, ia32_AddrModeD);
953 set_ia32_am_flavour(new_op, ia32_B);
954 set_ia32_ls_mode(new_op, mode);
955 set_ia32_frame_ent(new_op, ent);
956 set_ia32_use_frame(new_op);
958 DBG_OPT_SPILL2ST(irn, new_op);
960 proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, pn_ia32_Store_M);
963 sched_add_after(sched_point, new_op);
967 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, irn));
973 * Fix the mode of Spill/Reload
975 static ir_mode *fix_spill_mode(ia32_code_gen_t *cg, ir_mode *mode)
977 if (mode_is_float(mode)) {
989 * Block-Walker: Calls the transform functions Spill and Reload.
991 static void ia32_after_ra_walker(ir_node *block, void *env) {
992 ir_node *node, *prev;
993 ia32_code_gen_t *cg = env;
994 ia32_transform_env_t tenv;
997 tenv.irg = current_ir_graph;
999 DEBUG_ONLY(tenv.mod = cg->mod;)
1001 /* beware: the schedule is changed here */
1002 for (node = sched_last(block); !sched_is_begin(node); node = prev) {
1003 prev = sched_prev(node);
1004 if (be_is_Reload(node)) {
1005 /* we always reload the whole register */
1006 tenv.dbg = get_irn_dbg_info(node);
1008 tenv.mode = fix_spill_mode(cg, get_irn_mode(node));
1009 transform_to_Load(&tenv);
1011 else if (be_is_Spill(node)) {
1012 /* we always spill the whole register */
1013 tenv.dbg = get_irn_dbg_info(node);
1015 tenv.mode = fix_spill_mode(cg, get_irn_mode(be_get_Spill_context(node)));
1016 transform_to_Store(&tenv);
1022 * We transform Spill and Reload here. This needs to be done before
1023 * stack biasing otherwise we would miss the corrected offset for these nodes.
1025 * If x87 instruction should be emitted, run the x87 simulator and patch
1026 * the virtual instructions. This must obviously be done after register allocation.
1028 static void ia32_after_ra(void *self) {
1029 ia32_code_gen_t *cg = self;
1031 irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
1033 /* if we do x87 code generation, rewrite all the virtual instructions and registers */
1034 if (cg->used_fp == fp_x87 || cg->force_sim) {
1035 x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
1041 * Emits the code, closes the output file and frees
1042 * the code generator interface.
1044 static void ia32_codegen(void *self) {
1045 ia32_code_gen_t *cg = self;
1046 ir_graph *irg = cg->irg;
1048 ia32_finish_irg(irg, cg);
1050 be_dump(irg, "-finished", dump_ir_block_graph_sched);
1051 ia32_gen_routine(cg->isa->out, irg, cg);
1055 /* remove it from the isa */
1058 /* de-allocate code generator */
1059 del_set(cg->reg_set);
1064 static void *ia32_cg_init(const be_irg_t *birg);
1066 static const arch_code_generator_if_t ia32_code_gen_if = {
1068 NULL, /* before abi introduce hook */
1070 ia32_before_sched, /* before scheduling hook */
1071 ia32_before_ra, /* before register allocation hook */
1072 ia32_after_ra, /* after register allocation hook */
1073 ia32_codegen /* emit && done */
1077 * Initializes a IA32 code generator.
1079 static void *ia32_cg_init(const be_irg_t *birg) {
1080 ia32_isa_t *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
1081 ia32_code_gen_t *cg = xcalloc(1, sizeof(*cg));
1083 cg->impl = &ia32_code_gen_if;
1084 cg->irg = birg->irg;
1085 cg->reg_set = new_set(ia32_cmp_irn_reg_assoc, 1024);
1086 cg->arch_env = birg->main_env->arch_env;
1089 cg->blk_sched = NULL;
1090 cg->fp_to_gp = NULL;
1091 cg->gp_to_fp = NULL;
1092 cg->fp_kind = isa->fp_kind;
1093 cg->used_fp = fp_none;
1094 cg->dump = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
1096 FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.cg");
1098 /* copy optimizations from isa for easier access */
1100 cg->arch = isa->arch;
1101 cg->opt_arch = isa->opt_arch;
1107 if (isa->name_obst_size) {
1108 //printf("freed %d bytes from name obst\n", isa->name_obst_size);
1109 isa->name_obst_size = 0;
1110 obstack_free(isa->name_obst, NULL);
1111 obstack_init(isa->name_obst);
1115 cur_reg_set = cg->reg_set;
1117 ia32_irn_ops.cg = cg;
1119 return (arch_code_generator_t *)cg;
1124 /*****************************************************************
1125 * ____ _ _ _____ _____
1126 * | _ \ | | | | |_ _|/ ____| /\
1127 * | |_) | __ _ ___| | _____ _ __ __| | | | | (___ / \
1128 * | _ < / _` |/ __| |/ / _ \ '_ \ / _` | | | \___ \ / /\ \
1129 * | |_) | (_| | (__| < __/ | | | (_| | _| |_ ____) / ____ \
1130 * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/ \_\
1132 *****************************************************************/
1135 * Set output modes for GCC
1137 static const tarval_mode_info mo_integer = {
1144 * set the tarval output mode to C-semantics
1146 static void set_tarval_output_modes(void)
1148 set_tarval_mode_output_option(get_modeLs(), &mo_integer);
1149 set_tarval_mode_output_option(get_modeLu(), &mo_integer);
1150 set_tarval_mode_output_option(get_modeIs(), &mo_integer);
1151 set_tarval_mode_output_option(get_modeIu(), &mo_integer);
1152 set_tarval_mode_output_option(get_modeHs(), &mo_integer);
1153 set_tarval_mode_output_option(get_modeHu(), &mo_integer);
1154 set_tarval_mode_output_option(get_modeBs(), &mo_integer);
1155 set_tarval_mode_output_option(get_modeBu(), &mo_integer);
1156 set_tarval_mode_output_option(get_modeC(), &mo_integer);
1157 set_tarval_mode_output_option(get_modeU(), &mo_integer);
1158 set_tarval_mode_output_option(get_modeIu(), &mo_integer);
1163 * The template that generates a new ISA object.
1164 * Note that this template can be changed by command line
1167 static ia32_isa_t ia32_isa_template = {
1169 &ia32_isa_if, /* isa interface implementation */
1170 &ia32_gp_regs[REG_ESP], /* stack pointer register */
1171 &ia32_gp_regs[REG_EBP], /* base pointer register */
1172 -1, /* stack direction */
1174 NULL, /* 16bit register names */
1175 NULL, /* 8bit register names */
1179 IA32_OPT_INCDEC | /* optimize add 1, sub 1 into inc/dec default: on */
1180 IA32_OPT_DOAM | /* optimize address mode default: on */
1181 IA32_OPT_LEA | /* optimize for LEAs default: on */
1182 IA32_OPT_PLACECNST | /* place constants immediately before instructions, default: on */
1183 IA32_OPT_IMMOPS | /* operations can use immediates, default: on */
1184 IA32_OPT_EXTBB), /* use extended basic block scheduling, default: on */
1185 arch_pentium_4, /* instruction architecture */
1186 arch_pentium_4, /* optimize for architecture */
1187 fp_sse2, /* use sse2 unit */
1188 NULL, /* current code generator */
1190 NULL, /* name obstack */
1191 0 /* name obst size */
1196 * Initializes the backend ISA.
1198 static void *ia32_init(FILE *file_handle) {
1199 static int inited = 0;
1205 set_tarval_output_modes();
1207 isa = xmalloc(sizeof(*isa));
1208 memcpy(isa, &ia32_isa_template, sizeof(*isa));
1210 ia32_register_init(isa);
1211 ia32_create_opcodes();
1213 if ((ARCH_INTEL(isa->arch) && isa->arch < arch_pentium_4) ||
1214 (ARCH_AMD(isa->arch) && isa->arch < arch_athlon))
1215 /* no SSE2 for these cpu's */
1216 isa->fp_kind = fp_x87;
1218 if (ARCH_INTEL(isa->opt_arch) && isa->opt_arch >= arch_pentium_4) {
1219 /* Pentium 4 don't like inc and dec instructions */
1220 isa->opt &= ~IA32_OPT_INCDEC;
1223 isa->regs_16bit = pmap_create();
1224 isa->regs_8bit = pmap_create();
1225 isa->types = pmap_create();
1226 isa->tv_ent = pmap_create();
1227 isa->out = file_handle;
1229 ia32_build_16bit_reg_map(isa->regs_16bit);
1230 ia32_build_8bit_reg_map(isa->regs_8bit);
1232 /* patch register names of x87 registers */
1234 ia32_st_regs[0].name = "st";
1235 ia32_st_regs[1].name = "st(1)";
1236 ia32_st_regs[2].name = "st(2)";
1237 ia32_st_regs[3].name = "st(3)";
1238 ia32_st_regs[4].name = "st(4)";
1239 ia32_st_regs[5].name = "st(5)";
1240 ia32_st_regs[6].name = "st(6)";
1241 ia32_st_regs[7].name = "st(7)";
1245 isa->name_obst = xmalloc(sizeof(*isa->name_obst));
1246 obstack_init(isa->name_obst);
1247 isa->name_obst_size = 0;
1250 ia32_handle_intrinsics();
1251 ia32_switch_section(NULL, NO_SECTION);
1252 fprintf(isa->out, "\t.intel_syntax\n");
1262 * Closes the output file and frees the ISA structure.
1264 static void ia32_done(void *self) {
1265 ia32_isa_t *isa = self;
1267 /* emit now all global declarations */
1268 ia32_gen_decls(isa->out);
1270 pmap_destroy(isa->regs_16bit);
1271 pmap_destroy(isa->regs_8bit);
1272 pmap_destroy(isa->tv_ent);
1273 pmap_destroy(isa->types);
1276 //printf("name obst size = %d bytes\n", isa->name_obst_size);
1277 obstack_free(isa->name_obst, NULL);
1285 * Return the number of register classes for this architecture.
1286 * We report always these:
1287 * - the general purpose registers
1288 * - the SSE floating point register set
1289 * - the virtual floating point registers
1291 static int ia32_get_n_reg_class(const void *self) {
1296 * Return the register class for index i.
1298 static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
1299 const ia32_isa_t *isa = self;
1300 assert(i >= 0 && i < 3 && "Invalid ia32 register class requested.");
1302 return &ia32_reg_classes[CLASS_ia32_gp];
1304 return &ia32_reg_classes[CLASS_ia32_xmm];
1306 return &ia32_reg_classes[CLASS_ia32_vfp];
1310 * Get the register class which shall be used to store a value of a given mode.
1311 * @param self The this pointer.
1312 * @param mode The mode in question.
1313 * @return A register class which can hold values of the given mode.
1315 const arch_register_class_t *ia32_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
1316 const ia32_isa_t *isa = self;
1317 if (mode_is_float(mode)) {
1318 return USE_SSE2(isa) ? &ia32_reg_classes[CLASS_ia32_xmm] : &ia32_reg_classes[CLASS_ia32_vfp];
1321 return &ia32_reg_classes[CLASS_ia32_gp];
1325 * Get the ABI restrictions for procedure calls.
1326 * @param self The this pointer.
1327 * @param method_type The type of the method (procedure) in question.
1328 * @param abi The abi object to be modified
1330 static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
1331 const ia32_isa_t *isa = self;
1334 unsigned cc = get_method_calling_convention(method_type);
1335 int n = get_method_n_params(method_type);
1338 int i, ignore_1, ignore_2;
1340 const arch_register_t *reg;
1341 be_abi_call_flags_t call_flags = be_abi_call_get_flags(abi);
1343 unsigned use_push = !IS_P6_ARCH(isa->opt_arch);
1345 /* set abi flags for calls */
1346 call_flags.bits.left_to_right = 0; /* always last arg first on stack */
1347 call_flags.bits.store_args_sequential = use_push;
1348 /* call_flags.bits.try_omit_fp not changed: can handle both settings */
1349 call_flags.bits.fp_free = 0; /* the frame pointer is fixed in IA32 */
1350 call_flags.bits.call_has_imm = 1; /* IA32 calls can have immediate address */
1352 /* set stack parameter passing style */
1353 be_abi_call_set_flags(abi, call_flags, &ia32_abi_callbacks);
1355 /* collect the mode for each type */
1356 modes = alloca(n * sizeof(modes[0]));
1358 for (i = 0; i < n; i++) {
1359 tp = get_method_param_type(method_type, i);
1360 modes[i] = get_type_mode(tp);
1363 /* set register parameters */
1364 if (cc & cc_reg_param) {
1365 /* determine the number of parameters passed via registers */
1366 biggest_n = ia32_get_n_regparam_class(n, modes, &ignore_1, &ignore_2);
1368 /* loop over all parameters and set the register requirements */
1369 for (i = 0; i <= biggest_n; i++) {
1370 reg = ia32_get_RegParam_reg(n, modes, i, cc);
1371 assert(reg && "kaputt");
1372 be_abi_call_param_reg(abi, i, reg);
1379 /* set stack parameters */
1380 for (i = stack_idx; i < n; i++) {
1381 be_abi_call_param_stack(abi, i, 1, 0, 0);
1385 /* set return registers */
1386 n = get_method_n_ress(method_type);
1388 assert(n <= 2 && "more than two results not supported");
1390 /* In case of 64bit returns, we will have two 32bit values */
1392 tp = get_method_res_type(method_type, 0);
1393 mode = get_type_mode(tp);
1395 assert(!mode_is_float(mode) && "two FP results not supported");
1397 tp = get_method_res_type(method_type, 1);
1398 mode = get_type_mode(tp);
1400 assert(!mode_is_float(mode) && "two FP results not supported");
1402 be_abi_call_res_reg(abi, 0, &ia32_gp_regs[REG_EAX]);
1403 be_abi_call_res_reg(abi, 1, &ia32_gp_regs[REG_EDX]);
1406 const arch_register_t *reg;
1408 tp = get_method_res_type(method_type, 0);
1409 assert(is_atomic_type(tp));
1410 mode = get_type_mode(tp);
1412 reg = mode_is_float(mode) ?
1413 (USE_SSE2(isa) ? &ia32_xmm_regs[REG_XMM0] : &ia32_vfp_regs[REG_VF0]) :
1414 &ia32_gp_regs[REG_EAX];
1416 be_abi_call_res_reg(abi, 0, reg);
1421 static const void *ia32_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) {
1422 return &ia32_irn_ops;
1425 const arch_irn_handler_t ia32_irn_handler = {
1429 const arch_irn_handler_t *ia32_get_irn_handler(const void *self) {
1430 return &ia32_irn_handler;
1433 int ia32_to_appear_in_schedule(void *block_env, const ir_node *irn) {
1434 return is_ia32_irn(irn) ? 1 : -1;
1438 * Initializes the code generator interface.
1440 static const arch_code_generator_if_t *ia32_get_code_generator_if(void *self) {
1441 return &ia32_code_gen_if;
1444 list_sched_selector_t ia32_sched_selector;
1447 * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
1449 static const list_sched_selector_t *ia32_get_list_sched_selector(const void *self) {
1450 // memcpy(&ia32_sched_selector, reg_pressure_selector, sizeof(list_sched_selector_t));
1451 memcpy(&ia32_sched_selector, trivial_selector, sizeof(list_sched_selector_t));
1452 ia32_sched_selector.to_appear_in_schedule = ia32_to_appear_in_schedule;
1453 return &ia32_sched_selector;
1457 * Returns the necessary byte alignment for storing a register of given class.
1459 static int ia32_get_reg_class_alignment(const void *self, const arch_register_class_t *cls) {
1460 ir_mode *mode = arch_register_class_mode(cls);
1461 int bytes = get_mode_size_bytes(mode);
1463 if (mode_is_float(mode) && bytes > 8)
1468 static ia32_intrinsic_env_t intrinsic_env = { NULL, NULL };
1471 * Returns the libFirm configuration parameter for this backend.
1473 static const backend_params *ia32_get_libfirm_params(void) {
1474 static const arch_dep_params_t ad = {
1475 1, /* also use subs */
1476 4, /* maximum shifts */
1477 31, /* maximum shift amount */
1479 1, /* allow Mulhs */
1480 1, /* allow Mulus */
1481 32 /* Mulh allowed up to 32 bit */
1483 static backend_params p = {
1484 NULL, /* no additional opcodes */
1485 NULL, /* will be set later */
1486 1, /* need dword lowering */
1487 ia32_create_intrinsic_fkt,
1488 &intrinsic_env, /* context for ia32_create_intrinsic_fkt */
1496 /* instruction set architectures. */
1497 static const lc_opt_enum_int_items_t arch_items[] = {
1498 { "386", arch_i386, },
1499 { "486", arch_i486, },
1500 { "pentium", arch_pentium, },
1501 { "586", arch_pentium, },
1502 { "pentiumpro", arch_pentium_pro, },
1503 { "686", arch_pentium_pro, },
1504 { "pentiummmx", arch_pentium_mmx, },
1505 { "pentium2", arch_pentium_2, },
1506 { "p2", arch_pentium_2, },
1507 { "pentium3", arch_pentium_3, },
1508 { "p3", arch_pentium_3, },
1509 { "pentium4", arch_pentium_4, },
1510 { "p4", arch_pentium_4, },
1511 { "pentiumm", arch_pentium_m, },
1512 { "pm", arch_pentium_m, },
1513 { "core", arch_core, },
1515 { "athlon", arch_athlon, },
1516 { "athlon64", arch_athlon_64, },
1517 { "opteron", arch_opteron, },
1521 static lc_opt_enum_int_var_t arch_var = {
1522 &ia32_isa_template.arch, arch_items
1525 static lc_opt_enum_int_var_t opt_arch_var = {
1526 &ia32_isa_template.opt_arch, arch_items
1529 static const lc_opt_enum_int_items_t fp_unit_items[] = {
1531 { "sse2", fp_sse2 },
1535 static lc_opt_enum_int_var_t fp_unit_var = {
1536 &ia32_isa_template.fp_kind, fp_unit_items
1539 static const lc_opt_enum_int_items_t gas_items[] = {
1540 { "linux", ASM_LINUX_GAS },
1541 { "mingw", ASM_MINGW_GAS },
1545 static lc_opt_enum_int_var_t gas_var = {
1546 (int *)&asm_flavour, gas_items
1549 static const lc_opt_table_entry_t ia32_options[] = {
1550 LC_OPT_ENT_ENUM_INT("arch", "select the instruction architecture", &arch_var),
1551 LC_OPT_ENT_ENUM_INT("opt", "optimize for instruction architecture", &opt_arch_var),
1552 LC_OPT_ENT_ENUM_INT("fpunit", "select the floating point unit", &fp_unit_var),
1553 LC_OPT_ENT_NEGBIT("noaddrmode", "do not use address mode", &ia32_isa_template.opt, IA32_OPT_DOAM),
1554 LC_OPT_ENT_NEGBIT("nolea", "do not optimize for LEAs", &ia32_isa_template.opt, IA32_OPT_LEA),
1555 LC_OPT_ENT_NEGBIT("noplacecnst", "do not place constants", &ia32_isa_template.opt, IA32_OPT_PLACECNST),
1556 LC_OPT_ENT_NEGBIT("noimmop", "no operations with immediates", &ia32_isa_template.opt, IA32_OPT_IMMOPS),
1557 LC_OPT_ENT_NEGBIT("noextbb", "do not use extended basic block scheduling", &ia32_isa_template.opt, IA32_OPT_EXTBB),
1558 LC_OPT_ENT_ENUM_INT("gasmode", "set the GAS compatibility mode", &gas_var),
1563 * Register command line options for the ia32 backend.
1567 * ia32-arch=arch create instruction for arch
1568 * ia32-opt=arch optimize for run on arch
1569 * ia32-fpunit=unit select floating point unit (x87 or SSE2)
1570 * ia32-incdec optimize for inc/dec
1571 * ia32-noaddrmode do not use address mode
1572 * ia32-nolea do not optimize for LEAs
1573 * ia32-noplacecnst do not place constants,
1574 * ia32-noimmop no operations with immediates
1575 * ia32-noextbb do not use extended basic block scheduling
1576 * ia32-gasmode set the GAS compatibility mode
1578 static void ia32_register_options(lc_opt_entry_t *ent)
1580 lc_opt_entry_t *be_grp_ia32 = lc_opt_get_grp(ent, "ia32");
1581 lc_opt_add_table(be_grp_ia32, ia32_options);
1583 #endif /* WITH_LIBCORE */
1585 const arch_isa_if_t ia32_isa_if = {
1588 ia32_get_n_reg_class,
1590 ia32_get_reg_class_for_mode,
1592 ia32_get_irn_handler,
1593 ia32_get_code_generator_if,
1594 ia32_get_list_sched_selector,
1595 ia32_get_reg_class_alignment,
1596 ia32_get_libfirm_params,
1598 ia32_register_options