bearch_ia32.c 39.8 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/**
 * This is the main ia32 firm backend driver.
Christian Würdig's avatar
Christian Würdig committed
3
 * @author Christian Wuerdig
Christian Würdig's avatar
Christian Würdig committed
4
5
6
 * $Id$
 */

7
8
9
10
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

11
#ifdef HAVE_MALLOC_H
Christian Würdig's avatar
Christian Würdig committed
12
#include <malloc.h>
13
14
15
#endif

#ifdef HAVE_ALLOCA_H
Christian Würdig's avatar
Christian Würdig committed
16
17
18
#include <alloca.h>
#endif

19
20
21
22
23
#ifdef WITH_LIBCORE
#include <libcore/lc_opts.h>
#include <libcore/lc_opts_enum.h>
#endif /* WITH_LIBCORE */

Christian Würdig's avatar
Christian Würdig committed
24
25
#include "pseudo_irg.h"
#include "irgwalk.h"
Christian Würdig's avatar
Christian Würdig committed
26
27
#include "irprog.h"
#include "irprintf.h"
28
#include "iredges_t.h"
29
#include "ircons.h"
Christian Würdig's avatar
Christian Würdig committed
30
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
31
#include "irgopt.h"
Christian Würdig's avatar
Christian Würdig committed
32
33
34
35

#include "bitset.h"
#include "debug.h"

36
#include "../beabi.h"                 /* the general register allocator interface */
37
#include "../benode_t.h"
38
#include "../belower.h"
Christian Würdig's avatar
Christian Würdig committed
39
#include "../besched_t.h"
Christian Würdig's avatar
Christian Würdig committed
40
#include "../be.h"
41
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
42
43
44
45
46

#include "ia32_new_nodes.h"           /* ia32 nodes interface */
#include "gen_ia32_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
#include "ia32_gen_decls.h"           /* interface declaration emitter */
#include "ia32_transform.h"
Christian Würdig's avatar
Christian Würdig committed
47
48
#include "ia32_emitter.h"
#include "ia32_map_regs.h"
Christian Würdig's avatar
Christian Würdig committed
49
#include "ia32_optimize.h"
50
#include "ia32_x87.h"
51
#include "ia32_dbg_stat.h"
Christian Würdig's avatar
Christian Würdig committed
52

Christian Würdig's avatar
Christian Würdig committed
53
#define DEBUG_MODULE "firm.be.ia32.isa"
Christian Würdig's avatar
Christian Würdig committed
54

Christian Würdig's avatar
Christian Würdig committed
55
56
/* TODO: ugly */
static set *cur_reg_set = NULL;
Christian Würdig's avatar
Christian Würdig committed
57

Christian Würdig's avatar
Christian Würdig committed
58
59
#undef is_Start
#define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
Christian Würdig's avatar
Christian Würdig committed
60

61
/* Creates the unique per irg GP NoReg node. */
62
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
63
	return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_GP_NOREG]);
64
65
}

66
/* Creates the unique per irg FP NoReg node. */
67
ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
68
69
	return be_abi_get_callee_save_irn(cg->birg->abi,
		USE_SSE2(cg) ? &ia32_xmm_regs[REG_XMM_NOREG] : &ia32_vfp_regs[REG_VFP_NOREG]);
70
}
71

Christian Würdig's avatar
Christian Würdig committed
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**************************************************
 *                         _ _              _  __
 *                        | | |            (_)/ _|
 *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
 * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
 * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
 * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
 *            __/ |
 *           |___/
 **************************************************/

static ir_node *my_skip_proj(const ir_node *n) {
	while (is_Proj(n))
		n = get_Proj_pred(n);
	return (ir_node *)n;
}
Christian Würdig's avatar
Christian Würdig committed
88

Sebastian Hack's avatar
Sebastian Hack committed
89

Christian Würdig's avatar
Christian Würdig committed
90
91
92
93
94
/**
 * Return register requirements for an ia32 node.
 * If the node returns a tuple (mode_T) then the proj's
 * will be asked for this information.
 */
Christian Würdig's avatar
Christian Würdig committed
95
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) {
96
	const ia32_irn_ops_t      *ops = self;
97
98
	const ia32_register_req_t *irn_req;
	long                       node_pos = pos == -1 ? 0 : pos;
99
	ir_mode                   *mode     = is_Block(irn) ? NULL : get_irn_mode(irn);
100
	FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
Christian Würdig's avatar
Christian Würdig committed
101

102
103
104
105
106
107
108
	if (is_Block(irn) || mode == mode_M || mode == mode_X) {
		DBG((mod, LEVEL_1, "ignoring Block, mode_M, mode_X node %+F\n", irn));
		return NULL;
	}

	if (mode == mode_T && pos < 0) {
		DBG((mod, LEVEL_1, "ignoring request OUT requirements for node %+F\n", irn));
Christian Würdig's avatar
Christian Würdig committed
109
110
111
112
113
		return NULL;
	}

	DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));

