bearch_ia32.c 32.9 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"
Christian Würdig's avatar
Christian Würdig committed
51

Christian Würdig's avatar
Christian Würdig committed
52
#define DEBUG_MODULE "firm.be.ia32.isa"
Christian Würdig's avatar
Christian Würdig committed
53

Christian Würdig's avatar
Christian Würdig committed
54
55
/* TODO: ugly */
static set *cur_reg_set = NULL;
Christian Würdig's avatar
Christian Würdig committed
56

Christian Würdig's avatar
Christian Würdig committed
57
58
#undef is_Start
#define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
Christian Würdig's avatar
Christian Würdig committed
59

60
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
61
	return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_GP_NOREG]);
62
63
64
}

ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
65
66
	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]);
67
}
68

Christian Würdig's avatar
Christian Würdig committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**************************************************
 *                         _ _              _  __
 *                        | | |            (_)/ _|
 *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
 * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
 * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
 * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
 *            __/ |
 *           |___/
 **************************************************/

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
85

Sebastian Hack's avatar
Sebastian Hack committed
86

Christian Würdig's avatar
Christian Würdig committed
87
88
89
90
91
/**
 * 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
92
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) {
93
	const ia32_irn_ops_t      *ops = self;
94
95
	const ia32_register_req_t *irn_req;
	long                       node_pos = pos == -1 ? 0 : pos;
96
	ir_mode                   *mode     = is_Block(irn) ? NULL : get_irn_mode(irn);
97
	FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
Christian Würdig's avatar
Christian Würdig committed
98

99
100
101
102
103
104
105
	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
106
107
108
109
110
		return NULL;
	}

	DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));

111
	if (is_Proj(irn)) {
112
		if (pos == -1) {
113
			node_pos = ia32_translate_proj_pos(irn);
114
115
		}
		else {
Christian Würdig's avatar
Christian Würdig committed
116
			node_pos = pos;
117
		}
Christian Würdig's avatar
Christian Würdig committed
118
119
120

		irn = my_skip_proj(irn);

Christian Würdig's avatar
Christian Würdig committed
121
		DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
Christian Würdig's avatar
Christian Würdig committed
122
123
124
125
	}

	if (is_ia32_irn(irn)) {
		if (pos >= 0) {
126
			irn_req = get_ia32_in_req(irn, pos);
Christian Würdig's avatar
Christian Würdig committed
127
128
		}
		else {
129
			irn_req = get_ia32_out_req(irn, node_pos);
Christian Würdig's avatar
Christian Würdig committed
130
131
		}

Christian Würdig's avatar
Christian Würdig committed
132
		DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
Christian Würdig's avatar
Christian Würdig committed
133

134
135
		memcpy(req, &(irn_req->req), sizeof(*req));

136
137
138
139
140
141
142
143
		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);
144
		}
Christian Würdig's avatar
Christian Würdig committed
145
146
147
148
	}
	else {
		/* treat Phi like Const with default requirements */
		if (is_Phi(irn)) {
Christian Würdig's avatar
Christian Würdig committed
149
			DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
150
151
152
153
154
155
			if (mode_is_float(mode)) {
				if (USE_SSE2(ops->cg))
					memcpy(req, &(ia32_default_req_ia32_xmm.req), sizeof(*req));
				else
					memcpy(req, &(ia32_default_req_ia32_vfp.req), sizeof(*req));
			}
Christian Würdig's avatar
Christian Würdig committed
156
			else if (mode_is_int(mode) || mode_is_reference(mode))
157
				memcpy(req, &(ia32_default_req_ia32_gp.req), sizeof(*req));
Christian Würdig's avatar
Christian Würdig committed
158
159
160
161
162
163
164
165
			else if (mode == mode_T || mode == mode_M) {
				DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
				return NULL;
			}
			else
				assert(0 && "unsupported Phi-Mode");
		}
		else {
Christian Würdig's avatar
Christian Würdig committed
166
			DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
167
			req = NULL;
Christian Würdig's avatar
Christian Würdig committed
168
169
170
171
172
		}
	}

	return req;
}
Christian Würdig's avatar
Christian Würdig committed
173

