ia32_emitter.c 88.3 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

6
/**
7
 * @file
Christian Würdig's avatar
Christian Würdig committed
8
9
 * @brief       This file implements the ia32 node emitter.
 * @author      Christian Wuerdig, Matthias Braun
10
11
 *
 * Summary table for x86 floatingpoint compares:
12
13
 * (remember effect of unordered on x86: ZF=1, PF=1, CF=1)
 *
14
15
16
17
18
 *   pnc_Eq  => !P && E
 *   pnc_Lt  => !P && B
 *   pnc_Le  => !P && BE
 *   pnc_Gt  => A
 *   pnc_Ge  => AE
19
 *   pnc_Lg  => NE
20
21
22
23
24
25
26
 *   pnc_Leg => NP  (ordered)
 *   pnc_Uo  => P
 *   pnc_Ue  => E
 *   pnc_Ul  => B
 *   pnc_Ule => BE
 *   pnc_Ug  => P || A
 *   pnc_Uge => P || AE
27
 *   pnc_Ne  => P || NE
28
 */
Christian Würdig's avatar
Christian Würdig committed
29
30
#include <limits.h>

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

48
49
50
#include "besched.h"
#include "benode.h"
#include "beabi.h"
51
#include "bedwarf.h"
52
53
#include "beemitter.h"
#include "begnuas.h"
54
#include "beutil.h"
Christian Würdig's avatar
Christian Würdig committed
55

56
#include "ia32_emitter.h"
57
#include "ia32_common_transform.h"
Christian Würdig's avatar
Christian Würdig committed
58
#include "gen_ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
59
#include "gen_ia32_regalloc_if.h"
60
61
#include "ia32_nodes_attr.h"
#include "ia32_new_nodes.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
static const ia32_isa_t *isa;
68
static char              pic_base_label[128];
69
static ir_label_t        exc_label_id;
70
static int               mark_spill_reload = 0;
71
static int               do_pic;
72

73
74
75
76
static bool              sp_relative;
static int               frame_type_size;
static int               callframe_offset;

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

83
/** Checks if the current block is a fall-through target. */
84
static int is_fallthrough(const ir_node *cfgpred)
85
86
87
{
	ir_node *pred;

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

94
	return 1;
95
96
}

97
98
99
100
/**
 * returns non-zero if the given block needs a label
 * because of being a jump-target (and not a fall-through)
 */
101
static int block_needs_label(const ir_node *block)
102
{
103
	int need_label = 1;
104
105
	int  n_cfgpreds = get_Block_n_cfgpreds(block);

106
	if (get_Block_entity(block) != NULL)
107
108
		return 1;

109
	if (n_cfgpreds == 0) {
110
		need_label = 0;
111
	} else if (n_cfgpreds == 1) {
Christoph Mallon's avatar
Christoph Mallon committed
112
113
		ir_node *cfgpred       = get_Block_cfgpred(block, 0);
		ir_node *cfgpred_block = get_nodes_block(cfgpred);
114
115
116

		if (get_prev_block_sched(block) == cfgpred_block
				&& is_fallthrough(cfgpred)) {
117
			need_label = 0;
118
119
120
121
122
123
		}
	}

	return need_label;
}

Michael Beck's avatar
Michael Beck committed
124
/**
125
 * Add a number to a prefix. This number will not be used a second time.
Michael Beck's avatar
Michael Beck committed
126
 */
127
128
static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
{
129
	static unsigned long id = 0;
130
	snprintf(buf, buflen, "%s%s%lu", be_gas_get_private_prefix(), prefix, ++id);
131
132
133
	return buf;
}

Michael Beck's avatar
Michael Beck committed
134
135
136
/**
 * Emit the name of the 8bit low register
 */
137
138
static void emit_8bit_register(const arch_register_t *reg)
{
139
140
	assert(reg->index == REG_GP_EAX || reg->index == REG_GP_EBX
			|| reg->index == REG_GP_ECX || reg->index == REG_GP_EDX);
Christian Würdig's avatar
Christian Würdig committed
141

142
	be_emit_char('%');
143
	be_emit_char(reg->name[1]); /* get the basic name of the register */
144
145
146
	be_emit_char('l');
}

