bearch_ia32.c 29.4 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

Christian Würdig's avatar
Christian Würdig committed
11
12
13
14
15
16
#ifdef _WIN32
#include <malloc.h>
#else
#include <alloca.h>
#endif

Christian Würdig's avatar
Christian Würdig committed
17
18
#include "pseudo_irg.h"
#include "irgwalk.h"
Christian Würdig's avatar
Christian Würdig committed
19
20
#include "irprog.h"
#include "irprintf.h"
21
#include "iredges_t.h"
22
#include "ircons.h"
Christian Würdig's avatar
Christian Würdig committed
23
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
24
#include "irgopt.h"
Christian Würdig's avatar
Christian Würdig committed
25
26
27
28

#include "bitset.h"
#include "debug.h"

29
#include "../beabi.h"                 /* the general register allocator interface */
30
#include "../benode_t.h"
31
#include "../belower.h"
Christian Würdig's avatar
Christian Würdig committed
32
#include "../besched_t.h"
Christian Würdig's avatar
Christian Würdig committed
33
#include "../be.h"
34
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
35
36
37
38
39

#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
40
41
#include "ia32_emitter.h"
#include "ia32_map_regs.h"
Christian Würdig's avatar
Christian Würdig committed
42
#include "ia32_optimize.h"
43
#include "ia32_x87.h"
Christian Würdig's avatar
Christian Würdig committed
44

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

Christian Würdig's avatar
Christian Würdig committed
47
48
/* TODO: ugly */
static set *cur_reg_set = NULL;
Christian Würdig's avatar
Christian Würdig committed
49

Christian Würdig's avatar
Christian Würdig committed
50
51
#undef is_Start
#define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
Christian Würdig's avatar
Christian Würdig committed
52

53
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
54
	return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_GP_NOREG]);
55
56
57
}

ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
58
59
	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]);
60
}
61

Christian Würdig's avatar
Christian Würdig committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**************************************************
 *                         _ _              _  __
 *                        | | |            (_)/ _|
 *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
 * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
 * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
 * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
 *            __/ |
 *           |___/
 **************************************************/

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
78

Sebastian Hack's avatar
Sebastian Hack committed
79

Christian Würdig's avatar
Christian Würdig committed
80
81
82
83
84
/**
 * 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
85
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) {
86
	const ia32_irn_ops_t      *ops = self;
87
88
	const ia32_register_req_t *irn_req;
	long                       node_pos = pos == -1 ? 0 : pos;
89
	ir_mode                   *mode     = is_Block(irn) ? NULL : get_irn_mode(irn);
90
	FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
Christian Würdig's avatar
Christian Würdig committed
91

92
93
94
95
96
97
98
	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
99
100
101
102
103
		return NULL;
	}

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

104
	if (is_Proj(irn)) {
105
		if (pos == -1) {
106
			node_pos = ia32_translate_proj_pos(irn);
107
108
		}
		else {
Christian Würdig's avatar
Christian Würdig committed
109
			node_pos = pos;
110
		}
Christian Würdig's avatar
Christian Würdig committed
111
112
113

		irn = my_skip_proj(irn);

Christian Würdig's avatar
Christian Würdig committed
114
		DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
Christian Würdig's avatar
Christian Würdig committed
115
116
117
118
	}

	if (is_ia32_irn(irn)) {
		if (pos >= 0) {
119
			irn_req = get_ia32_in_req(irn, pos);
Christian Würdig's avatar
Christian Würdig committed
120
121
		}
		else {
122
			irn_req = get_ia32_out_req(irn, node_pos);
Christian Würdig's avatar
Christian Würdig committed
123
124
		}

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

127
128
		memcpy(req, &(irn_req->req), sizeof(*req));

129
130
131
132
133
134
135
136
		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);
137
		}
Christian Würdig's avatar
Christian Würdig committed
138
139
140
141
	}
	else {
		/* treat Phi like Const with default requirements */
		if (is_Phi(irn)) {
Christian Würdig's avatar
Christian Würdig committed
142
			DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
143
144
145
146
147
148
			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
149
			else if (mode_is_int(mode) || mode_is_reference(mode))
150
				memcpy(req, &(ia32_default_req_ia32_gp.req), sizeof(*req));
Christian Würdig's avatar
Christian Würdig committed
151
152
153
154
155
156
157
158
			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
159
			DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
160
			req = NULL;
Christian Würdig's avatar
Christian Würdig committed
161
162
163
164
165
		}
	}

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

Christian Würdig's avatar
Christian Würdig committed
167
static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
168
169
170
	int                   pos = 0;
	const ia32_irn_ops_t *ops = self;

