bearch_ia32.c 39 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
/**
 * This is the main ia32 firm backend driver.
 *
 * $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
455
456
457
458
459
460
461
462
463
}

/**
 * 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;
}

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
464
465
/* fill register allocator interface */

Christian Würdig's avatar
Christian Würdig committed
466
static const arch_irn_ops_if_t ia32_irn_ops_if = {
Christian Würdig's avatar
Christian Würdig committed
467
468
469
470
	ia32_get_irn_reg_req,
	ia32_set_irn_reg,
	ia32_get_irn_reg,
	ia32_classify,
471
	ia32_get_flags,
472
	ia32_get_frame_entity,
473
	ia32_set_stack_bias
Christian Würdig's avatar
Christian Würdig committed
474
475
};

Christian Würdig's avatar
Christian Würdig committed
476
477
478
479
480
ia32_irn_ops_t ia32_irn_ops = {
	&ia32_irn_ops_if,
	NULL
};

Christian Würdig's avatar
Christian Würdig committed
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498


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

/**
 * 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
499
	ia32_code_gen_t *cg = self;
500
	DEBUG_ONLY(firm_dbg_module_t *old_mod = cg->mod;)
501

502
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
503

504
505
	/* 1st: transform constants and psi condition trees */
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_psi_cond_tree, cg);
506
507

	/* 2nd: transform all remaining nodes */
508
	ia32_register_transformers();
509
	irg_walk_blkwise_graph(cg->irg, NULL, ia32_transform_node, cg);
Christian Würdig's avatar
Christian Würdig committed
510
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
511

512
	/* 3rd: optimize address mode */
513
514
515
	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
516
	DEBUG_ONLY(cg->mod = old_mod;)
Christian Würdig's avatar
Christian Würdig committed
517
518
}

519
520
521
522
523
static INLINE int need_constraint_copy(ir_node *irn) {
	return \
		! is_ia32_Lea(irn)          && \
		! is_ia32_Conv_I2I(irn)     && \
		! is_ia32_Conv_I2I8Bit(irn) && \
524
525
		! is_ia32_CmpCMov(irn)      && \
		! is_ia32_CmpSet(irn);
526
}
Christian Würdig's avatar
Christian Würdig committed
527

Christian Würdig's avatar
Christian Würdig committed
528
529
530
/**
 * Insert copies for all ia32 nodes where the should_be_same requirement
 * is not fulfilled.
Christian Würdig's avatar
Christian Würdig committed
531
 * Transform Sub into Neg -- Add if IN2 == OUT
Christian Würdig's avatar
Christian Würdig committed
532
 */
533
static void ia32_finish_node(ir_node *irn, void *env) {
Christian Würdig's avatar
Christian Würdig committed
534
535
	ia32_code_gen_t            *cg = env;
	const ia32_register_req_t **reqs;
Christian Würdig's avatar
Christian Würdig committed
536
	const arch_register_t      *out_reg, *in_reg, *in2_reg;
Christian Würdig's avatar
Christian Würdig committed
537
	int                         n_res, i;
Christian Würdig's avatar
Christian Würdig committed
538
	ir_node                    *copy, *in_node, *block, *in2_node;
Christian Würdig's avatar
Christian Würdig committed
539
	ia32_op_type_t              op_tp;
Christian Würdig's avatar
Christian Würdig committed
540

541
542
543
544
	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)
545
			goto end;
546
547
548
549
550
551

		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 */
552
		if ((op_tp == ia32_Normal || op_tp == ia32_AddrModeS) && need_constraint_copy(irn))
Christian Würdig's avatar
Christian Würdig committed
553
		{
554
555
556
			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
557
558
559
					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);
560
561

					/* don't copy ignore nodes */
Christian Würdig's avatar
Christian Würdig committed
562
					if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
563
564
565
						continue;

					/* check if in and out register are equal */
Christian Würdig's avatar
Christian Würdig committed
566
567
					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
