bearch_ia32.c 57.2 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

Christian Würdig's avatar
Christian Würdig committed
20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
24
 * @file
 * @brief       This is the main ia32 firm backend driver.
 * @author      Christian Wuerdig
 * @version     $Id$
Christian Würdig's avatar
Christian Würdig committed
25
 */
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
28
29
#endif

30
31
32
#include <libcore/lc_opts.h>
#include <libcore/lc_opts_enum.h>

Christian Würdig's avatar
Christian Würdig committed
33
34
#include <math.h>

Christian Würdig's avatar
Christian Würdig committed
35
36
#include "pseudo_irg.h"
#include "irgwalk.h"
Christian Würdig's avatar
Christian Würdig committed
37
38
#include "irprog.h"
#include "irprintf.h"
39
#include "iredges_t.h"
40
#include "ircons.h"
Christian Würdig's avatar
Christian Würdig committed
41
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
42
#include "irgopt.h"
43
#include "irbitset.h"
44
#include "irgopt.h"
45
#include "pdeq.h"
46
#include "pset.h"
Christian Würdig's avatar
Christian Würdig committed
47
#include "debug.h"
48
#include "error.h"
49
#include "xmalloc.h"
Christian Würdig's avatar
Christian Würdig committed
50

51
#include "../beabi.h"
52
#include "../beirg_t.h"
53
#include "../benode_t.h"
54
#include "../belower.h"
Christian Würdig's avatar
Christian Würdig committed
55
#include "../besched_t.h"
56
#include "be.h"
Christian Würdig's avatar
Christian Würdig committed
57
#include "../be_t.h"
58
#include "../beirgmod.h"
Michael Beck's avatar
Michael Beck committed
59
#include "../be_dbgout.h"
Matthias Braun's avatar
Matthias Braun committed
60
#include "../beblocksched.h"
61
#include "../bemachine.h"
62
#include "../beilpsched.h"
63
#include "../bespillslots.h"
64
#include "../bemodule.h"
Matthias Braun's avatar
Matthias Braun committed
65
#include "../begnuas.h"
66
#include "../bestate.h"
67

68
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
69

70
71
#include "ia32_new_nodes.h"
#include "gen_ia32_regalloc_if.h"
72
#include "gen_ia32_machine.h"
Christian Würdig's avatar
Christian Würdig committed
73
#include "ia32_transform.h"
Christian Würdig's avatar
Christian Würdig committed
74
75
#include "ia32_emitter.h"
#include "ia32_map_regs.h"
Christian Würdig's avatar
Christian Würdig committed
76
#include "ia32_optimize.h"
77
#include "ia32_x87.h"
78
#include "ia32_dbg_stat.h"
Christian Würdig's avatar
Christian Würdig committed
79
#include "ia32_finish.h"
80
#include "ia32_util.h"
81
82
83
#include "ia32_fpu.h"

DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
Christian Würdig's avatar
Christian Würdig committed
84

Christian Würdig's avatar
Christian Würdig committed
85
86
/* TODO: ugly */
static set *cur_reg_set = NULL;
Christian Würdig's avatar
Christian Würdig committed
87

88
89
ir_mode *mode_fpcw = NULL;

90
91
92
typedef ir_node *(*create_const_node_func) (dbg_info *dbg, ir_graph *irg, ir_node *block);

static INLINE ir_node *create_const(ia32_code_gen_t *cg, ir_node **place,
93
                                    create_const_node_func func,
94
                                    const arch_register_t* reg)
95
96
97
98
99
100
101
102
103
104
105
{
	ir_node *block, *res;

	if(*place != NULL)
		return *place;

	block = get_irg_start_block(cg->irg);
	res = func(NULL, cg->irg, block);
	arch_set_irn_register(cg->arch_env, res, reg);
	*place = res;

106
107
	add_irn_dep(get_irg_end(cg->irg), res);
	/* add_irn_dep(get_irg_start(cg->irg), res); */
108
109
110
111

	return res;
}

112
/* Creates the unique per irg GP NoReg node. */
113
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
114
115
116
117
118
119
120
121
122
123
124
125
	return create_const(cg, &cg->noreg_gp, new_rd_ia32_NoReg_GP,
	                    &ia32_gp_regs[REG_GP_NOREG]);
}

ir_node *ia32_new_NoReg_vfp(ia32_code_gen_t *cg) {
	return create_const(cg, &cg->noreg_vfp, new_rd_ia32_NoReg_VFP,
	                    &ia32_vfp_regs[REG_VFP_NOREG]);
}

ir_node *ia32_new_NoReg_xmm(ia32_code_gen_t *cg) {
	return create_const(cg, &cg->noreg_xmm, new_rd_ia32_NoReg_XMM,
	                    &ia32_xmm_regs[REG_XMM_NOREG]);
126
127
}