114
	if (is_Proj(irn)) {
115
		if (pos == -1) {
116
			node_pos = ia32_translate_proj_pos(irn);
117
118
		}
		else {
Christian Würdig's avatar
Christian Würdig committed
119
			node_pos = pos;
120
		}
Christian Würdig's avatar
Christian Würdig committed
121
122
123

		irn = my_skip_proj(irn);

Christian Würdig's avatar
Christian Würdig committed
124
		DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
Christian Würdig's avatar
Christian Würdig committed
125
126
127
128
	}

	if (is_ia32_irn(irn)) {
		if (pos >= 0) {
129
			irn_req = get_ia32_in_req(irn, pos);
Christian Würdig's avatar
Christian Würdig committed
130
131
		}
		else {
132
			irn_req = get_ia32_out_req(irn, node_pos);
Christian Würdig's avatar
Christian Würdig committed
133
134
		}

Christian Würdig's avatar
Christian Würdig committed
135
		DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
Christian Würdig's avatar
Christian Würdig committed
136

137
138
		memcpy(req, &(irn_req->req), sizeof(*req));

139
140
141
142
143
144
145
146
		if (arch_register_req_is(&(irn_req->req), should_be_same)) {
			assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
			req->other_same = get_irn_n(irn, irn_req->same_pos);
		}

		if (arch_register_req_is(&(irn_req->req), should_be_different)) {
			assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
			req->other_different = get_irn_n(irn, irn_req->different_pos);
147
		}
Christian Würdig's avatar
Christian Würdig committed
148
149
	}
	else {
150
151
152
		/* treat Unknowns like Const with default requirements */
		if (is_Unknown(irn)) {
			DB((mod, LEVEL_1, "returning UKNWN reqs for %+F\n", irn));
153
154
			if (mode_is_float(mode)) {
				if (USE_SSE2(ops->cg))
155
					memcpy(req, &(ia32_default_req_ia32_xmm_xmm_UKNWN), sizeof(*req));
156
				else
157
					memcpy(req, &(ia32_default_req_ia32_vfp_vfp_UKNWN), sizeof(*req));
158
			}
Christian Würdig's avatar
Christian Würdig committed
159
			else if (mode_is_int(mode) || mode_is_reference(mode))
160
				memcpy(req, &(ia32_default_req_ia32_gp_gp_UKNWN), sizeof(*req));
Christian Würdig's avatar
Christian Würdig committed
161
			else if (mode == mode_T || mode == mode_M) {
162
				DBG((mod, LEVEL_1, "ignoring Unknown node %+F\n", irn));
Christian Würdig's avatar
Christian Würdig committed
163
164
165
				return NULL;
			}
			else
166
				assert(0 && "unsupported Unknown-Mode");
Christian Würdig's avatar
Christian Würdig committed
167
168
		}
		else {
Christian Würdig's avatar
Christian Würdig committed
169
			DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
170
			req = NULL;
Christian Würdig's avatar
Christian Würdig committed
171
172
173
174
175
		}
	}

	return req;
}
Christian Würdig's avatar
Christian Würdig committed
176

Christian Würdig's avatar
Christian Würdig committed
177
static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
178
179
180
	int                   pos = 0;
	const ia32_irn_ops_t *ops = self;

181
182
183
184
	if (get_irn_mode(irn) == mode_X) {
		return;
	}

185
	DBG((ops->cg->mod, LEVEL_1, "ia32 assigned register %s to node %+F\n", reg->name, irn));
Christian Würdig's avatar
Christian Würdig committed
186

187
	if (is_Proj(irn)) {
188
		pos = ia32_translate_proj_pos(irn);
Christian Würdig's avatar
Christian Würdig committed
189
190
		irn = my_skip_proj(irn);
	}
Christian Würdig's avatar
Christian Würdig committed
191

Christian Würdig's avatar
Christian Würdig committed
192
193
	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
Christian Würdig's avatar
Christian Würdig committed
194

Christian Würdig's avatar
Christian Würdig committed
195
196
197
198
		slots      = get_ia32_slots(irn);
		slots[pos] = reg;
	}
	else {
199
		ia32_set_firm_reg(irn, reg, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
200
	}
Christian Würdig's avatar
Christian Würdig committed
201
202
}

Christian Würdig's avatar
Christian Würdig committed
203
static const arch_register_t *ia32_get_irn_reg(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
204
205
206
	int pos = 0;
	const arch_register_t *reg = NULL;

207
	if (is_Proj(irn)) {
208
209
210
211
212

		if (get_irn_mode(irn) == mode_X) {
			return NULL;
		}

213
		pos = ia32_translate_proj_pos(irn);
Christian Würdig's avatar
Christian Würdig committed
214
215
216
217
218
219
220
221
222
		irn = my_skip_proj(irn);
	}

	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
		slots = get_ia32_slots(irn);
		reg   = slots[pos];
	}
	else {
223
		reg = ia32_get_firm_reg(irn, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
224
225
226
	}

	return reg;
Christian Würdig's avatar
Christian Würdig committed
227
228
}

Christian Würdig's avatar
Christian Würdig committed
229
static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
230
231
232
	irn = my_skip_proj(irn);
	if (is_cfop(irn))
		return arch_irn_class_branch;
Christian Würdig's avatar
Christian Würdig committed
233
234
	else if (is_ia32_Cnst(irn))
		return arch_irn_class_const;
Christian Würdig's avatar
Christian Würdig committed
235
	else if (is_ia32_irn(irn))
Christian Würdig's avatar
Christian Würdig committed
236
		return arch_irn_class_normal;
Christian Würdig's avatar
Christian Würdig committed
237
238
	else
		return 0;
Christian Würdig's avatar
Christian Würdig committed
239
}
Christian Würdig's avatar
Christian Würdig committed
240

Christian Würdig's avatar
Christian Würdig committed
241
static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
242
243
244
245
	irn = my_skip_proj(irn);
	if (is_ia32_irn(irn))
		return get_ia32_flags(irn);
	else {
246
247
		if (is_Unknown(irn))
			return arch_irn_flags_ignore;
Christian Würdig's avatar
Christian Würdig committed
248
249
		return 0;
	}
Christian Würdig's avatar
Christian Würdig committed
250
251
}

Christian Würdig's avatar
Christian Würdig committed
252
253
static entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
254
255
}

