bearch_ia32.c 35.1 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
	if (cg->opt.doam) {
469
470
471
472
		edges_deactivate(cg->irg);
		//dead_node_elimination(cg->irg);
		edges_activate(cg->irg);

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

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

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

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

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

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

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

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

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

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

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

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

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

569
570
571
572
573
574
575
576
577
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
578
/**
Christian Würdig's avatar
Christian Würdig committed
579
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
580
 */
Christian Würdig's avatar
Christian Würdig committed
581
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
582
	irg_block_walk_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
583
584
}

585
586


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

	cur_reg_set = NULL;

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

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

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

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

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

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

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

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

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

839
840
841
	/* enter it */
	isa->cg = cg;

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

Christian Würdig's avatar
Christian Würdig committed
862
863
864
	return (arch_code_generator_t *)cg;
}

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

Christian Würdig's avatar
Christian Würdig committed
866
867
868
869
870
871
872
873
874
875
876

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

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

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

909
	if (inited)
Christian Würdig's avatar
Christian Würdig committed
910
911
		return NULL;

912
	isa = xmalloc(sizeof(*isa));
913
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
914

915
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
916
	ia32_create_opcodes();
917
	ia32_register_copy_attr_func();
Christian Würdig's avatar
Christian Würdig committed
918

919
920
	isa->regs_16bit = pmap_create();
	isa->regs_8bit  = pmap_create();
921
922
923
	isa->types      = pmap_create();
	isa->tv_ent     = pmap_create();
	isa->out        = file_handle;
924
925
926
927

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

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

948
949
	inited = 1;

Christian Würdig's avatar
Christian Würdig committed
950
	return isa;
Christian Würdig's avatar
Christian Würdig committed
951
952
}

Christian Würdig's avatar
Christian Würdig committed
953
954
955
956
957
958


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

961
962
963
	/* emit now all global declarations */
	ia32_gen_decls(isa->out);

964
965
	pmap_destroy(isa->regs_16bit);
	pmap_destroy(isa->regs_8bit);
966
967
	pmap_destroy(isa->tv_ent);
	pmap_destroy(isa->types);
968

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

Christian Würdig's avatar
Christian Würdig committed
974
	free(self);
Christian Würdig's avatar
Christian Würdig committed
975
976
}

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

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

989
990
991
/**
 * Return the register class for index i.
 */
Christian Würdig's avatar
Christian Würdig committed
992
static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
993
994
995
996
997
	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
998
999
}

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