bearch_ia32.c 34.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
/* Creates the unique per irg GP NoReg node. */
61
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
62
	return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_GP_NOREG]);
63
64
}

65
/* Creates the unique per irg FP NoReg node. */
66
ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
67
68
	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]);
69
}
70

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

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
87

Sebastian Hack's avatar
Sebastian Hack committed
88

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

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

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

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

		irn = my_skip_proj(irn);

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

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

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

136
137
		memcpy(req, &(irn_req->req), sizeof(*req));

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

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

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

180
181
182
183
	if (get_irn_mode(irn) == mode_X) {
		return;
	}

184
	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
185

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

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

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

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

206
	if (is_Proj(irn)) {
207
208
209
210
211

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

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

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

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

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

Christian Würdig's avatar
Christian Würdig committed
238
static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
239
240
241
242
243
244
	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
245
246
}

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

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

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

		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);
		}
269
270
271
	}
}

Sebastian Hack's avatar
Sebastian Hack committed
272
273
274
typedef struct {
	be_abi_call_flags_bits_t flags;
	const arch_isa_t *isa;
275
	const arch_env_t *aenv;
Sebastian Hack's avatar
Sebastian Hack committed
276
277
278
	ir_graph *irg;
} ia32_abi_env_t;

Sebastian Hack's avatar
Sebastian Hack committed
279
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
280
281
282
283
284
{
	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;
285
	env->aenv  = aenv;
Sebastian Hack's avatar
Sebastian Hack committed
286
	env->isa   = aenv->isa;
Sebastian Hack's avatar
Sebastian Hack committed
287
288
289
290
291
292
293
294
295
296
	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);
}

297
298
299
300
301
302
303
304
305
/**
 * Generate the prologue.
 * @param self    The callback object.
 * @param mem     A pointer to the mem node. Update this if you define new memory.
 * @param reg_map A mapping 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
306
static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
Sebastian Hack's avatar
Sebastian Hack committed
307
{
Sebastian Hack's avatar
Sebastian Hack committed
308
309
	ia32_abi_env_t *env              = self;

310
	if (!env->flags.try_omit_fp) {
Sebastian Hack's avatar
Sebastian Hack committed
311
312
313
314
		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);
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
		ir_node *store_bp;

318
		/* push ebp */
319
		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
320
		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
321
322
323
		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);
324
		set_ia32_ls_mode(store_bp, env->isa->bp->reg_class->mode);
Sebastian Hack's avatar
Sebastian Hack committed
325
		*mem     = new_r_Proj(env->irg, bl, store_bp, mode_M, 0);
326
327

		/* move esp to ebp */
Sebastian Hack's avatar
Sebastian Hack committed
328
329
		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);
330
331
		arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
		be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_dont_spill);
Sebastian Hack's avatar
Sebastian Hack committed
332
333
334

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

		return env->isa->bp;
Sebastian Hack's avatar
Sebastian Hack committed
337
338
	}

339
	return env->isa->sp;
Sebastian Hack's avatar
Sebastian Hack committed
340
341
342
343
}

static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
{
344
	ia32_abi_env_t *env  = self;
Sebastian Hack's avatar
Sebastian Hack committed
345
346
	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);
347
	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
348

349
350
	if (env->flags.try_omit_fp) {
		/* simply remove the stack frame here */
351
		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
352
353
354
355
356
	}

	else {
		ir_node *load_bp;
		ir_mode *mode_bp = env->isa->bp->reg_class->mode;
357
		int reg_size     = get_mode_size_bytes(env->isa->bp->reg_class->mode);
Sebastian Hack's avatar
Sebastian Hack committed
358

359
		/* copy ebp to esp */
Sebastian Hack's avatar
Sebastian Hack committed
360
		curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
361
362

		/* pop ebp */
Sebastian Hack's avatar
Sebastian Hack committed
363
		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
364
365
366
		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
367
368
369
		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);
370
371
372
		arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);

		curr_sp  = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, *mem, reg_size, be_stack_dir_shrink);
Sebastian Hack's avatar
Sebastian Hack committed
373
374
375
376
	}

	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
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
}

/**
 * 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
426
427
/* fill register allocator interface */