256
static void ia32_set_stack_bias(const void *self, ir_node *irn, int bias) {
Christian Würdig's avatar
Christian Würdig committed
257
258
259
	char buf[64];
	const ia32_irn_ops_t *ops = self;

Christian Würdig's avatar
Christian Würdig committed
260
	if (get_ia32_frame_ent(irn)) {
Christian Würdig's avatar
Christian Würdig committed
261
262
263
264
		ia32_am_flavour_t am_flav = get_ia32_am_flavour(irn);

		DBG((ops->cg->mod, LEVEL_1, "stack biased %+F with %d\n", irn, bias));
		snprintf(buf, sizeof(buf), "%d", bias);
Christian Würdig's avatar
Christian Würdig committed
265
266
267
268
269
270
271
272
273

		if (get_ia32_op_type(irn) == ia32_Normal) {
			set_ia32_cnst(irn, buf);
		}
		else {
			add_ia32_am_offs(irn, buf);
			am_flav |= ia32_O;
			set_ia32_am_flavour(irn, am_flav);
		}
274
275
276
	}
}

Sebastian Hack's avatar
Sebastian Hack committed
277
278
279
typedef struct {
	be_abi_call_flags_bits_t flags;
	const arch_isa_t *isa;
280
	const arch_env_t *aenv;
Sebastian Hack's avatar
Sebastian Hack committed
281
282
283
	ir_graph *irg;
} ia32_abi_env_t;

Sebastian Hack's avatar
Sebastian Hack committed
284
static void *ia32_abi_init(const be_abi_call_t *call, const arch_env_t *aenv, ir_graph *irg)
Sebastian Hack's avatar
Sebastian Hack committed
285
286
287
288
289
{
	ia32_abi_env_t *env    = xmalloc(sizeof(env[0]));
	be_abi_call_flags_t fl = be_abi_call_get_flags(call);
	env->flags = fl.bits;
	env->irg   = irg;
290
	env->aenv  = aenv;
Sebastian Hack's avatar
Sebastian Hack committed
291
	env->isa   = aenv->isa;
Sebastian Hack's avatar
Sebastian Hack committed
292
293
294
	return env;
}

295
296
297
298
299
300
/**
 * Put all registers which are saved by the prologue/epilogue in a set.
 *
 * @param self  The callback object.
 * @param s     The result set.
 */
Sebastian Hack's avatar
Sebastian Hack committed
301
302
303
304
305
306
307
static void ia32_abi_dont_save_regs(void *self, pset *s)
{
	ia32_abi_env_t *env = self;
	if(env->flags.try_omit_fp)
		pset_insert_ptr(s, env->isa->bp);
}

308
/**
Michael Beck's avatar
Michael Beck committed
309
 * Generate the routine prologue.
310
 *
311
312
 * @param self    The callback object.
 * @param mem     A pointer to the mem node. Update this if you define new memory.
Michael Beck's avatar
Michael Beck committed
313
 * @param reg_map A map mapping all callee_save/ignore/parameter registers to their defining nodes.
314
 *
315
316
317
318
 * @return        The register which shall be used as a stack frame base.
 *
 * All nodes which define registers in @p reg_map must keep @p reg_map current.
 */
Sebastian Hack's avatar
Sebastian Hack committed
319
static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
Sebastian Hack's avatar
Sebastian Hack committed
320
{
Sebastian Hack's avatar
Sebastian Hack committed
321
322
	ia32_abi_env_t *env              = self;

323
	if (!env->flags.try_omit_fp) {
Sebastian Hack's avatar
Sebastian Hack committed
324
325
326
327
		int reg_size         = get_mode_size_bytes(env->isa->bp->reg_class->mode);
		ir_node *bl          = get_irg_start_block(env->irg);
		ir_node *curr_sp     = be_abi_reg_map_get(reg_map, env->isa->sp);
		ir_node *curr_bp     = be_abi_reg_map_get(reg_map, env->isa->bp);
328
		ir_node *push;
Sebastian Hack's avatar
Sebastian Hack committed
329

330
		/* push ebp */
Michael Beck's avatar
Michael Beck committed
331
332
333
		push    = new_rd_ia32_Push(NULL, env->irg, bl, curr_sp, curr_bp, *mem);
		curr_sp = new_r_Proj(env->irg, bl, push, get_irn_mode(curr_sp), pn_ia32_Push_stack);
		*mem    = new_r_Proj(env->irg, bl, push, mode_M, pn_ia32_Push_M);
334
335

		/* the push must have SP out register */
Michael Beck's avatar
Michael Beck committed
336
337
		arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
		set_ia32_flags(push, arch_irn_flags_ignore);
338
339

		/* move esp to ebp */
Sebastian Hack's avatar
Sebastian Hack committed
340
341
		curr_bp  = be_new_Copy(env->isa->bp->reg_class, env->irg, bl, curr_sp);
		be_set_constr_single_reg(curr_bp, BE_OUT_POS(0), env->isa->bp);
342
		arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
Christian Würdig's avatar
Christian Würdig committed
343
		be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
344

345
346
347
348
349
350
		/* beware: the copy must be done before any other sp use */
		curr_sp = be_new_CopyKeep_single(env->isa->sp->reg_class, env->irg, bl, curr_sp, curr_bp, get_irn_mode(curr_sp));
		be_set_constr_single_reg(curr_sp, BE_OUT_POS(0), env->isa->sp);
		arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
		be_node_set_flags(curr_sp, BE_OUT_POS(0), arch_irn_flags_ignore);

Sebastian Hack's avatar
Sebastian Hack committed
351
352
		be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
		be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
353
354

		return env->isa->bp;
Sebastian Hack's avatar
Sebastian Hack committed
355
356
	}

357
	return env->isa->sp;
Sebastian Hack's avatar
Sebastian Hack committed
358
359
}

