bearch_ia32.c 60 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * 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

Matthias Braun's avatar
Matthias Braun committed
30
31
#include "lc_opts.h"
#include "lc_opts_enum.h"
32

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

Christian Würdig's avatar
Christian Würdig committed
35
#include "pseudo_irg.h"
Christoph Mallon's avatar
Christoph Mallon committed
36
#include "irarch.h"
Christian Würdig's avatar
Christian Würdig committed
37
#include "irgwalk.h"
Christian Würdig's avatar
Christian Würdig committed
38
39
#include "irprog.h"
#include "irprintf.h"
40
#include "iredges_t.h"
41
#include "ircons.h"
Christian Würdig's avatar
Christian Würdig committed
42
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
43
#include "irgopt.h"
44
#include "irbitset.h"
45
#include "irgopt.h"
46
#include "irdump_grgen.h"
47
#include "pdeq.h"
48
#include "pset.h"
Christian Würdig's avatar
Christian Würdig committed
49
#include "debug.h"
50
#include "error.h"
51
#include "xmalloc.h"
Michael Beck's avatar
Michael Beck committed
52
#include "irtools.h"
Matthias Braun's avatar
Matthias Braun committed
53
#include "iroptimize.h"
Christian Würdig's avatar
Christian Würdig committed
54

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

73
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
74

75
76
#include "ia32_new_nodes.h"
#include "gen_ia32_regalloc_if.h"
77
#include "gen_ia32_machine.h"
Christian Würdig's avatar
Christian Würdig committed
78
#include "ia32_transform.h"
Christian Würdig's avatar
Christian Würdig committed
79
80
#include "ia32_emitter.h"
#include "ia32_map_regs.h"
Christian Würdig's avatar
Christian Würdig committed
81
#include "ia32_optimize.h"
82
#include "ia32_x87.h"
83
#include "ia32_dbg_stat.h"
Christian Würdig's avatar
Christian Würdig committed
84
#include "ia32_finish.h"
85
#include "ia32_util.h"
86
#include "ia32_fpu.h"
87
#include "ia32_architecture.h"
88

89
90
91
92
#ifdef FIRM_GRGEN_BE
#include "ia32_pbqp_transform.h"
#endif

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

Christian Würdig's avatar
Christian Würdig committed
95
96
/* TODO: ugly */
static set *cur_reg_set = NULL;
Christian Würdig's avatar
Christian Würdig committed
97

98
99
ir_mode         *mode_fpcw       = NULL;
ia32_code_gen_t *ia32_current_cg = NULL;
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
 * The environment for the intrinsic mapping.
 */
static ia32_intrinsic_env_t intrinsic_env = {
	NULL,    /* the isa */
	NULL,    /* the irg, these entities belong to */
	NULL,    /* entity for first div operand (move into FPU) */
	NULL,    /* entity for second div operand (move into FPU) */
	NULL,    /* entity for converts ll -> d */
	NULL,    /* entity for converts d -> ll */
	NULL,    /* entity for __divdi3 library call */
	NULL,    /* entity for __moddi3 library call */
	NULL,    /* entity for __udivdi3 library call */
	NULL,    /* entity for __umoddi3 library call */
	NULL,    /* bias value for conversion from float to unsigned 64 */
};


119
120
121
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,
122
                                    create_const_node_func func,
123
                                    const arch_register_t* reg)
124
125
126
127
128
129
130
131
132
133
134
{
	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;

135
136
	add_irn_dep(get_irg_end(cg->irg), res);
	/* add_irn_dep(get_irg_start(cg->irg), res); */
137
138
139
140

	return res;
}

141
/* Creates the unique per irg GP NoReg node. */
142
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
143
144
145
146
147
148
149
150
151
152
153
154
	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]);
155
156
}

157
158
159
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]);
160
}
161

162
163
164
165
166
167
168
169
170
171
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]);
}

172
173
174
175
176
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]);
}

177