Michael Beck's avatar
Michael Beck committed
147
148
149
150
151
/**
 * Emit the name of the 8bit high register
 */
static void emit_8bit_register_high(const arch_register_t *reg)
{
152
153
	assert(reg->index == REG_GP_EAX || reg->index == REG_GP_EBX
			|| reg->index == REG_GP_ECX || reg->index == REG_GP_EDX);
Michael Beck's avatar
Michael Beck committed
154
155

	be_emit_char('%');
156
	be_emit_char(reg->name[1]); /* get the basic name of the register */
Michael Beck's avatar
Michael Beck committed
157
158
159
	be_emit_char('h');
}

160
161
162
static void emit_16bit_register(const arch_register_t *reg)
{
	be_emit_char('%');
163
	be_emit_string(reg->name + 1); /* skip the 'e' prefix of the 32bit names */
164
165
}

166
167
168
169
170
171
/**
 * emit a register, possible shortened by a mode
 *
 * @param reg   the register
 * @param mode  the mode of the register or NULL for full register
 */
172
173
static void emit_register(const arch_register_t *reg, const ir_mode *mode)
{
Christoph Mallon's avatar
Christoph Mallon committed
174
	if (mode != NULL) {
175
		int size = get_mode_size_bits(mode);
Christoph Mallon's avatar
Christoph Mallon committed
176
177
178
		switch (size) {
			case  8: emit_8bit_register(reg);  return;
			case 16: emit_16bit_register(reg); return;
179
		}
Christoph Mallon's avatar
Christoph Mallon committed
180
		assert(mode_is_float(mode) || size == 32);
181
182
183
	}

	be_emit_char('%');
184
	be_emit_string(reg->name);
Christian Würdig's avatar
Christian Würdig committed
185
186
}

187
188
static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
{
189
	be_gas_emit_entity(entity);
190
191

	if (get_entity_owner(entity) == get_tls_type()) {
Matthias Braun's avatar
Matthias Braun committed
192
		if (!entity_has_definition(entity)) {
193
194
195
196
197
198
			be_emit_cstring("@INDNTPOFF");
		} else {
			be_emit_cstring("@NTPOFF");
		}
	}

199
	if (do_pic && !no_pic_adjust && get_entity_type(entity) != get_code_type()) {
200
201
202
203
204
205
206
207
208
209
210
211
		be_emit_char('-');
		be_emit_string(pic_base_label);
	}
}

static void emit_ia32_Immediate_no_prefix(const ir_node *node)
{
	const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);

	if (attr->symconst != NULL) {
		if (attr->sc_sign)
			be_emit_char('-');
212
		ia32_emit_entity(attr->symconst, attr->no_pic_adjust);
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
	}
	if (attr->symconst == NULL || attr->offset != 0) {
		if (attr->symconst != NULL) {
			be_emit_irprintf("%+d", attr->offset);
		} else {
			be_emit_irprintf("0x%X", attr->offset);
		}
	}
}

static void emit_ia32_Immediate(const ir_node *node)
{
	be_emit_char('$');
	emit_ia32_Immediate_no_prefix(node);
}
228

Matthias Braun's avatar
Matthias Braun committed
229
static void ia32_emit_mode_suffix_mode(const ir_mode *mode)
230
{
231
232
233
234
235
	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
236
237
		/* gas docu says q is the suffix but gcc, objdump and icc use ll
		 * apparently */
Matthias Braun's avatar
Matthias Braun committed
238
239
		case 64: be_emit_cstring("ll"); return;
	}
240
	panic("Can't output mode_suffix for %+F", mode);
Christian Würdig's avatar
Christian Würdig committed
241
242
}

243
static void ia32_emit_x87_mode_suffix(ir_node const *const node)
244
{
245
246
	ir_mode *mode;

247
	/* we only need to emit the mode on address mode */
248
249
250
251
252
253
254
255
	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)) {
256
257
258
259
260
261
262
			case  32: be_emit_char('s'); return;
			case  64: be_emit_char('l'); return;
			/* long doubles have different sizes due to alignment on different
			 * platforms. */
			case  80:
			case  96:
			case 128: be_emit_char('t'); return;
263
264
		}
	} else {
265
		assert(mode_is_int(mode) || mode_is_reference(mode));
266
267
268
269
270
271
272
		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;
		}