Michael Beck's avatar
Michael Beck committed
360
361
362
/**
 * Generate the routine epilogue.
 * @param self    The callback object.
363
 * @param bl      The block for the epilog
Michael Beck's avatar
Michael Beck committed
364
365
366
367
368
369
 * @param mem     A pointer to the mem node. Update this if you define new memory.
 * @param reg_map A map mapping all callee_save/ignore/parameter registers to their defining nodes.
 * @return        The register which shall be used as a stack frame base.
 *
 * All nodes which define registers in @p reg_map must keep @p reg_map current.
 */
Sebastian Hack's avatar
Sebastian Hack committed
370
371
static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
{
372
	ia32_abi_env_t *env  = self;
Sebastian Hack's avatar
Sebastian Hack committed
373
374
375
	ir_node *curr_sp     = be_abi_reg_map_get(reg_map, env->isa->sp);
	ir_node *curr_bp     = be_abi_reg_map_get(reg_map, env->isa->bp);

376
377
	if (env->flags.try_omit_fp) {
		/* simply remove the stack frame here */
378
		curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, *mem, BE_STACK_FRAME_SIZE, be_stack_dir_shrink);
Sebastian Hack's avatar
Sebastian Hack committed
379
380
	}
	else {
381
		const ia32_isa_t *isa = (ia32_isa_t *)env->isa;
Sebastian Hack's avatar
Sebastian Hack committed
382
		ir_mode *mode_bp = env->isa->bp->reg_class->mode;
383
		int reg_size     = get_mode_size_bytes(env->isa->bp->reg_class->mode);
Sebastian Hack's avatar
Sebastian Hack committed
384

385
386
		/* gcc always emits a leave at the end of a routine */
		if (1 || ARCH_AMD(isa->opt_arch)) {
387
			ir_node *leave;
388

389
			/* leave */
Michael Beck's avatar
Michael Beck committed
390
			leave = new_rd_ia32_Leave(NULL, env->irg, bl, curr_sp, *mem);
391
			set_ia32_flags(leave, arch_irn_flags_ignore);
Michael Beck's avatar
Michael Beck committed
392
393
394
			curr_bp = new_r_Proj(current_ir_graph, bl, leave, mode_bp, pn_ia32_Leave_frame);
			curr_sp = new_r_Proj(current_ir_graph, bl, leave, get_irn_mode(curr_sp), pn_ia32_Leave_stack);
			*mem    = new_r_Proj(current_ir_graph, bl, leave, mode_M, pn_ia32_Leave_M);
395
396
397
398
399
400
401
402
		}
		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 */
Michael Beck's avatar
Michael Beck committed
403
			pop = new_rd_ia32_Pop(NULL, env->irg, bl, curr_sp, *mem);
404
			set_ia32_flags(pop, arch_irn_flags_ignore);
Michael Beck's avatar
Michael Beck committed
405
406
407
			curr_bp = new_r_Proj(current_ir_graph, bl, pop, mode_bp, pn_ia32_Pop_res);
			curr_sp = new_r_Proj(current_ir_graph, bl, pop, get_irn_mode(curr_sp), pn_ia32_Pop_stack);
			*mem    = new_r_Proj(current_ir_graph, bl, pop, mode_M, pn_ia32_Pop_M);
408
		}
409
		arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
410
		arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
Sebastian Hack's avatar
Sebastian Hack committed
411
412
413
414
	}

	be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
	be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
Sebastian Hack's avatar
Sebastian Hack committed
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
}

/**
 * Produces the type which sits between the stack args and the locals on the stack.
 * it will contain the return address and space to store the old base pointer.
 * @return The Firm type modeling the ABI between type.
 */
static ir_type *ia32_abi_get_between_type(void *self)
{
	static ir_type *omit_fp_between_type = NULL;
	static ir_type *between_type         = NULL;

	ia32_abi_env_t *env = self;

	if(!between_type) {
		entity *old_bp_ent;
		entity *ret_addr_ent;
		entity *omit_fp_ret_addr_ent;

		ir_type *old_bp_type   = new_type_primitive(new_id_from_str("bp"), mode_P);
		ir_type *ret_addr_type = new_type_primitive(new_id_from_str("return_addr"), mode_P);

		between_type           = new_type_class(new_id_from_str("ia32_between_type"));
		old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
		ret_addr_ent           = new_entity(between_type, new_id_from_str("ret_addr"), ret_addr_type);

		set_entity_offset_bytes(old_bp_ent, 0);
		set_entity_offset_bytes(ret_addr_ent, get_type_size_bytes(old_bp_type));
		set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));

		omit_fp_between_type   = new_type_class(new_id_from_str("ia32_between_type_omit_fp"));
		omit_fp_ret_addr_ent   = new_entity(omit_fp_between_type, new_id_from_str("ret_addr"), ret_addr_type);

		set_entity_offset_bytes(omit_fp_ret_addr_ent, 0);
		set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type));
	}

	return env->flags.try_omit_fp ? omit_fp_between_type : between_type;
}

Christian Würdig's avatar
Christian Würdig committed
455
456
457
458
459
460
461
462
463
464
465
466
467
/**
 * Returns the inverse operation if @p irn, recalculating the argument at position @p i.
 *
 * @param irn       The original operation
 * @param i         Index of the argument we want the inverse operation to yield
 * @param inverse   struct to be filled with the resulting inverse op
 * @param obstack   The obstack to use for allocation of the returned nodes array
 * @return          The inverse operation or NULL if operation invertible
 */