Christian Würdig's avatar
Christian Würdig committed
174
static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
175
176
177
	int                   pos = 0;
	const ia32_irn_ops_t *ops = self;

178
179
180
181
	if (get_irn_mode(irn) == mode_X) {
		return;
	}

182
	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
183

184
	if (is_Proj(irn)) {
185
		pos = ia32_translate_proj_pos(irn);
Christian Würdig's avatar
Christian Würdig committed
186
187
		irn = my_skip_proj(irn);
	}
Christian Würdig's avatar
Christian Würdig committed
188

Christian Würdig's avatar
Christian Würdig committed
189
190
	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
Christian Würdig's avatar
Christian Würdig committed
191

Christian Würdig's avatar
Christian Würdig committed
192
193
194
195
		slots      = get_ia32_slots(irn);
		slots[pos] = reg;
	}
	else {
196
		ia32_set_firm_reg(irn, reg, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
197
	}
Christian Würdig's avatar
Christian Würdig committed
198
199
}

Christian Würdig's avatar
Christian Würdig committed
200
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
201
202
203
	int pos = 0;
	const arch_register_t *reg = NULL;

204
	if (is_Proj(irn)) {
205
206
207
208
209

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

210
		pos = ia32_translate_proj_pos(irn);
Christian Würdig's avatar
Christian Würdig committed
211
212
213
214
215
216
217
218
219
		irn = my_skip_proj(irn);
	}

	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
		slots = get_ia32_slots(irn);
		reg   = slots[pos];
	}
	else {
220
		reg = ia32_get_firm_reg(irn, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
221
222
223
	}

	return reg;
Christian Würdig's avatar
Christian Würdig committed
224
225
}

Christian Würdig's avatar
Christian Würdig committed
226
static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
227
228
229
	irn = my_skip_proj(irn);
	if (is_cfop(irn))
		return arch_irn_class_branch;
Christian Würdig's avatar
Christian Würdig committed
230
	else if (is_ia32_irn(irn))
Christian Würdig's avatar
Christian Würdig committed
231
		return arch_irn_class_normal;
Christian Würdig's avatar
Christian Würdig committed
232
233
	else
		return 0;
Christian Würdig's avatar
Christian Würdig committed
234
}
Christian Würdig's avatar
Christian Würdig committed
235

Christian Würdig's avatar
Christian Würdig committed
236
static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
237
238
239
240
241
242
	irn = my_skip_proj(irn);
	if (is_ia32_irn(irn))
		return get_ia32_flags(irn);
	else {
		return 0;
	}
Christian Würdig's avatar
Christian Würdig committed
243
244
}

Christian Würdig's avatar
Christian Würdig committed
245
246
static entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
247
248
}

249
static void ia32_set_stack_bias(const void *self, ir_node *irn, int bias) {
Christian Würdig's avatar
Christian Würdig committed
250
251
252
	char buf[64];
	const ia32_irn_ops_t *ops = self;

Christian Würdig's avatar
Christian Würdig committed
253
	if (get_ia32_frame_ent(irn)) {
Christian Würdig's avatar
Christian Würdig committed
254
255
256
257
		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
258
259
260
261
262
263
264
265
266

		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);
		}
267
268
269
	}
}

Sebastian Hack's avatar
Sebastian Hack committed
270
271
272
273
274
275
typedef struct {
	be_abi_call_flags_bits_t flags;
	const arch_isa_t *isa;
	ir_graph *irg;
} ia32_abi_env_t;

Sebastian Hack's avatar
Sebastian Hack committed
276
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
277
278
279
280
281
{
	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;
Sebastian Hack's avatar
Sebastian Hack committed
282
	env->isa   = aenv->isa;
Sebastian Hack's avatar
Sebastian Hack committed
283
284
285
286
287
288
289
290
291
292
	return env;
}

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

