ia32_emitter.c 55.6 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
/**
21
 * @file
Christian Würdig's avatar
Christian Würdig committed
22
23
24
 * @brief       This file implements the ia32 node emitter.
 * @author      Christian Wuerdig, Matthias Braun
 * @version     $Id$
25
 */
Christian Würdig's avatar
Christian Würdig committed
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
Christian Würdig's avatar
Christian Würdig committed
28
29
#endif

Christian Würdig's avatar
Christian Würdig committed
30
31
#include <limits.h>

32
#include "xmalloc.h"
33
34
#include "tv.h"
#include "iredges.h"
Christian Würdig's avatar
Christian Würdig committed
35
36
37
38
#include "debug.h"
#include "irgwalk.h"
#include "irprintf.h"
#include "irop_t.h"
Christian Würdig's avatar
Christian Würdig committed
39
#include "irargs_t.h"
40
#include "irprog_t.h"
41
#include "iredges_t.h"
42
#include "execfreq.h"
43
#include "error.h"
Matthias Braun's avatar
Matthias Braun committed
44
#include "raw_bitset.h"
45
#include "dbginfo.h"
Christian Würdig's avatar
Christian Würdig committed
46

47
#include "../besched_t.h"
Christian Würdig's avatar
Christian Würdig committed
48
#include "../benode_t.h"
Michael Beck's avatar
Michael Beck committed
49
#include "../beabi.h"
50
#include "../be_dbgout.h"
Matthias Braun's avatar
Matthias Braun committed
51
52
#include "../beemitter.h"
#include "../begnuas.h"
53
#include "../beirg_t.h"
54
#include "../be_dbgout.h"
Christian Würdig's avatar
Christian Würdig committed
55

56
#include "ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
57
#include "gen_ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
58
#include "gen_ia32_regalloc_if.h"
59
60
#include "ia32_nodes_attr.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
61
#include "ia32_map_regs.h"
62
#include "ia32_architecture.h"
Christian Würdig's avatar
Christian Würdig committed
63
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
64

65
66
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

67
#define BLOCK_PREFIX ".L"
Michael Beck's avatar
Michael Beck committed
68

Christian Würdig's avatar
Christian Würdig committed
69
70
#define SNPRINTF_BUF_LEN 128

71
72
73
static const arch_env_t *arch_env;
static const ia32_isa_t *isa;
static ia32_code_gen_t  *cg;
74
75
static int               do_pic;
static char              pic_base_label[128];
76
static ir_label_t        exc_label_id;
77
static int               mark_spill_reload = 0;
78

79
80
81
82
83
84
/** Return the next block in Block schedule */
static ir_node *get_prev_block_sched(const ir_node *block)
{
	return get_irn_link(block);
}

85
static int is_fallthrough(const ir_node *cfgpred)
86
87
88
{
	ir_node *pred;

Christoph Mallon's avatar
Christoph Mallon committed
89
	if (!is_Proj(cfgpred))
90
		return 1;
91
	pred = get_Proj_pred(cfgpred);
Christoph Mallon's avatar
Christoph Mallon committed
92
	if (is_ia32_SwitchJmp(pred))
93
		return 0;
94

95
	return 1;
96
97
}

98
static int block_needs_label(const ir_node *block)
99
{
100
	int need_label = 1;
101
102
103
	int  n_cfgpreds = get_Block_n_cfgpreds(block);

	if (n_cfgpreds == 0) {
104
		need_label = 0;
105
	} else if (n_cfgpreds == 1) {
Christoph Mallon's avatar
Christoph Mallon committed
106
107
		ir_node *cfgpred       = get_Block_cfgpred(block, 0);
		ir_node *cfgpred_block = get_nodes_block(cfgpred);
108
109
110

		if (get_prev_block_sched(block) == cfgpred_block
				&& is_fallthrough(cfgpred)) {
111
			need_label = 0;
112
113
114
115
116
117
		}
	}

	return need_label;
}

Christian Würdig's avatar
Christian Würdig committed
118
/**
Christian Würdig's avatar
Christian Würdig committed
119
 * Returns the register at in position pos.
Christian Würdig's avatar
Christian Würdig committed
120
 */