static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obst) {
	return NULL;
}

Sebastian Hack's avatar
Sebastian Hack committed
468
469
470
471
472
473
474
475
476
static const be_abi_callbacks_t ia32_abi_callbacks = {
	ia32_abi_init,
	free,
	ia32_abi_get_between_type,
	ia32_abi_dont_save_regs,
	ia32_abi_prologue,
	ia32_abi_epilogue,
};

Christian Würdig's avatar
Christian Würdig committed
477
478
/* fill register allocator interface */

Christian Würdig's avatar
Christian Würdig committed
479
static const arch_irn_ops_if_t ia32_irn_ops_if = {
Christian Würdig's avatar
Christian Würdig committed
480
481
482
483
	ia32_get_irn_reg_req,
	ia32_set_irn_reg,
	ia32_get_irn_reg,
	ia32_classify,
484
	ia32_get_flags,
485
	ia32_get_frame_entity,
Christian Würdig's avatar
Christian Würdig committed
486
487
	ia32_set_stack_bias,
	ia32_get_inverse
Christian Würdig's avatar
Christian Würdig committed
488
489
};

Christian Würdig's avatar
Christian Würdig committed
490
491
492
493
494
ia32_irn_ops_t ia32_irn_ops = {
	&ia32_irn_ops_if,
	NULL
};

Christian Würdig's avatar
Christian Würdig committed
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512


/**************************************************
 *                _                         _  __
 *               | |                       (_)/ _|
 *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
 *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
 * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
 *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
 *                        __/ |
 *                       |___/
 **************************************************/

/**
 * Transforms the standard firm graph into
 * an ia32 firm graph
 */
static void ia32_prepare_graph(void *self) {
Christian Würdig's avatar
Christian Würdig committed
513
	ia32_code_gen_t *cg = self;
514
	dom_front_info_t *dom;
515
	DEBUG_ONLY(firm_dbg_module_t *old_mod = cg->mod;)
516

517
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
518

519
520
	/* 1st: transform constants and psi condition trees */
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_psi_cond_tree, cg);
521
522

	/* 2nd: transform all remaining nodes */
523
	ia32_register_transformers();
524
	dom = be_compute_dominance_frontiers(cg->irg);
525
	irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_node, cg);
526
	be_free_dominance_frontiers(dom);
Christian Würdig's avatar
Christian Würdig committed
527
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
528

529
	/* 3rd: optimize address mode */
530
531
532
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.am");
	ia32_optimize_addressmode(cg);
	be_dump(cg->irg, "-am", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
533
	DEBUG_ONLY(cg->mod = old_mod;)
Christian Würdig's avatar
Christian Würdig committed
534
535
}

536
537
538
539
540
static INLINE int need_constraint_copy(ir_node *irn) {
	return \
		! is_ia32_Lea(irn)          && \
		! is_ia32_Conv_I2I(irn)     && \
		! is_ia32_Conv_I2I8Bit(irn) && \
541
542
		! is_ia32_CmpCMov(irn)      && \
		! is_ia32_CmpSet(irn);
543
}
Christian Würdig's avatar
Christian Würdig committed
544

Christian Würdig's avatar
Christian Würdig committed
545
546
547
/**
 * Insert copies for all ia32 nodes where the should_be_same requirement
 * is not fulfilled.
Christian Würdig's avatar
Christian Würdig committed
548
 * Transform Sub into Neg -- Add if IN2 == OUT
Christian Würdig's avatar
Christian Würdig committed
549
 */
