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
			inc_irg_visited(current_ir_graph);
760
			cmp = find_original_value(cmp);
761
			assert(cmp != NULL);
762
			assert(is_ia32_FucomFnstsw(cmp) || is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp));
763
		}
764

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

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

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

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

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

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

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

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

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

817
	if (cc & ia32_cc_float_parity_cases) {
818
819
		/* Some floating point comparisons require a test of the parity flag,
		 * which indicates that the result is unordered */
820
		if (cc & ia32_cc_negated) {
821
			ia32_emitf(proj_true, "jp %L");
822
		} else {
823
824
825
826
			/* 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;
827
				ia32_emitf(proj_false, "jp 1f");
828
			} else {
829
				ia32_emitf(proj_false, "jp %L");
830
			}
831
		}
832
	}
833
	ia32_emitf(proj_true, "j%PX %L", (int)cc);
Christoph Mallon's avatar
Christoph Mallon committed
834
	if (need_parity_label) {
835
836
		be_emit_cstring("1:\n");
		be_emit_write_line();
837
838
	}

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

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

856
857
858
859
	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) {
860
861
862
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setp %>R", dreg);
			ia32_emitf(node, "orb %>R, %<R", dreg, dreg);
863
		} else {
864
865
866
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setnp %>R", dreg);
			ia32_emitf(node, "andb %>R, %<R", dreg, dreg);
867
		}
868
	} else {
869
		ia32_emitf(node, "set%PX %#R", (int)cc, dreg);
870
871
872
873
	}
}

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

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

889
890
	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));
891
892

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

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

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

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

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

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

917
/**
918
 * Emits code for a SwitchJmp
919
920
921
 */
static void emit_ia32_SwitchJmp(const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
922
923
	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
924

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

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

Michael Beck's avatar
Michael Beck committed
943
944
945
946
947
948
949
950
/**
 * 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
 */
951
static const char* emit_asm_operand(const ir_node *node, const char *s)
952
{
953
954
955
	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);
956
	const arch_register_t *reg;
957
958
	const ia32_asm_reg_t  *asm_regs = attr->register_map;
	const ia32_asm_reg_t  *asm_reg;
959
960
	char                   c;
	char                   modifier =