bearch_ia32.c 36.4 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
/**
 * This is the main ia32 firm backend driver.
 *
 * $Id$
 */

7
8
9
10
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

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"
51
#include "ia32_dbg_stat.h"
Christian Würdig's avatar
Christian Würdig committed
52

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

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

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

61
/* Creates the unique per irg GP NoReg node. */
62
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
63
	return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_GP_NOREG]);
64
65
}

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

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

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
88

Sebastian Hack's avatar
Sebastian Hack committed
89

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

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

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

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

		irn = my_skip_proj(irn);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

298
299
300
301
302
303
304
305
306
/**
 * 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
307
static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
Sebastian Hack's avatar
Sebastian Hack committed
308
{
Sebastian Hack's avatar
Sebastian Hack committed
309
310
	ia32_abi_env_t *env              = self;

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

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

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

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

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

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

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

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

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

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

		/* pop ebp */
Sebastian Hack's avatar
Sebastian Hack committed
364
		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
365
366
367
		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
368
369
370
		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);
371
372
373
		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
374
375
376
377
	}

	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
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
426
}

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

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

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

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


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

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

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

470
	if (cg->opt & IA32_OPT_DOAM) {
471
472
473
474
		edges_deactivate(cg->irg);
		//dead_node_elimination(cg->irg);
		edges_activate(cg->irg);

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

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

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

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

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

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

		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 */
509
		if (op_tp == ia32_Normal && ! is_ia32_Lea(irn)) {
510
511
512
			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
513
514
515
516
517
					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);
518
519

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

					/* check if in and out register are equal */
Christian Würdig's avatar
Christian Würdig committed
524
525
					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
526
527
528
						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
529
530
531
532
533
534
						}
						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);

535
536
							DBG_OPT_2ADDRCPY(copy);

Christian Würdig's avatar
Christian Würdig committed
537
538
539
540
541
542
543
544
545
							/* 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);
						}
546
					}
547
				}
Christian Würdig's avatar
Christian Würdig committed
548
549
			}
		}
Christian Würdig's avatar
Christian Würdig committed
550

551
552
553
554
555
556
557
558
559
		/* 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
560

561
562
		/* check if there is a sub which need to be transformed */
		ia32_transform_sub_to_neg_add(irn, cg);
563

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

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

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

589
590


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

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

605
606
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
607

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

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

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

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

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

645
646
	DBG_OPT_RELOAD2LD(irn, new_op);

Christian Würdig's avatar
Christian Würdig committed
647
648
649
650
651
652
653
654
655
	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);
	}

656
657
	/* 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
658
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
659

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

Christian Würdig's avatar
Christian Würdig committed
662
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
}

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

703
704
	DBG_OPT_SPILL2ST(irn, new_op);

705
	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, 0);
Christian Würdig's avatar
Christian Würdig committed
706
707
708
709
710
711
712
713

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

Christian Würdig's avatar
Christian Würdig committed
716
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
717
718
719
}

/**
720
 * Fix the mode of Spill/Reload
Christian Würdig's avatar
Christian Würdig committed
721
 */
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
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
740
741
742
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

743
	tenv.block = block;
Christian Würdig's avatar
Christian Würdig committed
744
745
	tenv.irg   = current_ir_graph;
	tenv.cg    = cg;
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
	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
765
766
767
768
	}
}

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

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
780
	if (cg->used_fp == fp_x87) {
781
782
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
783
784
785
}


Christian Würdig's avatar
Christian Würdig committed
786
787
788
789
790
791
/**
 * 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
792
	ir_graph        *irg = cg->irg;
Christian Würdig's avatar
Christian Würdig committed
793

Christian Würdig's avatar
Christian Würdig committed
794
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
795
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
796
	ia32_gen_routine(cg->isa->out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
797
798
799

	cur_reg_set = NULL;

800
801
	/* remove it from the isa */
	cg->isa->cg = NULL;
802

Christian Würdig's avatar
Christian Würdig committed
803
804
805
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
806

Christian Würdig's avatar
Christian Würdig committed
807
808
}

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

Christian Würdig's avatar
Christian Würdig committed
811
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
812
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
813
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
814
	ia32_prepare_graph,
815
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
816
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
817
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
818
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
819
820
};

Christian Würdig's avatar
Christian Würdig committed
821
/**
822
 * Initializes a IA32 code generator.
Christian Würdig's avatar
Christian Würdig committed
823
 */
