bearch_ia32.c 38.6 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
	ia32_register_transformers();
Christian Würdig's avatar
Christian Würdig committed
504
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
Christian Würdig's avatar
Christian Würdig committed
505
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
506

507
508
509
	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
510
	DEBUG_ONLY(cg->mod = old_mod;)
Christian Würdig's avatar
Christian Würdig committed
511
512
}

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

Christian Würdig's avatar
Christian Würdig committed
514
515
516
/**
 * Insert copies for all ia32 nodes where the should_be_same requirement
 * is not fulfilled.
Christian Würdig's avatar
Christian Würdig committed
517
 * Transform Sub into Neg -- Add if IN2 == OUT
Christian Würdig's avatar
Christian Würdig committed
518
 */
519
static void ia32_finish_node(ir_node *irn, void *env) {
Christian Würdig's avatar
Christian Würdig committed
520
521
	ia32_code_gen_t            *cg = env;
	const ia32_register_req_t **reqs;
Christian Würdig's avatar
Christian Würdig committed
522
	const arch_register_t      *out_reg, *in_reg, *in2_reg;
Christian Würdig's avatar
Christian Würdig committed
523
	int                         n_res, i;
Christian Würdig's avatar
Christian Würdig committed
524
	ir_node                    *copy, *in_node, *block, *in2_node;
Christian Würdig's avatar
Christian Würdig committed
525
	ia32_op_type_t              op_tp;
Christian Würdig's avatar
Christian Würdig committed
526

527
528
529
530
	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)
531
			goto end;
532
533
534
535
536
537

		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 */
Christian Würdig's avatar
Christian Würdig committed
538
		if ((op_tp == ia32_Normal || op_tp == ia32_AddrModeS) &&
539
540
			! is_ia32_Lea(irn) && ! is_ia32_Conv_I2I(irn) && ! is_ia32_Conv_I2I8Bit(irn) &&
			! is_ia32_CMov(irn))
Christian Würdig's avatar
Christian Würdig committed
541
		{
542
543
544
			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
545
546
547
					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);
548
549

					/* don't copy ignore nodes */
Christian Würdig's avatar
Christian Würdig committed
550
					if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
551
552
553
						continue;

					/* check if in and out register are equal */
Christian Würdig's avatar
Christian Würdig committed
554
555
					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
556
557
558
559
560
561
562
563
564
565
566
567
						/* 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
568
569
						}
						else {
Christian Würdig's avatar
Christian Würdig committed
570
insert_copy:
Christian Würdig's avatar
Christian Würdig committed
571
572
573
574
							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);

575
576
							DBG_OPT_2ADDRCPY(copy);

Christian Würdig's avatar
Christian Würdig committed
577
578
579
580
581
582
583
584
585
							/* 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);
						}
586
					}
587
				}
Christian Würdig's avatar
Christian Würdig committed
588
589
			}
		}
Christian Würdig's avatar
Christian Würdig committed
590

591
592
593
594
595
596
		/* 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
597
			set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
598
		}
Christian Würdig's avatar
Christian Würdig committed
599

600
601
		/* check if there is a sub which need to be transformed */
		ia32_transform_sub_to_neg_add(irn, cg);
602

603
		/* transform a LEA into an Add if possible */
604
		//ia32_transform_lea_to_add(irn, cg);
605
	}
606
end:
607
608
609

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

612
613
614
615
616
617
618
619
620
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
621
/**
Christian Würdig's avatar
Christian Würdig committed
622
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
623
 */
Christian Würdig's avatar
Christian Würdig committed
624
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
625
	irg_block_walk_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
626
627
}

628
629


630
/**
631
 * Dummy functions for hooks we don't need but which must be filled.
632
 */
633
static void ia32_before_sched(void *self) {
634
635
}

636
637
638
639
640
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
641
static void ia32_before_ra(void *self) {
642
	ia32_code_gen_t *cg = self;
643

644
645
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
646

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

Christian Würdig's avatar
Christian Würdig committed
648
649
650
651
/**
 * 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
652
653
654
655
656
	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
657
	ir_node *sched_point = NULL;
Christian Würdig's avatar
Christian Würdig committed
658
659
660
	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;
661
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
662
663
664
665
666
667

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

	if (mode_is_float(mode)) {
668
		if (USE_SSE2(env->cg))
Michael Beck's avatar
Michael Beck committed
669
			new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, mem);
670
		else
Michael Beck's avatar
Michael Beck committed
671
			new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
672
673
	}
	else {
Michael Beck's avatar
Michael Beck committed
674
		new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
675
676
677
678
679
680
681
682
683
	}

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

684
685
	DBG_OPT_RELOAD2LD(irn, new_op);

Christian Würdig's avatar
Christian Würdig committed
686
687
688
689
690
691
692
693
694
	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);
	}

695
696
	/* 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
697
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
698

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

Christian Würdig's avatar
Christian Würdig committed
701
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
}

/**
 * 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)) {
723
		if (USE_SSE2(env->cg))
Michael Beck's avatar
Michael Beck committed
724
			new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
725
		else
Michael Beck's avatar
Michael Beck committed
726
			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
727
	}
728
	else if (get_mode_size_bits(mode) == 8) {
Michael Beck's avatar
Michael Beck committed
729
		new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem);
730
	}
Christian Würdig's avatar
Christian Würdig committed
731
	else {
Michael Beck's avatar
Michael Beck committed
732
		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
733
734
735
736
737
	}

	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
738
	set_ia32_ls_mode(new_op, mode);
Christian Würdig's avatar
Christian Würdig committed
739
740
741
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

742
743
	DBG_OPT_SPILL2ST(irn, new_op);

Michael Beck's avatar
Michael Beck committed
744
	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
745
746
747
748
749
750
751
752

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

Christian Würdig's avatar
Christian Würdig committed
755
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
756
757
758
}

/**
759
 * Fix the mode of Spill/Reload
Christian Würdig's avatar
Christian Würdig committed
760
 */
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
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
779
780
781
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

782
	tenv.block = block;
Christian Würdig's avatar
Christian Würdig committed
783
784
	tenv.irg   = current_ir_graph;
	tenv.cg    = cg;
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
	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
804
805
806
807
	}
}