273
	}
274
	panic("Can't output mode_suffix for %+F", mode);
275
276
}

277
static char get_xmm_mode_suffix(ir_mode *mode)
278
279
{
	assert(mode_is_float(mode));
280
	switch (get_mode_size_bits(mode)) {
Christoph Mallon's avatar
Christoph Mallon committed
281
282
283
	case 32: return 's';
	case 64: return 'd';
	default: panic("Invalid XMM mode");
284
285
286
	}
}

287
static void ia32_emit_xmm_mode_suffix(ir_node const *const node)
288
289
290
{
	ir_mode *mode = get_ia32_ls_mode(node);
	assert(mode != NULL);
291
	be_emit_char(get_xmm_mode_suffix(mode));
292
293
}

Christian Würdig's avatar
Christian Würdig committed
294
/**
295
 * Returns the target block for a control flow node.
Christian Würdig's avatar
Christian Würdig committed
296
 */
297
static ir_node *get_cfop_target_block(const ir_node *irn)
Christoph Mallon's avatar
Christoph Mallon committed
298
{
299
	assert(get_irn_mode(irn) == mode_X);
300
	return (ir_node*)get_irn_link(irn);
301
}
Christian Würdig's avatar
Christian Würdig committed
302

303
304
305
306
307
308
/**
 * Emits the target label for a control flow node.
 */
static void ia32_emit_cfop_target(const ir_node *node)
{
	ir_node *block = get_cfop_target_block(node);
309
	be_gas_emit_block_name(block);
310
311
}

Michael Beck's avatar
Michael Beck committed
312
313
314
/**
 * Emit the suffix for a compare instruction.
 */
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
static void ia32_emit_condition_code(ia32_condition_code_t cc)
{
	switch (cc) {
	case ia32_cc_overflow:      be_emit_cstring("o");  return;
	case ia32_cc_not_overflow:  be_emit_cstring("no"); return;
	case ia32_cc_float_below:
	case ia32_cc_float_unordered_below:
	case ia32_cc_below:         be_emit_cstring("b");  return;
	case ia32_cc_float_above_equal:
	case ia32_cc_float_unordered_above_equal:
	case ia32_cc_above_equal:   be_emit_cstring("ae"); return;
	case ia32_cc_float_equal:
	case ia32_cc_equal:         be_emit_cstring("e");  return;
	case ia32_cc_float_not_equal:
	case ia32_cc_not_equal:     be_emit_cstring("ne"); return;
	case ia32_cc_float_below_equal:
	case ia32_cc_float_unordered_below_equal:
	case ia32_cc_below_equal:   be_emit_cstring("be"); return;
	case ia32_cc_float_above:
	case ia32_cc_float_unordered_above:
	case ia32_cc_above:         be_emit_cstring("a");  return;
	case ia32_cc_sign:          be_emit_cstring("s");  return;
	case ia32_cc_not_sign:      be_emit_cstring("ns"); return;
	case ia32_cc_parity:        be_emit_cstring("p");  return;
	case ia32_cc_not_parity:    be_emit_cstring("np"); return;
	case ia32_cc_less:          be_emit_cstring("l");  return;
	case ia32_cc_greater_equal: be_emit_cstring("ge"); return;
	case ia32_cc_less_equal:    be_emit_cstring("le"); return;
	case ia32_cc_greater:       be_emit_cstring("g");  return;
	case ia32_cc_float_parity_cases:
	case ia32_cc_additional_float_cases:
		break;
347
	}
348
	panic("Invalid ia32 condition code");
349
350
}

351
typedef enum ia32_emit_mod_t {
352
	EMIT_NONE         = 0,
353
	EMIT_RESPECT_LS   = 1U << 0,
354
	EMIT_ALTERNATE_AM = 1U << 1,
355
356
	EMIT_LONG         = 1U << 2,
	EMIT_HIGH_REG     = 1U << 3,
357
358
	EMIT_LOW_REG      = 1U << 4,
	EMIT_16BIT_REG    = 1U << 5
359
} ia32_emit_mod_t;
360
ENUM_BITSET(ia32_emit_mod_t)
361

362
363
364
/**
 * Emits address mode.
 */