128
/* Creates the unique per irg FP NoReg node. */
129
ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
130
131
132
133
134
135
	return USE_SSE2(cg) ? ia32_new_NoReg_xmm(cg) : ia32_new_NoReg_vfp(cg);
}

ir_node *ia32_new_Unknown_gp(ia32_code_gen_t *cg) {
	return create_const(cg, &cg->unknown_gp, new_rd_ia32_Unknown_GP,
	                    &ia32_gp_regs[REG_GP_UKNWN]);
136
}
137

138
139
140
141
142
143
144
145
146
147
ir_node *ia32_new_Unknown_vfp(ia32_code_gen_t *cg) {
	return create_const(cg, &cg->unknown_vfp, new_rd_ia32_Unknown_VFP,
	                    &ia32_vfp_regs[REG_VFP_UKNWN]);
}

ir_node *ia32_new_Unknown_xmm(ia32_code_gen_t *cg) {
	return create_const(cg, &cg->unknown_xmm, new_rd_ia32_Unknown_XMM,
	                    &ia32_xmm_regs[REG_XMM_UKNWN]);
}

148
149
150
151
152
ir_node *ia32_new_Fpu_truncate(ia32_code_gen_t *cg) {
	return create_const(cg, &cg->fpu_trunc_mode, new_rd_ia32_ChangeCW,
                        &ia32_fp_cw_regs[REG_FPCW]);
}

153

154
155
156
157
/**
 * Returns gp_noreg or fp_noreg, depending in input requirements.
 */
ir_node *ia32_get_admissible_noreg(ia32_code_gen_t *cg, ir_node *irn, int pos) {
Matthias Braun's avatar
Matthias Braun committed
158
	const arch_register_req_t *req;
159

Matthias Braun's avatar
Matthias Braun committed
160
161
162
	req = arch_get_register_req(cg->arch_env, irn, pos);
	assert(req != NULL && "Missing register requirements");
	if (req->cls == &ia32_reg_classes[CLASS_ia32_gp])
163
		return ia32_new_NoReg_gp(cg);
Matthias Braun's avatar
Matthias Braun committed
164
165

	return ia32_new_NoReg_fp(cg);
166
167
}

Christian Würdig's avatar
Christian Würdig committed
168
169
170
171
172
173
174
175
176
177
178
/**************************************************
 *                         _ _              _  __
 *                        | | |            (_)/ _|
 *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
 * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
 * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
 * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
 *            __/ |
 *           |___/
 **************************************************/

Christian Würdig's avatar
Christian Würdig committed
179
180
181
182
183
/**
 * 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.
 */
Matthias Braun's avatar
Matthias Braun committed
184
185
186
187
188
189
190
191
static const arch_register_req_t *ia32_get_irn_reg_req(const void *self,
                                                       const ir_node *node,
													   int pos) {
	long node_pos = pos == -1 ? 0 : pos;
	ir_mode *mode     = is_Block(node) ? NULL : get_irn_mode(node);

	if (is_Block(node) || mode == mode_X) {
		return arch_no_register_req;
192
193
194
	}

	if (mode == mode_T && pos < 0) {
Matthias Braun's avatar
Matthias Braun committed
195
		return arch_no_register_req;
Christian Würdig's avatar
Christian Würdig committed
196
197
	}

Matthias Braun's avatar
Matthias Braun committed
198
	if (is_Proj(node)) {
199
		if(mode == mode_M)
Matthias Braun's avatar
Matthias Braun committed
200
			return arch_no_register_req;
201

202
		if(pos >= 0) {
Matthias Braun's avatar
Matthias Braun committed
203
			return arch_no_register_req;
204
205
		}

Matthias Braun's avatar
Matthias Braun committed
206
207
		node_pos = (pos == -1) ? get_Proj_proj(node) : pos;
		node     = skip_Proj_const(node);
Christian Würdig's avatar
Christian Würdig committed
208
209
	}

Matthias Braun's avatar
Matthias Braun committed
210
211
212
213
214
215
	if (is_ia32_irn(node)) {
		const arch_register_req_t *req;
		if(pos >= 0)
			req = get_ia32_in_req(node, pos);
		else
			req = get_ia32_out_req(node, node_pos);
216

Matthias Braun's avatar
Matthias Braun committed
217
		assert(req != NULL);
218

Matthias Braun's avatar
Matthias Braun committed
219
		return req;
Christian Würdig's avatar
Christian Würdig committed
220
221
	}

Matthias Braun's avatar
Matthias Braun committed
222
223
224
225
	/* unknowns should be transformed already */
	assert(!is_Unknown(node));

	return arch_no_register_req;
Christian Würdig's avatar
Christian Würdig committed
226
}
Christian Würdig's avatar
Christian Würdig committed
227