Christian Würdig's avatar
Christian Würdig committed
428
static const arch_irn_ops_if_t ia32_irn_ops_if = {
Christian Würdig's avatar
Christian Würdig committed
429
430
431
432
	ia32_get_irn_reg_req,
	ia32_set_irn_reg,
	ia32_get_irn_reg,
	ia32_classify,
433
	ia32_get_flags,
434
	ia32_get_frame_entity,
435
	ia32_set_stack_bias
Christian Würdig's avatar
Christian Würdig committed
436
437
};

Christian Würdig's avatar
Christian Würdig committed
438
439
440
441
442
ia32_irn_ops_t ia32_irn_ops = {
	&ia32_irn_ops_if,
	NULL
};

Christian Würdig's avatar
Christian Würdig committed
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460


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

/**
 * 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
461
	ia32_code_gen_t *cg = self;
462
	DEBUG_ONLY(firm_dbg_module_t *old_mod = cg->mod;)
463

464
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
Christian Würdig's avatar
Christian Würdig committed
465
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
Christian Würdig's avatar
Christian Würdig committed
466
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
467

468
	DEBUG_ONLY(cg->mod = old_mod;)
469
470

	if (cg->opt.doam) {
471
472
473
474
		edges_deactivate(cg->irg);
		//dead_node_elimination(cg->irg);
		edges_activate(cg->irg);

475
		irg_walk_blkwise_graph(cg->irg, NULL, ia32_optimize_am, cg);
Christian Würdig's avatar
Christian Würdig committed
476
		be_dump(cg->irg, "-am", dump_ir_block_graph_sched);
477
	}
Christian Würdig's avatar
Christian Würdig committed
478
479
}

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

Christian Würdig's avatar
Christian Würdig committed
481
482
483
/**
 * Insert copies for all ia32 nodes where the should_be_same requirement
 * is not fulfilled.
Christian Würdig's avatar
Christian Würdig committed
484
 * Transform Sub into Neg -- Add if IN2 == OUT
Christian Würdig's avatar
Christian Würdig committed
485
486
487
488
 */
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
489
	const arch_register_t      *out_reg, *in_reg, *in2_reg;
Christian Würdig's avatar
Christian Würdig committed
490
	int                         n_res, i;
Christian Würdig's avatar
Christian Würdig committed
491
	ir_node                    *copy, *in_node, *block, *in2_node;
Christian Würdig's avatar
Christian Würdig committed
492
	ia32_op_type_t              op_tp;
Christian Würdig's avatar
Christian Würdig committed
493

494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
	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
509
510
511
512
513
					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);
514
515

					/* don't copy ignore nodes */
Christian Würdig's avatar
Christian Würdig committed
516
					if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
517
518
519
						continue;

					/* check if in and out register are equal */
Christian Würdig's avatar
Christian Würdig committed
520
521
					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
522
523
524
						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
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
						}
						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);
						}
540
					}
541
				}
Christian Würdig's avatar
Christian Würdig committed
542
543
			}
		}
Christian Würdig's avatar
Christian Würdig committed
544

545
546
547
548
549
550
551
552
553
		/* 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
554

555
556
		/* check if there is a sub which need to be transformed */
		ia32_transform_sub_to_neg_add(irn, cg);
557

558
559
560
		/* transform a LEA into an Add if possible */
		ia32_transform_lea_to_add(irn, cg);
	}
561
562
563

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

/**
Christian Würdig's avatar
Christian Würdig committed
567
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
568
 */
Christian Würdig's avatar
Christian Würdig committed
569
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
Christian Würdig's avatar
Christian Würdig committed
570
	irg_walk_blkwise_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
571
572
}

573
574


575
/**
576
 * Dummy functions for hooks we don't need but which must be filled.
577
 */
578
static void ia32_before_sched(void *self) {
579
580
}