365
static void ia32_emit_am(ir_node const *const node)
366
367
368
369
370
{
	ir_entity *ent       = get_ia32_am_sc(node);
	int        offs      = get_ia32_am_offs_int(node);
	ir_node   *base      = get_irn_n(node, n_ia32_base);
	int        has_base  = !is_ia32_NoReg_GP(base);
371
372
	ir_node   *idx       = get_irn_n(node, n_ia32_index);
	int        has_index = !is_ia32_NoReg_GP(idx);
373
374
375
376

	/* just to be sure... */
	assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);

377
378
379
	if (get_ia32_am_tls_segment(node))
		be_emit_cstring("%gs:");

380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
	/* emit offset */
	if (ent != NULL) {
		const ia32_attr_t *attr = get_ia32_attr_const(node);
		if (is_ia32_am_sc_sign(node))
			be_emit_char('-');
		ia32_emit_entity(ent, attr->data.am_sc_no_pic_adjust);
	}

	/* also handle special case if nothing is set */
	if (offs != 0 || (ent == NULL && !has_base && !has_index)) {
		if (ent != NULL) {
			be_emit_irprintf("%+d", offs);
		} else {
			be_emit_irprintf("%d", offs);
		}
	}

	if (has_base || has_index) {
		be_emit_char('(');

		/* emit base */
		if (has_base) {
402
			const arch_register_t *reg = arch_get_irn_register_in(node, n_ia32_base);
403
404
405
406
407
			emit_register(reg, NULL);
		}

		/* emit index + scale */
		if (has_index) {
408
			const arch_register_t *reg = arch_get_irn_register_in(node, n_ia32_index);
409
410
411
412
413
414
415
416
417
418
419
420
421
			int scale;
			be_emit_char(',');
			emit_register(reg, NULL);

			scale = get_ia32_am_scale(node);
			if (scale > 0) {
				be_emit_irprintf(",%d", 1 << scale);
			}
		}
		be_emit_char(')');
	}
}

422
423
424
static ia32_condition_code_t determine_final_cc(ir_node const *node, int flags_pos, ia32_condition_code_t cc);