Sebastian Hack's avatar
Sebastian Hack committed
293
static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
Sebastian Hack's avatar
Sebastian Hack committed
294
{
Sebastian Hack's avatar
Sebastian Hack committed
295
296
297
298
299
300
301
302
	ia32_abi_env_t *env              = self;
	const arch_register_t *frame_reg = env->isa->sp;

	if(!env->flags.try_omit_fp) {
		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);
303
		ir_node *curr_no_reg = be_abi_reg_map_get(reg_map, &ia32_gp_regs[REG_GP_NOREG]);
Sebastian Hack's avatar
Sebastian Hack committed
304
305
		ir_node *store_bp;

306
		curr_sp  = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, *mem, reg_size, be_stack_dir_expand);
Sebastian Hack's avatar
Sebastian Hack committed
307
		store_bp = new_rd_ia32_Store(NULL, env->irg, bl, curr_sp, curr_no_reg, curr_bp, *mem, mode_T);
Daniel Grund's avatar
Daniel Grund committed
308
309
310
		set_ia32_am_support(store_bp, ia32_am_Dest);
		set_ia32_am_flavour(store_bp, ia32_B);
		set_ia32_op_type(store_bp, ia32_AddrModeD);
Sebastian Hack's avatar
Sebastian Hack committed
311
312
313
314
315
316
317
318
319
320
		*mem     = new_r_Proj(env->irg, bl, store_bp, mode_M, 0);
		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);
		be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_ignore);

		be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
		be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
	}

	return frame_reg;
Sebastian Hack's avatar
Sebastian Hack committed
321
322
323
324
}

static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
{
Sebastian Hack's avatar
Sebastian Hack committed
325
326
327
	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);
328
	ir_node *curr_no_reg = be_abi_reg_map_get(reg_map, &ia32_gp_regs[REG_GP_NOREG]);
Sebastian Hack's avatar
Sebastian Hack committed
329
330

	if(env->flags.try_omit_fp) {
331
		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
332
333
334
335
336
337
338
339
	}

	else {
		ir_node *load_bp;
		ir_mode *mode_bp = env->isa->bp->reg_class->mode;

		curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
		load_bp = new_rd_ia32_Load(NULL, env->irg, bl, curr_sp, curr_no_reg, *mem, mode_T);
Daniel Grund's avatar
Daniel Grund committed
340
341
342
		set_ia32_am_support(load_bp, ia32_am_Source);
		set_ia32_am_flavour(load_bp, ia32_B);
		set_ia32_op_type(load_bp, ia32_AddrModeS);
Sebastian Hack's avatar
Sebastian Hack committed
343
344
345
346
347
348
349
		set_ia32_ls_mode(load_bp, mode_bp);
		curr_bp = new_r_Proj(env->irg, bl, load_bp, mode_bp, 0);
		*mem    = new_r_Proj(env->irg, bl, load_bp, mode_M, 1);
	}

	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
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
}

/**
 * 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
399
400
/* fill register allocator interface */

Christian Würdig's avatar
Christian Würdig committed
401
static const arch_irn_ops_if_t ia32_irn_ops_if = {
Christian Würdig's avatar
Christian Würdig committed
402
403
404
405
	ia32_get_irn_reg_req,
	ia32_set_irn_reg,
	ia32_get_irn_reg,
	ia32_classify,
406
	ia32_get_flags,
407
	ia32_get_frame_entity,
408
	ia32_set_stack_bias
Christian Würdig's avatar
Christian Würdig committed
409
410
};

Christian Würdig's avatar
Christian Würdig committed
411
412
413
414
415
ia32_irn_ops_t ia32_irn_ops = {
	&ia32_irn_ops_if,
	NULL
};

Christian Würdig's avatar
Christian Würdig committed
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433


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