581
582
583
584
585
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
586
static void ia32_before_ra(void *self) {
587
	ia32_code_gen_t *cg = self;
588

589
590
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
591

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

Christian Würdig's avatar
Christian Würdig committed
593
594
595
596
/**
 * 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
597
598
599
600
601
	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
602
	ir_node *sched_point = NULL;
Christian Würdig's avatar
Christian Würdig committed
603
604
605
	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;
606
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
607
608
609
610
611
612

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

	if (mode_is_float(mode)) {
613
614
615
616
		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
617
618
	}
	else {
Christian Würdig's avatar
Christian Würdig committed
619
		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
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
	}

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

638
639
	/* 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
640
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
641

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

Christian Würdig's avatar
Christian Würdig committed
644
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
}

/**
 * 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)) {
666
667
668
669
		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
670
	}
671
672
673
	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
674
675
676
677
678
679
680
	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
681
	set_ia32_ls_mode(new_op, mode);
Christian Würdig's avatar
Christian Würdig committed
682
683
684
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

685
	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, 0);
Christian Würdig's avatar
Christian Würdig committed
686
687
688
689
690
691
692
693

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

Christian Würdig's avatar
Christian Würdig committed
696
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
697
698
699
}

/**
700
 * Fix the mode of Spill/Reload
Christian Würdig's avatar
Christian Würdig committed
701
 */
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
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
720
721
722
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

723
	tenv.block = block;
Christian Würdig's avatar
Christian Würdig committed
724
725
	tenv.irg   = current_ir_graph;
	tenv.cg    = cg;
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
	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
745
746
747
748
	}
}

/**
749
 * We transform Spill and Reload here. This needs to be done before
Christian Würdig's avatar
Christian Würdig committed
750
 * stack biasing otherwise we would miss the corrected offset for these nodes.
751
752
753
 *
 * 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
754
755
756
 */
static void ia32_after_ra(void *self) {
	ia32_code_gen_t *cg = self;
757
	irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
758
759

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
760
	if (cg->used_fp == fp_x87) {
761
762
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
763
764
765
}


Christian Würdig's avatar
Christian Würdig committed
766
767
768
769
770
771
/**
 * 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
772
	ir_graph        *irg = cg->irg;
Christian Würdig's avatar
Christian Würdig committed
773

Christian Würdig's avatar
Christian Würdig committed
774
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
775
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
776
	ia32_gen_routine(cg->isa->out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
777
778
779

	cur_reg_set = NULL;

780
781
	/* remove it from the isa */
	cg->isa->cg = NULL;
782

Christian Würdig's avatar
Christian Würdig committed
783
784
785
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
786

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

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

Christian Würdig's avatar
Christian Würdig committed
791
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
792
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
793
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
794
	ia32_prepare_graph,
795
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
796
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
797
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
798
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
799
800
};

Christian Würdig's avatar
Christian Würdig committed
801
/**
802
 * Initializes a IA32 code generator.
Christian Würdig's avatar
Christian Würdig committed
803
 */
804
static void *ia32_cg_init(const be_irg_t *birg) {
Christian Würdig's avatar
Christian Würdig committed
805
	ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
806
807
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

808
809
810
811
	cg->impl      = &ia32_code_gen_if;
	cg->irg       = birg->irg;
	cg->reg_set   = new_set(ia32_cmp_irn_reg_assoc, 1024);
	cg->arch_env  = birg->main_env->arch_env;
812
	cg->isa       = isa;
813
814
815
	cg->birg      = birg;
	cg->blk_sched = NULL;
	cg->fp_kind   = isa->fp_kind;
816
	cg->used_fp   = fp_none;
817

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

820
821
	/* set optimizations */
	cg->opt.incdec    = 0;
Christian Würdig's avatar
Christian Würdig committed
822
	cg->opt.doam      = 1;
823
824
	cg->opt.placecnst = 1;
	cg->opt.immops    = 1;
825
	cg->opt.extbb     = 1;
826

827
828
829
	/* enter it */
	isa->cg = cg;

Christian Würdig's avatar
Christian Würdig committed
830
831
832
833
834
835
836
837
838
#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
839
840
841
842
843
844
845
846
847
	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
848
849
	ia32_irn_ops.cg = cg;

Christian Würdig's avatar
Christian Würdig committed
850
851
852
	return (arch_code_generator_t *)cg;
}

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

Christian Würdig's avatar
Christian Würdig committed
854
855
856
857
858
859
860
861
862
863
864

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

865
866
867
868
869
/**
 * The template that generates a new ISA object.
 * Note that this template can be changed by command line
 * arguments.
 */