void ia32_emitf(ir_node const *const node, char const *fmt, ...)
425
426
427
428
{
	va_list ap;
	va_start(ap, fmt);

429
	be_emit_char('\t');
430
	for (;;) {
431
		const char      *start = fmt;
432
		ia32_emit_mod_t  mod   = EMIT_NONE;
433
434
435
436
437
438
439
440

		while (*fmt != '%' && *fmt != '\n' && *fmt != '\0')
			++fmt;
		if (fmt != start) {
			be_emit_string_len(start, fmt - start);
		}

		if (*fmt == '\n') {
441
442
443
			be_emit_char('\n');
			be_emit_write_line();
			be_emit_char('\t');
444
445
446
447
448
449
450
			++fmt;
			if (*fmt == '\0')
				break;
			continue;
		}

		if (*fmt == '\0')
Christian Würdig's avatar
Christian Würdig committed
451
			break;
452
453

		++fmt;
454
455
		for (;;) {
			switch (*fmt) {
456
457
458
			case '*': mod |= EMIT_ALTERNATE_AM; break;
			case '#': mod |= EMIT_RESPECT_LS;   break;
			case 'l': mod |= EMIT_LONG;         break;
459
460
			case '>': mod |= EMIT_HIGH_REG;     break;
			case '<': mod |= EMIT_LOW_REG;      break;
461
			case '^': mod |= EMIT_16BIT_REG;    break;
462
463
464
			default:
				goto end_of_mods;
			}
465
466
			++fmt;
		}
467
end_of_mods:
468

469
		switch (*fmt++) {
470
471
472
			arch_register_t const *reg;
			ir_node         const *imm;

473
474
475
476
477
478
			case '%':
				be_emit_char('%');
				break;

			case 'A': {
				switch (*fmt++) {
479
					case 'F':
480
						if (get_ia32_op_type(node) == ia32_Normal) {
481
482
483
							ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
							char            const *const fmt  = attr->res_in_reg ? "%%st, %%%s" : "%%%s, %%st";
							be_emit_irprintf(fmt, attr->reg->name);
484
							break;
485
486
						} else {
							goto emit_AM;
487
488
						}

489
emit_AM:
490
					case 'M':
491
492
						if (mod & EMIT_ALTERNATE_AM)
							be_emit_char('*');
493
494
495
						ia32_emit_am(node);
						break;

496
497
					case 'R':
						reg = va_arg(ap, const arch_register_t*);
498
						if (get_ia32_op_type(node) == ia32_Normal) {
499
							goto emit_R;
500
501
						} else {
							goto emit_AM;
502
503
504
						}

					case 'S':
505
506
507
						if (get_ia32_op_type(node) == ia32_Normal) {
							goto emit_S;
						} else {
508
							++fmt;
509
							goto emit_AM;
510
511
512
513
514
515
516
						}

					default: goto unknown;
				}
				break;
			}

517
518
519
520
521
			case 'B':
				imm = get_irn_n(node, n_ia32_binary_right);
				if (is_ia32_Immediate(imm)) {
					emit_ia32_Immediate(imm);
					be_emit_cstring(", ");
522
523
					if (get_ia32_op_type(node) == ia32_Normal) {
						goto destination_operand;
524
					} else {
525
						ia32_emit_am(node);
526
527
					}
				} else {
528
					if (get_ia32_op_type(node) == ia32_Normal) {
529
530
						reg = arch_get_irn_register_in(node, n_ia32_binary_right);
						emit_register(reg, get_ia32_ls_mode(node));
531
532
					} else {
						ia32_emit_am(node);
533
534
					}
					be_emit_cstring(", ");
535
destination_operand:
536
537
538
539
540
					reg = arch_get_irn_register_in(node, n_ia32_binary_left);
					emit_register(reg, get_ia32_ls_mode(node));
				}
				break;

541
			case 'D':
542
				if (*fmt < '0' || '9' < *fmt)
543
					goto unknown;
544
				reg = arch_get_irn_register_out(node, *fmt++ - '0');
545
				goto emit_R;
546

547
548
549
			case 'F':
				if (*fmt == 'M') {
					ia32_emit_x87_mode_suffix(node);
550
551
552
553
				} else if (*fmt == 'P') {
					ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
					if (attr->pop)
						be_emit_char('p');
554
555
556
557
558
559
560
561
562
563
564
565
				} else if (*fmt == 'R') {
					/* NOTE: Work around a gas quirk for non-commutative operations if the
					 * destination register is not %st0.  In this case r/non-r is swapped.
					 * %st0 = %st0 - %st1 -> fsub  %st1, %st0 (as expected)
					 * %st0 = %st1 - %st0 -> fsubr %st1, %st0 (as expected)
					 * %st1 = %st0 - %st1 -> fsub  %st0, %st1 (expected: fsubr)
					 * %st1 = %st1 - %st0 -> fsubr %st0, %st1 (expected: fsub)
					 * In fact this corresponds to the encoding of the instruction:
					 * - The r suffix selects whether %st0 is on the left (no r) or on the
					 *   right (r) side of the executed operation.
					 * - The placement of %st0 selects whether the result is written to
					 *   %st0 (right) or the other register (left).
566
567
568
569
					 * This means that it is sufficient to test whether the operands are
					 * permuted.  In particular it is not necessary to consider wether the
					 * result is to be placed into the explicit register operand. */
					if (get_ia32_x87_attr_const(node)->attr.data.ins_permuted)
570
						be_emit_char('r');
571
572
				} else if (*fmt == 'X') {
					ia32_emit_xmm_mode_suffix(node);
573
				} else if (*fmt == '0') {
574
					be_emit_char('%');
575
					be_emit_string(get_ia32_x87_attr_const(node)->reg->name);
576
577
578
				} else {
					goto unknown;
				}
579
				++fmt;
580
581
				break;

582
			case 'I':
583
584
				imm = node;
emit_I:
585
586
				if (!(mod & EMIT_ALTERNATE_AM))
					be_emit_char('$');
587
				emit_ia32_Immediate_no_prefix(imm);
588
589
590
591
592
593
				break;

			case 'L':
				ia32_emit_cfop_target(node);
				break;

594
595
596
597
598
599
600
601
602
603
			case 'M': {
				ir_mode *mode = get_ia32_ls_mode(node);
				if (!mode)
					mode = mode_Iu;
				if (mod & EMIT_RESPECT_LS) {
					if (get_mode_size_bits(mode) == 32)
						break;
					be_emit_char(mode_is_signed(mode) ? 's' : 'z');
				}
				ia32_emit_mode_suffix_mode(mode);
604
				break;
605
			}
606
607

			case 'P': {
608
609
610
611
612
613
614
				ia32_condition_code_t cc;
				if (*fmt == 'X') {
					++fmt;
					cc = (ia32_condition_code_t)va_arg(ap, int);
				} else if ('0' <= *fmt && *fmt <= '9') {
					cc = get_ia32_condcode(node);
					cc = determine_final_cc(node, *fmt - '0', cc);
yb9976's avatar
yb9976 committed
615
					++fmt;
616
617
618
				} else {
					goto unknown;
				}
619
				ia32_emit_condition_code(cc);
620
621
622
				break;
			}

623
624
625
626
627
			case 'R':
				reg = va_arg(ap, const arch_register_t*);
emit_R:
				if (mod & EMIT_ALTERNATE_AM)
					be_emit_char('*');
628
629
630
631
				if (mod & EMIT_HIGH_REG) {
					emit_8bit_register_high(reg);
				} else if (mod & EMIT_LOW_REG) {
					emit_8bit_register(reg);
632
633
				} else if (mod & EMIT_16BIT_REG) {
					emit_16bit_register(reg);
634
635
636
				} else {
					emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
				}
637
638
639
640
				break;

emit_S:
			case 'S': {
641
				unsigned pos;
642

643
				if (*fmt < '0' || '9' < *fmt)
644
645
646
					goto unknown;

				pos = *fmt++ - '0';
647
648
649
				imm = get_irn_n(node, pos);
				if (is_ia32_Immediate(imm)) {
					goto emit_I;
650
				} else {
651
					reg = arch_get_irn_register_in(node, pos);
652
					goto emit_R;
653
654
655
656
657
658
659
660
661
				}
			}

			case 's': {
				const char *str = va_arg(ap, const char*);
				be_emit_string(str);
				break;
			}

662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
			case 'u':
				if (mod & EMIT_LONG) {
					unsigned long num = va_arg(ap, unsigned long);
					be_emit_irprintf("%lu", num);
				} else {
					unsigned num = va_arg(ap, unsigned);
					be_emit_irprintf("%u", num);
				}
				break;

			case 'd':
				if (mod & EMIT_LONG) {
					long num = va_arg(ap, long);
					be_emit_irprintf("%ld", num);
				} else {
					int num = va_arg(ap, int);
					be_emit_irprintf("%d", num);
				}
680
681
682
683
				break;

			default:
unknown:
684
				panic("unknown format conversion");
685
		}
686
687
	}

688
	be_emit_finish_line_gas(node);
689
690
691
	va_end(ap);
}