/**
 * 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
434
	ia32_code_gen_t *cg = self;
435
	DEBUG_ONLY(firm_dbg_module_t *old_mod = cg->mod;)
436

437
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
Christian Würdig's avatar
Christian Würdig committed
438
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
Christian Würdig's avatar
Christian Würdig committed
439
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
440

441
	DEBUG_ONLY(cg->mod = old_mod;)
442
443

	if (cg->opt.doam) {
444
445
446
447
		edges_deactivate(cg->irg);
		//dead_node_elimination(cg->irg);
		edges_activate(cg->irg);

448
		irg_walk_blkwise_graph(cg->irg, NULL, ia32_optimize_am, cg);
Christian Würdig's avatar
Christian Würdig committed
449
		be_dump(cg->irg, "-am", dump_ir_block_graph_sched);
450
	}
Christian Würdig's avatar
Christian Würdig committed
451
452
}

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

Christian Würdig's avatar
Christian Würdig committed
454
455
456
/**
 * Insert copies for all ia32 nodes where the should_be_same requirement
 * is not fulfilled.
Christian Würdig's avatar
Christian Würdig committed
457
 * Transform Sub into Neg -- Add if IN2 == OUT
Christian Würdig's avatar
Christian Würdig committed
458
459
460
461
 */
static void ia32_finish_irg_walker(ir_node *irn, void *env) {
	ia32_code_gen_t            *cg = env;
	const ia32_register_req_t **reqs;
Christian Würdig's avatar
Christian Würdig committed
462
	const arch_register_t      *out_reg, *in_reg, *in2_reg;
Christian Würdig's avatar
Christian Würdig committed
463
	int                         n_res, i;
Christian Würdig's avatar
Christian Würdig committed
464
	ir_node                    *copy, *in_node, *block, *in2_node;
Christian Würdig's avatar
Christian Würdig committed
465
	ia32_op_type_t              op_tp;
Christian Würdig's avatar
Christian Würdig committed
466

467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
	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)
			return;

		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 */
		if (op_tp == ia32_Normal) {
			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
482
483
484
485
486
					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);
					in2_node = get_irn_n(irn, reqs[i]->same_pos ^ 1);
					in2_reg  = arch_get_irn_register(cg->arch_env, in2_node);
487
488

					/* don't copy ignore nodes */
Christian Würdig's avatar
Christian Würdig committed
489
					if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
490
491
492
						continue;

					/* check if in and out register are equal */
Christian Würdig's avatar
Christian Würdig committed
493
494
					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
495
496
497
						if (is_ia32_commutative(irn) && 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);
Christian Würdig's avatar
Christian Würdig committed
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
						}
						else {
							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);

							/* 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);
						}
513
					}
514
				}
Christian Würdig's avatar
Christian Würdig committed
515
516
			}
		}
Christian Würdig's avatar
Christian Würdig committed
517

518
519
520
521
522
523
524
525
526
		/* 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) {
			long pnc = get_negated_pnc(get_ia32_pncode(irn), get_ia32_res_mode(irn));
			set_ia32_op_type(irn, ia32_AddrModeD);
			set_ia32_pncode(irn, pnc);
		}
Christian Würdig's avatar
Christian Würdig committed
527

528
529
		/* check if there is a sub which need to be transformed */
		ia32_transform_sub_to_neg_add(irn, cg);
530

531
532
533
		/* transform a LEA into an Add if possible */
		ia32_transform_lea_to_add(irn, cg);
	}
534
535
536

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

/**
Christian Würdig's avatar
Christian Würdig committed
540
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
541
 */
Christian Würdig's avatar
Christian Würdig committed
542
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
Christian Würdig's avatar
Christian Würdig committed
543
	irg_walk_blkwise_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
544
545
}

546
547


548
/**
549
 * Dummy functions for hooks we don't need but which must be filled.
550
 */
551
static void ia32_before_sched(void *self) {
552
553
}