870
static ia32_isa_t ia32_isa_template = {
Christian Würdig's avatar
Christian Würdig committed
871
872
873
874
875
	&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 */
876
877
	NULL,                    /* 16bit register names */
	NULL,                    /* 8bit register names */
878
879
	NULL,                    /* types */
	NULL,                    /* tv_ents */
880
881
882
	arch_pentium_4,          /* instruction architecture */
	arch_pentium_4,          /* optimize for architecture */
	fp_sse2,                 /* use sse2 unit */
883
	NULL,                    /* current code generator */
884
885
886
887
#ifndef NDEBUG
	NULL,                    /* name obstack */
	0                        /* name obst size */
#endif
888
889
};

Christian Würdig's avatar
Christian Würdig committed
890
/**
891
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
892
 */
893
static void *ia32_init(FILE *file_handle) {
894
	static int inited = 0;
895
	ia32_isa_t *isa;
Christian Würdig's avatar
Christian Würdig committed
896

897
	if (inited)
Christian Würdig's avatar
Christian Würdig committed
898
899
		return NULL;

900
	isa = xmalloc(sizeof(*isa));
901
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
902

903
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
904
	ia32_create_opcodes();
905
	ia32_register_copy_attr_func();
Christian Würdig's avatar
Christian Würdig committed
906

907
908
	isa->regs_16bit = pmap_create();
	isa->regs_8bit  = pmap_create();
909
910
911
	isa->types      = pmap_create();
	isa->tv_ent     = pmap_create();
	isa->out        = file_handle;
912
913
914
915

	ia32_build_16bit_reg_map(isa->regs_16bit);
	ia32_build_8bit_reg_map(isa->regs_8bit);

916
917
918
919
920
921
922
923
924
925
926
927
	/* patch regigter names of x87 registers */
	if (USE_x87(isa)) {
	  ia32_st_regs[0].name = "st";
	  ia32_st_regs[1].name = "st(1)";
	  ia32_st_regs[2].name = "st(2)";
	  ia32_st_regs[3].name = "st(3)";
	  ia32_st_regs[4].name = "st(4)";
	  ia32_st_regs[5].name = "st(5)";
	  ia32_st_regs[6].name = "st(6)";
	  ia32_st_regs[7].name = "st(7)";
	}

Christian Würdig's avatar
Christian Würdig committed
928
#ifndef NDEBUG
929
	isa->name_obst = xmalloc(sizeof(*isa->name_obst));
Christian Würdig's avatar
Christian Würdig committed
930
	obstack_init(isa->name_obst);
Christian Würdig's avatar
Christian Würdig committed
931
	isa->name_obst_size = 0;
Christian Würdig's avatar
Christian Würdig committed
932
933
#endif /* NDEBUG */

934
935
  fprintf(isa->out, "\t.intel_syntax\n");

936
937
	inited = 1;

Christian Würdig's avatar
Christian Würdig committed
938
	return isa;
Christian Würdig's avatar
Christian Würdig committed
939
940
}

Christian Würdig's avatar
Christian Würdig committed
941
942
943
944
945
946


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

949
950
951
	/* emit now all global declarations */
	ia32_gen_decls(isa->out);

952
953
	pmap_destroy(isa->regs_16bit);
	pmap_destroy(isa->regs_8bit);
954
955
	pmap_destroy(isa->tv_ent);
	pmap_destroy(isa->types);
956

Christian Würdig's avatar
Christian Würdig committed
957
#ifndef NDEBUG
Christian Würdig's avatar
Christian Würdig committed
958
	//printf("name obst size = %d bytes\n", isa->name_obst_size);
Christian Würdig's avatar
Christian Würdig committed
959
960
961
	obstack_free(isa->name_obst, NULL);
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
962
	free(self);
Christian Würdig's avatar
Christian Würdig committed
963
964
}

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

966
967
968
969
970
/**
 * 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)
971
 *  - MMX/SSE registers (currently not supported)
972
 */
Christian Würdig's avatar
Christian Würdig committed
973
static int ia32_get_n_reg_class(const void *self) {
974
	return 2;
Christian Würdig's avatar
Christian Würdig committed
975
976
}

977
978
979
/**
 * Return the register class for index i.
 */
Christian Würdig's avatar
Christian Würdig committed
980
static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
981
982
983
984
985
	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
986
987
}

988
989
990
991
992
993
994
/**
 * 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) {
995
996
997
998
	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];
	}
999
1000
	else
		return &ia32_reg_classes[CLASS_ia32_gp];
For faster browsing, not all history is shown. View entire blame