178
179
180
181
/**
 * 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
182
	const arch_register_req_t *req;
183

Matthias Braun's avatar
Matthias Braun committed
184
185
186
	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])
187
		return ia32_new_NoReg_gp(cg);
Matthias Braun's avatar
Matthias Braun committed
188

189
190
191
192
193
	if (ia32_cg_config.use_sse2) {
		return ia32_new_NoReg_xmm(cg);
	} else {
		return ia32_new_NoReg_vfp(cg);
	}
194
195
}

Christian Würdig's avatar
Christian Würdig committed
196
197
198
199
200
201
202
203
204
205
206
/**************************************************
 *                         _ _              _  __
 *                        | | |            (_)/ _|
 *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
 * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
 * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
 * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
 *            __/ |
 *           |___/
 **************************************************/

Christian Würdig's avatar
Christian Würdig committed
207
208
209
210
211
/**
 * 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
212
213
static const arch_register_req_t *ia32_get_irn_reg_req(const void *self,
                                                       const ir_node *node,
214
215
													   int pos)
{
Matthias Braun's avatar
Matthias Braun committed
216
217
	long node_pos = pos == -1 ? 0 : pos;
	ir_mode *mode     = is_Block(node) ? NULL : get_irn_mode(node);
Matthias Braun's avatar
Matthias Braun committed
218
	(void) self;
Matthias Braun's avatar
Matthias Braun committed
219
220
221

	if (is_Block(node) || mode == mode_X) {
		return arch_no_register_req;
222
223
224
	}

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

Matthias Braun's avatar
Matthias Braun committed
228
	if (is_Proj(node)) {
229
		if(mode == mode_M)
Matthias Braun's avatar
Matthias Braun committed
230
			return arch_no_register_req;
231

232
		if(pos >= 0) {
Matthias Braun's avatar
Matthias Braun committed
233
			return arch_no_register_req;
234
235
		}

Matthias Braun's avatar
Matthias Braun committed
236
237
		node_pos = (pos == -1) ? get_Proj_proj(node) : pos;
		node     = skip_Proj_const(node);
Christian Würdig's avatar
Christian Würdig committed
238
239
	}

Matthias Braun's avatar
Matthias Braun committed
240
241
242
243
244
245
	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);
246

Matthias Braun's avatar
Matthias Braun committed
247
		assert(req != NULL);
248

Matthias Braun's avatar
Matthias Braun committed
249
		return req;
Christian Würdig's avatar
Christian Würdig committed
250
251
	}

Matthias Braun's avatar
Matthias Braun committed
252
253
254
255
	/* unknowns should be transformed already */
	assert(!is_Unknown(node));

	return arch_no_register_req;
Christian Würdig's avatar
Christian Würdig committed
256
}
Christian Würdig's avatar
Christian Würdig committed
257

258
259
260
static void ia32_set_irn_reg(const void *self, ir_node *irn,
                             const arch_register_t *reg)
{
261
	int                   pos = 0;
Matthias Braun's avatar
Matthias Braun committed
262
	(void) self;
263

264
265
266
267
	if (get_irn_mode(irn) == mode_X) {
		return;
	}

268
	if (is_Proj(irn)) {
269
		pos = get_Proj_proj(irn);
Michael Beck's avatar
Michael Beck committed
270
		irn = skip_Proj(irn);
Christian Würdig's avatar
Christian Würdig committed
271
	}
Christian Würdig's avatar
Christian Würdig committed
272

Christian Würdig's avatar
Christian Würdig committed
273
274
	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
Christian Würdig's avatar
Christian Würdig committed
275

Christian Würdig's avatar
Christian Würdig committed
276
277
		slots      = get_ia32_slots(irn);
		slots[pos] = reg;
Matthias Braun's avatar
Matthias Braun committed
278
	} else {
279
		ia32_set_firm_reg(irn, reg, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
280
	}
Christian Würdig's avatar
Christian Würdig committed
281
282
}

283
284
285
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
286
287
	int pos = 0;
	const arch_register_t *reg = NULL;
Matthias Braun's avatar
Matthias Braun committed
288
	(void) self;
Christian Würdig's avatar
Christian Würdig committed
289

290
	if (is_Proj(irn)) {
291
292
293
294
295

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

296
		pos = get_Proj_proj(irn);
297
		irn = skip_Proj_const(irn);
Christian Würdig's avatar
Christian Würdig committed
298
299
300
	}

	if (is_ia32_irn(irn)) {
Michael Beck's avatar
Michael Beck committed
301
302
		const arch_register_t **slots;
		slots = get_ia32_slots(irn);
303
		assert(pos < get_ia32_n_res(irn));
Michael Beck's avatar
Michael Beck committed
304
		reg   = slots[pos];
Matthias Braun's avatar
Matthias Braun committed
305
	} else {
306
		reg = ia32_get_firm_reg(irn, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
307
308
309
	}

	return reg;
Christian Würdig's avatar
Christian Würdig committed
310
311
}