121
static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
122
{
123
124
	ir_node               *op;
	const arch_register_t *reg = NULL;
Christian Würdig's avatar
Christian Würdig committed
125
126
127
128
129
130
131

	assert(get_irn_arity(irn) > pos && "Invalid IN position");

	/* The out register of the operator at position pos is the
	   in register we need. */
	op = get_irn_n(irn, pos);

Christian Würdig's avatar
Christian Würdig committed
132
	reg = arch_get_irn_register(arch_env, op);
Christian Würdig's avatar
Christian Würdig committed
133

Christian Würdig's avatar
Christian Würdig committed
134
	assert(reg && "no in register found");
135

Christoph Mallon's avatar
Christoph Mallon committed
136
	if (reg == &ia32_gp_regs[REG_GP_NOREG])
137
		panic("trying to emit noreg for %+F input %d", irn, pos);
138
139
140

	/* in case of unknown register: just return a valid register */
	if (reg == &ia32_gp_regs[REG_GP_UKNWN]) {
Matthias Braun's avatar
Matthias Braun committed
141
		const arch_register_req_t *req;
142
143

		/* ask for the requirements */
Matthias Braun's avatar
Matthias Braun committed
144
		req = arch_get_register_req(arch_env, irn, pos);
145

Matthias Braun's avatar
Matthias Braun committed
146
		if (arch_register_req_is(req, limited)) {
147
			/* in case of limited requirements: get the first allowed register */
Matthias Braun's avatar
Matthias Braun committed
148
149
			unsigned idx = rbitset_next(req->limited, 0, 1);
			reg = arch_register_for_index(req->cls, idx);
150
		} else {
151
			/* otherwise get first register in class */
Matthias Braun's avatar
Matthias Braun committed
152
			reg = arch_register_for_index(req->cls, 0);
153
154
		}
	}
155

Christian Würdig's avatar
Christian Würdig committed
156
157
158
159
160
161
	return reg;
}

/**
 * Returns the register at out position pos.
 */
162
static const arch_register_t *get_out_reg(const ir_node *irn, int pos)
163
164
165
{
	ir_node               *proj;
	const arch_register_t *reg = NULL;
Christian Würdig's avatar
Christian Würdig committed
166
167
168
169
170
171
172

	/* 1st case: irn is not of mode_T, so it has only                 */
	/*           one OUT register -> good                             */
	/* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
	/*           Proj with the corresponding projnum for the register */

	if (get_irn_mode(irn) != mode_T) {
173
		assert(pos == 0);
Christian Würdig's avatar
Christian Würdig committed
174
		reg = arch_get_irn_register(arch_env, irn);
175
	} else if (is_ia32_irn(irn)) {
Christian Würdig's avatar
Christian Würdig committed
176
		reg = get_ia32_out_reg(irn, pos);
177
	} else {
Christian Würdig's avatar
Christian Würdig committed
178
179
180
181
182
183
184
185
186
187
188
189
190
		const ir_edge_t *edge;

		foreach_out_edge(irn, edge) {
			proj = get_edge_src_irn(edge);
			assert(is_Proj(proj) && "non-Proj from mode_T node");
			if (get_Proj_proj(proj) == pos) {
				reg = arch_get_irn_register(arch_env, proj);
				break;
			}
		}
	}

	assert(reg && "no out register found");
Christian Würdig's avatar
Christian Würdig committed
191
192
193
	return reg;
}

Michael Beck's avatar
Michael Beck committed
194
/**
195
 * Add a number to a prefix. This number will not be used a second time.
Michael Beck's avatar
Michael Beck committed
196
 */
197
198
static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
{
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
	static unsigned long id = 0;
	snprintf(buf, buflen, "%s%lu", prefix, ++id);
	return buf;
}

/*************************************************************
 *             _       _    __   _          _
 *            (_)     | |  / _| | |        | |
 *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
 * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
 * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
 * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
 * | |                                       | |
 * |_|                                       |_|
 *************************************************************/

215
216
static void emit_8bit_register(const arch_register_t *reg)
{
217
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
218

219
220
221
222
223
224
225
226
	be_emit_char('%');
	be_emit_char(reg_name[1]);
	be_emit_char('l');
}

static void emit_16bit_register(const arch_register_t *reg)
{
	const char *reg_name = ia32_get_mapped_reg_name(isa->regs_16bit, reg);
Christian Würdig's avatar
Christian Würdig committed
227

228
229
	be_emit_char('%');
	be_emit_string(reg_name);
230
231
}

232
233
234
235
static void emit_register(const arch_register_t *reg, const ir_mode *mode)
{
	const char *reg_name;

Christoph Mallon's avatar
Christoph Mallon committed
236
	if (mode != NULL) {
237
		int size = get_mode_size_bits(mode);
Christoph Mallon's avatar
Christoph Mallon committed
238
239
240
		switch (size) {
			case  8: emit_8bit_register(reg);  return;
			case 16: emit_16bit_register(reg); return;
241
		}
Christoph Mallon's avatar
Christoph Mallon committed
242
		assert(mode_is_float(mode) || size == 32);
243
244
245
	}

	reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
246

247
248
	be_emit_char('%');
	be_emit_string(reg_name);
Christian Würdig's avatar
Christian Würdig committed
249
250
}