Christian Würdig's avatar
Christian Würdig committed
228
static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
229
230
	int                   pos = 0;

231
232
233
234
	if (get_irn_mode(irn) == mode_X) {
		return;
	}

235
	if (is_Proj(irn)) {
236
		pos = get_Proj_proj(irn);
Michael Beck's avatar
Michael Beck committed
237
		irn = skip_Proj(irn);
Christian Würdig's avatar
Christian Würdig committed
238
	}
Christian Würdig's avatar
Christian Würdig committed
239

Christian Würdig's avatar
Christian Würdig committed
240
241
	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
Christian Würdig's avatar
Christian Würdig committed
242

Christian Würdig's avatar
Christian Würdig committed
243
244
		slots      = get_ia32_slots(irn);
		slots[pos] = reg;
Matthias Braun's avatar
Matthias Braun committed
245
	} else {
246
		ia32_set_firm_reg(irn, reg, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
247
	}
Christian Würdig's avatar
Christian Würdig committed
248
249
}

Christian Würdig's avatar
Christian Würdig committed
250
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
251
252
253
	int pos = 0;
	const arch_register_t *reg = NULL;

254
	if (is_Proj(irn)) {
255
256
257
258
259

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

260
		pos = get_Proj_proj(irn);
261
		irn = skip_Proj_const(irn);
Christian Würdig's avatar
Christian Würdig committed
262
263
264
	}

	if (is_ia32_irn(irn)) {
Michael Beck's avatar
Michael Beck committed
265
266
267
		const arch_register_t **slots;
		slots = get_ia32_slots(irn);
		reg   = slots[pos];
Matthias Braun's avatar
Matthias Braun committed
268
	} else {
269
		reg = ia32_get_firm_reg(irn, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
270
271
272
	}

	return reg;
Christian Würdig's avatar
Christian Würdig committed
273
274
}

Christian Würdig's avatar
Christian Würdig committed
275
static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
276
277
	arch_irn_class_t classification = arch_irn_class_normal;

278
	irn = skip_Proj_const(irn);
279

Christian Würdig's avatar
Christian Würdig committed
280
	if (is_cfop(irn))
281
282
283
284
285
286
287
288
289
290
291
		classification |= arch_irn_class_branch;

	if (! is_ia32_irn(irn))
		return classification & ~arch_irn_class_normal;

	if (is_ia32_Cnst(irn))
		classification |= arch_irn_class_const;

	if (is_ia32_Ld(irn))
		classification |= arch_irn_class_load;

292
	if (is_ia32_St(irn))
293
294
		classification |= arch_irn_class_store;

295
	if (is_ia32_need_stackent(irn))
296
297
298
		classification |= arch_irn_class_reload;

	return classification;
Christian Würdig's avatar
Christian Würdig committed
299
}
Christian Würdig's avatar
Christian Würdig committed
300

Christian Würdig's avatar
Christian Würdig committed
301
static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
302
	arch_irn_flags_t flags = arch_irn_flags_none;
303

Christian Würdig's avatar
Christian Würdig committed
304
	if (is_Unknown(irn))
305
		return arch_irn_flags_ignore;
Christian Würdig's avatar
Christian Würdig committed
306

307
308
309
310
311
312
313
314
315
316
317
318
	if(is_Proj(irn) && mode_is_datab(get_irn_mode(irn))) {
		ir_node *pred = get_Proj_pred(irn);

		if(is_ia32_irn(pred)) {
			flags = get_ia32_out_flags(pred, get_Proj_proj(irn));
		}

		irn = pred;
	}

	if (is_ia32_irn(irn)) {
		flags |= get_ia32_flags(irn);
Christian Würdig's avatar
Christian Würdig committed
319
	}
320
321

	return flags;
Christian Würdig's avatar
Christian Würdig committed
322
323
}

324
325
326
/**
 * The IA32 ABI callback object.
 */
327
typedef struct {
328
329
330
331
	be_abi_call_flags_bits_t flags;  /**< The call flags. */
	const arch_isa_t *isa;           /**< The ISA handle. */
	const arch_env_t *aenv;          /**< The architecture environment. */
	ir_graph *irg;                   /**< The associated graph. */
332
333
} ia32_abi_env_t;

334
static ir_entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
335
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
336
337
}

338
static void ia32_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent) {
339
340
341
	set_ia32_frame_ent(irn, ent);
}