554
555
556
557
558
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
559
static void ia32_before_ra(void *self) {
560
	ia32_code_gen_t *cg = self;
561

562
563
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
564

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

Christian Würdig's avatar
Christian Würdig committed
566
567
568
569
/**
 * 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
570
571
572
573
574
	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
575
	ir_node *sched_point = NULL;
Christian Würdig's avatar
Christian Würdig committed
576
577
578
	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;
579
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
580
581
582
583
584
585

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

	if (mode_is_float(mode)) {
586
587
588
589
		if (USE_SSE2(env->cg))
			new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
		else
			new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
590
591
	}
	else {
Christian Würdig's avatar
Christian Würdig committed
592
		new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
	}

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

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

611
612
	/* 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
613
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
614

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

Christian Würdig's avatar
Christian Würdig committed
617
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
}

/**
 * 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)) {
639
640
641
642
		if (USE_SSE2(env->cg))
			new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
		else
			new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
643
	}
644
645
646
	else if (get_mode_size_bits(mode) == 8) {
		new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
	}
Christian Würdig's avatar
Christian Würdig committed
647
648
649
650
651
652
653
	else {
		new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
	}

	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
654
	set_ia32_ls_mode(new_op, mode);
Christian Würdig's avatar
Christian Würdig committed
655
656
657
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

658
	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, 0);
Christian Würdig's avatar
Christian Würdig committed
659
660
661
662
663
664
665
666

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

Christian Würdig's avatar
Christian Würdig committed
669
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
670
671
672
}

/**
673
 * Fix the mode of Spill/Reload
Christian Würdig's avatar
Christian Würdig committed
674
 */
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
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
693
694
695
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

696
	tenv.block = block;
Christian Würdig's avatar
Christian Würdig committed
697
698
	tenv.irg   = current_ir_graph;
	tenv.cg    = cg;
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
	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
718
719
720
721
	}
}

/**
722
 * We transform Spill and Reload here. This needs to be done before
Christian Würdig's avatar
Christian Würdig committed
723
 * stack biasing otherwise we would miss the corrected offset for these nodes.
724
725
726
 *
 * 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
727
728
729
 */