Christian Würdig's avatar
Christian Würdig committed
312
static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
313
	arch_irn_class_t classification = arch_irn_class_normal;
Matthias Braun's avatar
Matthias Braun committed
314
	(void) self;
315

316
	irn = skip_Proj_const(irn);
317

Christian Würdig's avatar
Christian Würdig committed
318
	if (is_cfop(irn))
319
320
321
322
323
324
325
326
		classification |= arch_irn_class_branch;

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

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

327
	if (is_ia32_St(irn))
328
329
		classification |= arch_irn_class_store;

330
	if (is_ia32_need_stackent(irn))
331
332
333
		classification |= arch_irn_class_reload;

	return classification;
Christian Würdig's avatar
Christian Würdig committed
334
}
Christian Würdig's avatar
Christian Würdig committed
335

Christian Würdig's avatar
Christian Würdig committed
336
static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
337
	arch_irn_flags_t flags = arch_irn_flags_none;
Matthias Braun's avatar
Matthias Braun committed
338
	(void) self;
339

Christian Würdig's avatar
Christian Würdig committed
340
	if (is_Unknown(irn))
341
		return arch_irn_flags_ignore;
Christian Würdig's avatar
Christian Würdig committed
342

343
344
345
346
347
348
349
350
351
352
353
354
	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
355
	}
356
357

	return flags;
Christian Würdig's avatar
Christian Würdig committed
358
359
}

360
361
362
/**
 * The IA32 ABI callback object.
 */
363
typedef struct {
364
365
366
367
	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. */
368
369
} ia32_abi_env_t;

370
static ir_entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
Matthias Braun's avatar
Matthias Braun committed
371
	(void) self;
Christian Würdig's avatar
Christian Würdig committed
372
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
373
374
}

375
static void ia32_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent) {
Matthias Braun's avatar
Matthias Braun committed
376
	(void) self;
377
378
379
	set_ia32_frame_ent(irn, ent);
}

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

Christian Würdig's avatar
Christian Würdig committed
383
	if (get_ia32_frame_ent(irn)) {
Christian Würdig's avatar
Christian Würdig committed
384
		if (is_ia32_Pop(irn)) {
385
386
387
388
389
			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
				 */
390
				bias -= 4;
391
			}
392
393
		}

394
		add_ia32_am_offs_int(irn, bias);
395
396
397
	}
}

398
399
static int ia32_get_sp_bias(const void *self, const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
400
	(void) self;
401

402
403
404
405
406
	if (is_ia32_Push(node))
		return 4;

	if (is_ia32_Pop(node))
		return -4;
407
408
409
410

	return 0;
}

411
412
413
414
415
416
/**
 * 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
417
418
419
420
421
422
423
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);
}

424
/**
Michael Beck's avatar
Michael Beck committed
425
 * Generate the routine prologue.
426
 *
427
428
 * @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
429
 * @param reg_map A map mapping all callee_save/ignore/parameter registers to their defining nodes.
430
 *
431
432
433
434
 * @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
435
static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
Sebastian Hack's avatar
Sebastian Hack committed
436
{
Christian Würdig's avatar
Christian Würdig committed
437
	ia32_abi_env_t *env = self;
438
439
	const ia32_isa_t *isa     = (ia32_isa_t *)env->isa;
	ia32_code_gen_t *cg = isa->cg;
Sebastian Hack's avatar
Sebastian Hack committed
440

Christian Würdig's avatar
Christian Würdig committed
441
442
443
444
	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);
445
		ir_node *noreg = ia32_new_NoReg_gp(cg);
446
		ir_node *push;
Sebastian Hack's avatar
Sebastian Hack committed
447

448
449
450
		/* 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);

451
		/* push ebp */
452
		push    = new_rd_ia32_Push(NULL, env->irg, bl, noreg, noreg, *mem, curr_sp, curr_bp);
Michael Beck's avatar
Michael Beck committed
453
454
		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);