251
void ia32_emit_source_register(const ir_node *node, int pos)
252
{
Christoph Mallon's avatar
Christoph Mallon committed
253
	const arch_register_t *reg = get_in_reg(node, pos);
254

255
	emit_register(reg, NULL);
256
257
}

258
259
260
261
262
263
static void emit_ia32_Immediate(const ir_node *node);

void ia32_emit_8bit_source_register_or_immediate(const ir_node *node, int pos)
{
	const arch_register_t *reg;
	ir_node               *in = get_irn_n(node, pos);
Christoph Mallon's avatar
Christoph Mallon committed
264
	if (is_ia32_Immediate(in)) {
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
		emit_ia32_Immediate(in);
		return;
	}

	reg = get_in_reg(node, pos);
	emit_8bit_register(reg);
}

void ia32_emit_dest_register(const ir_node *node, int pos)
{
	const arch_register_t *reg  = get_out_reg(node, pos);

	emit_register(reg, NULL);
}

void ia32_emit_8bit_dest_register(const ir_node *node, int pos)
{
	const arch_register_t *reg  = get_out_reg(node, pos);

	emit_register(reg, mode_Bu);
}

void ia32_emit_x87_register(const ir_node *node, int pos)
Christian Würdig's avatar
Christian Würdig committed
288
{
289
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
290

Matthias Braun's avatar
Matthias Braun committed
291
	assert(pos < 3);
292
293
	be_emit_char('%');
	be_emit_string(attr->x87[pos]->name);
294
}
Christian Würdig's avatar
Christian Würdig committed
295

Matthias Braun's avatar
Matthias Braun committed
296
static void ia32_emit_mode_suffix_mode(const ir_mode *mode)
297
{
298
299
300
301
302
	assert(mode_is_int(mode) || mode_is_reference(mode));
	switch (get_mode_size_bits(mode)) {
		case 8:  be_emit_char('b');     return;
		case 16: be_emit_char('w');     return;
		case 32: be_emit_char('l');     return;
Christoph Mallon's avatar
Christoph Mallon committed
303
304
		/* gas docu says q is the suffix but gcc, objdump and icc use ll
		 * apparently */
Matthias Braun's avatar
Matthias Braun committed
305
306
		case 64: be_emit_cstring("ll"); return;
	}
307
	panic("Can't output mode_suffix for %+F", mode);
Christian Würdig's avatar
Christian Würdig committed
308
309
}

310
void ia32_emit_mode_suffix(const ir_node *node)
311
312
{
	ir_mode *mode = get_ia32_ls_mode(node);
Christoph Mallon's avatar
Christoph Mallon committed
313
	if (mode == NULL)
Matthias Braun's avatar
Matthias Braun committed
314
315
		mode = mode_Iu;

316
	ia32_emit_mode_suffix_mode(mode);
317
318
}

319
void ia32_emit_x87_mode_suffix(const ir_node *node)
320
{
321
322
	ir_mode *mode;

323
	/* we only need to emit the mode on address mode */
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
	if (get_ia32_op_type(node) == ia32_Normal)
		return;

	mode = get_ia32_ls_mode(node);
	assert(mode != NULL);

	if (mode_is_float(mode)) {
		switch (get_mode_size_bits(mode)) {
			case 32: be_emit_char('s'); return;
			case 64: be_emit_char('l'); return;
			case 80:
			case 96: be_emit_char('t'); return;
		}
	} else {
		assert(mode_is_int(mode));
		switch (get_mode_size_bits(mode)) {
			case 16: be_emit_char('s');     return;
			case 32: be_emit_char('l');     return;
			/* gas docu says q is the suffix but gcc, objdump and icc use ll
			 * apparently */
			case 64: be_emit_cstring("ll"); return;
		}
346
	}
347
	panic("Can't output mode_suffix for %+F", mode);
348
349
}

350
static char get_xmm_mode_suffix(ir_mode *mode)
351
352
353
{
	assert(mode_is_float(mode));
	switch(get_mode_size_bits(mode)) {
Christoph Mallon's avatar
Christoph Mallon committed
354
355
356
	case 32: return 's';
	case 64: return 'd';
	default: panic("Invalid XMM mode");
357
358
359
	}
}

360
void ia32_emit_xmm_mode_suffix(const ir_node *node)
361
362
{
	ir_mode *mode = get_ia32_ls_mode(node);
363
	assert(mode != NULL);
364
365
	be_emit_char('s');
	be_emit_char(get_xmm_mode_suffix(mode));
366
367
}

368
void ia32_emit_xmm_mode_suffix_s(const ir_node *node)
369
370
371
{
	ir_mode *mode = get_ia32_ls_mode(node);
	assert(mode != NULL);
372
	be_emit_char(get_xmm_mode_suffix(mode));
373
374
}