342
static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias) {
Christian Würdig's avatar
Christian Würdig committed
343
344
	const ia32_irn_ops_t *ops = self;

Christian Würdig's avatar
Christian Würdig committed
345
	if (get_ia32_frame_ent(irn)) {
Christian Würdig's avatar
Christian Würdig committed
346
347
348
		ia32_am_flavour_t am_flav;

		if (is_ia32_Pop(irn)) {
349
350
351
352
353
			int omit_fp = be_abi_omit_fp(ops->cg->birg->abi);
			if (omit_fp) {
				/* Pop nodes modify the stack pointer before calculating the destination
				 * address, so fix this here
				 */
354
				bias -= 4;
355
			}
356
357
		}

Christian Würdig's avatar
Christian Würdig committed
358
		am_flav  = get_ia32_am_flavour(irn);
359
360
		am_flav |= ia32_O;
		set_ia32_am_flavour(irn, am_flav);
361

362
		add_ia32_am_offs_int(irn, bias);
363
364
365
	}
}

366
367
static int ia32_get_sp_bias(const void *self, const ir_node *irn) {
	if(is_Proj(irn)) {
Michael Beck's avatar
Michael Beck committed
368
		long proj = get_Proj_proj(irn);
369
370
		ir_node *pred = get_Proj_pred(irn);

371
		if (is_ia32_Push(pred) && proj == pn_ia32_Push_stack)
372
			return 4;
373
		if (is_ia32_Pop(pred) && proj == pn_ia32_Pop_stack)
374
375
376
377
378
379
			return -4;
	}

	return 0;
}

380
381
382
383
384
385
/**
 * 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
386
387
388
389
390
391
392
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);
}

393
/**
Michael Beck's avatar
Michael Beck committed
394
 * Generate the routine prologue.
395
 *
396
397
 * @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
398
 * @param reg_map A map mapping all callee_save/ignore/parameter registers to their defining nodes.
399
 *
400
401
402
403
 * @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
404
static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
Sebastian Hack's avatar
Sebastian Hack committed
405
{
Christian Würdig's avatar
Christian Würdig committed
406
	ia32_abi_env_t *env = self;
407
408
	const ia32_isa_t *isa     = (ia32_isa_t *)env->isa;
	ia32_code_gen_t *cg = isa->cg;
Sebastian Hack's avatar
Sebastian Hack committed
409

Christian Würdig's avatar
Christian Würdig committed
410
411
412
413
	if (! env->flags.try_omit_fp) {
		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);
414
		ir_node *noreg = ia32_new_NoReg_gp(cg);
415
		ir_node *push;
Sebastian Hack's avatar
Sebastian Hack committed
416

417
418
419
		/* ALL nodes representing bp must be set to ignore. */
		be_node_set_flags(get_Proj_pred(curr_bp), BE_OUT_POS(get_Proj_proj(curr_bp)), arch_irn_flags_ignore);

420
		/* push ebp */
421
		push    = new_rd_ia32_Push(NULL, env->irg, bl, noreg, noreg, curr_bp, curr_sp, *mem);
Michael Beck's avatar
Michael Beck committed
422
423
		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);
424
425

		/* the push must have SP out register */
Michael Beck's avatar
Michael Beck committed
426
427
		arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
		set_ia32_flags(push, arch_irn_flags_ignore);
428
429

		/* move esp to ebp */
Sebastian Hack's avatar
Sebastian Hack committed
430
431
		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);
432
		arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
Christian Würdig's avatar
Christian Würdig committed
433
		be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
434

435
436
437
438
439
440
		/* 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
441
442
		be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
		be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
443
444

		return env->isa->bp;
Sebastian Hack's avatar
Sebastian Hack committed
445
446
	}

447
	return env->isa->sp;
Sebastian Hack's avatar
Sebastian Hack committed
448
449
}

Michael Beck's avatar
Michael Beck committed
450
451
452
/**
 * Generate the routine epilogue.
 * @param self    The callback object.
453
 * @param bl      The block for the epilog
Michael Beck's avatar
Michael Beck committed
454
455
456
457
458
459
 * @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
460
461
static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
{
Christian Würdig's avatar
Christian Würdig committed
462
463
464
	ia32_abi_env_t *env     = self;
	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);
Sebastian Hack's avatar
Sebastian Hack committed
465

466
467
	if (env->flags.try_omit_fp) {
		/* simply remove the stack frame here */
Sebastian Hack's avatar
Sebastian Hack committed
468
469
		curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK);
		add_irn_dep(curr_sp, *mem);