455
456

		/* the push must have SP out register */
Michael Beck's avatar
Michael Beck committed
457
458
		arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
		set_ia32_flags(push, arch_irn_flags_ignore);
459
460

		/* move esp to ebp */
Sebastian Hack's avatar
Sebastian Hack committed
461
462
		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);
463
		arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
Christian Würdig's avatar
Christian Würdig committed
464
		be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
465

466
467
468
469
470
471
		/* 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
472
473
		be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
		be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
474
475

		return env->isa->bp;
Sebastian Hack's avatar
Sebastian Hack committed
476
477
	}

478
	return env->isa->sp;
Sebastian Hack's avatar
Sebastian Hack committed
479
480
}

Michael Beck's avatar
Michael Beck committed
481
482
483
/**
 * Generate the routine epilogue.
 * @param self    The callback object.
484
 * @param bl      The block for the epilog
Michael Beck's avatar
Michael Beck committed
485
486
487
488
489
490
 * @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
491
492
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
493
494
495
	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
496

497
498
	if (env->flags.try_omit_fp) {
		/* simply remove the stack frame here */
Sebastian Hack's avatar
Sebastian Hack committed
499
500
		curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK);
		add_irn_dep(curr_sp, *mem);
501
	} else {
Christian Würdig's avatar
Christian Würdig committed
502
		const ia32_isa_t *isa     = (ia32_isa_t *)env->isa;
503
		ia32_code_gen_t *cg = isa->cg;
Christoph Mallon's avatar
Christoph Mallon committed
504
505
		ir_mode         *mode_bp = env->isa->bp->reg_class->mode;
		ir_graph        *irg     = current_ir_graph;
Sebastian Hack's avatar
Sebastian Hack committed
506

507
		if (ia32_cg_config.use_leave) {
508
			ir_node *leave;
509

510
			/* leave */
511
			leave   = new_rd_ia32_Leave(NULL, irg, bl, curr_sp, curr_bp);
512
			set_ia32_flags(leave, arch_irn_flags_ignore);
Christoph Mallon's avatar
Christoph Mallon committed
513
514
			curr_bp = new_r_Proj(irg, bl, leave, mode_bp, pn_ia32_Leave_frame);
			curr_sp = new_r_Proj(irg, bl, leave, get_irn_mode(curr_sp), pn_ia32_Leave_stack);
515
516
		} else {
			ir_node *noreg = ia32_new_NoReg_gp(cg);
517
518
			ir_node *pop;

Christoph Mallon's avatar
Christoph Mallon committed
519
520
521
522
			/* the old SP is not needed anymore (kill the proj) */
			assert(is_Proj(curr_sp));
			be_kill_node(curr_sp);

523
			/* copy ebp to esp */
Christoph Mallon's avatar
Christoph Mallon committed
524
525
526
			curr_sp = be_new_Copy(&ia32_reg_classes[CLASS_ia32_gp], irg, bl, curr_bp);
			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);
527
528

			/* pop ebp */
529
			pop     = new_rd_ia32_Pop(NULL, env->irg, bl, noreg, noreg, *mem, curr_sp);
530
			set_ia32_flags(pop, arch_irn_flags_ignore);
Christoph Mallon's avatar
Christoph Mallon committed
531
532
			curr_bp = new_r_Proj(irg, bl, pop, mode_bp, pn_ia32_Pop_res);
			curr_sp = new_r_Proj(irg, bl, pop, get_irn_mode(curr_sp), pn_ia32_Pop_stack);
533

Christoph Mallon's avatar
Christoph Mallon committed
534
			*mem = new_r_Proj(irg, bl, pop, mode_M, pn_ia32_Pop_M);
535
		}
536
		arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
537
		arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
Sebastian Hack's avatar
Sebastian Hack committed
538
539
540
541
	}

	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
542
543
}