375
void ia32_emit_extend_suffix(const ir_mode *mode)
376
{
Christoph Mallon's avatar
Christoph Mallon committed
377
	if (get_mode_size_bits(mode) == 32)
378
		return;
Christoph Mallon's avatar
Christoph Mallon committed
379
	be_emit_char(mode_is_signed(mode) ? 's' : 'z');
Matthias Braun's avatar
Matthias Braun committed
380
381
}

382
void ia32_emit_source_register_or_immediate(const ir_node *node, int pos)
383
384
{
	ir_node *in = get_irn_n(node, pos);
Christoph Mallon's avatar
Christoph Mallon committed
385
	if (is_ia32_Immediate(in)) {
386
		emit_ia32_Immediate(in);
387
	} else {
388
389
390
		const ir_mode         *mode = get_ia32_ls_mode(node);
		const arch_register_t *reg  = get_in_reg(node, pos);
		emit_register(reg, mode);
391
392
393
	}
}

Christian Würdig's avatar
Christian Würdig committed
394
395
396
/**
 * Emits registers and/or address mode of a binary operation.
 */
Christoph Mallon's avatar
Christoph Mallon committed
397
398
void ia32_emit_binop(const ir_node *node)
{
399
400
401
	const ir_node         *right_op  = get_irn_n(node, n_ia32_binary_right);
	const ir_mode         *mode      = get_ia32_ls_mode(node);
	const arch_register_t *reg_left;
Christian Würdig's avatar
Christian Würdig committed
402

403
404
	switch(get_ia32_op_type(node)) {
	case ia32_Normal:
405
		reg_left = get_in_reg(node, n_ia32_binary_left);
Christoph Mallon's avatar
Christoph Mallon committed
406
		if (is_ia32_Immediate(right_op)) {
407
408
409
			emit_ia32_Immediate(right_op);
			be_emit_cstring(", ");
			emit_register(reg_left, mode);
Christian Würdig's avatar
Christian Würdig committed
410
			break;
411
		} else {
412
413
414
415
416
			const arch_register_t *reg_right
				= get_in_reg(node, n_ia32_binary_right);
			emit_register(reg_right, mode);
			be_emit_cstring(", ");
			emit_register(reg_left, mode);
417
418
419
		}
		break;
	case ia32_AddrModeS:
Christoph Mallon's avatar
Christoph Mallon committed
420
		if (is_ia32_Immediate(right_op)) {
421
422
423
			emit_ia32_Immediate(right_op);
			be_emit_cstring(", ");
			ia32_emit_am(node);
424
		} else {
425
426
427
428
			reg_left = get_in_reg(node, n_ia32_binary_left);
			ia32_emit_am(node);
			be_emit_cstring(", ");
			emit_register(reg_left, mode);
429
430
431
		}
		break;
	case ia32_AddrModeD:
432
		panic("DestMode can't be output by %%binop anymore");
433
434
435
		break;
	default:
		assert(0 && "unsupported op type");
Christian Würdig's avatar
Christian Würdig committed
436
	}
437
438
}

439
440
441
/**
 * Emits registers and/or address mode of a binary operation.
 */
Christoph Mallon's avatar
Christoph Mallon committed
442
443
void ia32_emit_x87_binop(const ir_node *node)
{
444
	switch(get_ia32_op_type(node)) {
445
		case ia32_Normal:
446
			{
447
448
449
450
				const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
				const arch_register_t *in1      = x87_attr->x87[0];
				const arch_register_t *in2      = x87_attr->x87[1];
				const arch_register_t *out      = x87_attr->x87[2];
451
452
				const arch_register_t *in;

453
				in  = out ? ((out == in2) ? in1 : in2) : in2;
454
				out = out ? out : in1;
455

456
457
458
459
				be_emit_char('%');
				be_emit_string(arch_register_get_name(in));
				be_emit_cstring(", %");
				be_emit_string(arch_register_get_name(out));
460
461
462
			}
			break;
		case ia32_AddrModeS:
463
			ia32_emit_am(node);
464
			break;
465
		case ia32_AddrModeD:
466
467
468
469
470
		default:
			assert(0 && "unsupported op type");
	}
}

Christian Würdig's avatar
Christian Würdig committed
471
472
473
/**
 * Emits registers and/or address mode of a unary operation.
 */