171
172
173
174
	if (get_irn_mode(irn) == mode_X) {
		return;
	}

175
	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
176

177
	if (is_Proj(irn)) {
178
		pos = ia32_translate_proj_pos(irn);
Christian Würdig's avatar
Christian Würdig committed
179
180
		irn = my_skip_proj(irn);
	}
Christian Würdig's avatar
Christian Würdig committed
181

Christian Würdig's avatar
Christian Würdig committed
182
183
	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
Christian Würdig's avatar
Christian Würdig committed
184

Christian Würdig's avatar
Christian Würdig committed
185
186
187
188
		slots      = get_ia32_slots(irn);
		slots[pos] = reg;
	}
	else {
189
		ia32_set_firm_reg(irn, reg, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
190
	}
Christian Würdig's avatar
Christian Würdig committed
191
192
}

Christian Würdig's avatar
Christian Würdig committed
193
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
194
195
196
	int pos = 0;
	const arch_register_t *reg = NULL;

197
	if (is_Proj(irn)) {
198
199
200
201
202

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

203
		pos = ia32_translate_proj_pos(irn);
Christian Würdig's avatar
Christian Würdig committed
204
205
206
207
208
209
210
211
212
		irn = my_skip_proj(irn);
	}

	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
		slots = get_ia32_slots(irn);
		reg   = slots[pos];
	}
	else {
213
		reg = ia32_get_firm_reg(irn, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
214
215
216
	}

	return reg;
Christian Würdig's avatar
Christian Würdig committed
217
218
}

Christian Würdig's avatar
Christian Würdig committed
219
static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
220
221
222
	irn = my_skip_proj(irn);
	if (is_cfop(irn))
		return arch_irn_class_branch;
Christian Würdig's avatar
Christian Würdig committed
223
	else if (is_ia32_irn(irn))
Christian Würdig's avatar
Christian Würdig committed
224
		return arch_irn_class_normal;
Christian Würdig's avatar
Christian Würdig committed
225
226
	else
		return 0;
Christian Würdig's avatar
Christian Würdig committed
227
}
Christian Würdig's avatar
Christian Würdig committed
228

Christian Würdig's avatar
Christian Würdig committed
229
static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
230
231
232
233
234
235
	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
236
237
}

Christian Würdig's avatar
Christian Würdig committed
238
239
static entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
240
241
}

242
static void ia32_set_stack_bias(const void *self, ir_node *irn, int bias) {
Christian Würdig's avatar
Christian Würdig committed
243
244
245
	char buf[64];
	const ia32_irn_ops_t *ops = self;

Christian Würdig's avatar
Christian Würdig committed
246
	if (get_ia32_frame_ent(irn) && bias != 0) {
Christian Würdig's avatar
Christian Würdig committed
247
248
249
250
251
252
253
		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);
		add_ia32_am_offs(irn, buf);
		am_flav |= ia32_O;
		set_ia32_am_flavour(irn, am_flav);
254
255
256
	}
}

Sebastian Hack's avatar
Sebastian Hack committed
257
258
259
260
261
262
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
263
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
264
265
266
267
268
{
	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
269
	env->isa   = aenv->isa;
Sebastian Hack's avatar
Sebastian Hack committed
270
271
272
273
274
275
276
277
278
279
	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
280
static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
Sebastian Hack's avatar
Sebastian Hack committed
281
{
Sebastian Hack's avatar
Sebastian Hack committed
282
283
284
285
286
287
288
289
	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);
290
		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
291
292
		ir_node *store_bp;

293
		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
294
		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
295
296
297
		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
298
299
300
301
302
303
304
305
306
307
		*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
308
309
310
311
}

static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
{
Sebastian Hack's avatar
Sebastian Hack committed
312
313
314
	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);
315
	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
316
317

	if(env->flags.try_omit_fp) {
318
		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
319
320
321
322
323
324
325
326
	}

	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
327
328
329
		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
330
331
332
333
334
335
336
		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
337
338
339
340
341
342
343
344
345
346
347
348
349
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
}

/**
 * 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
386
387
/* fill register allocator interface */

Christian Würdig's avatar
Christian Würdig committed
388
static const arch_irn_ops_if_t ia32_irn_ops_if = {
Christian Würdig's avatar
Christian Würdig committed
389
390
391
392
	ia32_get_irn_reg_req,
	ia32_set_irn_reg,
	ia32_get_irn_reg,
	ia32_classify,
393
	ia32_get_flags,
394
	ia32_get_frame_entity,
395
	ia32_set_stack_bias
Christian Würdig's avatar
Christian Würdig committed
396
397
};