824
static void *ia32_cg_init(const be_irg_t *birg) {
Christian Würdig's avatar
Christian Würdig committed
825
	ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
826
827
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

828
829
830
831
	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;
832
	cg->isa       = isa;
833
834
	cg->birg      = birg;
	cg->blk_sched = NULL;
835
836
	cg->fp_to_gp  = NULL;
	cg->gp_to_fp  = NULL;
837
	cg->fp_kind   = isa->fp_kind;
838
	cg->used_fp   = fp_none;
839

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

842
843
	/* copy optimizations from isa for easier access */
	cg->opt = isa->opt;
844

845
846
847
	/* enter it */
	isa->cg = cg;

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

Christian Würdig's avatar
Christian Würdig committed
868
869
870
	return (arch_code_generator_t *)cg;
}

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

Christian Würdig's avatar
Christian Würdig committed
872
873
874
875
876
877
878
879
880
881
882

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

883
884
885
886
887
/**
 * The template that generates a new ISA object.
 * Note that this template can be changed by command line
 * arguments.
 */
888
static ia32_isa_t ia32_isa_template = {
Christian Würdig's avatar
Christian Würdig committed
889
890
891
892
893
	&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 */
894
895
	NULL,                    /* 16bit register names */
	NULL,                    /* 8bit register names */
896
897
	NULL,                    /* types */
	NULL,                    /* tv_ents */
898
899
900
901
902
	(0 |
	IA32_OPT_DOAM      |     /* optimize address mode                            default: on  */
	IA32_OPT_PLACECNST |     /* place constants immediately before instructions, default: on  */
	IA32_OPT_IMMOPS    |     /* operations can use immediates,                   default: on  */
	IA32_OPT_EXTBB),         /* use extended basic block scheduling,             default: on  */
903
904
905
	arch_pentium_4,          /* instruction architecture */
	arch_pentium_4,          /* optimize for architecture */
	fp_sse2,                 /* use sse2 unit */
906
	NULL,                    /* current code generator */
907
908
909
910
#ifndef NDEBUG
	NULL,                    /* name obstack */
	0                        /* name obst size */
#endif
911
912
};

Christian Würdig's avatar
Christian Würdig committed
913
/**
914
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
915
 */
916
static void *ia32_init(FILE *file_handle) {
917
	static int inited = 0;
918
	ia32_isa_t *isa;
Christian Würdig's avatar
Christian Würdig committed
919

920
	if (inited)
Christian Würdig's avatar
Christian Würdig committed
921
922
		return NULL;

923
	isa = xmalloc(sizeof(*isa));
924
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
925

926
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
927
	ia32_create_opcodes();
928
	ia32_register_copy_attr_func();
Christian Würdig's avatar
Christian Würdig committed
929

930
931
	isa->regs_16bit = pmap_create();
	isa->regs_8bit  = pmap_create();
932
933
934
	isa->types      = pmap_create();
	isa->tv_ent     = pmap_create();
	isa->out        = file_handle;
935
936
937
938

	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
939
	/* patch register names of x87 registers */
940
941
942
943
944
945
946
947
948
949
950
	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
951
#ifndef NDEBUG
952
	isa->name_obst = xmalloc(sizeof(*isa->name_obst));
Christian Würdig's avatar
Christian Würdig committed
953
	obstack_init(isa->name_obst);
Christian Würdig's avatar
Christian Würdig committed
954
	isa->name_obst_size = 0;
Christian Würdig's avatar
Christian Würdig committed
955
956
#endif /* NDEBUG */

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

959
960
	inited = 1;

Christian Würdig's avatar
Christian Würdig committed
961
	return isa;
Christian Würdig's avatar
Christian Würdig committed
962
963
}

Christian Würdig's avatar
Christian Würdig committed
964
965
966
967
968
969


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

972
973
974
	/* emit now all global declarations */
	ia32_gen_decls(isa->out);

975
976
	pmap_destroy(isa->regs_16bit);
	pmap_destroy(isa->regs_8bit);
977
978
	pmap_destroy(isa->tv_ent);
	pmap_destroy(isa->types);
979

Christian Würdig's avatar
Christian Würdig committed
980
#ifndef NDEBUG
Christian Würdig's avatar
Christian Würdig committed
981
	//printf("name obst size = %d bytes\n", isa->name_obst_size);
Christian Würdig's avatar
Christian Würdig committed
982
983
984
	obstack_free(isa->name_obst, NULL);
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
985
	free(self);
Christian Würdig's avatar
Christian Würdig committed
986
987
}

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

989
990
991
992
993
/**
 * 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)
994
 *  - MMX/SSE registers (currently not supported)
995
 */
Christian Würdig's avatar
Christian Würdig committed
996
static int ia32_get_n_reg_class(const void *self) {
997
	return 2;
Christian Würdig's avatar
Christian Würdig committed
998
999
}

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