470
	} else {
Christian Würdig's avatar
Christian Würdig committed
471
		const ia32_isa_t *isa     = (ia32_isa_t *)env->isa;
472
		ia32_code_gen_t *cg = isa->cg;
Christian Würdig's avatar
Christian Würdig committed
473
		ir_mode          *mode_bp = env->isa->bp->reg_class->mode;
Sebastian Hack's avatar
Sebastian Hack committed
474

475
476
		/* gcc always emits a leave at the end of a routine */
		if (1 || ARCH_AMD(isa->opt_arch)) {
477
			ir_node *leave;
478

479
			/* leave */
Sebastian Hack's avatar
Sebastian Hack committed
480
			leave   = new_rd_ia32_Leave(NULL, env->irg, bl, curr_sp, curr_bp);
481
			set_ia32_flags(leave, arch_irn_flags_ignore);
Michael Beck's avatar
Michael Beck committed
482
483
			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);
484
485
		} else {
			ir_node *noreg = ia32_new_NoReg_gp(cg);
486
487
488
489
490
491
			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 */
492
			pop     = new_rd_ia32_Pop(NULL, env->irg, bl, noreg, noreg, curr_sp, *mem);
493
			set_ia32_flags(pop, arch_irn_flags_ignore);
Michael Beck's avatar
Michael Beck committed
494
495
			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);
496
497

			*mem = new_r_Proj(current_ir_graph, bl, pop, mode_M, pn_ia32_Pop_M);
498
		}
499
		arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
500
		arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
Sebastian Hack's avatar
Sebastian Hack committed
501
502
503
504
	}

	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
505
506
}

507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
/**
 * Initialize the callback object.
 * @param call The call object.
 * @param aenv The architecture environment.
 * @param irg  The graph with the method.
 * @return     Some pointer. This pointer is passed to all other callback functions as self object.
 */
static void *ia32_abi_init(const be_abi_call_t *call, const arch_env_t *aenv, ir_graph *irg)
{
	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;
	env->aenv  = aenv;
	env->isa   = aenv->isa;
	return env;
}

/**
 * Destroy the callback object.
 * @param self The callback object.
 */
static void ia32_abi_done(void *self) {
	free(self);
}

Sebastian Hack's avatar
Sebastian Hack committed
533
534
535
536
537
538
539
/**
 * 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)
{
540
#define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
Sebastian Hack's avatar
Sebastian Hack committed
541
542
543
544
545
	static ir_type *omit_fp_between_type = NULL;
	static ir_type *between_type         = NULL;

	ia32_abi_env_t *env = self;

546
	if (! between_type) {
547
548
549
		ir_entity *old_bp_ent;
		ir_entity *ret_addr_ent;
		ir_entity *omit_fp_ret_addr_ent;
Sebastian Hack's avatar
Sebastian Hack committed
550

551
552
		ir_type *old_bp_type   = new_type_primitive(IDENT("bp"), mode_Iu);
		ir_type *ret_addr_type = new_type_primitive(IDENT("return_addr"), mode_Iu);
Sebastian Hack's avatar
Sebastian Hack committed
553

554
555
556
		between_type           = new_type_struct(IDENT("ia32_between_type"));
		old_bp_ent             = new_entity(between_type, IDENT("old_bp"), old_bp_type);
		ret_addr_ent           = new_entity(between_type, IDENT("ret_addr"), ret_addr_type);
Sebastian Hack's avatar
Sebastian Hack committed
557

558
559
		set_entity_offset(old_bp_ent, 0);
		set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
Sebastian Hack's avatar
Sebastian Hack committed
560
		set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
561
		set_type_state(between_type, layout_fixed);
Sebastian Hack's avatar
Sebastian Hack committed
562

Christian Würdig's avatar
Christian Würdig committed
563
564
		omit_fp_between_type = new_type_struct(IDENT("ia32_between_type_omit_fp"));
		omit_fp_ret_addr_ent = new_entity(omit_fp_between_type, IDENT("ret_addr"), ret_addr_type);
Sebastian Hack's avatar
Sebastian Hack committed
565

566
		set_entity_offset(omit_fp_ret_addr_ent, 0);
Sebastian Hack's avatar
Sebastian Hack committed
567
		set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type));
568
		set_type_state(omit_fp_between_type, layout_fixed);
Sebastian Hack's avatar
Sebastian Hack committed
569
570
571
	}

	return env->flags.try_omit_fp ? omit_fp_between_type : between_type;
572
#undef IDENT
Sebastian Hack's avatar
Sebastian Hack committed
573
574
}

575
576
577
578
579
580
581
582
583
584
/**
 * Get the estimated cycle count for @p irn.
 *
 * @param self The this pointer.
 * @param irn  The node.
 *
 * @return     The estimated cycle count for this operation
 */