Christoph Mallon's avatar
Christoph Mallon committed
474
475
void ia32_emit_unop(const ir_node *node, int pos)
{
476
477
	const ir_node *op;

478
	switch(get_ia32_op_type(node)) {
479
480
481
	case ia32_Normal:
		op = get_irn_n(node, pos);
		if (is_ia32_Immediate(op)) {
482
			emit_ia32_Immediate(op);
483
		} else {
484
			ia32_emit_source_register(node, pos);
485
486
487
488
		}
		break;
	case ia32_AddrModeS:
	case ia32_AddrModeD:
489
		ia32_emit_am(node);
490
491
492
		break;
	default:
		assert(0 && "unsupported op type");
Christian Würdig's avatar
Christian Würdig committed
493
494
495
	}
}

496
static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
497
498
499
500
501
502
503
{
	ident *id;

	set_entity_backend_marked(entity, 1);
	id = get_entity_ld_ident(entity);
	be_emit_ident(id);

504
	if (get_entity_owner(entity) == get_tls_type()) {
505
506
507
508
509
510
		if (get_entity_visibility(entity) == visibility_external_allocated) {
			be_emit_cstring("@INDNTPOFF");
		} else {
			be_emit_cstring("@NTPOFF");
		}
	}
511
512
513
514
515
516

	if (!no_pic_adjust && do_pic) {
		/* TODO: only do this when necessary */
		be_emit_char('-');
		be_emit_string(pic_base_label);
	}
517
518
}

Christian Würdig's avatar
Christian Würdig committed
519
/**
520
 * Emits address mode.
Christian Würdig's avatar
Christian Würdig committed
521
 */
Christoph Mallon's avatar
Christoph Mallon committed
522
523
void ia32_emit_am(const ir_node *node)
{
524
525
	ir_entity *ent       = get_ia32_am_sc(node);
	int        offs      = get_ia32_am_offs_int(node);
Christoph Mallon's avatar
Christoph Mallon committed
526
	ir_node   *base      = get_irn_n(node, n_ia32_base);
527
	int        has_base  = !is_ia32_NoReg_GP(base);
Christoph Mallon's avatar
Christoph Mallon committed
528
	ir_node   *index     = get_irn_n(node, n_ia32_index);
529
	int        has_index = !is_ia32_NoReg_GP(index);
Christian Würdig's avatar
Christian Würdig committed
530

531
	/* just to be sure... */
532
	assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
Christian Würdig's avatar
Christian Würdig committed
533

534
	/* emit offset */
535
	if (ent != NULL) {
536
		if (is_ia32_am_sc_sign(node))
537
			be_emit_char('-');
538
		ia32_emit_entity(ent, 0);
Christian Würdig's avatar
Christian Würdig committed
539
540
	}

Christoph Mallon's avatar
Christoph Mallon committed
541
542
543
	/* also handle special case if nothing is set */
	if (offs != 0 || (ent == NULL && !has_base && !has_index)) {
		if (ent != NULL) {
544
			be_emit_irprintf("%+d", offs);
545
		} else {
546
			be_emit_irprintf("%d", offs);
547
		}
548
	}
Christian Würdig's avatar
Christian Würdig committed
549

550
	if (has_base || has_index) {
551
		be_emit_char('(');
Christian Würdig's avatar
Christian Würdig committed
552

553
		/* emit base */
554
		if (has_base) {
555
556
			const arch_register_t *reg = get_in_reg(node, n_ia32_base);
			emit_register(reg, NULL);
Christian Würdig's avatar
Christian Würdig committed
557
558
		}

559
		/* emit index + scale */
560
		if (has_index) {
561
			const arch_register_t *reg = get_in_reg(node, n_ia32_index);
562
			int scale;
563
564
			be_emit_char(',');
			emit_register(reg, NULL);
565

566
567
			scale = get_ia32_am_scale(node);
			if (scale > 0) {
Christoph Mallon's avatar
Christoph Mallon committed
568
				be_emit_irprintf(",%d", 1 << scale);
569
570
			}
		}
571
		be_emit_char(')');
Christian Würdig's avatar
Christian Würdig committed
572
	}
573
}
Christian Würdig's avatar
Christian Würdig committed
574

Matthias Braun's avatar
Matthias Braun committed
575
576
577
578
579
580
581
582
583
584
585
586
static void emit_ia32_IMul(const ir_node *node)
{
	ir_node               *left    = get_irn_n(node, n_ia32_IMul_left);
	const arch_register_t *out_reg = get_out_reg(node, pn_ia32_IMul_res);

	be_emit_cstring("\timul");
	ia32_emit_mode_suffix(node);
	be_emit_char(' ');

	ia32_emit_binop(node);

	/* do we need the 3-address form? */
Christoph Mallon's avatar
Christoph Mallon committed
587
	if (is_ia32_NoReg_GP(left) ||
Matthias Braun's avatar
Matthias Braun committed
588
589
590
591
592
593
594
			get_in_reg(node, n_ia32_IMul_left) != out_reg) {
		be_emit_cstring(", ");
		emit_register(out_reg, get_ia32_ls_mode(node));
	}
	be_emit_finish_line_gas(node);
}