Christian Würdig's avatar
Christian Würdig committed
398
399
400
401
402
ia32_irn_ops_t ia32_irn_ops = {
	&ia32_irn_ops_if,
	NULL
};

Christian Würdig's avatar
Christian Würdig committed
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420


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

/**
 * 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
421
	ia32_code_gen_t *cg = self;
Christian Würdig's avatar
Christian Würdig committed
422
	firm_dbg_module_t *old_mod = cg->mod;
423

424
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
Christian Würdig's avatar
Christian Würdig committed
425
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
Christian Würdig's avatar
Christian Würdig committed
426
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
427
428

	cg->mod = old_mod;
429
430

	if (cg->opt.doam) {
431
432
433
434
		edges_deactivate(cg->irg);
		//dead_node_elimination(cg->irg);
		edges_activate(cg->irg);

435
		irg_walk_blkwise_graph(cg->irg, NULL, ia32_optimize_am, cg);
Christian Würdig's avatar
Christian Würdig committed
436
		be_dump(cg->irg, "-am", dump_ir_block_graph_sched);
437
	}
Christian Würdig's avatar
Christian Würdig committed
438
439
}

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

Christian Würdig's avatar
Christian Würdig committed
441
442
443
/**
 * Insert copies for all ia32 nodes where the should_be_same requirement
 * is not fulfilled.
Christian Würdig's avatar
Christian Würdig committed
444
 * Transform Sub into Neg -- Add if IN2 == OUT
Christian Würdig's avatar
Christian Würdig committed
445
446
447
448
449
450
451
 */
static void ia32_finish_irg_walker(ir_node *irn, void *env) {
	ia32_code_gen_t            *cg = env;
	const ia32_register_req_t **reqs;
	const arch_register_t      *out_reg, *in_reg;
	int                         n_res, i;
	ir_node                    *copy, *in_node, *block;
Christian Würdig's avatar
Christian Würdig committed
452
	ia32_op_type_t              op_tp;
Christian Würdig's avatar
Christian Würdig committed
453
454
455
456

	if (! is_ia32_irn(irn))
		return;

457
458
459
	/* AM Dest nodes don't produce any values  */
	op_tp = get_ia32_op_type(irn);
	if (op_tp == ia32_AddrModeD)
Christian Würdig's avatar
Christian Würdig committed
460
461
		return;

Christian Würdig's avatar
Christian Würdig committed
462
463
464
465
466
	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 */
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
	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 */
				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);

				/* don't copy ignore nodes */
				if (arch_irn_is(cg->arch_env, in_node, ignore))
					continue;

				/* check if in and out register are equal */
				if (arch_register_get_index(out_reg) != arch_register_get_index(in_reg)) {
					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);
				}
Christian Würdig's avatar
Christian Würdig committed
495
496
497
			}
		}
	}
Christian Würdig's avatar
Christian Würdig committed
498

Christian Würdig's avatar
Christian Würdig committed
499
500
501
502
503
504
505
506
507
508
	/* 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
509
510
	/* check if there is a sub which need to be transformed */
	ia32_transform_sub_to_neg_add(irn, cg);
511
512
513

	/* transform a LEA into an Add if possible */
	ia32_transform_lea_to_add(irn, cg);
514
515
516

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

/**
Christian Würdig's avatar
Christian Würdig committed
520
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
521
 */
Christian Würdig's avatar
Christian Würdig committed
522
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
Christian Würdig's avatar
Christian Würdig committed
523
	irg_walk_blkwise_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
524
525
}

526
527


528
/**
529
 * Dummy functions for hooks we don't need but which must be filled.
530
 */
531
static void ia32_before_sched(void *self) {
532
533
}

