bearch_ia32.c 35.2 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");
465
	ia32_register_transformers();
Christian Würdig's avatar
Christian Würdig committed
466
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
Christian Würdig's avatar
Christian Würdig committed
467
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
468

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

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

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

	DEBUG_ONLY(cg->mod = old_mod;)
Christian Würdig's avatar
Christian Würdig committed
481
482
}

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

Christian Würdig's avatar
Christian Würdig committed
484
485
486
/**
 * Insert copies for all ia32 nodes where the should_be_same requirement
 * is not fulfilled.
Christian Würdig's avatar
Christian Würdig committed
487
 * Transform Sub into Neg -- Add if IN2 == OUT
Christian Würdig's avatar
Christian Würdig committed
488
 */
489
static void ia32_finish_node(ir_node *irn, void *env) {
Christian Würdig's avatar
Christian Würdig committed
490
491
	ia32_code_gen_t            *cg = env;
	const ia32_register_req_t **reqs;
Christian Würdig's avatar
Christian Würdig committed
492
	const arch_register_t      *out_reg, *in_reg, *in2_reg;
Christian Würdig's avatar
Christian Würdig committed
493
	int                         n_res, i;
Christian Würdig's avatar
Christian Würdig committed
494
	ir_node                    *copy, *in_node, *block, *in2_node;
Christian Würdig's avatar
Christian Würdig committed
495
	ia32_op_type_t              op_tp;
Christian Würdig's avatar
Christian Würdig committed
496

497
498
499
500
	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)
501
			goto end;
502
503
504
505
506
507
508
509
510
511

		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
512
513
514
515
516
					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);
517
518

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

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

548
549
550
551
552
553
554
555
556
		/* 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
557

558
559
		/* check if there is a sub which need to be transformed */
		ia32_transform_sub_to_neg_add(irn, cg);
560

561
562
563
		/* transform a LEA into an Add if possible */
		ia32_transform_lea_to_add(irn, cg);
	}
564
end:
565
566
567

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

570
571
572
573
574
575
576
577
578
static void ia32_finish_irg_walker(ir_node *block, void *env) {
	ir_node *irn, *next;

	for (irn = sched_first(block); !sched_is_end(irn); irn = next) {
		next = sched_next(irn);
		ia32_finish_node(irn, env);
	}
}

Christian Würdig's avatar
Christian Würdig committed
579
/**
Christian Würdig's avatar
Christian Würdig committed
580
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
581
 */
Christian Würdig's avatar
Christian Würdig committed
582
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
583
	irg_block_walk_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
584
585
}

586
587


588
/**
589
 * Dummy functions for hooks we don't need but which must be filled.
590
 */
591
static void ia32_before_sched(void *self) {
592
593
}

594
595
596
597
598
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
599
static void ia32_before_ra(void *self) {
600
	ia32_code_gen_t *cg = self;
601

602
603
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
604

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

Christian Würdig's avatar
Christian Würdig committed
606
607
608
609
/**
 * 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
610
611
612
613
614
	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
615
	ir_node *sched_point = NULL;
Christian Würdig's avatar
Christian Würdig committed
616
617
618
	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;
619
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
620
621
622
623
624
625

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

	if (mode_is_float(mode)) {
626
627
628
629
		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
630
631
	}
	else {
Christian Würdig's avatar
Christian Würdig committed
632
		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
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
	}

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

651
652
	/* 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
653
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
654

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

Christian Würdig's avatar
Christian Würdig committed
657
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
}

/**
 * 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)) {
679
680
681
682
		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
683
	}
684
685
686
	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
687
688
689
690
691
692
693
	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
694
	set_ia32_ls_mode(new_op, mode);
Christian Würdig's avatar
Christian Würdig committed
695
696
697
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

698
	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, 0);
Christian Würdig's avatar
Christian Würdig committed
699
700
701
702
703
704
705
706

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

Christian Würdig's avatar
Christian Würdig committed
709
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
710
711
712
}

/**
713
 * Fix the mode of Spill/Reload
Christian Würdig's avatar
Christian Würdig committed
714
 */
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
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
733
734
735
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

736
	tenv.block = block;
Christian Würdig's avatar
Christian Würdig committed
737
738
	tenv.irg   = current_ir_graph;
	tenv.cg    = cg;
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
	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
758
759
760
761
	}
}

/**
762
 * We transform Spill and Reload here. This needs to be done before
Christian Würdig's avatar
Christian Würdig committed
763
 * stack biasing otherwise we would miss the corrected offset for these nodes.
764
765
766
 *
 * 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
767
768
769
 */
static void ia32_after_ra(void *self) {
	ia32_code_gen_t *cg = self;
770
	irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
771
772

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
773
	if (cg->used_fp == fp_x87) {
774
775
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
776
777
778
}


Christian Würdig's avatar
Christian Würdig committed
779
780
781
782
783
784
/**
 * 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
785
	ir_graph        *irg = cg->irg;
Christian Würdig's avatar
Christian Würdig committed
786

Christian Würdig's avatar
Christian Würdig committed
787
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
788
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
789
	ia32_gen_routine(cg->isa->out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
790
791
792

	cur_reg_set = NULL;

793
794
	/* remove it from the isa */
	cg->isa->cg = NULL;
795

Christian Würdig's avatar
Christian Würdig committed
796
797
798
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
799

Christian Würdig's avatar
Christian Würdig committed
800
801
}

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