544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
/**
 * 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
570
571
572
573
574
575
576
/**
 * 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)
{
577
#define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
Sebastian Hack's avatar
Sebastian Hack committed
578
579
580
581
582
	static ir_type *omit_fp_between_type = NULL;
	static ir_type *between_type         = NULL;

	ia32_abi_env_t *env = self;

583
	if (! between_type) {
584
585
586
		ir_entity *old_bp_ent;
		ir_entity *ret_addr_ent;
		ir_entity *omit_fp_ret_addr_ent;
Sebastian Hack's avatar
Sebastian Hack committed
587

588
589
		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
590

591
592
593
		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
594

595
596
		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
597
		set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
598
		set_type_state(between_type, layout_fixed);
Sebastian Hack's avatar
Sebastian Hack committed
599

Christian Würdig's avatar
Christian Würdig committed
600
601
		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
602

603
		set_entity_offset(omit_fp_ret_addr_ent, 0);
Sebastian Hack's avatar
Sebastian Hack committed
604
		set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type));
605
		set_type_state(omit_fp_between_type, layout_fixed);
Sebastian Hack's avatar
Sebastian Hack committed
606
607
608
	}

	return env->flags.try_omit_fp ? omit_fp_between_type : between_type;
609
#undef IDENT
Sebastian Hack's avatar
Sebastian Hack committed
610
611
}

612
613
614
615
616
617
618
619
620
621
/**
 * 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)
{
622
	int            cost;
Christian Würdig's avatar
Christian Würdig committed
623
	ia32_op_type_t op_tp;
624
	(void) self;
Adam Szalkowski's avatar
Adam Szalkowski committed
625

Christian Würdig's avatar
Christian Würdig committed
626
	if (is_Proj(irn))
627
628
629
		return 0;
	if (!is_ia32_irn(irn))
		return 0;
Adam Szalkowski's avatar
Adam Szalkowski committed
630

Christian Würdig's avatar
Christian Würdig committed
631
632
633
634
635
636
637
638
639
	assert(is_ia32_irn(irn));

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

	if (is_ia32_CopyB(irn)) {
		cost = 250;
	}
	else if (is_ia32_CopyB_i(irn)) {
Michael Beck's avatar
Michael Beck committed
640
		int size = get_ia32_copyb_size(irn);
Christian Würdig's avatar
Christian Würdig committed
641
642
643
644
645
		cost     = 20 + (int)ceil((4/3) * size);
	}
	/* in case of address mode operations add additional cycles */
	else if (op_tp == ia32_AddrModeD || op_tp == ia32_AddrModeS) {
		/*
646
647
648
			In case of stack access and access to fixed addresses add 5 cycles
			(we assume they are in cache), other memory operations cost 20
			cycles.
Christian Würdig's avatar
Christian Würdig committed
649
		*/
650
651
652
653
654
655
656
		if(is_ia32_use_frame(irn) ||
				(is_ia32_NoReg_GP(get_irn_n(irn, 0)) &&
		         is_ia32_NoReg_GP(get_irn_n(irn, 1)))) {
			cost += 5;
		} else {
			cost += 20;
		}
Christian Würdig's avatar
Christian Würdig committed
657
658
659
	}

	return cost;
660
661
}

Christian Würdig's avatar
Christian Würdig committed
662
663
664
665
666
667
668
669
670
671
/**
 * 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) {
672
673
	ir_graph *irg;
	ir_mode  *mode;
674
	ir_mode  *irn_mode;
675
	ir_node  *block, *noreg, *nomem;
676
	dbg_info *dbg;
Matthias Braun's avatar
Matthias Braun committed
677
	(void) self;
678
679
680
681
682
683

	/* 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) */
684
	if (i != n_ia32_binary_left && i != n_ia32_binary_right)
685
686
687
688
689
690
		return NULL;

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

691
692
693
694
695
	/* TODO: adjust for new immediates... */
	ir_fprintf(stderr, "TODO: fix get_inverse for new immediates (%+F)\n",
	           irn);
	return NULL;

696
697
	irg      = get_irn_irg(irn);
	block    = get_nodes_block(irn);
698
	mode     = get_irn_mode(irn);
699
700
701
702
	irn_mode = get_irn_mode(irn);
	noreg    = get_irn_n(irn, 0);
	nomem    = new_r_NoMem(irg);
	dbg      = get_irn_dbg_info(irn);
703
704

	/* initialize structure */
705
	inverse->nodes = obstack_alloc(obst, 2 * sizeof(inverse->nodes[0]));
706
	inverse->costs = 0;
707
	inverse->n     = 1;
708