534
535
536
537
538
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
539
static void ia32_before_ra(void *self) {
540
	ia32_code_gen_t *cg = self;
541

542
543
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
544

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

Christian Würdig's avatar
Christian Würdig committed
546
547
548
549
/**
 * 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
550
551
552
553
554
	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
555
	ir_node *sched_point = NULL;
Christian Würdig's avatar
Christian Würdig committed
556
557
558
	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;
559
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
560
561
562
563
564
565

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

	if (mode_is_float(mode)) {
566
567
568
569
		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
570
571
	}
	else {
Christian Würdig's avatar
Christian Würdig committed
572
		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
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
	}

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

591
592
	/* 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
593
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
594

Christian Würdig's avatar
Christian Würdig committed
595
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env));
Christian Würdig's avatar
Christian Würdig committed
596

Christian Würdig's avatar
Christian Würdig committed
597
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
}

/**
 * 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)) {
619
620
621
622
		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
623
	}
624
625
626
	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
627
628
629
630
631
632
633
	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
634
	set_ia32_ls_mode(new_op, mode);
Christian Würdig's avatar
Christian Würdig committed
635
636
637
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

638
	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, 0);
Christian Würdig's avatar
Christian Würdig committed
639
640
641
642
643
644
645
646

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

Christian Würdig's avatar
Christian Würdig committed
649
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
}

/**
 * Calls the transform functions for StackParam, Spill and Reload.
 */
static void ia32_after_ra_walker(ir_node *node, void *env) {
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

	if (is_Block(node))
		return;

	tenv.block = get_nodes_block(node);
	tenv.dbg   = get_irn_dbg_info(node);
	tenv.irg   = current_ir_graph;
	tenv.irn   = node;
	tenv.mod   = cg->mod;
	tenv.mode  = get_irn_mode(node);
	tenv.cg    = cg;

Christian Würdig's avatar
Christian Würdig committed
670
671
	/* be_is_StackParam(node) || */
	if (be_is_Reload(node)) {
Christian Würdig's avatar
Christian Würdig committed
672
673
674
		transform_to_Load(&tenv);
	}
	else if (be_is_Spill(node)) {
Christian Würdig's avatar
Christian Würdig committed
675
676
		/* we always spill the whole register  */
		tenv.mode = mode_is_float(get_irn_mode(be_get_Spill_context(node))) ? mode_D : mode_Is;
Christian Würdig's avatar
Christian Würdig committed
677
678
679
680
681
682
683
684
685
686
687
		transform_to_Store(&tenv);
	}
}

/**
 * We transform StackParam, Spill and Reload here. This needs to be done before
 * stack biasing otherwise we would miss the corrected offset for these nodes.
 */
static void ia32_after_ra(void *self) {
	ia32_code_gen_t *cg = self;
	irg_walk_blkwise_graph(cg->irg, NULL, ia32_after_ra_walker, self);
688
689

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
690
	if (cg->used_x87) {
691
692
693
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
		be_dump(cg->irg, "-x87", dump_ir_extblock_graph_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
694
695
696
}


Christian Würdig's avatar
Christian Würdig committed
697
698
699
700
701
702
/**
 * 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
703
704
	ir_graph        *irg = cg->irg;
	FILE            *out = cg->out;
Christian Würdig's avatar
Christian Würdig committed
705
706
707
708
709
710

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

Christian Würdig's avatar
Christian Würdig committed
711
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
712
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
713
	ia32_gen_routine(out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
714
715
716

	cur_reg_set = NULL;

717
718
719
	pmap_destroy(cg->tv_ent);
	pmap_destroy(cg->types);

Christian Würdig's avatar
Christian Würdig committed
720
721
722
723
724
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
}

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

Christian Würdig's avatar
Christian Würdig committed
727
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
728
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
729
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
730
	ia32_prepare_graph,
731
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
732
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
733
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
734
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
735
736
};

Christian Würdig's avatar
Christian Würdig committed
737
738
739
/**
 * Initializes the code generator.
 */
Christian Würdig's avatar
Christian Würdig committed
740
741
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;
742
743
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

744
745
746
747
748
749
750
751
752
753
	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;
754
755
	cg->used_x87  = 0;

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

758
759
	/* set optimizations */
	cg->opt.incdec    = 0;
760
	cg->opt.doam      = 1;
761
762
	cg->opt.placecnst = 1;
	cg->opt.immops    = 1;
763
	cg->opt.extbb     = 1;
764

Christian Würdig's avatar
Christian Würdig committed
765
766
767
768
769
770
771
772
773
#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
774
775
776
777
778
779
780
781
782
	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
783
784
	ia32_irn_ops.cg = cg;

Christian Würdig's avatar
Christian Würdig committed
785
786
787
	return (arch_code_generator_t *)cg;
}

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

Christian Würdig's avatar
Christian Würdig committed
789
790
791
792
793
794
795
796
797
798
799

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

800
static ia32_isa_t ia32_isa_template = {
Christian Würdig's avatar
Christian Würdig committed
801
802
803
804
805
	&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 */
806
807
	NULL,                    /* 16bit register names */
	NULL,                    /* 8bit register names */
808
	fp_sse2,                 /* use SSE2 unit for fp operations */
809
810
811
812
#ifndef NDEBUG
	NULL,                    /* name obstack */
	0                        /* name obst size */
#endif
813
814
};

Christian Würdig's avatar
Christian Würdig committed
815
/**
816
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
817
 */
Christian Würdig's avatar
Christian Würdig committed
818
static void *ia32_init(void) {
819
	static int inited = 0;
820
	ia32_isa_t *isa;
Christian Würdig's avatar
Christian Würdig committed
821
822
823
824

	if(inited)
		return NULL;

825
826
	isa = xcalloc(1, sizeof(*isa));
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
827

828
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
829
	ia32_create_opcodes();
830
	ia32_register_copy_attr_func();
Christian Würdig's avatar
Christian Würdig committed
831

832
833
	isa->regs_16bit = pmap_create();
	isa->regs_8bit  = pmap_create();
834
//	isa->fp_kind    = fp_x87;
835
836
837
838

	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
839
840
841
#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
842
	isa->name_obst_size = 0;
Christian Würdig's avatar
Christian Würdig committed
843
844
#endif /* NDEBUG */

845
846
	inited = 1;

Christian Würdig's avatar
Christian Würdig committed
847
	return isa;
Christian Würdig's avatar
Christian Würdig committed
848
849
}

Christian Würdig's avatar
Christian Würdig committed
850
851
852
853
854
855


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

858
859
860
	pmap_destroy(isa->regs_16bit);
	pmap_destroy(isa->regs_8bit);

Christian Würdig's avatar
Christian Würdig committed
861
#ifndef NDEBUG
Christian Würdig's avatar
Christian Würdig committed
862
	//printf("name obst size = %d bytes\n", isa->name_obst_size);
Christian Würdig's avatar
Christian Würdig committed
863
864
865
	obstack_free(isa->name_obst, NULL);
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
866
	free(self);
Christian Würdig's avatar
Christian Würdig committed
867
868
}

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

870
871
872
873
874
875
876
/**
 * 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
877
static int ia32_get_n_reg_class(const void *self) {
878
	return 2;
Christian Würdig's avatar
Christian Würdig committed
879
880
}

881
882
883
/**
 * Return the register class for index i.
 */
Christian Würdig's avatar
Christian Würdig committed
884
static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
885
886
887
888
889
	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
890
891
}