550
static void ia32_finish_node(ir_node *irn, void *env) {
Christian Würdig's avatar
Christian Würdig committed
551
552
	ia32_code_gen_t            *cg = env;
	const ia32_register_req_t **reqs;
Christian Würdig's avatar
Christian Würdig committed
553
	const arch_register_t      *out_reg, *in_reg, *in2_reg;
Christian Würdig's avatar
Christian Würdig committed
554
	int                         n_res, i;
Christian Würdig's avatar
Christian Würdig committed
555
	ir_node                    *copy, *in_node, *block, *in2_node;
Christian Würdig's avatar
Christian Würdig committed
556
	ia32_op_type_t              op_tp;
Christian Würdig's avatar
Christian Würdig committed
557

558
559
560
561
	if (is_ia32_irn(irn)) {
		/* AM Dest nodes don't produce any values  */
		op_tp = get_ia32_op_type(irn);
		if (op_tp == ia32_AddrModeD)
562
			goto end;
563
564
565
566
567
568

		reqs  = get_ia32_out_req_all(irn);
		n_res = get_ia32_n_res(irn);
		block = get_nodes_block(irn);

		/* check all OUT requirements, if there is a should_be_same */
569
		if ((op_tp == ia32_Normal || op_tp == ia32_AddrModeS) && need_constraint_copy(irn))
Christian Würdig's avatar
Christian Würdig committed
570
		{
571
572
573
			for (i = 0; i < n_res; i++) {
				if (arch_register_req_is(&(reqs[i]->req), should_be_same)) {
					/* get in and out register */
Christian Würdig's avatar
Christian Würdig committed
574
575
576
					out_reg  = get_ia32_out_reg(irn, i);
					in_node  = get_irn_n(irn, reqs[i]->same_pos);
					in_reg   = arch_get_irn_register(cg->arch_env, in_node);
577
578

					/* don't copy ignore nodes */
Christian Würdig's avatar
Christian Würdig committed
579
					if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
580
581
582
						continue;

					/* check if in and out register are equal */
Christian Würdig's avatar
Christian Würdig committed
583
584
					if (! REGS_ARE_EQUAL(out_reg, in_reg)) {
						/* in case of a commutative op: just exchange the in's */
Christian Würdig's avatar
Christian Würdig committed
585
586
587
588
589
590
591
592
593
594
595
596
						/* beware: the current op could be everything, so test for ia32 */
						/*         commutativity first before getting the second in     */
						if (is_ia32_commutative(irn)) {
							in2_node = get_irn_n(irn, reqs[i]->same_pos ^ 1);
							in2_reg  = arch_get_irn_register(cg->arch_env, in2_node);

							if (REGS_ARE_EQUAL(out_reg, in2_reg)) {
								set_irn_n(irn, reqs[i]->same_pos, in2_node);
								set_irn_n(irn, reqs[i]->same_pos ^ 1, in_node);
							}
							else
								goto insert_copy;
Christian Würdig's avatar
Christian Würdig committed
597
598
						}
						else {
Christian Würdig's avatar
Christian Würdig committed
599
insert_copy:
Christian Würdig's avatar
Christian Würdig committed
600
601
602
603
							DBG((cg->mod, LEVEL_1, "inserting copy for %+F in_pos %d\n", irn, reqs[i]->same_pos));
							/* create copy from in register */
							copy = be_new_Copy(arch_register_get_class(in_reg), cg->irg, block, in_node);

604
605
							DBG_OPT_2ADDRCPY(copy);

Christian Würdig's avatar
Christian Würdig committed
606
607
608
609
610
611
612
613
614
							/* destination is the out register */
							arch_set_irn_register(cg->arch_env, copy, out_reg);

							/* insert copy before the node into the schedule */
							sched_add_before(irn, copy);

							/* set copy as in */
							set_irn_n(irn, reqs[i]->same_pos, copy);
						}
615
					}
616
				}
Christian Würdig's avatar
Christian Würdig committed
617
618
			}
		}
Christian Würdig's avatar
Christian Würdig committed
619

620
		/* If we have a CondJmp/CmpSet/xCmpSet with immediate, we need to    */
621
622
623
		/* check if it's the right operand, otherwise we have */
		/* to change it, as CMP doesn't support immediate as  */
		/* left operands.                                     */
624
625
626
627
		if ((is_ia32_CondJmp(irn) || is_ia32_CmpSet(irn) || is_ia32_xCmpSet(irn)) &&
			(is_ia32_ImmConst(irn) || is_ia32_ImmSymConst(irn))                   &&
			op_tp == ia32_AddrModeS)
		{
628
			set_ia32_op_type(irn, ia32_AddrModeD);
Michael Beck's avatar
Michael Beck committed
629
			set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
630
		}
Christian Würdig's avatar
Christian Würdig committed
631

632
633
		/* check if there is a sub which need to be transformed */
		ia32_transform_sub_to_neg_add(irn, cg);
634

635
		/* transform a LEA into an Add if possible */
636
		ia32_transform_lea_to_add(irn, cg);
637
	}
638
end:
639
640
641

	/* check for peephole optimization */
	ia32_peephole_optimization(irn, cg);
Christian Würdig's avatar
Christian Würdig committed
642
}
Christian Würdig's avatar
Christian Würdig committed
643

644
645
646
647
648
649
650
651
652
static void ia32_finish_irg_walker(ir_node *block, void *env) {
	ir_node *irn, *next;

	for (irn = sched_first(block); !sched_is_end(irn); irn = next) {
		next = sched_next(irn);
		ia32_finish_node(irn, env);
	}
}

Christian Würdig's avatar
Christian Würdig committed
653
/**
Christian Würdig's avatar
Christian Würdig committed
654
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
655
 */
Christian Würdig's avatar
Christian Würdig committed
656
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
657
	irg_block_walk_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
658
659
}

660
661


662
/**
663
 * Dummy functions for hooks we don't need but which must be filled.
664
 */
665
static void ia32_before_sched(void *self) {
666
667
}

668
669
670
671
672
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
673
static void ia32_before_ra(void *self) {
674
	ia32_code_gen_t *cg = self;
675

676
677
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
678

Christian Würdig's avatar
Christian Würdig committed
679

Christian Würdig's avatar
Christian Würdig committed
680
681
682
683
/**
 * Transforms a be node into a Load.
 */
static void transform_to_Load(ia32_transform_env_t *env) {
Christian Würdig's avatar
Christian Würdig committed
684
685
686
687
688
	ir_node *irn         = env->irn;
	entity  *ent         = be_get_frame_entity(irn);
	ir_mode *mode        = env->mode;
	ir_node *noreg       = ia32_new_NoReg_gp(env->cg);
	ir_node *nomem       = new_rd_NoMem(env->irg);
Christian Würdig's avatar
Christian Würdig committed
689
	ir_node *sched_point = NULL;
Christian Würdig's avatar
Christian Würdig committed
690
691
692
	ir_node *ptr         = get_irn_n(irn, 0);
	ir_node *mem         = be_is_Reload(irn) ? get_irn_n(irn, 1) : nomem;
	ir_node *new_op, *proj;
693
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
694
695
696
697
698
699

	if (sched_is_scheduled(irn)) {
		sched_point = sched_prev(irn);
	}

	if (mode_is_float(mode)) {
700
		if (USE_SSE2(env->cg))
Michael Beck's avatar
Michael Beck committed
701
			new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, mem);
702
		else
Michael Beck's avatar
Michael Beck committed
703
			new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
704
705
	}
	else {
Michael Beck's avatar
Michael Beck committed
706
		new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
707
708
709
710
711
712
713
714
715
	}

	set_ia32_am_support(new_op, ia32_am_Source);
	set_ia32_op_type(new_op, ia32_AddrModeS);
	set_ia32_am_flavour(new_op, ia32_B);
	set_ia32_ls_mode(new_op, mode);
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

716
717
	DBG_OPT_RELOAD2LD(irn, new_op);

Christian Würdig's avatar
Christian Würdig committed
718
719
720
721
722
723
724
725
726
	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, pn_Load_res);

	if (sched_point) {
		sched_add_after(sched_point, new_op);
		sched_add_after(new_op, proj);

		sched_remove(irn);
	}