static int ia32_get_op_estimated_cost(const void *self, const ir_node *irn)
{
Christian Würdig's avatar
Christian Würdig committed
585
	int cost;
Christian Würdig's avatar
Christian Würdig committed
586
587
	ia32_op_type_t op_tp;
	const ia32_irn_ops_t *ops = self;
Adam Szalkowski's avatar
Adam Szalkowski committed
588

Christian Würdig's avatar
Christian Würdig committed
589
	if (is_Proj(irn))
590
591
592
		return 0;
	if (!is_ia32_irn(irn))
		return 0;
Adam Szalkowski's avatar
Adam Szalkowski committed
593

Christian Würdig's avatar
Christian Würdig committed
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
	assert(is_ia32_irn(irn));

	cost  = get_ia32_latency(irn);
	op_tp = get_ia32_op_type(irn);

	if (is_ia32_CopyB(irn)) {
		cost = 250;
		if (ARCH_INTEL(ops->cg->arch))
			cost += 150;
	}
	else if (is_ia32_CopyB_i(irn)) {
		int size = get_tarval_long(get_ia32_Immop_tarval(irn));
		cost     = 20 + (int)ceil((4/3) * size);
		if (ARCH_INTEL(ops->cg->arch))
			cost += 150;
	}
	/* in case of address mode operations add additional cycles */
	else if (op_tp == ia32_AddrModeD || op_tp == ia32_AddrModeS) {
		/*
			In case of stack access add 5 cycles (we assume stack is in cache),
			other memory operations cost 20 cycles.
		*/
		cost += is_ia32_use_frame(irn) ? 5 : 20;
Christian Würdig's avatar
Christian Würdig committed
617
618
619
	}

	return cost;
620
621
}

Christian Würdig's avatar
Christian Würdig committed
622
623
624
625
626
627
628
629
630
631
/**
 * Returns the inverse operation if @p irn, recalculating the argument at position @p i.
 *
 * @param irn       The original operation
 * @param i         Index of the argument we want the inverse operation to yield
 * @param inverse   struct to be filled with the resulting inverse op
 * @param obstack   The obstack to use for allocation of the returned nodes array
 * @return          The inverse operation or NULL if operation invertible
 */
static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obst) {
632
633
	ir_graph *irg;
	ir_mode  *mode;
634
	ir_mode  *irn_mode;
635
	ir_node  *block, *noreg, *nomem;
636
	dbg_info *dbg;
637
638
639
640
641
642
643
644
645
646
647
648
649

	/* we cannot invert non-ia32 irns */
	if (! is_ia32_irn(irn))
		return NULL;

	/* operand must always be a real operand (not base, index or mem) */
	if (i != 2 && i != 3)
		return NULL;

	/* we don't invert address mode operations */
	if (get_ia32_op_type(irn) != ia32_Normal)
		return NULL;

650
651
	irg      = get_irn_irg(irn);
	block    = get_nodes_block(irn);
652
	mode     = get_irn_mode(irn);
653
654
655
656
	irn_mode = get_irn_mode(irn);
	noreg    = get_irn_n(irn, 0);
	nomem    = new_r_NoMem(irg);
	dbg      = get_irn_dbg_info(irn);
657
658

	/* initialize structure */
659
	inverse->nodes = obstack_alloc(obst, 2 * sizeof(inverse->nodes[0]));
660
	inverse->costs = 0;
661
	inverse->n     = 1;
662

663
	switch (get_ia32_irn_opcode(irn)) {
664
665
666
667
		case iro_ia32_Add:
			if (get_ia32_immop_type(irn) == ia32_ImmConst) {
				/* we have an add with a const here */
				/* invers == add with negated const */
668
				inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
669
670
671
672
673
674
675
676
				inverse->costs   += 1;
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
				set_ia32_Immop_tarval(inverse->nodes[0], tarval_neg(get_ia32_Immop_tarval(irn)));
				set_ia32_commutative(inverse->nodes[0]);
			}
			else if (get_ia32_immop_type(irn) == ia32_ImmSymConst) {
				/* we have an add with a symconst here */
				/* invers == sub with const */
677
				inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
678
				inverse->costs   += 2;
679
680
681
682
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal add: inverse == sub */
683
				inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, (ir_node*) irn, get_irn_n(irn, i ^ 1), nomem);
684
				inverse->costs   += 2;
685
686
687
688
689
690
			}
			break;
		case iro_ia32_Sub:
			if (get_ia32_immop_type(irn) != ia32_ImmNone) {
				/* we have a sub with a const/symconst here */
				/* invers == add with this const */
691
				inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
692
693
694
695
696
697
				inverse->costs   += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal sub */
				if (i == 2) {
698
					inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, (ir_node*) irn, get_irn_n(irn, 3), nomem);
699
700
				}
				else {
701
					inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, get_irn_n(irn, 2), (ir_node*) irn, nomem);
702
703
704
705
				}
				inverse->costs += 1;
			}
			break;
706
		case iro_ia32_Xor:
707
708
			if (get_ia32_immop_type(irn) != ia32_ImmNone) {
				/* xor with const: inverse = xor */
709
				inverse->nodes[0] = new_rd_ia32_Xor(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
710
711
712
713
714
				inverse->costs   += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal xor */
715
				inverse->nodes[0] = new_rd_ia32_Xor(dbg, irg, block, noreg, noreg, (ir_node *) irn, get_irn_n(irn, i), nomem);
716
717
718
				inverse->costs   += 1;
			}
			break;
719
		case iro_ia32_Not: {
720
			inverse->nodes[0] = new_rd_ia32_Not(dbg, irg, block, noreg, noreg, (ir_node*) irn, nomem);
721
722
			inverse->costs   += 1;
			break;
723
		}
724
725
		case iro_ia32_Neg: {
			inverse->nodes[0] = new_rd_ia32_Neg(dbg, irg, block, noreg, noreg, (ir_node*) irn, nomem);
726
727
			inverse->costs   += 1;
			break;
728
		}
729
730
731
732
733
734
		default:
			/* inverse operation not supported */
			return NULL;
	}

	return inverse;
Christian Würdig's avatar
Christian Würdig committed
735
736
}

737
738
739
740
741
742
743
744
static ir_mode *get_spill_mode_mode(const ir_mode *mode)
{
	if(mode_is_float(mode))
		return mode_D;

	return mode_Iu;
}

745
746
747
/**
 * Get the mode that should be used for spilling value node
 */
748
static ir_mode *get_spill_mode(const ir_node *node)
749
750
{
	ir_mode *mode = get_irn_mode(node);
751
	return get_spill_mode_mode(mode);
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
}

/**
 * Checks wether an addressmode reload for a node with mode mode is compatible
 * with a spillslot of mode spill_mode
 */
static int ia32_is_spillmode_compatible(const ir_mode *mode, const ir_mode *spillmode)
{
	if(mode_is_float(mode)) {
		return mode == spillmode;
	} else {
		return 1;
	}
}

767
768
769
770
771
772
773
774
/**
 * Check if irn can load it's operand at position i from memory (source addressmode).
 * @param self   Pointer to irn ops itself
 * @param irn    The irn to be checked
 * @param i      The operands position
 * @return Non-Zero if operand can be loaded
 */
static int ia32_possible_memory_operand(const void *self, const ir_node *irn, unsigned int i) {
775
776
	ir_node *op = get_irn_n(irn, i);
	const ir_mode *mode = get_irn_mode(op);
777
	const ir_mode *spillmode = get_spill_mode(op);
778

779
780
781
782
	if (! is_ia32_irn(irn)                            ||  /* must be an ia32 irn */
		get_irn_arity(irn) != 5                       ||  /* must be a binary operation */
		get_ia32_op_type(irn) != ia32_Normal          ||  /* must not already be a addressmode irn */
		! (get_ia32_am_support(irn) & ia32_am_Source) ||  /* must be capable of source addressmode */
783
		! ia32_is_spillmode_compatible(mode, spillmode) ||
784
		(i != 2 && i != 3)                            ||  /* a "real" operand position must be requested */
785
786
787
788
789
790
791
		(i == 2 && ! is_ia32_commutative(irn))        ||  /* if first operand requested irn must be commutative */
		is_ia32_use_frame(irn))                           /* must not already use frame */
		return 0;

	return 1;
}

792
static void ia32_perform_memory_operand(const void *self, ir_node *irn, ir_node *spill, unsigned int i) {
793
794
795
	const ia32_irn_ops_t *ops = self;
	ia32_code_gen_t      *cg  = ops->cg;

796
797
798
799
800
801
802
803
804
805
806
	assert(ia32_possible_memory_operand(self, irn, i) && "Cannot perform memory operand change");

	if (i == 2) {
		ir_node *tmp = get_irn_n(irn, 3);
		set_irn_n(irn, 3, get_irn_n(irn, 2));
		set_irn_n(irn, 2, tmp);
	}

	set_ia32_am_support(irn, ia32_am_Source);
	set_ia32_op_type(irn, ia32_AddrModeS);
	set_ia32_am_flavour(irn, ia32_B);
807
	set_ia32_ls_mode(irn, get_irn_mode(get_irn_n(irn, i)));
808
	set_ia32_use_frame(irn);
809
	set_ia32_need_stackent(irn);
810

811
	set_irn_n(irn, 0, get_irg_frame(get_irn_irg(irn)));
812
	set_irn_n(irn, 3, ia32_get_admissible_noreg(cg, irn, 3));
813
	set_irn_n(irn, 4, spill);
814

815
	//FIXME DBG_OPT_AM_S(reload, irn);
816
817
}

Sebastian Hack's avatar
Sebastian Hack committed
818
819
static const be_abi_callbacks_t ia32_abi_callbacks = {
	ia32_abi_init,
820
	ia32_abi_done,
Sebastian Hack's avatar
Sebastian Hack committed
821
822
823
	ia32_abi_get_between_type,
	ia32_abi_dont_save_regs,
	ia32_abi_prologue,
824
	ia32_abi_epilogue
Sebastian Hack's avatar
Sebastian Hack committed
825
826
};