709
	switch (get_ia32_irn_opcode(irn)) {
710
		case iro_ia32_Add:
711
#if 0
712
713
714
			if (get_ia32_immop_type(irn) == ia32_ImmConst) {
				/* we have an add with a const here */
				/* invers == add with negated const */
715
				inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
716
717
718
719
720
721
722
723
				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 */
724
				inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
725
				inverse->costs   += 2;
726
727
728
729
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal add: inverse == sub */
730
				inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, i ^ 1));
731
				inverse->costs   += 2;
732
			}
733
#endif
734
735
			break;
		case iro_ia32_Sub:
736
#if 0
737
738
739
			if (get_ia32_immop_type(irn) != ia32_ImmNone) {
				/* we have a sub with a const/symconst here */
				/* invers == add with this const */
740
				inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
741
742
743
744
745
				inverse->costs   += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal sub */
746
747
				if (i == n_ia32_binary_left) {
					inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, 3));
748
749
				}
				else {
750
					inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, nomem, get_irn_n(irn, n_ia32_binary_left), (ir_node*) irn);
751
752
753
				}
				inverse->costs += 1;
			}
754
#endif
755
			break;
756
		case iro_ia32_Xor:
757
#if 0
758
759
			if (get_ia32_immop_type(irn) != ia32_ImmNone) {
				/* xor with const: inverse = xor */
760
				inverse->nodes[0] = new_rd_ia32_Xor(dbg, irg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
761
762
763
764
765
				inverse->costs   += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal xor */
766
				inverse->nodes[0] = new_rd_ia32_Xor(dbg, irg, block, noreg, noreg, nomem, (ir_node *) irn, get_irn_n(irn, i));
767
768
				inverse->costs   += 1;
			}
769
#endif
770
			break;
771
		case iro_ia32_Not: {
772
			inverse->nodes[0] = new_rd_ia32_Not(dbg, irg, block, (ir_node*) irn);
773
774
			inverse->costs   += 1;
			break;
775
		}
776
		case iro_ia32_Neg: {
777
			inverse->nodes[0] = new_rd_ia32_Neg(dbg, irg, block, (ir_node*) irn);
778
779
			inverse->costs   += 1;
			break;
780
		}
781
782
783
784
785
786
		default:
			/* inverse operation not supported */
			return NULL;
	}

	return inverse;
Christian Würdig's avatar
Christian Würdig committed
787
788
}

789
790
791
792
793
794
795
796
static ir_mode *get_spill_mode_mode(const ir_mode *mode)
{
	if(mode_is_float(mode))
		return mode_D;

	return mode_Iu;
}

797
798
799
/**
 * Get the mode that should be used for spilling value node
 */
800
static ir_mode *get_spill_mode(const ir_node *node)
801
802
{
	ir_mode *mode = get_irn_mode(node);
803
	return get_spill_mode_mode(mode);
804
805
806
}

/**
Michael Beck's avatar
Michael Beck committed
807
 * Checks whether an addressmode reload for a node with mode mode is compatible
808
809
810
811
812
813
814
815
816
817
818
 * 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;
	}
}

819
820
821
822
823
824
825
826
/**
 * 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) {
827
828
	ir_node *op = get_irn_n(irn, i);
	const ir_mode *mode = get_irn_mode(op);
829
	const ir_mode *spillmode = get_spill_mode(op);
Matthias Braun's avatar
Matthias Braun committed
830
	(void) self;
831

832
	if (! is_ia32_irn(irn)                                  ||  /* must be an ia32 irn */
833
		get_ia32_am_arity(irn) != ia32_am_binary              ||  /* must be a binary operation TODO is this necessary? */
834
835
836
837
838
		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 */
		! ia32_is_spillmode_compatible(mode, spillmode)       ||
		(i != n_ia32_binary_left && i != n_ia32_binary_right) || /* a "real" operand position must be requested */
		is_ia32_use_frame(irn))                                  /* must not already use frame */
839
840
		return 0;

841
	if (i == n_ia32_binary_left) {
842
843
844
845
846
847
		const arch_register_req_t *req;
		if(!is_ia32_commutative(irn))
			return 0;
		/* we can't swap left/right for limited registers
		 * (As this (currently) breaks constraint handling copies)
		 */
848
		req = get_ia32_in_req(irn, n_ia32_binary_left);
849
850
851
852
853
		if(req->type & arch_register_req_type_limited) {
			return 0;
		}
	}