727
728
	/* copy the register from the old node to the new Load */
	reg = arch_get_irn_register(env->cg->arch_env, irn);
Christian Würdig's avatar
Christian Würdig committed
729
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
730

Christian Würdig's avatar
Christian Würdig committed
731
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, new_op));
Christian Würdig's avatar
Christian Würdig committed
732

Christian Würdig's avatar
Christian Würdig committed
733
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
}

/**
 * Transforms a be node into a Store.
 */
static void transform_to_Store(ia32_transform_env_t *env) {
	ir_node *irn   = env->irn;
	entity  *ent   = be_get_frame_entity(irn);
	ir_mode *mode  = env->mode;
	ir_node *noreg = ia32_new_NoReg_gp(env->cg);
	ir_node *nomem = new_rd_NoMem(env->irg);
	ir_node *ptr   = get_irn_n(irn, 0);
	ir_node *val   = get_irn_n(irn, 1);
	ir_node *new_op, *proj;
	ir_node *sched_point = NULL;

	if (sched_is_scheduled(irn)) {
		sched_point = sched_prev(irn);
	}

	if (mode_is_float(mode)) {
755
		if (USE_SSE2(env->cg))
Michael Beck's avatar
Michael Beck committed
756
			new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
757
		else
Michael Beck's avatar
Michael Beck committed
758
			new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
Christian Würdig's avatar
Christian Würdig committed
759
	}
760
	else if (get_mode_size_bits(mode) == 8) {
Michael Beck's avatar
Michael Beck committed
761
		new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
762
	}
Christian Würdig's avatar
Christian Würdig committed
763
	else {
Michael Beck's avatar
Michael Beck committed
764
		new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
Christian Würdig's avatar
Christian Würdig committed
765
766
767
768
769
	}

	set_ia32_am_support(new_op, ia32_am_Dest);
	set_ia32_op_type(new_op, ia32_AddrModeD);
	set_ia32_am_flavour(new_op, ia32_B);
Christian Würdig's avatar
Christian Würdig committed
770
	set_ia32_ls_mode(new_op, mode);
Christian Würdig's avatar
Christian Würdig committed
771
772
773
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

774
775
	DBG_OPT_SPILL2ST(irn, new_op);

Michael Beck's avatar
Michael Beck committed
776
	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, pn_ia32_Store_M);
Christian Würdig's avatar
Christian Würdig committed
777
778
779
780
781
782
783
784

	if (sched_point) {
		sched_add_after(sched_point, new_op);
		sched_add_after(new_op, proj);

		sched_remove(irn);
	}

Christian Würdig's avatar
Christian Würdig committed
785
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, new_op));
Christian Würdig's avatar
Christian Würdig committed
786

Christian Würdig's avatar
Christian Würdig committed
787
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
788
789
790
}

/**
791
 * Fix the mode of Spill/Reload
Christian Würdig's avatar
Christian Würdig committed
792
 */
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
static ir_mode *fix_spill_mode(ia32_code_gen_t *cg, ir_mode *mode)
{
	if (mode_is_float(mode)) {
		if (USE_SSE2(cg))
			mode = mode_D;
		else
			mode = mode_E;
	}
	else
		mode = mode_Is;
	return mode;
}

/**
 * Block-Walker: Calls the transform functions Spill and Reload.
 */
static void ia32_after_ra_walker(ir_node *block, void *env) {
	ir_node *node, *prev;
Christian Würdig's avatar
Christian Würdig committed
811
812
813
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

814
	tenv.block = block;
Christian Würdig's avatar
Christian Würdig committed
815
816
	tenv.irg   = current_ir_graph;
	tenv.cg    = cg;
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
	DEBUG_ONLY(tenv.mod = cg->mod;)

	/* beware: the schedule is changed here */
	for (node = sched_last(block); !sched_is_begin(node); node = prev) {
		prev = sched_prev(node);
		if (be_is_Reload(node)) {
			/* we always reload the whole register  */
			tenv.dbg  = get_irn_dbg_info(node);
			tenv.irn  = node;
			tenv.mode = fix_spill_mode(cg, get_irn_mode(node));
			transform_to_Load(&tenv);
		}
		else if (be_is_Spill(node)) {
			/* we always spill the whole register  */
			tenv.dbg  = get_irn_dbg_info(node);
			tenv.irn  = node;
			tenv.mode = fix_spill_mode(cg, get_irn_mode(be_get_Spill_context(node)));
			transform_to_Store(&tenv);
		}
Christian Würdig's avatar
Christian Würdig committed
836
837
838
839
	}
}

/**
840
 * We transform Spill and Reload here. This needs to be done before
Christian Würdig's avatar
Christian Würdig committed
841
 * stack biasing otherwise we would miss the corrected offset for these nodes.
842
843
844
 *
 * If x87 instruction should be emitted, run the x87 simulator and patch
 * the virtual instructions. This must obviously be done after register allocation.
Christian Würdig's avatar
Christian Würdig committed
845
846
847
 */