Christian Würdig's avatar
Christian Würdig committed
827
828
/* fill register allocator interface */

Christian Würdig's avatar
Christian Würdig committed
829
static const arch_irn_ops_if_t ia32_irn_ops_if = {
Christian Würdig's avatar
Christian Würdig committed
830
831
832
833
	ia32_get_irn_reg_req,
	ia32_set_irn_reg,
	ia32_get_irn_reg,
	ia32_classify,
834
	ia32_get_flags,
835
	ia32_get_frame_entity,
836
	ia32_set_frame_entity,
837
838
	ia32_set_frame_offset,
	ia32_get_sp_bias,
839
	ia32_get_inverse,
840
841
842
	ia32_get_op_estimated_cost,
	ia32_possible_memory_operand,
	ia32_perform_memory_operand,
Christian Würdig's avatar
Christian Würdig committed
843
844
};

Christian Würdig's avatar
Christian Würdig committed
845
846
847
848
849
ia32_irn_ops_t ia32_irn_ops = {
	&ia32_irn_ops_if,
	NULL
};

Christian Würdig's avatar
Christian Würdig committed
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867


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

/**
 * 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
868
	ia32_code_gen_t *cg = self;
869

870
	/* transform psi condition trees */
871
	ia32_pre_transform_phase(cg);
872

873
	/* transform all remaining nodes */
874
	ia32_transform_graph(cg);
875
	//add_fpu_edges(cg->birg);
876

877
	// Matze: disabled for now. Because after transformation start block has no
878
879
880
	// self-loop anymore so it might be merged with its successor block. This
	// will bring several nodes to the startblock which sometimes get scheduled
	// before the initial IncSP/Barrier
881
	local_optimize_graph(cg->irg);
882

883
884
	if (cg->dump)
		be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
885

886
	/* optimize address mode */
887
	ia32_optimize_graph(cg);
888

889
890
891
	if (cg->dump)
		be_dump(cg->irg, "-am", dump_ir_block_graph_sched);

892
893
894
	/* do code placement, to optimize the position of constants */
	place_code(cg->irg);

895
	if (cg->dump)
896
		be_dump(cg->irg, "-place", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
897
898
}

899
/**
900
 * Dummy functions for hooks we don't need but which must be filled.
901
 */
902
static void ia32_before_sched(void *self) {
903
904
}

905
906
907
908
909
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
910
static void ia32_before_ra(void *self) {
911
	ia32_code_gen_t *cg              = self;
912

913
914
	/* setup fpu rounding modes */
	ia32_setup_fpu_mode(cg);
915
}
916

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

Christian Würdig's avatar
Christian Würdig committed
918
/**
919
 * Transforms a be_Reload into a ia32 Load.
Christian Würdig's avatar
Christian Würdig committed
920
 */
921
922
923
924
925
926
static void transform_to_Load(ia32_code_gen_t *cg, ir_node *node) {
	ir_graph *irg        = get_irn_irg(node);
	dbg_info *dbg        = get_irn_dbg_info(node);
	ir_node *block       = get_nodes_block(node);
	ir_entity *ent       = be_get_frame_entity(node);
	ir_mode *mode        = get_irn_mode(node);
927
	ir_mode *spillmode   = get_spill_mode(node);
928
	ir_node *noreg       = ia32_new_NoReg_gp(cg);
Christian Würdig's avatar
Christian Würdig committed
929
	ir_node *sched_point = NULL;
930
931
	ir_node *ptr         = get_irg_frame(irg);
	ir_node *mem         = get_irn_n(node, be_pos_Reload_mem);
Christian Würdig's avatar
Christian Würdig committed
932
	ir_node *new_op, *proj;
933
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
934

935
936
	if (sched_is_scheduled(node)) {
		sched_point = sched_prev(node);
Christian Würdig's avatar
Christian Würdig committed
937
938
	}

939
	if (mode_is_float(spillmode)) {
940
941
		if (USE_SSE2(cg))
			new_op = new_rd_ia32_xLoad(dbg, irg, block, ptr, noreg, mem);
942
		else
943
			new_op = new_rd_ia32_vfld(dbg, irg, block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
944
	}
945
946
947
948
	else if (get_mode_size_bits(spillmode) == 128) {
		// Reload 128 bit sse registers
		new_op = new_rd_ia32_xxLoad(dbg, irg, block, ptr, noreg, mem);
	}
949
	else
950
		new_op = new_rd_ia32_Load(dbg, irg, block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
951
952
953
954

	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);
955
	set_ia32_ls_mode(new_op, spillmode);
Christian Würdig's avatar
Christian Würdig committed
956
957
958
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

959
	DBG_OPT_RELOAD2LD(node, new_op);
960

961
	proj = new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_Load_res);