Christian Würdig's avatar
Christian Würdig committed
595
596
597
598
599
600
601
602
603
604
/*************************************************
 *                 _ _                         _
 *                (_) |                       | |
 *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
 *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
 * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
 *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
 *
 *************************************************/

Christian Würdig's avatar
Christian Würdig committed
605
#undef IA32_DO_EMIT
Christian Würdig's avatar
Christian Würdig committed
606
#define IA32_DO_EMIT(irn) ia32_fprintf_format(F, irn, cmd_buf, cmnt_buf)
Christian Würdig's avatar
Christian Würdig committed
607

608
609
610
611
/*
 * coding of conditions
 */
struct cmp2conditon_t {
Christian Würdig's avatar
Christian Würdig committed
612
	const char *name;
613
	int         num;
614
615
616
617
618
};

/*
 * positive conditions for signed compares
 */
619
static const struct cmp2conditon_t cmp2condition_s[] = {
620
621
622
623
624
625
626
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "l",               pn_Cmp_Lt },     /* < */
	{ "le",              pn_Cmp_Le },     /* <= */
	{ "g",               pn_Cmp_Gt },     /* > */
	{ "ge",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
627
	{ NULL,              pn_Cmp_Leg},     /* always true */
628
629
630
631
632
};

/*
 * positive conditions for unsigned compares
 */
633
static const struct cmp2conditon_t cmp2condition_u[] = {
Christian Würdig's avatar
Christian Würdig committed
634
635
636
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "b",               pn_Cmp_Lt },     /* < */
Christian Würdig's avatar
Christian Würdig committed
637
	{ "be",              pn_Cmp_Le },     /* <= */
Christian Würdig's avatar
Christian Würdig committed
638
639
640
	{ "a",               pn_Cmp_Gt },     /* > */
	{ "ae",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
641
	{ NULL,              pn_Cmp_Leg },   /* always true  */
642
643
};

644
645
646
/**
 * walks up a tree of copies/perms/spills/reloads to find the original value
 * that is moved around
647
 */
648
649
static ir_node *find_original_value(ir_node *node)
{
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
	if (irn_visited(node))
		return NULL;

	mark_irn_visited(node);
	if (be_is_Copy(node)) {
		return find_original_value(be_get_Copy_op(node));
	} else if (be_is_CopyKeep(node)) {
		return find_original_value(be_get_CopyKeep_op(node));
	} else if (is_Proj(node)) {
		ir_node *pred = get_Proj_pred(node);
		if (be_is_Perm(pred)) {
			return find_original_value(get_irn_n(pred, get_Proj_proj(node)));
		} else if (be_is_MemPerm(pred)) {
			return find_original_value(get_irn_n(pred, get_Proj_proj(node) + 1));
		} else if (is_ia32_Load(pred)) {
			return find_original_value(get_irn_n(pred, n_ia32_Load_mem));
666
667
668
		} else {
			return node;
		}
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
	} else if (is_ia32_Store(node)) {
		return find_original_value(get_irn_n(node, n_ia32_Store_val));
	} else if (is_Phi(node)) {
		int i, arity;
		arity = get_irn_arity(node);
		for (i = 0; i < arity; ++i) {
			ir_node *in  = get_irn_n(node, i);
			ir_node *res = find_original_value(in);

			if (res != NULL)
				return res;
		}
		return NULL;
	} else {
		return node;
684
685
686
687
688
	}
}

static int determine_final_pnc(const ir_node *node, int flags_pos,
                               int pnc)
689
{
690
691
692
693
	ir_node           *flags = get_irn_n(node, flags_pos);
	const ia32_attr_t *flags_attr;
	flags = skip_Proj(flags);

Christoph Mallon's avatar
Christoph Mallon committed
694
	if (is_ia32_Sahf(flags)) {
695
		ir_node *cmp = get_irn_n(flags, n_ia32_Sahf_val);
Christoph Mallon's avatar
Christoph Mallon committed
696
		if (!(is_ia32_FucomFnstsw(cmp) || is_ia32_FucompFnstsw(cmp)
697
				|| is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp))) {
698
			inc_irg_visited(current_ir_graph);
699
			cmp = find_original_value(cmp);
700
			assert(cmp != NULL);
701
			assert(is_ia32_FucomFnstsw(cmp) || is_ia32_FucompFnstsw(cmp)
702
			       || is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp));
703
		}
704

705
		flags_attr = get_ia32_attr_const(cmp);
Christoph Mallon's avatar
Christoph Mallon committed
706
		if (flags_attr->data.ins_permuted)
707
708
			pnc = get_mirrored_pnc(pnc);
		pnc |= ia32_pn_Cmp_float;