Matthias Braun's avatar
Matthias Braun committed
692
693
694
static void emit_ia32_IMul(const ir_node *node)
{
	ir_node               *left    = get_irn_n(node, n_ia32_IMul_left);
695
	const arch_register_t *out_reg = arch_get_irn_register_out(node, pn_ia32_IMul_res);
Matthias Braun's avatar
Matthias Braun committed
696
697

	/* do we need the 3-address form? */
Christoph Mallon's avatar
Christoph Mallon committed
698
	if (is_ia32_NoReg_GP(left) ||
699
			arch_get_irn_register_in(node, n_ia32_IMul_left) != out_reg) {
700
		ia32_emitf(node, "imul%M %#S4, %#AS3, %#D0");
701
	} else {
702
		ia32_emitf(node, "imul%M %#AS4, %#S3");
Matthias Braun's avatar
Matthias Braun committed
703
704
705
	}
}

706
707
708
/**
 * walks up a tree of copies/perms/spills/reloads to find the original value
 * that is moved around
709
 */
710
711
static ir_node *find_original_value(ir_node *node)
{
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
	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));
Andreas Zwinkau's avatar
Andreas Zwinkau committed
728
729
		} else if (is_ia32_Store(pred)) {
			return find_original_value(get_irn_n(pred, n_ia32_Store_val));
730
731
732
		} else {
			return node;
		}