/**
808
 * We transform Spill and Reload here. This needs to be done before
Christian Würdig's avatar
Christian Würdig committed
809
 * stack biasing otherwise we would miss the corrected offset for these nodes.
810
811
812
 *
 * 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
813
814
815
 */
static void ia32_after_ra(void *self) {
	ia32_code_gen_t *cg = self;
816
	irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
817
818

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
819
	if (cg->used_fp == fp_x87) {
820
821
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
822
823
824
}


Christian Würdig's avatar
Christian Würdig committed
825
826
827
828
829
830
/**
 * 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
831
	ir_graph        *irg = cg->irg;
Christian Würdig's avatar
Christian Würdig committed
832

Christian Würdig's avatar
Christian Würdig committed
833
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
834
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
835
	ia32_gen_routine(cg->isa->out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
836
837
838

	cur_reg_set = NULL;

839
840
	/* remove it from the isa */
	cg->isa->cg = NULL;
841

Christian Würdig's avatar
Christian Würdig committed
842
843
844
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
845

Christian Würdig's avatar
Christian Würdig committed
846
847
}

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

Christian Würdig's avatar
Christian Würdig committed
850
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
851
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
852
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
853
	ia32_prepare_graph,
854
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
855
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
856
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
857
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
858
859
};

Christian Würdig's avatar
Christian Würdig committed
860
/**
861
 * Initializes a IA32 code generator.
Christian Würdig's avatar
Christian Würdig committed
862
 */
863
static void *ia32_cg_init(const be_irg_t *birg) {
Christian Würdig's avatar
Christian Würdig committed
864
	ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
865
866
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

867
868
869
870
	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;
871
	cg->isa       = isa;
872
873
	cg->birg      = birg;
	cg->blk_sched = NULL;
874
875
	cg->fp_to_gp  = NULL;
	cg->gp_to_fp  = NULL;
876
	cg->fp_kind   = isa->fp_kind;
877
	cg->used_fp   = fp_none;
878

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

881
882
	/* copy optimizations from isa for easier access */
	cg->opt = isa->opt;
883

884
885
886
	/* enter it */
	isa->cg = cg;

Christian Würdig's avatar
Christian Würdig committed
887
888
889
890
891
892
893
894
895
#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
896
897
	cur_reg_set = cg->reg_set;

Christian Würdig's avatar
Christian Würdig committed
898
899
	ia32_irn_ops.cg = cg;

Christian Würdig's avatar
Christian Würdig committed
900
901
902
	return (arch_code_generator_t *)cg;
}

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

Christian Würdig's avatar
Christian Würdig committed
904
905
906
907
908
909
910
911
912
913
914

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

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

Christian Würdig's avatar
Christian Würdig committed
948
/**
949
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
950
 */
951
static void *ia32_init(FILE *file_handle) {
952
	static int inited = 0;
953
	ia32_isa_t *isa;
Christian Würdig's avatar
Christian Würdig committed
954

955
	if (inited)
Christian Würdig's avatar
Christian Würdig committed
956
957
		return NULL;

958
	isa = xmalloc(sizeof(*isa));
959
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
960

961
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
962
963
	ia32_create_opcodes();

964
965
966
967
968
969
970
971
972
973
	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;
	}

974
975
	isa->regs_16bit = pmap_create();
	isa->regs_8bit  = pmap_create();
976
977
978
	isa->types      = pmap_create();
	isa->tv_ent     = pmap_create();
	isa->out        = file_handle;
979
980
981
982

	ia32_build_16bit_reg_map(isa->regs_16bit);
	ia32_build_8bit_reg_map(isa->regs_8bit);

Christian Würdig's avatar
Christian Würdig committed
983
	/* patch register names of x87 registers */
984
985
986
987
988
989
990
991
992
993
994
	if (USE_x87(isa)) {
	  ia32_st_regs[0].name = "st";
	  ia32_st_regs[1].name = "st(1)";
	  ia32_st_regs[2].name = "st(2)";
	  ia32_st_regs[3].name = "st(3)";