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)
480 switch (get_ia32_irn_opcode(irn)) {
482 case iro_ia32_DivMod:
487 case iro_ia32_l_Load:
497 case iro_ia32_xStore:
498 case iro_ia32_l_Store:
500 case iro_ia32_Store8Bit:
508 case iro_ia32_l_MulS:
521 * Returns the inverse operation if @p irn, recalculating the argument at position @p i.
523 * @param irn The original operation
524 * @param i Index of the argument we want the inverse operation to yield
525 * @param inverse struct to be filled with the resulting inverse op
526 * @param obstack The obstack to use for allocation of the returned nodes array
527 * @return The inverse operation or NULL if operation invertible
529 static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obst) {
532 ir_node *block, *noreg, *nomem;
535 /* we cannot invert non-ia32 irns */
536 if (! is_ia32_irn(irn))
539 /* operand must always be a real operand (not base, index or mem) */
540 if (i != 2 && i != 3)
543 /* we don't invert address mode operations */
544 if (get_ia32_op_type(irn) != ia32_Normal)
547 irg = get_irn_irg(irn);
548 block = get_nodes_block(irn);
549 mode = get_ia32_res_mode(irn);
550 noreg = get_irn_n(irn, 0);
551 nomem = new_r_NoMem(irg);
553 /* initialize structure */
554 inverse->nodes = obstack_alloc(obst, 2 * sizeof(inverse->nodes[0]));
558 switch (get_ia32_irn_opcode(irn)) {
560 if (get_ia32_immop_type(irn) == ia32_ImmConst) {
561 /* we have an add with a const here */
562 /* invers == add with negated const */
563 inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
564 pnc = pn_ia32_Add_res;
566 copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
567 set_ia32_Immop_tarval(inverse->nodes[0], tarval_neg(get_ia32_Immop_tarval(irn)));
568 set_ia32_commutative(inverse->nodes[0]);
570 else if (get_ia32_immop_type(irn) == ia32_ImmSymConst) {
571 /* we have an add with a symconst here */
572 /* invers == sub with const */
573 inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
574 pnc = pn_ia32_Sub_res;
576 copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
579 /* normal add: inverse == sub */
580 ir_node *proj = ia32_get_res_proj(irn);
583 inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, proj, get_irn_n(irn, i ^ 1), nomem);
584 pnc = pn_ia32_Sub_res;
589 if (get_ia32_immop_type(irn) != ia32_ImmNone) {
590 /* we have a sub with a const/symconst here */
591 /* invers == add with this const */
592 inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
593 pnc = pn_ia32_Add_res;
594 inverse->costs += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
595 copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
599 ir_node *proj = ia32_get_res_proj(irn);
603 inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, proj, get_irn_n(irn, 3), nomem);
606 inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, get_irn_n(irn, 2), proj, nomem);
608 pnc = pn_ia32_Sub_res;
613 if (get_ia32_immop_type(irn) != ia32_ImmNone) {
614 /* xor with const: inverse = xor */
615 inverse->nodes[0] = new_rd_ia32_Eor(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
616 pnc = pn_ia32_Eor_res;
617 inverse->costs += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
618 copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
622 inverse->nodes[0] = new_rd_ia32_Eor(NULL, irg, block, noreg, noreg, (ir_node *)irn, get_irn_n(irn, i), nomem);
623 pnc = pn_ia32_Eor_res;
628 ir_node *proj = ia32_get_res_proj(irn);
631 inverse->nodes[0] = new_rd_ia32_Not(NULL, irg, block, noreg, noreg, proj, nomem);
632 pnc = pn_ia32_Not_res;
636 case iro_ia32_Minus: {
637 ir_node *proj = ia32_get_res_proj(irn);
640 inverse->nodes[0] = new_rd_ia32_Minus(NULL, irg, block, noreg, noreg, proj, nomem);
641 pnc = pn_ia32_Minus_res;
646 /* inverse operation not supported */
650 set_ia32_res_mode(inverse->nodes[0], mode);
651 inverse->nodes[1] = new_r_Proj(irg, block, inverse->nodes[0], mode, pnc);
657 * Check if irn can load it's operand at position i from memory (source addressmode).
658 * @param self Pointer to irn ops itself
659 * @param irn The irn to be checked
660 * @param i The operands position
661 * @return Non-Zero if operand can be loaded
663 static int ia32_possible_memory_operand(const void *self, const ir_node *irn, unsigned int i) {
664 if (! is_ia32_irn(irn) || /* must be an ia32 irn */
665 get_irn_arity(irn) != 5 || /* must be a binary operation */
666 get_ia32_op_type(irn) != ia32_Normal || /* must not already be a addressmode irn */
667 ! (get_ia32_am_support(irn) & ia32_am_Source) || /* must be capable of source addressmode */
668 (i != 2 && i != 3) || /* a "real" operand position must be requested */
669 (i == 2 && ! is_ia32_commutative(irn)) || /* if first operand requested irn must be commutative */
670 is_ia32_use_frame(irn)) /* must not already use frame */
676 static void ia32_perform_memory_operand(const void *self, ir_node *irn, ir_node *reload, unsigned int i) {
677 assert(ia32_possible_memory_operand(self, irn, i) && "Cannot perform memory operand change");
678 assert(get_nodes_block(reload) == get_nodes_block(irn) && "Reload must be in same block as irn.");
680 if (get_irn_n_edges(reload) > 1)
684 ir_node *tmp = get_irn_n(irn, 3);
685 set_irn_n(irn, 3, get_irn_n(irn, 2));
686 set_irn_n(irn, 2, tmp);
689 set_ia32_am_support(irn, ia32_am_Source);
690 set_ia32_op_type(irn, ia32_AddrModeS);
691 set_ia32_am_flavour(irn, ia32_B);
692 set_ia32_ls_mode(irn, get_irn_mode(reload));
693 set_ia32_frame_ent(irn, be_get_frame_entity(reload));
694 set_ia32_use_frame(irn);
696 set_irn_n(irn, 0, be_get_Reload_frame(reload));
697 set_irn_n(irn, 4, be_get_Reload_mem(reload));
700 Input at position one is index register, which is NoReg.
701 We would need cg object to get a real noreg, but we cannot
704 set_irn_n(irn, 3, get_irn_n(irn, 1));
706 DBG_OPT_AM_S(reload, irn);
709 static const be_abi_callbacks_t ia32_abi_callbacks = {
712 ia32_abi_get_between_type,
713 ia32_abi_dont_save_regs,
718 /* fill register allocator interface */
720 static const arch_irn_ops_if_t ia32_irn_ops_if = {
721 ia32_get_irn_reg_req,
726 ia32_get_frame_entity,
729 ia32_get_op_estimated_cost,
730 ia32_possible_memory_operand,
731 ia32_perform_memory_operand,
734 ia32_irn_ops_t ia32_irn_ops = {
741 /**************************************************
744 * ___ ___ __| | ___ __ _ ___ _ __ _| |_
745 * / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \ | | _|
746 * | (_| (_) | (_| | __/ (_| | __/ | | | | | |
747 * \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
750 **************************************************/
753 * Transforms the standard firm graph into
756 static void ia32_prepare_graph(void *self) {
757 ia32_code_gen_t *cg = self;
758 dom_front_info_t *dom;
759 DEBUG_ONLY(firm_dbg_module_t *old_mod = cg->mod;)
761 FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
763 /* 1st: transform constants and psi condition trees */
764 ia32_pre_transform_phase(cg);
766 /* 2nd: transform all remaining nodes */
767 ia32_register_transformers();
768 dom = be_compute_dominance_frontiers(cg->irg);
769 irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_node, cg);
770 be_free_dominance_frontiers(dom);
773 be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
775 /* 3rd: optimize address mode */
776 FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.am");
777 ia32_optimize_addressmode(cg);
780 be_dump(cg->irg, "-am", dump_ir_block_graph_sched);
782 DEBUG_ONLY(cg->mod = old_mod;)
786 * Dummy functions for hooks we don't need but which must be filled.
788 static void ia32_before_sched(void *self) {
791 static void remove_unused_nodes(ir_node *irn, bitset_t *already_visited) {
799 mode = get_irn_mode(irn);
801 /* check if we already saw this node or the node has more than one user */
802 if (bitset_contains_irn(already_visited, irn) || get_irn_n_edges(irn) > 1)
805 /* mark irn visited */
806 bitset_add_irn(already_visited, irn);
808 /* non-Tuple nodes with one user: ok, return */
809 if (get_irn_n_edges(irn) >= 1 && mode != mode_T)
812 /* tuple node has one user which is not the mem proj-> ok */
813 if (mode == mode_T && get_irn_n_edges(irn) == 1) {
814 mem_proj = ia32_get_proj_for_mode(irn, mode_M);
819 for (i = get_irn_arity(irn) - 1; i >= 0; i--) {
820 ir_node *pred = get_irn_n(irn, i);
822 /* do not follow memory edges or we will accidentally remove stores */
823 if (is_Proj(pred) && get_irn_mode(pred) == mode_M)
826 set_irn_n(irn, i, new_Bad());
829 The current node is about to be removed: if the predecessor
830 has only this node as user, it need to be removed as well.
832 if (get_irn_n_edges(pred) <= 1)
833 remove_unused_nodes(pred, already_visited);
836 if (sched_is_scheduled(irn))
840 static void remove_unused_loads_walker(ir_node *irn, void *env) {
841 bitset_t *already_visited = env;
842 if (is_ia32_Ld(irn) && ! bitset_contains_irn(already_visited, irn))
843 remove_unused_nodes(irn, env);
847 * Called before the register allocator.
848 * Calculate a block schedule here. We need it for the x87
849 * simulator and the emitter.
851 static void ia32_before_ra(void *self) {
852 ia32_code_gen_t *cg = self;
853 bitset_t *already_visited = bitset_irg_malloc(cg->irg);
855 cg->blk_sched = sched_create_block_schedule(cg->irg);
859 There are sometimes unused loads, only pinned by memory.
860 We need to remove those Loads and all other nodes which won't be used
861 after removing the Load from schedule.
863 irg_walk_graph(cg->irg, remove_unused_loads_walker, NULL, already_visited);
864 bitset_free(already_visited);
869 * Transforms a be node into a Load.
871 static void transform_to_Load(ia32_transform_env_t *env) {
872 ir_node *irn = env->irn;
873 entity *ent = be_get_frame_entity(irn);
874 ir_mode *mode = env->mode;
875 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
876 ir_node *nomem = new_rd_NoMem(env->irg);
877 ir_node *sched_point = NULL;
878 ir_node *ptr = get_irn_n(irn, 0);
879 ir_node *mem = be_is_Reload(irn) ? get_irn_n(irn, 1) : nomem;
880 ir_node *new_op, *proj;
881 const arch_register_t *reg;
883 if (sched_is_scheduled(irn)) {
884 sched_point = sched_prev(irn);
887 if (mode_is_float(mode)) {
888 if (USE_SSE2(env->cg))
889 new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, mem);
891 new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
894 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem);
897 set_ia32_am_support(new_op, ia32_am_Source);
898 set_ia32_op_type(new_op, ia32_AddrModeS);
899 set_ia32_am_flavour(new_op, ia32_B);
900 set_ia32_ls_mode(new_op, mode);
901 set_ia32_frame_ent(new_op, ent);
902 set_ia32_use_frame(new_op);
904 DBG_OPT_RELOAD2LD(irn, new_op);
906 proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, pn_Load_res);
909 sched_add_after(sched_point, new_op);
910 sched_add_after(new_op, proj);
915 /* copy the register from the old node to the new Load */
916 reg = arch_get_irn_register(env->cg->arch_env, irn);
917 arch_set_irn_register(env->cg->arch_env, new_op, reg);
919 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, irn));
925 * Transforms a be node into a Store.
927 static void transform_to_Store(ia32_transform_env_t *env) {
928 ir_node *irn = env->irn;
929 entity *ent = be_get_frame_entity(irn);
930 ir_mode *mode = env->mode;
931 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
932 ir_node *nomem = new_rd_NoMem(env->irg);
933 ir_node *ptr = get_irn_n(irn, 0);
934 ir_node *val = get_irn_n(irn, 1);
935 ir_node *new_op, *proj;
936 ir_node *sched_point = NULL;
938 if (sched_is_scheduled(irn)) {
939 sched_point = sched_prev(irn);
942 if (mode_is_float(mode)) {
943 if (USE_SSE2(env->cg))
944 new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
946 new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
948 else if (get_mode_size_bits(mode) == 8) {
949 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
952 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
955 set_ia32_am_support(new_op, ia32_am_Dest);
956 set_ia32_op_type(new_op, ia32_AddrModeD);
957 set_ia32_am_flavour(new_op, ia32_B);
958 set_ia32_ls_mode(new_op, mode);
959 set_ia32_frame_ent(new_op, ent);
960 set_ia32_use_frame(new_op);
962 DBG_OPT_SPILL2ST(irn, new_op);
964 proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, pn_ia32_Store_M);
967 sched_add_after(sched_point, new_op);
971 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, irn));
977 * Fix the mode of Spill/Reload
979 static ir_mode *fix_spill_mode(ia32_code_gen_t *cg, ir_mode *mode)
981 if (mode_is_float(mode)) {
993 * Block-Walker: Calls the transform functions Spill and Reload.
995 static void ia32_after_ra_walker(ir_node *block, void *env) {
996 ir_node *node, *prev;
997 ia32_code_gen_t *cg = env;
998 ia32_transform_env_t tenv;
1001 tenv.irg = current_ir_graph;
1003 DEBUG_ONLY(tenv.mod = cg->mod;)
1005 /* beware: the schedule is changed here */
1006 for (node = sched_last(block); !sched_is_begin(node); node = prev) {
1007 prev = sched_prev(node);
1008 if (be_is_Reload(node)) {
1009 /* we always reload the whole register */
1010 tenv.dbg = get_irn_dbg_info(node);
1012 tenv.mode = fix_spill_mode(cg, get_irn_mode(node));
1013 transform_to_Load(&tenv);
1015 else if (be_is_Spill(node)) {
1016 /* we always spill the whole register */
1017 tenv.dbg = get_irn_dbg_info(node);
1019 tenv.mode = fix_spill_mode(cg, get_irn_mode(be_get_Spill_context(node)));
1020 transform_to_Store(&tenv);
1026 * We transform Spill and Reload here. This needs to be done before
1027 * stack biasing otherwise we would miss the corrected offset for these nodes.
1029 * If x87 instruction should be emitted, run the x87 simulator and patch
1030 * the virtual instructions. This must obviously be done after register allocation.
1032 static void ia32_after_ra(void *self) {
1033 ia32_code_gen_t *cg = self;
1035 irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
1037 /* if we do x87 code generation, rewrite all the virtual instructions and registers */
1038 if (cg->used_fp == fp_x87 || cg->force_sim) {
1039 x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
1045 * Emits the code, closes the output file and frees
1046 * the code generator interface.
1048 static void ia32_codegen(void *self) {
1049 ia32_code_gen_t *cg = self;
1050 ir_graph *irg = cg->irg;
1052 ia32_finish_irg(irg, cg);
1054 be_dump(irg, "-finished", dump_ir_block_graph_sched);
1055 ia32_gen_routine(cg->isa->out, irg, cg);
1059 /* remove it from the isa */
1062 /* de-allocate code generator */
1063 del_set(cg->reg_set);
1068 static void *ia32_cg_init(const be_irg_t *birg);
1070 static const arch_code_generator_if_t ia32_code_gen_if = {
1072 NULL, /* before abi introduce hook */
1074 ia32_before_sched, /* before scheduling hook */
1075 ia32_before_ra, /* before register allocation hook */
1076 ia32_after_ra, /* after register allocation hook */
1077 ia32_codegen /* emit && done */
1081 * Initializes a IA32 code generator.
1083 static void *ia32_cg_init(const be_irg_t *birg) {
1084 ia32_isa_t *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
1085 ia32_code_gen_t *cg = xcalloc(1, sizeof(*cg));
1087 cg->impl = &ia32_code_gen_if;
1088 cg->irg = birg->irg;
1089 cg->reg_set = new_set(ia32_cmp_irn_reg_assoc, 1024);
1090 cg->arch_env = birg->main_env->arch_env;
1093 cg->blk_sched = NULL;
1094 cg->fp_to_gp = NULL;
1095 cg->gp_to_fp = NULL;
1096 cg->fp_kind = isa->fp_kind;
1097 cg->used_fp = fp_none;
1098 cg->dump = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
1100 FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.cg");
1102 /* copy optimizations from isa for easier access */
1104 cg->arch = isa->arch;
1105 cg->opt_arch = isa->opt_arch;
1111 if (isa->name_obst_size) {
1112 //printf("freed %d bytes from name obst\n", isa->name_obst_size);
1113 isa->name_obst_size = 0;
1114 obstack_free(isa->name_obst, NULL);
1115 obstack_init(isa->name_obst);
1119 cur_reg_set = cg->reg_set;
1121 ia32_irn_ops.cg = cg;
1123 return (arch_code_generator_t *)cg;
1128 /*****************************************************************
1129 * ____ _ _ _____ _____
1130 * | _ \ | | | | |_ _|/ ____| /\
1131 * | |_) | __ _ ___| | _____ _ __ __| | | | | (___ / \
1132 * | _ < / _` |/ __| |/ / _ \ '_ \ / _` | | | \___ \ / /\ \
1133 * | |_) | (_| | (__| < __/ | | | (_| | _| |_ ____) / ____ \
1134 * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/ \_\
1136 *****************************************************************/
1139 * Set output modes for GCC
1141 static const tarval_mode_info mo_integer = {
1148 * set the tarval output mode to C-semantics
1150 static void set_tarval_output_modes(void)
1152 set_tarval_mode_output_option(get_modeLs(), &mo_integer);
1153 set_tarval_mode_output_option(get_modeLu(), &mo_integer);
1154 set_tarval_mode_output_option(get_modeIs(), &mo_integer);
1155 set_tarval_mode_output_option(get_modeIu(), &mo_integer);
1156 set_tarval_mode_output_option(get_modeHs(), &mo_integer);
1157 set_tarval_mode_output_option(get_modeHu(), &mo_integer);
1158 set_tarval_mode_output_option(get_modeBs(), &mo_integer);
1159 set_tarval_mode_output_option(get_modeBu(), &mo_integer);
1160 set_tarval_mode_output_option(get_modeC(), &mo_integer);
1161 set_tarval_mode_output_option(get_modeU(), &mo_integer);
1162 set_tarval_mode_output_option(get_modeIu(), &mo_integer);
1167 * The template that generates a new ISA object.
1168 * Note that this template can be changed by command line
1171 static ia32_isa_t ia32_isa_template = {
1173 &ia32_isa_if, /* isa interface implementation */
1174 &ia32_gp_regs[REG_ESP], /* stack pointer register */
1175 &ia32_gp_regs[REG_EBP], /* base pointer register */
1176 -1, /* stack direction */
1178 NULL, /* 16bit register names */
1179 NULL, /* 8bit register names */
1183 IA32_OPT_INCDEC | /* optimize add 1, sub 1 into inc/dec default: on */
1184 IA32_OPT_DOAM | /* optimize address mode default: on */
1185 IA32_OPT_LEA | /* optimize for LEAs default: on */
1186 IA32_OPT_PLACECNST | /* place constants immediately before instructions, default: on */
1187 IA32_OPT_IMMOPS | /* operations can use immediates, default: on */
1188 IA32_OPT_EXTBB), /* use extended basic block scheduling, default: on */
1189 arch_pentium_4, /* instruction architecture */
1190 arch_pentium_4, /* optimize for architecture */
1191 fp_sse2, /* use sse2 unit */
1192 NULL, /* current code generator */
1194 NULL, /* name obstack */
1195 0 /* name obst size */
1200 * Initializes the backend ISA.
1202 static void *ia32_init(FILE *file_handle) {
1203 static int inited = 0;
1209 set_tarval_output_modes();
1211 isa = xmalloc(sizeof(*isa));
1212 memcpy(isa, &ia32_isa_template, sizeof(*isa));
1214 ia32_register_init(isa);
1215 ia32_create_opcodes();
1217 if ((ARCH_INTEL(isa->arch) && isa->arch < arch_pentium_4) ||
1218 (ARCH_AMD(isa->arch) && isa->arch < arch_athlon))
1219 /* no SSE2 for these cpu's */
1220 isa->fp_kind = fp_x87;
1222 if (ARCH_INTEL(isa->opt_arch) && isa->opt_arch >= arch_pentium_4) {
1223 /* Pentium 4 don't like inc and dec instructions */
1224 isa->opt &= ~IA32_OPT_INCDEC;
1227 isa->regs_16bit = pmap_create();
1228 isa->regs_8bit = pmap_create();
1229 isa->types = pmap_create();
1230 isa->tv_ent = pmap_create();
1231 isa->out = file_handle;
1233 ia32_build_16bit_reg_map(isa->regs_16bit);
1234 ia32_build_8bit_reg_map(isa->regs_8bit);
1236 /* patch register names of x87 registers */
1238 ia32_st_regs[0].name = "st";
1239 ia32_st_regs[1].name = "st(1)";
1240 ia32_st_regs[2].name = "st(2)";
1241 ia32_st_regs[3].name = "st(3)";
1242 ia32_st_regs[4].name = "st(4)";
1243 ia32_st_regs[5].name = "st(5)";
1244 ia32_st_regs[6].name = "st(6)";
1245 ia32_st_regs[7].name = "st(7)";
1249 isa->name_obst = xmalloc(sizeof(*isa->name_obst));
1250 obstack_init(isa->name_obst);
1251 isa->name_obst_size = 0;
1254 ia32_handle_intrinsics();
1255 ia32_switch_section(NULL, NO_SECTION);
1256 fprintf(isa->out, "\t.intel_syntax\n");
1266 * Closes the output file and frees the ISA structure.
1268 static void ia32_done(void *self) {
1269 ia32_isa_t *isa = self;
1271 /* emit now all global declarations */
1272 ia32_gen_decls(isa->out);
1274 pmap_destroy(isa->regs_16bit);
1275 pmap_destroy(isa->regs_8bit);
1276 pmap_destroy(isa->tv_ent);
1277 pmap_destroy(isa->types);
1280 //printf("name obst size = %d bytes\n", isa->name_obst_size);
1281 obstack_free(isa->name_obst, NULL);
1289 * Return the number of register classes for this architecture.
1290 * We report always these:
1291 * - the general purpose registers
1292 * - the SSE floating point register set
1293 * - the virtual floating point registers
1295 static int ia32_get_n_reg_class(const void *self) {
1300 * Return the register class for index i.
1302 static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
1303 const ia32_isa_t *isa = self;
1304 assert(i >= 0 && i < 3 && "Invalid ia32 register class requested.");
1306 return &ia32_reg_classes[CLASS_ia32_gp];
1308 return &ia32_reg_classes[CLASS_ia32_xmm];
1310 return &ia32_reg_classes[CLASS_ia32_vfp];
1314 * Get the register class which shall be used to store a value of a given mode.
1315 * @param self The this pointer.
1316 * @param mode The mode in question.
1317 * @return A register class which can hold values of the given mode.
1319 const arch_register_class_t *ia32_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
1320 const ia32_isa_t *isa = self;
1321 if (mode_is_float(mode)) {
1322 return USE_SSE2(isa) ? &ia32_reg_classes[CLASS_ia32_xmm] : &ia32_reg_classes[CLASS_ia32_vfp];
1325 return &ia32_reg_classes[CLASS_ia32_gp];
1329 * Get the ABI restrictions for procedure calls.
1330 * @param self The this pointer.
1331 * @param method_type The type of the method (procedure) in question.
1332 * @param abi The abi object to be modified
1334 static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
1335 const ia32_isa_t *isa = self;
1338 unsigned cc = get_method_calling_convention(method_type);
1339 int n = get_method_n_params(method_type);
1342 int i, ignore_1, ignore_2;
1344 const arch_register_t *reg;
1345 be_abi_call_flags_t call_flags = be_abi_call_get_flags(abi);
1347 unsigned use_push = !IS_P6_ARCH(isa->opt_arch);
1349 /* set abi flags for calls */
1350 call_flags.bits.left_to_right = 0; /* always last arg first on stack */
1351 call_flags.bits.store_args_sequential = use_push;
1352 /* call_flags.bits.try_omit_fp not changed: can handle both settings */
1353 call_flags.bits.fp_free = 0; /* the frame pointer is fixed in IA32 */
1354 call_flags.bits.call_has_imm = 1; /* IA32 calls can have immediate address */
1356 /* set stack parameter passing style */
1357 be_abi_call_set_flags(abi, call_flags, &ia32_abi_callbacks);
1359 /* collect the mode for each type */
1360 modes = alloca(n * sizeof(modes[0]));
1362 for (i = 0; i < n; i++) {
1363 tp = get_method_param_type(method_type, i);
1364 modes[i] = get_type_mode(tp);
1367 /* set register parameters */
1368 if (cc & cc_reg_param) {
1369 /* determine the number of parameters passed via registers */
1370 biggest_n = ia32_get_n_regparam_class(n, modes, &ignore_1, &ignore_2);
1372 /* loop over all parameters and set the register requirements */
1373 for (i = 0; i <= biggest_n; i++) {
1374 reg = ia32_get_RegParam_reg(n, modes, i, cc);
1375 assert(reg && "kaputt");
1376 be_abi_call_param_reg(abi, i, reg);
1383 /* set stack parameters */
1384 for (i = stack_idx; i < n; i++) {
1385 be_abi_call_param_stack(abi, i, 1, 0, 0);
1389 /* set return registers */
1390 n = get_method_n_ress(method_type);
1392 assert(n <= 2 && "more than two results not supported");
1394 /* In case of 64bit returns, we will have two 32bit values */
1396 tp = get_method_res_type(method_type, 0);
1397 mode = get_type_mode(tp);
1399 assert(!mode_is_float(mode) && "two FP results not supported");
1401 tp = get_method_res_type(method_type, 1);
1402 mode = get_type_mode(tp);
1404 assert(!mode_is_float(mode) && "two FP results not supported");
1406 be_abi_call_res_reg(abi, 0, &ia32_gp_regs[REG_EAX]);
1407 be_abi_call_res_reg(abi, 1, &ia32_gp_regs[REG_EDX]);
1410 const arch_register_t *reg;
1412 tp = get_method_res_type(method_type, 0);
1413 assert(is_atomic_type(tp));
1414 mode = get_type_mode(tp);
1416 reg = mode_is_float(mode) ?
1417 (USE_SSE2(isa) ? &ia32_xmm_regs[REG_XMM0] : &ia32_vfp_regs[REG_VF0]) :
1418 &ia32_gp_regs[REG_EAX];
1420 be_abi_call_res_reg(abi, 0, reg);
1425 static const void *ia32_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) {
1426 return &ia32_irn_ops;
1429 const arch_irn_handler_t ia32_irn_handler = {
1433 const arch_irn_handler_t *ia32_get_irn_handler(const void *self) {
1434 return &ia32_irn_handler;
1437 int ia32_to_appear_in_schedule(void *block_env, const ir_node *irn) {
1438 return is_ia32_irn(irn) ? 1 : -1;
1442 * Initializes the code generator interface.
1444 static const arch_code_generator_if_t *ia32_get_code_generator_if(void *self) {
1445 return &ia32_code_gen_if;
1448 list_sched_selector_t ia32_sched_selector;
1451 * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
1453 static const list_sched_selector_t *ia32_get_list_sched_selector(const void *self) {
1454 // memcpy(&ia32_sched_selector, reg_pressure_selector, sizeof(list_sched_selector_t));
1455 memcpy(&ia32_sched_selector, trivial_selector, sizeof(list_sched_selector_t));
1456 ia32_sched_selector.to_appear_in_schedule = ia32_to_appear_in_schedule;
1457 return &ia32_sched_selector;
1461 * Returns the necessary byte alignment for storing a register of given class.
1463 static int ia32_get_reg_class_alignment(const void *self, const arch_register_class_t *cls) {
1464 ir_mode *mode = arch_register_class_mode(cls);
1465 int bytes = get_mode_size_bytes(mode);
1467 if (mode_is_float(mode) && bytes > 8)
1472 static ia32_intrinsic_env_t intrinsic_env = { NULL, NULL };
1475 * Returns the libFirm configuration parameter for this backend.
1477 static const backend_params *ia32_get_libfirm_params(void) {
1478 static const arch_dep_params_t ad = {
1479 1, /* also use subs */
1480 4, /* maximum shifts */
1481 31, /* maximum shift amount */
1483 1, /* allow Mulhs */
1484 1, /* allow Mulus */
1485 32 /* Mulh allowed up to 32 bit */
1487 static backend_params p = {
1488 NULL, /* no additional opcodes */
1489 NULL, /* will be set later */
1490 1, /* need dword lowering */
1491 ia32_create_intrinsic_fkt,
1492 &intrinsic_env, /* context for ia32_create_intrinsic_fkt */
1500 /* instruction set architectures. */
1501 static const lc_opt_enum_int_items_t arch_items[] = {
1502 { "386", arch_i386, },
1503 { "486", arch_i486, },
1504 { "pentium", arch_pentium, },
1505 { "586", arch_pentium, },
1506 { "pentiumpro", arch_pentium_pro, },
1507 { "686", arch_pentium_pro, },
1508 { "pentiummmx", arch_pentium_mmx, },
1509 { "pentium2", arch_pentium_2, },
1510 { "p2", arch_pentium_2, },
1511 { "pentium3", arch_pentium_3, },
1512 { "p3", arch_pentium_3, },
1513 { "pentium4", arch_pentium_4, },
1514 { "p4", arch_pentium_4, },
1515 { "pentiumm", arch_pentium_m, },
1516 { "pm", arch_pentium_m, },
1517 { "core", arch_core, },
1519 { "athlon", arch_athlon, },
1520 { "athlon64", arch_athlon_64, },
1521 { "opteron", arch_opteron, },
1525 static lc_opt_enum_int_var_t arch_var = {
1526 &ia32_isa_template.arch, arch_items
1529 static lc_opt_enum_int_var_t opt_arch_var = {
1530 &ia32_isa_template.opt_arch, arch_items
1533 static const lc_opt_enum_int_items_t fp_unit_items[] = {
1535 { "sse2", fp_sse2 },
1539 static lc_opt_enum_int_var_t fp_unit_var = {
1540 &ia32_isa_template.fp_kind, fp_unit_items
1543 static const lc_opt_enum_int_items_t gas_items[] = {
1544 { "linux", ASM_LINUX_GAS },
1545 { "mingw", ASM_MINGW_GAS },
1549 static lc_opt_enum_int_var_t gas_var = {
1550 (int *)&asm_flavour, gas_items
1553 static const lc_opt_table_entry_t ia32_options[] = {
1554 LC_OPT_ENT_ENUM_INT("arch", "select the instruction architecture", &arch_var),
1555 LC_OPT_ENT_ENUM_INT("opt", "optimize for instruction architecture", &opt_arch_var),
1556 LC_OPT_ENT_ENUM_INT("fpunit", "select the floating point unit", &fp_unit_var),
1557 LC_OPT_ENT_NEGBIT("noaddrmode", "do not use address mode", &ia32_isa_template.opt, IA32_OPT_DOAM),
1558 LC_OPT_ENT_NEGBIT("nolea", "do not optimize for LEAs", &ia32_isa_template.opt, IA32_OPT_LEA),
1559 LC_OPT_ENT_NEGBIT("noplacecnst", "do not place constants", &ia32_isa_template.opt, IA32_OPT_PLACECNST),
1560 LC_OPT_ENT_NEGBIT("noimmop", "no operations with immediates", &ia32_isa_template.opt, IA32_OPT_IMMOPS),
1561 LC_OPT_ENT_NEGBIT("noextbb", "do not use extended basic block scheduling", &ia32_isa_template.opt, IA32_OPT_EXTBB),
1562 LC_OPT_ENT_ENUM_INT("gasmode", "set the GAS compatibility mode", &gas_var),
1567 * Register command line options for the ia32 backend.
1571 * ia32-arch=arch create instruction for arch
1572 * ia32-opt=arch optimize for run on arch
1573 * ia32-fpunit=unit select floating point unit (x87 or SSE2)
1574 * ia32-incdec optimize for inc/dec
1575 * ia32-noaddrmode do not use address mode
1576 * ia32-nolea do not optimize for LEAs
1577 * ia32-noplacecnst do not place constants,
1578 * ia32-noimmop no operations with immediates
1579 * ia32-noextbb do not use extended basic block scheduling
1580 * ia32-gasmode set the GAS compatibility mode
1582 static void ia32_register_options(lc_opt_entry_t *ent)
1584 lc_opt_entry_t *be_grp_ia32 = lc_opt_get_grp(ent, "ia32");
1585 lc_opt_add_table(be_grp_ia32, ia32_options);
1587 #endif /* WITH_LIBCORE */
1589 const arch_isa_if_t ia32_isa_if = {
1592 ia32_get_n_reg_class,
1594 ia32_get_reg_class_for_mode,
1596 ia32_get_irn_handler,
1597 ia32_get_code_generator_if,
1598 ia32_get_list_sched_selector,
1599 ia32_get_reg_class_alignment,
1600 ia32_get_libfirm_params,
1602 ia32_register_options