733
734
735
736
737
738
739
740
741
742
743
744
745
	} 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;
746
747
748
	}
}

749
750
static ia32_condition_code_t determine_final_cc(const ir_node *node,
		int flags_pos, ia32_condition_code_t cc)
751
{
752
753
754
755
	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
756
	if (is_ia32_Sahf(flags)) {
757
		ir_node *cmp = get_irn_n(flags, n_ia32_Sahf_val);
758
		if (!(is_ia32_FucomFnstsw(cmp) || is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp))) {
759
760
			ir_graph *irg = get_irn_irg(node);
			inc_irg_visited(irg);
761
			cmp = find_original_value(cmp);
762
			assert(cmp != NULL);
763
			assert(is_ia32_FucomFnstsw(cmp) || is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp));
764
		}
765

766
		flags_attr = get_ia32_attr_const(cmp);
767
	} else {
768
		flags_attr = get_ia32_attr_const(flags);
769
	}
770

771
772
773
	if (flags_attr->data.ins_permuted)
		cc = ia32_invert_condition_code(cc);
	return cc;
774
775
}

776
777
778
779
780
781
/**
 * 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());
782
	be_emit_irprintf("%lu", get_ia32_exc_label_id(node));
783
784
}

785
static int can_be_fallthrough(const ir_node *node)
786
787
788
789
790
791
{
	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
792
793
794
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
795
static void emit_ia32_Jcc(const ir_node *node)
796
{
797
798
	int                   need_parity_label = 0;
	ia32_condition_code_t cc                = get_ia32_condcode(node);
Christian Würdig's avatar
Christian Würdig committed
799

800
	cc = determine_final_cc(node, 0, cc);
Christian Würdig's avatar
Christian Würdig committed
801

802
	/* get both Projs */
803
	ir_node const *proj_true = be_get_Proj_for_pn(node, pn_ia32_Jcc_true);
804
	assert(proj_true && "Jcc without true Proj");
805

806
	ir_node const *proj_false = be_get_Proj_for_pn(node, pn_ia32_Jcc_false);
807
	assert(proj_false && "Jcc without false Proj");
808

809
	if (can_be_fallthrough(proj_true)) {
810
		/* exchange both proj's so the second one can be omitted */
811
812
		const ir_node *t = proj_true;

813
814
		proj_true  = proj_false;
		proj_false = t;
815
		cc         = ia32_negate_condition_code(cc);
816
817
	}

818
	if (cc & ia32_cc_float_parity_cases) {
819
820
		/* Some floating point comparisons require a test of the parity flag,
		 * which indicates that the result is unordered */
821
		if (cc & ia32_cc_negated) {
822
			ia32_emitf(proj_true, "jp %L");
823
		} else {
824
825
826
827
			/* we need a local label if the false proj is a fallthrough
			 * as the falseblock might have no label emitted then */
			if (can_be_fallthrough(proj_false)) {
				need_parity_label = 1;
828
				ia32_emitf(proj_false, "jp 1f");
829
			} else {
830
				ia32_emitf(proj_false, "jp %L");
831
			}
832
		}
833
	}
834
	ia32_emitf(proj_true, "j%PX %L", (int)cc);
Christoph Mallon's avatar
Christoph Mallon committed
835
	if (need_parity_label) {
836
837
		be_emit_cstring("1:\n");
		be_emit_write_line();
838
839
	}

840
	/* the second Proj might be a fallthrough */
Matthias Braun's avatar
Matthias Braun committed
841
	if (can_be_fallthrough(proj_false)) {
842
		if (be_options.verbose_asm)
843
			ia32_emitf(proj_false, "/* fallthrough to %L */");
844
	} else {
845
		ia32_emitf(proj_false, "jmp %L");
846
	}
Michael Beck's avatar
Michael Beck committed
847
848
}

849
850
851
852
853
854
/**
 * Emits an ia32 Setcc. This is mostly easy but some floating point compares
 * are tricky.
 */