892
893
894
895
896
897
898
/**
 * 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) {
899
900
901
902
	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];
	}
903
904
905
906
907
908
909
910
911
912
	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
 */
913
914
static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
	const ia32_isa_t *isa = self;
915
916
917
918
919
920
	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
921
	int       i, ignore_1, ignore_2;
922
923
	ir_mode **modes;
	const arch_register_t *reg;
924
925
926
927
928
929
930
931
	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;
932
933

	/* set stack parameter passing style */
Sebastian Hack's avatar
Sebastian Hack committed
934
	be_abi_call_set_flags(abi, call_flags, &ia32_abi_callbacks);
935
936
937
938
939
940
941
942
943
944

	/* 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  */
945
	if (cc & cc_reg_param) {
946
		/* determine the number of parameters passed via registers */
Christian Würdig's avatar
Christian Würdig committed
947
		biggest_n = ia32_get_n_regparam_class(n, modes, &ignore_1, &ignore_2);
948
949
950
951
952
953
954
955
956
957
958
959
960
961

		/* 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;
	}


	/* set stack parameters */
	for (i = stack_idx; i < n; i++) {
962
		be_abi_call_param_stack(abi, i, 1, 0, 0);
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
	}


	/* set return registers */
	n = get_method_n_ress(method_type);

	assert(n <= 2 && "more than two results not supported");

	/* In case of 64bit returns, we will have two 32bit values */
	if (n == 2) {
		tp   = get_method_res_type(method_type, 0);
		mode = get_type_mode(tp);

		assert(!mode_is_float(mode) && "two FP results not supported");

		tp   = get_method_res_type(method_type, 1);
		mode = get_type_mode(tp);

		assert(!mode_is_float(mode) && "two FP results not supported");

		be_abi_call_res_reg(abi, 0, &ia32_gp_regs[REG_EAX]);
		be_abi_call_res_reg(abi, 1, &ia32_gp_regs[REG_EDX]);
	}
	else if (n == 1) {
987
988
		const arch_register_t *reg;

989
		tp   = get_method_res_type(method_type, 0);
Sebastian Hack's avatar
Sebastian Hack committed
990
		assert(is_atomic_type(tp));
991
992
		mode = get_type_mode(tp);

993
994
995
996
997
		reg = mode_is_float(mode) ?
			(USE_SSE2(isa) ? &ia32_xmm_regs[REG_XMM0] : &ia32_vfp_regs[REG_VF0]) :
			&ia32_gp_regs[REG_EAX];

		be_abi_call_res_reg(abi, 0, reg);
998
999
1000
	}
}

For faster browsing, not all history is shown. View entire blame