568
569
570
571
572
573
574
575
576
577
578
579
						/* 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
580
581
						}
						else {
Christian Würdig's avatar
Christian Würdig committed
582
insert_copy:
Christian Würdig's avatar
Christian Würdig committed
583
584
585
586
							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);

587
588
							DBG_OPT_2ADDRCPY(copy);

Christian Würdig's avatar
Christian Würdig committed
589
590
591
592
593
594
595
596
597
							/* 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);
						}
598
					}
599
				}
Christian Würdig's avatar
Christian Würdig committed
600
601
			}
		}
Christian Würdig's avatar
Christian Würdig committed
602

603
604
605
606
607
608
		/* If we have a CondJmp with immediate, we need to    */
		/* check if it's the right operand, otherwise we have */
		/* to change it, as CMP doesn't support immediate as  */
		/* left operands.                                     */
		if (is_ia32_CondJmp(irn) && (is_ia32_ImmConst(irn) || is_ia32_ImmSymConst(irn)) && op_tp == ia32_AddrModeS) {
			set_ia32_op_type(irn, ia32_AddrModeD);
Michael Beck's avatar
Michael Beck committed
609
			set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
610
		}
Christian Würdig's avatar
Christian Würdig committed
611

612
613
		/* check if there is a sub which need to be transformed */
		ia32_transform_sub_to_neg_add(irn, cg);
614

615
		/* transform a LEA into an Add if possible */
616
		//ia32_transform_lea_to_add(irn, cg);
617
	}
618
end:
619
620
621

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

624
625
626
627
628
629
630
631
632
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
633
/**
Christian Würdig's avatar
Christian Würdig committed
634
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
635
 */
Christian Würdig's avatar
Christian Würdig committed
636
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
637
	irg_block_walk_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
638
639
}

640
641


642
/**
643
 * Dummy functions for hooks we don't need but which must be filled.
644
 */
645
static void ia32_before_sched(void *self) {
646
647
}

648
649
650
651
652
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
653
static void ia32_before_ra(void *self) {
654
	ia32_code_gen_t *cg = self;
655

656
657
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
658

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

Christian Würdig's avatar
Christian Würdig committed
660
661
662
663
/**
 * 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
664
665
666
667
668
	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
669
	ir_node *sched_point = NULL;
Christian Würdig's avatar
Christian Würdig committed
670
671
672
	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;
673
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
674
675
676
677
678
679

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

	if (mode_is_float(mode)) {
680
		if (USE_SSE2(env->cg))
Michael Beck's avatar
Michael Beck committed
681
			new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, mem);
682
		else
Michael Beck's avatar
Michael Beck committed
683
			new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
684
685
	}
	else {
Michael Beck's avatar
Michael Beck committed
686
		new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
687
688
689
690
691
692
693
694
695
	}

	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);

696
697
	DBG_OPT_RELOAD2LD(irn, new_op);

Christian Würdig's avatar
Christian Würdig committed
698
699
700
701
702
703
704
705
706
	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);
	}

707
708
	/* 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
709
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
710

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

Christian Würdig's avatar
Christian Würdig committed
713
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
}

/**
 * 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)) {
735
		if (USE_SSE2(env->cg))
Michael Beck's avatar
Michael Beck committed
736
			new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
737
		else
Michael Beck's avatar
Michael Beck committed
738
			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
739
	}
740
	else if (get_mode_size_bits(mode) == 8) {
Michael Beck's avatar
Michael Beck committed
741
		new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
742
	}
Christian Würdig's avatar
Christian Würdig committed
743
	else {
Michael Beck's avatar
Michael Beck committed
744
		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
745
746
747
748
749
	}

	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
750
	set_ia32_ls_mode(new_op, mode);
Christian Würdig's avatar
Christian Würdig committed
751
752
753
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

754
755
	DBG_OPT_SPILL2ST(irn, new_op);

Michael Beck's avatar
Michael Beck committed
756
	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
757
758
759
760
761
762
763
764

	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
765
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, new_op));
Christian Würdig's avatar
Christian Würdig committed
766

Christian Würdig's avatar
Christian Würdig committed
767
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
768
769
770
}

/**
771
 * Fix the mode of Spill/Reload
Christian Würdig's avatar
Christian Würdig committed
772
 */
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
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
791
792
793
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

794
	tenv.block = block;
Christian Würdig's avatar
Christian Würdig committed
795
796
	tenv.irg   = current_ir_graph;
	tenv.cg    = cg;
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
	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
816
817
818
819
	}
}

