curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, *mem, BE_STACK_FRAME_SIZE, be_stack_dir_shrink);
}
else {
- ir_node *pop;
+ const ia32_isa_t *isa = (ia32_isa_t *)env->isa;
ir_mode *mode_bp = env->isa->bp->reg_class->mode;
int reg_size = get_mode_size_bytes(env->isa->bp->reg_class->mode);
- /* copy ebp to esp */
- curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
+ if (ARCH_AMD(isa->opt_arch)) {
+ ir_node *leave;
- /* pop ebp */
- pop = new_rd_ia32_Pop(NULL, env->irg, bl, curr_sp, *mem, mode_T);
- set_ia32_flags(pop, arch_irn_flags_ignore);
- curr_bp = new_r_Proj(current_ir_graph, bl, pop, mode_bp, 0);
- curr_sp = new_r_Proj(current_ir_graph, bl, pop, get_irn_mode(curr_sp), 1);
- *mem = new_r_Proj(current_ir_graph, bl, pop, mode_M, 2);
+ /* leave */
+ leave = new_rd_ia32_Leave(NULL, env->irg, bl, curr_sp, *mem, mode_T);
+ set_ia32_flags(leave, arch_irn_flags_ignore);
+ curr_bp = new_r_Proj(current_ir_graph, bl, leave, mode_bp, 0);
+ curr_sp = new_r_Proj(current_ir_graph, bl, leave, get_irn_mode(curr_sp), 1);
+ *mem = new_r_Proj(current_ir_graph, bl, leave, mode_M, 2);
+ }
+ else {
+ ir_node *pop;
+
+ /* copy ebp to esp */
+ curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
+
+ /* pop ebp */
+ pop = new_rd_ia32_Pop(NULL, env->irg, bl, curr_sp, *mem, mode_T);
+ set_ia32_flags(pop, arch_irn_flags_ignore);
+ curr_bp = new_r_Proj(current_ir_graph, bl, pop, mode_bp, 0);
+ curr_sp = new_r_Proj(current_ir_graph, bl, pop, get_irn_mode(curr_sp), 1);
+ *mem = new_r_Proj(current_ir_graph, bl, pop, mode_M, 2);
+ }
arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
}
NULL, /* types */
NULL, /* tv_ents */
(0 |
+ IA32_OPT_INCDEC | /* optimize add 1, sub 1 into inc/dec default: on */
IA32_OPT_DOAM | /* optimize address mode default: on */
IA32_OPT_PLACECNST | /* place constants immediately before instructions, default: on */
IA32_OPT_IMMOPS | /* operations can use immediates, default: on */
ia32_create_opcodes();
ia32_register_copy_attr_func();
+ if ((ARCH_INTEL(isa->arch) && isa->arch < arch_pentium_4) ||
+ (ARCH_AMD(isa->arch) && isa->arch < arch_athlon))
+ /* no SSE2 for these cpu's */
+ isa->fp_kind = fp_x87;
+
+ if (ARCH_INTEL(isa->opt_arch) && isa->opt_arch >= arch_pentium_4) {
+ /* Pentium 4 don't like inc and dec instructions */
+ isa->opt &= ~IA32_OPT_INCDEC;
+ }
+
isa->regs_16bit = pmap_create();
isa->regs_8bit = pmap_create();
isa->types = pmap_create();
LC_OPT_ENT_ENUM_INT("arch", "select the instruction architecture", &arch_var),
LC_OPT_ENT_ENUM_INT("opt", "optimize for instruction architecture", &opt_arch_var),
LC_OPT_ENT_ENUM_INT("fpunit", "select the floating point unit", &fp_unit_var),
- LC_OPT_ENT_BIT("incdec", "optimize for inc/dec", &ia32_isa_template.opt, IA32_OPT_INCDEC),
LC_OPT_ENT_NEGBIT("noaddrmode", "do not use address mode", &ia32_isa_template.opt, IA32_OPT_DOAM),
LC_OPT_ENT_NEGBIT("noplacecnst", "do not place constants", &ia32_isa_template.opt, IA32_OPT_PLACECNST),
LC_OPT_ENT_NEGBIT("noimmop", "no operations with immediates", &ia32_isa_template.opt, IA32_OPT_IMMOPS),
IA32_OPT_EXTBB = 16, /**< do extended basic block scheduling */
} ia32_optimize_t;
-/** architectures */
+/**
+ * Architectures. Clustered for easier macro implementation,
+ * do not change.
+ */
typedef enum cpu_support {
arch_i386, /**< i386 */
arch_i486, /**< i486 */
arch_opteron, /**< Opteron */
} cpu_support;
+/** checks for l <= x <= h */
+#define _IN_RANGE(x, l, h) ((unsigned)((x) - (l)) <= (unsigned)((h) - (l)))
+
+/** returns true if it's Intel architecture */
+#define ARCH_INTEL(x) _IN_RANGE((x), arch_i386, arch_core)
+
+/** returns true if it's AMD architecture */
+#define ARCH_AMD(x) _IN_RANGE((x), arch_k6, arch_opteron)
+
/** floating point support */
typedef enum fp_support {
fp_none, /**< no floating point instructions are used */
fp_sse2 /**< use SSE2 instructions */
} fp_support;
+/** Sets the used flag to the current floating point architecture. */
+#define FP_USED(cg) ((cg)->used_fp = (cg)->fp_kind)
+
+/** Returns non-zero if the current floating point architecture is SSE2. */
+#define USE_SSE2(cg) ((cg)->fp_kind == fp_sse2)
+
+/** Returns non-zero if the current floating point architecture is x87. */
+#define USE_x87(cg) ((cg)->fp_kind == fp_x87)
+
typedef struct _ia32_isa_t ia32_isa_t;
/**
IA32_DO_EMIT(irn);
}
+/**
+ * Emits code for Constant loading.
+ */
+static void emit_ia32_Const(const ir_node *n, ia32_emit_env_t *env) {
+ FILE *F = env->out;
+ char cmd_buf[256], cmnt_buf[256];
+ const lc_arg_env_t *arg_env = ia32_get_arg_env();
+
+ if (get_ia32_Immop_tarval(n) == get_tarval_null(get_irn_mode(n))) {
+ const char *instr = "xor";
+ if (env->isa->opt_arch == arch_pentium_4) {
+ /* P4 prefers sub r, r, others xor r, r */
+ instr = "sub";
+ }
+ lc_esnprintf(arg_env, cmd_buf, 256, "%s %1D, %1D ", instr, n, n);
+ lc_esnprintf(arg_env, cmnt_buf, 256, "/* optimized mov 0 to register */");
+ }
+ else {
+ if (get_ia32_op_type(n) == ia32_SymConst) {
+ lc_esnprintf(arg_env, cmd_buf, 256, "mov %1D, OFFSET FLAT:%C ", n, n);
+ lc_esnprintf(arg_env, cmnt_buf, 256, "/* Move address of SymConst into register */");
+ }
+ else {
+ lc_esnprintf(arg_env, cmd_buf, 256, "mov %1D, %C ", n, n);
+ lc_esnprintf(arg_env, cmnt_buf, 256, "/* Mov Const into register */");
+ }
+ }
+ lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", cmd_buf, cmnt_buf, n, n);
+}
+
/***********************************************************************************
IA32_EMIT(Conv_FP2FP);
IA32_EMIT(Conv_I2I);
IA32_EMIT(Conv_I2I8Bit);
+ IA32_EMIT(Const);
/* benode emitter */
BE_EMIT(Call);
"comment" => "represents an integer constant",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "out" => [ "gp" ] },
- "emit" =>
-' if (get_ia32_Immop_tarval(n) == get_tarval_null(get_irn_mode(n))) {
-4. sub %D1, %D1 /* optimized mov 0 to register */
- }
- else {
- if (get_ia32_op_type(n) == ia32_SymConst) {
-6. mov %D1, OFFSET FLAT:%C /* Move address of SymConst into register */
- }
- else {
-6. mov %D1, %C /* Mov Const into register */
- }
- }
-',
},
"Cdq" => {
"Leave" => {
"comment" => "destroy stack frame",
- "reg_req" => { "in" => [ "esp", "ebp" ], "out" => [ "esp" ] },
- "emit" => '. leave /* Enter */'
+ "reg_req" => { "in" => [ "esp", "ebp" ], "out" => [ "ebp", "esp" ] },
+ "emit" => '. leave /* Leave */'
},
#-----------------------------------------------------------------------------#