static void emit_ia32_Setcc(const ir_node *node)
{
855
	const arch_register_t *dreg = arch_get_irn_register_out(node, pn_ia32_Setcc_res);
856

857
858
859
860
	ia32_condition_code_t cc = get_ia32_condcode(node);
	cc = determine_final_cc(node, n_ia32_Setcc_eflags, cc);
	if (cc & ia32_cc_float_parity_cases) {
		if (cc & ia32_cc_negated) {
861
862
863
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setp %>R", dreg);
			ia32_emitf(node, "orb %>R, %<R", dreg, dreg);
864
		} else {
865
866
867
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setnp %>R", dreg);
			ia32_emitf(node, "andb %>R, %<R", dreg, dreg);
868
		}
869
	} else {
870
		ia32_emitf(node, "set%PX %#R", (int)cc, dreg);
871
872
873
874
	}
}

static void emit_ia32_CMovcc(const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
875
{
876
	const ia32_attr_t     *attr = get_ia32_attr_const(node);
877
	const arch_register_t *out  = arch_get_irn_register_out(node, pn_ia32_res);
878
	ia32_condition_code_t  cc   = get_ia32_condcode(node);
879
880
881
	const arch_register_t *in_true;
	const arch_register_t *in_false;

882
	cc = determine_final_cc(node, n_ia32_CMovcc_eflags, cc);
883
	/* although you can't set ins_permuted in the constructor it might still
884
885
886
	 * be set by memory operand folding
	 * Permuting inputs of a cmov means the condition is negated!
	 */
887
	if (attr->data.ins_permuted)
888
		cc = ia32_negate_condition_code(cc);
889

890
891
	in_true  = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_true));
	in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_false));
892
893

	/* should be same constraint fullfilled? */
Christoph Mallon's avatar
Christoph Mallon committed
894
	if (out == in_false) {
895
		/* yes -> nothing to do */
Christoph Mallon's avatar
Christoph Mallon committed
896
	} else if (out == in_true) {
897
898
		const arch_register_t *tmp;

899
900
		assert(get_ia32_op_type(node) == ia32_Normal);

901
		cc = ia32_negate_condition_code(cc);
902
903
904
905

		tmp      = in_true;
		in_true  = in_false;
		in_false = tmp;
906
	} else {
907
		/* we need a mov */
908
		ia32_emitf(node, "movl %R, %R", in_false, out);
909
	}
910

911
912
	if (cc & ia32_cc_float_parity_cases) {
		panic("CMov with floatingpoint compare/parity not supported yet");
913
	}
914

915
	ia32_emitf(node, "cmov%PX %#AR, %#R", (int)cc, in_true, out);
916
917
}

918
/**
919
 * Emits code for a SwitchJmp
920
921
922
 */
static void emit_ia32_SwitchJmp(const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
923
924
	ir_entity             *jump_table = get_ia32_am_sc(node);
	const ir_switch_table *table      = get_ia32_switch_table(node);
Christian Würdig's avatar
Christian Würdig committed
925

926
	ia32_emitf(node, "jmp %*AM");
Matthias Braun's avatar
Matthias Braun committed
927
	be_emit_jump_table(node, table, jump_table, get_cfop_target_block);
Christian Würdig's avatar
Christian Würdig committed
928
929
930
931
932
}

/**
 * Emits code for a unconditional jump.
 */
933
static void emit_ia32_Jmp(const ir_node *node)
934
{
935
	/* we have a block schedule */
936
	if (can_be_fallthrough(node)) {
937
		if (be_options.verbose_asm)
938
			ia32_emitf(node, "/* fallthrough to %L */");
939
	} else {
940
		ia32_emitf(node, "jmp %L");
Christian Würdig's avatar
Christian Würdig committed
941
942
943
	}
}

Michael Beck's avatar
Michael Beck committed
944
945
946
947
948
949
950
951
/**
 * Emit an inline assembler operand.
 *
 * @param node  the ia32_ASM node
 * @param s     points to the operand (a %c)
 *
 * @return  pointer to the first char in s NOT in the current operand
 */
952
static const char* emit_asm_operand(const ir_node *node, const char *s)
953
{
954
955
956
	const ia32_attr_t     *ia32_attr = get_ia32_attr_const(node);
	const ia32_asm_attr_t *attr      = CONST_CAST_IA32_ATTR(ia32_asm_attr_t,
                                                            ia32_attr);
957
	const arch_register_t *reg;