Christoph Mallon's avatar
Christoph Mallon committed
709
	} else if (is_ia32_Ucomi(flags) || is_ia32_Fucomi(flags)
Matthias Braun's avatar
Matthias Braun committed
710
			|| is_ia32_Fucompi(flags)) {
711
712
		flags_attr = get_ia32_attr_const(flags);

Christoph Mallon's avatar
Christoph Mallon committed
713
		if (flags_attr->data.ins_permuted)
714
715
			pnc = get_mirrored_pnc(pnc);
		pnc |= ia32_pn_Cmp_float;
716
	} else {
717
718
		flags_attr = get_ia32_attr_const(flags);

Christoph Mallon's avatar
Christoph Mallon committed
719
		if (flags_attr->data.ins_permuted)
720
			pnc = get_mirrored_pnc(pnc);
Christoph Mallon's avatar
Christoph Mallon committed
721
		if (flags_attr->data.cmp_unsigned)
722
			pnc |= ia32_pn_Cmp_unsigned;
723
	}
724
725

	return pnc;
726
727
}

728
static void ia32_emit_cmp_suffix(int pnc)
729
{
730
731
	const char        *str;

Christoph Mallon's avatar
Christoph Mallon committed
732
	if ((pnc & ia32_pn_Cmp_float) || (pnc & ia32_pn_Cmp_unsigned)) {
733
734
735
736
737
738
739
740
741
		pnc = pnc & 7;
		assert(cmp2condition_u[pnc].num == pnc);
		str = cmp2condition_u[pnc].name;
	} else {
		pnc = pnc & 7;
		assert(cmp2condition_s[pnc].num == pnc);
		str = cmp2condition_s[pnc].name;
	}

742
	be_emit_string(str);
743
744
}

745
void ia32_emit_cmp_suffix_node(const ir_node *node,
746
747
                               int flags_pos)
{
748
749
	const ia32_attr_t *attr = get_ia32_attr_const(node);

Michael Beck's avatar
Michael Beck committed
750
	pn_Cmp pnc = get_ia32_condcode(node);
751
752

	pnc = determine_final_pnc(node, flags_pos, pnc);
Christoph Mallon's avatar
Christoph Mallon committed
753
754
	if (attr->data.ins_permuted) {
		if (pnc & ia32_pn_Cmp_float) {
755
756
757
758
759
760
			pnc = get_negated_pnc(pnc, mode_F);
		} else {
			pnc = get_negated_pnc(pnc, mode_Iu);
		}
	}

761
	ia32_emit_cmp_suffix(pnc);
762
}
763

764
765
766
/**
 * Returns the target block for a control flow node.
 */
Christoph Mallon's avatar
Christoph Mallon committed
767
768
static ir_node *get_cfop_target_block(const ir_node *irn)
{
769
	assert(get_irn_mode(irn) == mode_X);
770
771
772
	return get_irn_link(irn);
}

773
774
775
/**
 * Emits a block label for the given block.
 */
776
static void ia32_emit_block_name(const ir_node *block)
777
{
Michael Beck's avatar
Michael Beck committed
778
	if (has_Block_label(block)) {
779
		be_emit_string(be_gas_block_label_prefix());
780
		be_emit_irprintf("%lu", get_Block_label(block));
Michael Beck's avatar
Michael Beck committed
781
	} else {
782
		be_emit_cstring(BLOCK_PREFIX);
783
		be_emit_irprintf("%ld", get_irn_node_nr(block));
Michael Beck's avatar
Michael Beck committed
784
	}
785
786
}

787
788
789
790
791
792
/**
 * Emits an exception label for a given node.
 */
static void ia32_emit_exc_label(const ir_node *node)
{
	be_emit_string(be_gas_insn_label_prefix());
793
	be_emit_irprintf("%lu", get_ia32_exc_label_id(node));
794
795
}

Christian Würdig's avatar
Christian Würdig committed
796
/**
797
 * Emits the target label for a control flow node.
Christian Würdig's avatar
Christian Würdig committed
798
 */
799
800
static void ia32_emit_cfop_target(const ir_node *node)
{
801
	ir_node *block = get_cfop_target_block(node);
802

803
	ia32_emit_block_name(block);
Christian Würdig's avatar
Christian Würdig committed
804
}
805

806
807
808
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
Christoph Mallon's avatar
Christoph Mallon committed
809
810
static ir_node *get_proj(const ir_node *node, long proj)
{
811
812
813
	const ir_edge_t *edge;
	ir_node         *src;

814
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
815

816
	foreach_out_edge(node, edge) {
817
818
819
820
821
822
823
824
825
826
827
828
		src = get_edge_src_irn(edge);

		assert(is_Proj(src) && "Proj expected");
		if (get_irn_mode(src) == mode_M)
			continue;

		if (get_Proj_proj(src) == proj)
			return src;
	}
	return NULL;
}

