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
363
364
365
366
367
368
/**
 * Generate the routine epilogue.
 * @param self    The callback object.
 * @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
369
370
static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
{
371
	ia32_abi_env_t *env  = self;
Sebastian Hack's avatar
Sebastian Hack committed
372
373
374
	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);

375
376
	if (env->flags.try_omit_fp) {
		/* simply remove the stack frame here */
377
		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
378
379
	}
	else {
380
		const ia32_isa_t *isa = (ia32_isa_t *)env->isa;
Sebastian Hack's avatar
Sebastian Hack committed
381
		ir_mode *mode_bp = env->isa->bp->reg_class->mode;
382
		int reg_size     = get_mode_size_bytes(env->isa->bp->reg_class->mode);
Sebastian Hack's avatar
Sebastian Hack committed
383

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

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

	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
414
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
}

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

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

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

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


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

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

501
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
502
	ia32_register_transformers();
Christian Würdig's avatar
Christian Würdig committed
503
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
Christian Würdig's avatar
Christian Würdig committed
504
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
505

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

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

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

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

		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
537
538
539
		if ((op_tp == ia32_Normal || op_tp == ia32_AddrModeS) &&
			! is_ia32_Lea(irn) && ! is_ia32_Conv_I2I(irn) && ! is_ia32_Conv_I2I8Bit(irn))
		{
540
541
542
			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
543
544
545
					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);
546
547

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

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

573
574
							DBG_OPT_2ADDRCPY(copy);

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

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

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

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

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

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

626
627


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

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

642
643
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
644

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

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

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

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

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

682
683
	DBG_OPT_RELOAD2LD(irn, new_op);

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

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

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

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

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

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

740
741
	DBG_OPT_SPILL2ST(irn, new_op);

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

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

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

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

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

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

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


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

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

	cur_reg_set = NULL;

837
838
	/* remove it from the isa */
	cg->isa->cg = NULL;
839

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

Christian Würdig's avatar
Christian Würdig committed
844
845
}

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

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

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

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

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

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

882
883
884
	/* enter it */
	isa->cg = cg;

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

Christian Würdig's avatar
Christian Würdig committed
896
897
	ia32_irn_ops.cg = cg;

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

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

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

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

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

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

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

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

959
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
960
961
	ia32_create_opcodes();

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

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

	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
981
	/* patch register names of x87 registers */
982
983
984
985
986
987
988
989
990
991
992
	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)";
	  ia32_st_regs[4].name = "st(4)";
	  ia32_st_regs[5].name = "st(5)";
	  ia32_st_regs[6].name = "st(6)";
	  ia32_st_regs[7].name = "st(7)";
	}

Christian Würdig's avatar
Christian Würdig committed
993
#ifndef NDEBUG
994
	isa->name_obst = xmalloc(sizeof(*isa->name_obst));
Christian Würdig's avatar
Christian Würdig committed
995
	obstack_init(isa->name_obst);
Christian Würdig's avatar
Christian Würdig committed
996
	isa->name_obst_size = 0;
Christian Würdig's avatar
Christian Würdig committed
997
998
#endif /* NDEBUG */