static void ia32_after_ra(void *self) {
	ia32_code_gen_t *cg = self;
848
	irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
849
850

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
851
	if (cg->used_fp == fp_x87) {
852
853
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
854
855
856
}


Christian Würdig's avatar
Christian Würdig committed
857
858
859
860
861
862
/**
 * Emits the code, closes the output file and frees
 * the code generator interface.
 */
static void ia32_codegen(void *self) {
	ia32_code_gen_t *cg = self;
Christian Würdig's avatar
Christian Würdig committed
863
	ir_graph        *irg = cg->irg;
Christian Würdig's avatar
Christian Würdig committed
864

Christian Würdig's avatar
Christian Würdig committed
865
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
866
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
867
	ia32_gen_routine(cg->isa->out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
868
869
870

	cur_reg_set = NULL;

871
872
	/* remove it from the isa */
	cg->isa->cg = NULL;
873

Christian Würdig's avatar
Christian Würdig committed
874
875
876
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
877

Christian Würdig's avatar
Christian Würdig committed
878
879
}

880
static void *ia32_cg_init(const be_irg_t *birg);
Christian Würdig's avatar
Christian Würdig committed
881

Christian Würdig's avatar
Christian Würdig committed
882
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
883
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
884
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
885
	ia32_prepare_graph,
886
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
887
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
888
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
889
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
890
891
};

Christian Würdig's avatar
Christian Würdig committed
892
/**
893
 * Initializes a IA32 code generator.
Christian Würdig's avatar
Christian Würdig committed
894
 */
895
static void *ia32_cg_init(const be_irg_t *birg) {
Christian Würdig's avatar
Christian Würdig committed
896
	ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
897
898
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

899
900
901
902
	cg->impl      = &ia32_code_gen_if;
	cg->irg       = birg->irg;
	cg->reg_set   = new_set(ia32_cmp_irn_reg_assoc, 1024);
	cg->arch_env  = birg->main_env->arch_env;
903
	cg->isa       = isa;
904
905
	cg->birg      = birg;
	cg->blk_sched = NULL;
906
907
	cg->fp_to_gp  = NULL;
	cg->gp_to_fp  = NULL;
908
	cg->fp_kind   = isa->fp_kind;
909
	cg->used_fp   = fp_none;
910

911
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.cg");
Christian Würdig's avatar
Christian Würdig committed
912

913
914
	/* copy optimizations from isa for easier access */
	cg->opt = isa->opt;
915

916
917
918
	/* enter it */
	isa->cg = cg;

Christian Würdig's avatar
Christian Würdig committed
919
920
921
922
923
924
925
926
927
#ifndef NDEBUG
	if (isa->name_obst_size) {
		//printf("freed %d bytes from name obst\n", isa->name_obst_size);
		isa->name_obst_size = 0;
		obstack_free(isa->name_obst, NULL);
		obstack_init(isa->name_obst);
	}
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
928
929
	cur_reg_set = cg->reg_set;

Christian Würdig's avatar
Christian Würdig committed
930
931
	ia32_irn_ops.cg = cg;

Christian Würdig's avatar
Christian Würdig committed
932
933
934
	return (arch_code_generator_t *)cg;
}

Christian Würdig's avatar
Christian Würdig committed
935

Christian Würdig's avatar
Christian Würdig committed
936
937
938
939
940
941
942
943
944
945
946

/*****************************************************************
 *  ____             _                  _   _____  _____
 * |  _ \           | |                | | |_   _|/ ____|  /\
 * | |_) | __ _  ___| | _____ _ __   __| |   | | | (___   /  \
 * |  _ < / _` |/ __| |/ / _ \ '_ \ / _` |   | |  \___ \ / /\ \
 * | |_) | (_| | (__|   <  __/ | | | (_| |  _| |_ ____) / ____ \
 * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/    \_\
 *
 *****************************************************************/

947
948
949
950
951
/**
 * The template that generates a new ISA object.
 * Note that this template can be changed by command line
 * arguments.
 */
952
static ia32_isa_t ia32_isa_template = {
953
954
955
956
957
958
	{
		&ia32_isa_if,            /* isa interface implementation */
		&ia32_gp_regs[REG_ESP],  /* stack pointer register */
		&ia32_gp_regs[REG_EBP],  /* base pointer register */
		-1,                      /* stack direction */
	},
959
960
	NULL,                    /* 16bit register names */
	NULL,                    /* 8bit register names */
961
962
	NULL,                    /* types */
	NULL,                    /* tv_ents */
963
	(0                 |
964
	IA32_OPT_INCDEC    |     /* optimize add 1, sub 1 into inc/dec               default: on  */
965
	IA32_OPT_DOAM      |     /* optimize address mode                            default: on  */
966
	IA32_OPT_LEA       |     /* optimize for LEAs                                default: on  */
967
968
969
	IA32_OPT_PLACECNST |     /* place constants immediately before instructions, default: on  */
	IA32_OPT_IMMOPS    |     /* operations can use immediates,                   default: on  */
	IA32_OPT_EXTBB),         /* use extended basic block scheduling,             default: on  */
970
971
972
	arch_pentium_4,          /* instruction architecture */
	arch_pentium_4,          /* optimize for architecture */
	fp_sse2,                 /* use sse2 unit */
973
	NULL,                    /* current code generator */
974
975
976
977
#ifndef NDEBUG
	NULL,                    /* name obstack */
	0                        /* name obst size */
#endif
978
979
};

Christian Würdig's avatar
Christian Würdig committed
980
/**
981
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
982
 */
983
static void *ia32_init(FILE *file_handle) {
984
	static int inited = 0;
985
	ia32_isa_t *isa;