829
static int can_be_fallthrough(const ir_node *node)
830
831
832
833
834
835
{
	ir_node *target_block = get_cfop_target_block(node);
	ir_node *block        = get_nodes_block(node);
	return get_prev_block_sched(target_block) == block;
}

Christian Würdig's avatar
Christian Würdig committed
836
837
838
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
839
static void emit_ia32_Jcc(const ir_node *node)
840
{
841
	int            need_parity_label = 0;
842
843
844
	const ir_node *proj_true;
	const ir_node *proj_false;
	const ir_node *block;
Michael Beck's avatar
Michael Beck committed
845
	pn_Cmp         pnc = get_ia32_condcode(node);
Christian Würdig's avatar
Christian Würdig committed
846

847
	pnc = determine_final_pnc(node, 0, pnc);
Christian Würdig's avatar
Christian Würdig committed
848

849
850
851
	/* get both Projs */
	proj_true = get_proj(node, pn_ia32_Jcc_true);
	assert(proj_true && "Jcc without true Proj");
852

853
854
	proj_false = get_proj(node, pn_ia32_Jcc_false);
	assert(proj_false && "Jcc without false Proj");
855

856
	block      = get_nodes_block(node);
857

858
	if (can_be_fallthrough(proj_true)) {
859
		/* exchange both proj's so the second one can be omitted */
860
861
		const ir_node *t = proj_true;

862
863
		proj_true  = proj_false;
		proj_false = t;
Christoph Mallon's avatar
Christoph Mallon committed
864
		if (pnc & ia32_pn_Cmp_float) {
865
866
867
868
			pnc = get_negated_pnc(pnc, mode_F);
		} else {
			pnc = get_negated_pnc(pnc, mode_Iu);
		}
869
870
	}

871
872
873
874
	if (pnc & ia32_pn_Cmp_float) {
		/* Some floating point comparisons require a test of the parity flag,
		 * which indicates that the result is unordered */
		switch (pnc & 15) {
875
			case pn_Cmp_Uo: {
876
877
878
				be_emit_cstring("\tjp ");
				ia32_emit_cfop_target(proj_true);
				be_emit_finish_line_gas(proj_true);
879
				break;
880
			}
881
882

			case pn_Cmp_Leg:
883
884
885
				be_emit_cstring("\tjnp ");
				ia32_emit_cfop_target(proj_true);
				be_emit_finish_line_gas(proj_true);
886
887
888
889
				break;

			case pn_Cmp_Eq:
			case pn_Cmp_Lt:
890
891
892
			case pn_Cmp_Le:
				/* we need a local label if the false proj is a fallthrough
				 * as the falseblock might have no label emitted then */
Michael Beck's avatar
Michael Beck committed
893
				if (can_be_fallthrough(proj_false)) {
894
895
896
897
898
899
					need_parity_label = 1;
					be_emit_cstring("\tjp 1f");
				} else {
					be_emit_cstring("\tjp ");
					ia32_emit_cfop_target(proj_false);
				}
900
				be_emit_finish_line_gas(proj_false);
901
				goto emit_jcc;
902
903
904

			case pn_Cmp_Ug:
			case pn_Cmp_Uge:
905
			case pn_Cmp_Ne:
906
907
908
				be_emit_cstring("\tjp ");
				ia32_emit_cfop_target(proj_true);
				be_emit_finish_line_gas(proj_true);
909
				goto emit_jcc;
910
911
912
913
914
915

			default:
				goto emit_jcc;
		}
	} else {
emit_jcc:
916
917
918
919
920
		be_emit_cstring("\tj");
		ia32_emit_cmp_suffix(pnc);
		be_emit_char(' ');
		ia32_emit_cfop_target(proj_true);
		be_emit_finish_line_gas(proj_true);
921
922
	}

Christoph Mallon's avatar
Christoph Mallon committed
923
	if (need_parity_label) {
924
925
926
927
		be_emit_cstring("1:");
		be_emit_write_line();
	}

928
	/* the second Proj might be a fallthrough */
Matthias Braun's avatar
Matthias Braun committed
929
930
	if (can_be_fallthrough(proj_false)) {
		be_emit_cstring("\t/* fallthrough to ");
931
		ia32_emit_cfop_target(proj_false);
Matthias Braun's avatar
Matthias Braun committed
932
		be_emit_cstring(" */");
933
		be_emit_finish_line_gas(proj_false);
934
	} else {
Matthias Braun's avatar
Matthias Braun committed
935
		be_emit_cstring("\tjmp ");