854
855
856
	return 1;
}

857
858
859
static void ia32_perform_memory_operand(const void *self, ir_node *irn,
                                        ir_node *spill, unsigned int i)
{
860
861
862
	const ia32_irn_ops_t *ops = self;
	ia32_code_gen_t      *cg  = ops->cg;

863
864
	assert(ia32_possible_memory_operand(self, irn, i) && "Cannot perform memory operand change");

865
	if (i == n_ia32_binary_left) {
866
		ia32_swap_left_right(irn);
867
868
869
	}

	set_ia32_op_type(irn, ia32_AddrModeS);
870
	set_ia32_ls_mode(irn, get_irn_mode(get_irn_n(irn, i)));
871
	set_ia32_use_frame(irn);
872
	set_ia32_need_stackent(irn);
873

874
875
876
	set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn)));
	set_irn_n(irn, n_ia32_binary_right, ia32_get_admissible_noreg(cg, irn, n_ia32_binary_right));
	set_irn_n(irn, n_ia32_mem, spill);
877

878
	/* immediates are only allowed on the right side */
879
	if (i == n_ia32_binary_left && is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_left))) {
880
		ia32_swap_left_right(irn);
881
	}
882
883
}

Sebastian Hack's avatar
Sebastian Hack committed
884
885
static const be_abi_callbacks_t ia32_abi_callbacks = {
	ia32_abi_init,
886
	ia32_abi_done,
Sebastian Hack's avatar
Sebastian Hack committed
887
888
889
	ia32_abi_get_between_type,
	ia32_abi_dont_save_regs,
	ia32_abi_prologue,
890
	ia32_abi_epilogue
Sebastian Hack's avatar
Sebastian Hack committed
891
892
};

Christian Würdig's avatar
Christian Würdig committed
893
894
/* fill register allocator interface */

Christian Würdig's avatar
Christian Würdig committed
895
static const arch_irn_ops_if_t ia32_irn_ops_if = {
Christian Würdig's avatar
Christian Würdig committed
896
897
898
899
	ia32_get_irn_reg_req,
	ia32_set_irn_reg,
	ia32_get_irn_reg,
	ia32_classify,
900
	ia32_get_flags,
901
	ia32_get_frame_entity,
902
	ia32_set_frame_entity,
903
904
	ia32_set_frame_offset,
	ia32_get_sp_bias,
905
	ia32_get_inverse,
906
907
908
	ia32_get_op_estimated_cost,
	ia32_possible_memory_operand,
	ia32_perform_memory_operand,
Christian Würdig's avatar
Christian Würdig committed
909
910
};

Matthias Braun's avatar
Matthias Braun committed
911
static ia32_irn_ops_t ia32_irn_ops = {
Christian Würdig's avatar
Christian Würdig committed
912
913
914
915
	&ia32_irn_ops_if,
	NULL
};

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


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

929
static void ia32_before_abi(void *self) {
Matthias Braun's avatar
Matthias Braun committed
930
931
932
933
934
	lower_mode_b_config_t lower_mode_b_config = {
		mode_Iu,  /* lowered mode */
		mode_Bu,  /* prefered mode for set */
		0,        /* don't lower direct compares */
	};
Christian Würdig's avatar
Christian Würdig committed
935
	ia32_code_gen_t *cg = self;
936

Matthias Braun's avatar
Matthias Braun committed
937
	ir_lower_mode_b(cg->irg, &lower_mode_b_config);
Michael Beck's avatar
Michael Beck committed
938
	if (cg->dump)
939
		be_dump(cg->irg, "-lower_modeb", dump_ir_block_graph_sched);
940
941
942
943
944
945
946
947
948
}

/**
 * Transforms the standard firm graph into
 * an ia32 firm graph
 */
static void ia32_prepare_graph(void *self) {
	ia32_code_gen_t *cg = self;

Matthias Braun's avatar
Matthias Braun committed
949
950
951
	/* do local optimisations */
	optimize_graph_df(cg->irg);

952
953
954
955
956
957
958
	/* TODO: we often have dead code reachable through out-edges here. So for
	 * now we rebuild edges (as we need correct user count for code selection)
	 */
#if 1
	edges_deactivate(cg->irg);
	edges_activate(cg->irg);
<