Christian Würdig's avatar
Christian Würdig committed
804
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
805
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
806
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
807
	ia32_prepare_graph,
808
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
809
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
810
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
811
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
812
813
};

Christian Würdig's avatar
Christian Würdig committed
814
/**
815
 * Initializes a IA32 code generator.
Christian Würdig's avatar
Christian Würdig committed
816
 */
817
static void *ia32_cg_init(const be_irg_t *birg) {
Christian Würdig's avatar
Christian Würdig committed
818
	ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
819
820
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

821
822
823
824
	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;
825
	cg->isa       = isa;
826
827
	cg->birg      = birg;
	cg->blk_sched = NULL;
828
829
	cg->fp_to_gp  = NULL;
	cg->gp_to_fp  = NULL;
830
	cg->fp_kind   = isa->fp_kind;
831
	cg->used_fp   = fp_none;
832

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

835
836
	/* set optimizations */
	cg->opt.incdec    = 0;
Christian Würdig's avatar
Christian Würdig committed
837
	cg->opt.doam      = 1;
838
839
	cg->opt.placecnst = 1;
	cg->opt.immops    = 1;
840
	cg->opt.extbb     = 1;
841

842
843
844
	/* enter it */
	isa->cg = cg;

Christian Würdig's avatar
Christian Würdig committed
845
846
847
848
849
850
851
852
853
#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
854
855
856
857
858
859
860
861
862
	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
863
864
	ia32_irn_ops.cg = cg;

Christian Würdig's avatar
Christian Würdig committed
865
866
867
	return (arch_code_generator_t *)cg;
}

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

Christian Würdig's avatar
Christian Würdig committed
869
870
871
872
873
874
875
876
877
878
879

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

880
881
882
883
884
/**
 * The template that generates a new ISA object.
 * Note that this template can be changed by command line
 * arguments.
 */
885
static ia32_isa_t ia32_isa_template = {
Christian Würdig's avatar
Christian Würdig committed
886
887
888
889
890
	&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 */
891
892
	NULL,                    /* 16bit register names */
	NULL,                    /* 8bit register names */
893
894
	NULL,                    /* types */
	NULL,                    /* tv_ents */
895
896
897
	arch_pentium_4,          /* instruction architecture */
	arch_pentium_4,          /* optimize for architecture */
	fp_sse2,                 /* use sse2 unit */
898
	NULL,                    /* current code generator */
899
900
901
902
#ifndef NDEBUG
	NULL,                    /* name obstack */
	0                        /* name obst size */
#endif
903
904
};

Christian Würdig's avatar
Christian Würdig committed
905
/**
906
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
907
 */
908
static void *ia32_init(FILE *file_handle) {
909
	static int inited = 0;
910
	ia32_isa_t *isa;
Christian Würdig's avatar
Christian Würdig committed
911

912
	if (inited)
Christian Würdig's avatar
Christian Würdig committed
913
914
		return NULL;

915
	isa = xmalloc(sizeof(*isa));
916
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
917

918
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
919
	ia32_create_opcodes();
920
	ia32_register_copy_attr_func();
Christian Würdig's avatar
Christian Würdig committed
921

922
923
	isa->regs_16bit = pmap_create();
	isa->regs_8bit  = pmap_create();
924
925
926
	isa->types      = pmap_create();
	isa->tv_ent     = pmap_create();
	isa->out        = file_handle;
927
928
929
930

	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
931
	/* patch register names of x87 registers */
932
933
934
935
936
937
938
939
940
941
942
	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
943
#ifndef NDEBUG
944
	isa->name_obst = xmalloc(sizeof(*isa->name_obst));
Christian Würdig's avatar
Christian Würdig committed
945
	obstack_init(isa->name_obst);
Christian Würdig's avatar
Christian Würdig committed
946
	isa->name_obst_size = 0;
Christian Würdig's avatar
Christian Würdig committed
947
948
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
949
	fprintf(isa->out, "\t.intel_syntax\n");
950

951
952
	inited = 1;

Christian Würdig's avatar
Christian Würdig committed
953
	return isa;
Christian Würdig's avatar
Christian Würdig committed
954
955
}

Christian Würdig's avatar
Christian Würdig committed
956
957
958
959
960
961


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

964
965
966
	/* emit now all global declarations */
	ia32_gen_decls(isa->out);

967
968
	pmap_destroy(isa->regs_16bit);
	pmap_destroy(isa->regs_8bit);
969
970
	pmap_destroy(isa->tv_ent);
	pmap_destroy(isa->types);
971

Christian Würdig's avatar
Christian Würdig committed
972
#ifndef NDEBUG
Christian Würdig's avatar
Christian Würdig committed
973
	//printf("name obst size = %d bytes\n", isa->name_obst_size);
Christian Würdig's avatar
Christian Würdig committed
974
975
976
	obstack_free(isa->name_obst, NULL);
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
977
	free(self);
Christian Würdig's avatar
Christian Würdig committed
978
979
}

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

981
982
983
984
985
/**
 * 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)
986
 *  - MMX/SSE registers (currently not supported)
987
 */
Christian Würdig's avatar
Christian Würdig committed
988
static int ia32_get_n_reg_class(const void *self) {
989
	return 2;
Christian Würdig's avatar
Christian Würdig committed
990
991
}

992
993
994
/**
 * Return the register class for index i.
 */
Christian Würdig's avatar
Christian Würdig committed
995
static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
996
997
998
999
1000
	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];
For faster browsing, not all history is shown. View entire blame