/**
820
 * We transform Spill and Reload here. This needs to be done before
Christian Würdig's avatar
Christian Würdig committed
821
 * stack biasing otherwise we would miss the corrected offset for these nodes.
822
823
824
 *
 * 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
825
826
827
 */
static void ia32_after_ra(void *self) {
	ia32_code_gen_t *cg = self;
828
	irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
829
830

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
831
	if (cg->used_fp == fp_x87) {
832
833
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
834
835
836
}


Christian Würdig's avatar
Christian Würdig committed
837
838
839
840
841
842
/**
 * 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
843
	ir_graph        *irg = cg->irg;
Christian Würdig's avatar
Christian Würdig committed
844

Christian Würdig's avatar
Christian Würdig committed
845
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
846
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
847
	ia32_gen_routine(cg->isa->out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
848
849
850

	cur_reg_set = NULL;

851
852
	/* remove it from the isa */
	cg->isa->cg = NULL;
853

Christian Würdig's avatar
Christian Würdig committed
854
855
856
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
857

Christian Würdig's avatar
Christian Würdig committed
858
859
}

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

Christian Würdig's avatar
Christian Würdig committed
862
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
863
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
864
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
865
	ia32_prepare_graph,
866
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
867
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
868
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
869
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
870
871
};

Christian Würdig's avatar
Christian Würdig committed
872
/**
873
 * Initializes a IA32 code generator.
Christian Würdig's avatar
Christian Würdig committed
874
 */
875
static void *ia32_cg_init(const be_irg_t *birg) {
Christian Würdig's avatar
Christian Würdig committed
876
	ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
877
878
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

879
880
881
882
	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;
883
	cg->isa       = isa;
884
885
	cg->birg      = birg;
	cg->blk_sched = NULL;
886
887
	cg->fp_to_gp  = NULL;
	cg->gp_to_fp  = NULL;
888
	cg->fp_kind   = isa->fp_kind;
889
	cg->used_fp   = fp_none;
890

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

893
894
	/* copy optimizations from isa for easier access */
	cg->opt = isa->opt;
895

896
897
898
	/* enter it */
	isa->cg = cg;

Christian Würdig's avatar
Christian Würdig committed
899
900
901
902
903
904
905
906
907
#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
908
909
	cur_reg_set = cg->reg_set;

Christian Würdig's avatar
Christian Würdig committed
910
911
	ia32_irn_ops.cg = cg;

Christian Würdig's avatar
Christian Würdig committed
912
913
914
	return (arch_code_generator_t *)cg;
}

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

Christian Würdig's avatar
Christian Würdig committed
916
917
918
919
920
921
922
923
924
925
926

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

927
928
929
930
931
/**
 * The template that generates a new ISA object.
 * Note that this template can be changed by command line
 * arguments.
 */
932
static ia32_isa_t ia32_isa_template = {
933
934
935
936
937
938
	{
		&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 */
	},
939
940
	NULL,                    /* 16bit register names */
	NULL,                    /* 8bit register names */
941
942
	NULL,                    /* types */
	NULL,                    /* tv_ents */
943
	(0                 |
944
	IA32_OPT_INCDEC    |     /* optimize add 1, sub 1 into inc/dec               default: on  */
945
	IA32_OPT_DOAM      |     /* optimize address mode                            default: on  */
946
	IA32_OPT_LEA       |     /* optimize for LEAs                                default: on  */
947
948
949
	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  */
950
951
952
	arch_pentium_4,          /* instruction architecture */
	arch_pentium_4,          /* optimize for architecture */
	fp_sse2,                 /* use sse2 unit */
953
	NULL,                    /* current code generator */
954
955
956
957
#ifndef NDEBUG
	NULL,                    /* name obstack */
	0                        /* name obst size */
#endif
958
959
};

Christian Würdig's avatar
Christian Würdig committed
960
/**
961
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
962
 */
963
static void *ia32_init(FILE *file_handle) {
964
	static int inited = 0;
965
	ia32_isa_t *isa;
Christian Würdig's avatar
Christian Würdig committed
966

967
	if (inited)
Christian Würdig's avatar
Christian Würdig committed
968
969
		return NULL;

970
	isa = xmalloc(sizeof(*isa));
971
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
972

973
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
974
975
	ia32_create_opcodes();

976
977
978
979
980
981
982
983
984
985
	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;
	}