static void ia32_after_ra(void *self) {
	ia32_code_gen_t *cg = self;
730
	irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
731
732

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
733
	if (cg->used_x87) {
734
735
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
736
737
738
}


Christian Würdig's avatar
Christian Würdig committed
739
740
741
742
743
744
/**
 * 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
745
746
	ir_graph        *irg = cg->irg;
	FILE            *out = cg->out;
Christian Würdig's avatar
Christian Würdig committed
747
748
749
750
751
752

	if (cg->emit_decls) {
		ia32_gen_decls(cg->out);
		cg->emit_decls = 0;
	}

Christian Würdig's avatar
Christian Würdig committed
753
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
754
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
755
	ia32_gen_routine(out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
756
757
758

	cur_reg_set = NULL;

759
760
761
	pmap_destroy(cg->tv_ent);
	pmap_destroy(cg->types);

Christian Würdig's avatar
Christian Würdig committed
762
763
764
765
766
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
}

Christian Würdig's avatar
Christian Würdig committed
767
static void *ia32_cg_init(FILE *F, const be_irg_t *birg);
Christian Würdig's avatar
Christian Würdig committed
768

Christian Würdig's avatar
Christian Würdig committed
769
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
770
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
771
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
772
	ia32_prepare_graph,
773
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
774
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
775
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
776
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
777
778
};

Christian Würdig's avatar
Christian Würdig committed
779
780
781
/**
 * Initializes the code generator.
 */
Christian Würdig's avatar
Christian Würdig committed
782
783
static void *ia32_cg_init(FILE *F, const be_irg_t *birg) {
	ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
784
785
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

786
787
788
789
790
791
792
793
794
795
	cg->impl      = &ia32_code_gen_if;
	cg->irg       = birg->irg;
	cg->reg_set   = new_set(ia32_cmp_irn_reg_assoc, 1024);
	cg->out       = F;
	cg->arch_env  = birg->main_env->arch_env;
	cg->types     = pmap_create();
	cg->tv_ent    = pmap_create();
	cg->birg      = birg;
	cg->blk_sched = NULL;
	cg->fp_kind   = isa->fp_kind;
796
797
	cg->used_x87  = 0;

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

800
801
	/* set optimizations */
	cg->opt.incdec    = 0;
Christian Würdig's avatar
Christian Würdig committed
802
	cg->opt.doam      = 1;
803
804
	cg->opt.placecnst = 1;
	cg->opt.immops    = 1;
805
	cg->opt.extbb     = 1;
806

Christian Würdig's avatar
Christian Würdig committed
807
808
809
810
811
812
813
814
815
#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
816
817
818
819
820
821
822
823
824
	isa->num_codegens++;

	if (isa->num_codegens > 1)
		cg->emit_decls = 0;
	else
		cg->emit_decls = 1;

	cur_reg_set = cg->reg_set;

Christian Würdig's avatar
Christian Würdig committed
825
826
	ia32_irn_ops.cg = cg;

Christian Würdig's avatar
Christian Würdig committed
827
828
829
	return (arch_code_generator_t *)cg;
}

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

Christian Würdig's avatar
Christian Würdig committed
831
832
833
834
835
836
837
838
839
840
841

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

842
static ia32_isa_t ia32_isa_template = {
Christian Würdig's avatar
Christian Würdig committed
843
844
845
846
847
	&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 */
	0,                       /* number of code generator objects so far */
848
849
	NULL,                    /* 16bit register names */
	NULL,                    /* 8bit register names */
850
851
852
	arch_pentium_4,          /* instruction architecture */
	arch_pentium_4,          /* optimize for architecture */
	fp_sse2,                 /* use sse2 unit */
853
854
855
856
#ifndef NDEBUG
	NULL,                    /* name obstack */
	0                        /* name obst size */
#endif
857
858
};

Christian Würdig's avatar
Christian Würdig committed
859
/**
860
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
861
 */
Christian Würdig's avatar
Christian Würdig committed
862
static void *ia32_init(void) {
863
	static int inited = 0;
864
	ia32_isa_t *isa;
Christian Würdig's avatar
Christian Würdig committed
865
866
867
868

	if(inited)
		return NULL;

869
870
	isa = xcalloc(1, sizeof(*isa));
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
871

872
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
873
	ia32_create_opcodes();
874
	ia32_register_copy_attr_func();
Christian Würdig's avatar
Christian Würdig committed
875

876
877
878
879
880
881
	isa->regs_16bit = pmap_create();
	isa->regs_8bit  = pmap_create();

	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
882
883
884
#ifndef NDEBUG
	isa->name_obst = xcalloc(1, sizeof(*(isa->name_obst)));
	obstack_init(isa->name_obst);
Christian Würdig's avatar
Christian Würdig committed
885
	isa->name_obst_size = 0;
Christian Würdig's avatar
Christian Würdig committed
886
887
#endif /* NDEBUG */

888
889
	inited = 1;

Christian Würdig's avatar
Christian Würdig committed
890
	return isa;
Christian Würdig's avatar
Christian Würdig committed
891
892
}

Christian Würdig's avatar
Christian Würdig committed
893
894
895
896
897
898


/**
 * Closes the output file and frees the ISA structure.
 */
static void ia32_done(void *self) {
Christian Würdig's avatar
Christian Würdig committed
899
900
	ia32_isa_t *isa = self;

901
902
903
	pmap_destroy(isa->regs_16bit);
	pmap_destroy(isa->regs_8bit);

Christian Würdig's avatar
Christian Würdig committed
904
#ifndef NDEBUG
Christian Würdig's avatar
Christian Würdig committed
905
	//printf("name obst size = %d bytes\n", isa->name_obst_size);
Christian Würdig's avatar
Christian Würdig committed
906
907
908
	obstack_free(isa->name_obst, NULL);
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
909
	free(self);
Christian Würdig's avatar
Christian Würdig committed
910
911
}

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

913
914
915
916
917
918
919
/**
 * Return the number of register classes for this architecture.
 * We report always these:
 *  - the general purpose registers
 *  - the floating point register set (depending on the unit used for FP)
 *  - MMX/SE registers (currently not supported)
 */
Christian Würdig's avatar
Christian Würdig committed
920
static int ia32_get_n_reg_class(const void *self) {
921
	return 2;
Christian Würdig's avatar
Christian Würdig committed
922
923
}

924
925
926
/**
 * Return the register class for index i.
 */
Christian Würdig's avatar
Christian Würdig committed
927
static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
928
929
930
931
932
	const ia32_isa_t *isa = self;
	assert(i >= 0 && i < 2 && "Invalid ia32 register class requested.");
	if (i == 0)
		return &ia32_reg_classes[CLASS_ia32_gp];
	return USE_SSE2(isa) ? &ia32_reg_classes[CLASS_ia32_xmm] : &ia32_reg_classes[CLASS_ia32_vfp];
Christian Würdig's avatar
Christian Würdig committed
933
934
}

935
936
937
938
939
940
941
/**
 * Get the register class which shall be used to store a value of a given mode.
 * @param self The this pointer.
 * @param mode The mode in question.
 * @return A register class which can hold values of the given mode.
 */
const arch_register_class_t *ia32_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
942
943
944
945
	const ia32_isa_t *isa = self;
	if (mode_is_float(mode)) {
		return USE_SSE2(isa) ? &ia32_reg_classes[CLASS_ia32_xmm] : &ia32_reg_classes[CLASS_ia32_vfp];
	}
946
947
948
949
950
951
952
953
954
955
	else
		return &ia32_reg_classes[CLASS_ia32_gp];
}

/**
 * Get the ABI restrictions for procedure calls.
 * @param self        The this pointer.
 * @param method_type The type of the method (procedure) in question.
 * @param abi         The abi object to be modified
 */
956
957
static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
	const ia32_isa_t *isa = self;
958
959
960
961
962
963
	ir_type  *tp;
	ir_mode  *mode;
	unsigned  cc        = get_method_calling_convention(method_type);
	int       n         = get_method_n_params(method_type);
	int       biggest_n = -1;
	int       stack_idx = 0;
Christian Würdig's avatar
Christian Würdig committed
964
	int       i, ignore_1, ignore_2;
965
966
	ir_mode **modes;
	const arch_register_t *reg;
967
968
969
970
971
972
973
974
	be_abi_call_flags_t call_flags;

	/* set abi flags for calls */
	call_flags.bits.left_to_right         = 0;
	call_flags.bits.store_args_sequential = 0;
	call_flags.bits.try_omit_fp           = 1;
	call_flags.bits.fp_free               = 0;
	call_flags.bits.call_has_imm          = 1;
975
976

	/* set stack parameter passing style */
Sebastian Hack's avatar
Sebastian Hack committed
977
	be_abi_call_set_flags(abi, call_flags, &ia32_abi_callbacks);
978
979
980
981
982
983
984
985
986
987

	/* collect the mode for each type */
	modes = alloca(n * sizeof(modes[0]));

	for (i = 0; i < n; i++) {
		tp       = get_method_param_type(method_type, i);
		modes[i] = get_type_mode(tp);
	}

	/* set register parameters  */
988
	if (cc & cc_reg_param) {
989
		/* determine the number of parameters passed via registers */
Christian Würdig's avatar
Christian Würdig committed
990
		biggest_n = ia32_get_n_regparam_class(n, modes, &ignore_1, &ignore_2);
991
992
993
994
995
996
997
998
999
1000

		/* loop over all parameters and set the register requirements */
		for (i = 0; i <= biggest_n; i++) {
			reg = ia32_get_RegParam_reg(n, modes, i, cc);
			assert(reg && "kaputt");
			be_abi_call_param_reg(abi, i, reg);
		}

		stack_idx = i;
	}
For faster browsing, not all history is shown. View entire blame