ia32_emitter.c 44.7 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
 */
29
#include <inttypes.h>
30
#include <dlfcn.h>
Christian Würdig's avatar
Christian Würdig committed
31

32
#include "be_t.h"
33
#include "beasm.h"
34
#include "beblocksched.h"
35
#include "bediagnostic.h"
36
37
#include "beemithlp.h"
#include "beemitter.h"
38
#include "begnuas.h"
39
#include "bejit.h"
40
#include "besched.h"
41
#include "bestack.h"
42
#include "beutil.h"
43
#include "debug.h"
44
#include "execfreq.h"
Christian Würdig's avatar
Christian Würdig committed
45
#include "gen_ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
46
#include "gen_ia32_regalloc_if.h"
47
#include "ia32_architecture.h"
48
#include "ia32_bearch_t.h"
49
#include "ia32_emitter.h"
50
#include "ia32_encode.h"
51
52
#include "ia32_new_nodes.h"
#include "irgwalk.h"
53
#include "irnodehashmap.h"
54
55
#include "irtools.h"
#include "lc_opts.h"
56
#include "lc_opts_enum.h"
57
#include "panic.h"
Christian Würdig's avatar
Christian Würdig committed
58

59
60
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

61
62
63
static char       pic_base_label[128];
static ir_label_t exc_label_id;
static bool       mark_spill_reload;
64

65
static bool       omit_fp;
66
67
static int        frame_type_size;
static int        callframe_offset;
68
static ir_entity *thunks[N_ia32_gp_REGS];
69
static ir_type   *thunk_type;
70

71
72
73
74
75
76
77
typedef enum get_ip_style_t {
	IA32_GET_IP_POP,
	IA32_GET_IP_THUNK,
} get_ip_style_t;

static int get_ip_style = IA32_GET_IP_THUNK;

78
/** Checks if the current block is a fall-through target. */
79
static bool is_fallthrough(const ir_node *cfgpred)
80
{
Christoph Mallon's avatar
Christoph Mallon committed
81
	if (!is_Proj(cfgpred))
82
83
		return true;
	ir_node *pred = get_Proj_pred(cfgpred);
Christoph Mallon's avatar
Christoph Mallon committed
84
	if (is_ia32_SwitchJmp(pred))
85
86
		return false;
	return true;
87
88
}

89
90
91
92
/**
 * returns non-zero if the given block needs a label
 * because of being a jump-target (and not a fall-through)
 */
93
static bool block_needs_label(const ir_node *block)
94
{
95
	if (get_Block_entity(block) != NULL)
96
		return true;
97

98
	int n_cfgpreds = get_Block_n_cfgpreds(block);
99
	if (n_cfgpreds == 0) {
100
		return false;
101
	} else if (n_cfgpreds == 1) {
Christoph Mallon's avatar
Christoph Mallon committed
102
103
		ir_node *cfgpred       = get_Block_cfgpred(block, 0);
		ir_node *cfgpred_block = get_nodes_block(cfgpred);
104
105
106
107
108
		if (!is_fallthrough(cfgpred))
			return true;
		return be_emit_get_prev_block(block) != cfgpred_block;
	} else {
		return true;
109
110
111
	}
}

Michael Beck's avatar
Michael Beck committed
112
/**
113
 * Add a number to a prefix. This number will not be used a second time.
Michael Beck's avatar
Michael Beck committed
114
 */
115
116
static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
{
117
	static unsigned long id = 0;
118
	snprintf(buf, buflen, "%s%s%lu", be_gas_get_private_prefix(), prefix, ++id);
119
120
121
	return buf;
}

122
static const char *get_register_name_8bit_low(const arch_register_t *reg)
123
{
124
125
126
127
128
129
130
	switch (reg->global_index) {
	case REG_EAX: return "al";
	case REG_EBX: return "bl";
	case REG_ECX: return "cl";
	case REG_EDX: return "dl";
	}
	panic("unexpected register");
131
132
}

133
static const char *get_register_name_8bit_high(const arch_register_t *reg)
Michael Beck's avatar
Michael Beck committed
134
{
135
136
137
138
139
140
141
142
	switch (reg->global_index) {
	case REG_EAX: return "ah";
	case REG_EBX: return "bh";
	case REG_ECX: return "ch";
	case REG_EDX: return "dh";
	}
	panic("unexpected register");
}
Michael Beck's avatar
Michael Beck committed
143

144
145
146
147
148
149
150
151
152
153
154
155
156
static const char *get_register_name_16bit(const arch_register_t *reg)
{
	switch (reg->global_index) {
	case REG_EAX: return "ax";
	case REG_EBX: return "bx";
	case REG_ECX: return "cx";
	case REG_EDX: return "dx";
	case REG_ESI: return "si";
	case REG_EDI: return "di";
	case REG_ESP: return "sp";
	case REG_EBP: return "bp";
	}
	panic("unexpected register");
Michael Beck's avatar
Michael Beck committed
157
158
}

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
static const char *get_register_name_size(arch_register_t const *const reg,
                                          x86_insn_size_t const size,
                                          bool use_8bit_high)
{
	switch (size) {
	case X86_SIZE_8:
		return use_8bit_high ? get_register_name_8bit_high(reg)
		                     : get_register_name_8bit_low(reg);
	case X86_SIZE_16: return get_register_name_16bit(reg);
	case X86_SIZE_32: return reg->name;
	case X86_SIZE_64:
	case X86_SIZE_80:
	case X86_SIZE_128:
		break;
	}
	panic("Unexpected size");
175
176
}

177
178
179
/**
 * emit a register, possible shortened by a mode
 */
180
181
static void emit_register(arch_register_t const *const reg,
                          x86_insn_size_t const size, bool const use_8bit_high)
182
{
183
	const char *name = get_register_name_size(reg, size, use_8bit_high);
184
	be_emit_char('%');
185
	be_emit_string(name);
Christian Würdig's avatar
Christian Würdig committed
186
187
}

188
189
static void emit_ia32_immediate_attr(bool const prefix,
                                     ir_node const *const node)
190
{
191
192
	ia32_immediate_attr_t const *const attr
		= get_ia32_immediate_attr_const(node);
193
194
	if (prefix)
		be_emit_char('$');
195
	x86_emit_imm32(&attr->imm);
196
}
197

198
static void ia32_emit_mode_suffix(x86_insn_size_t const size)
199
{
200
201
202
203
204
205
206
207
208
209
	switch (size) {
	case X86_SIZE_8:  be_emit_char('b');     return;
	case X86_SIZE_16: be_emit_char('w');     return;
	case X86_SIZE_32: be_emit_char('l');     return;
	/* gas docu says q is the suffix but gcc, objdump and icc use ll
	 * apparently */
	case X86_SIZE_64: be_emit_cstring("ll"); return;
	case X86_SIZE_80:
	case X86_SIZE_128:
		break;
Matthias Braun's avatar
Matthias Braun committed
210
	}
211
	panic("Unexpected mode size");
Christian Würdig's avatar
Christian Würdig committed
212
213
}

214
static void ia32_emit_x87_mode_suffix(ir_node const *const node)
215
{
216
	/* we only need to emit the mode on address mode */
217
218
219
	if (get_ia32_op_type(node) == ia32_Normal)
		return;

220
221
222
223
224
225
226
227
228
229
230
	ia32_attr_t const *const attr = get_ia32_attr_const(node);
	switch (attr->size) {
	case X86_SIZE_32: be_emit_char('s'); return;
	case X86_SIZE_64: be_emit_char('l'); return;
	/* long doubles have different sizes due to alignment on different
	 * platforms. */
	case X86_SIZE_80:
	case X86_SIZE_128: be_emit_char('t'); return;
	case X86_SIZE_8:
	case X86_SIZE_16:
		break;
231
	}
232
	panic("Unexpected size");
233
}
234

235
236
237
static void ia32_emit_x87_mode_suffix_int(ir_node const *const node)
{
	assert(get_ia32_op_type(node) != ia32_Normal);
238
239
240
241
242
243
244
245
246
247
248
	ia32_attr_t const *const attr = get_ia32_attr_const(node);
	switch (attr->size) {
	case X86_SIZE_16: be_emit_char('s');     return;
	case X86_SIZE_32: be_emit_char('l');     return;
	/* gas docu says q is the suffix but gcc, objdump and icc use ll
	 * apparently */
	case X86_SIZE_64: be_emit_cstring("ll"); return;
	case X86_SIZE_8:
	case X86_SIZE_80:
	case X86_SIZE_128:
		break;
249
	}
250
	panic("Unexpected size");
251
252
}

253
static char get_xmm_mode_suffix(x86_insn_size_t const size)
254
{
255
256
257
258
259
260
261
262
	switch (size) {
	case X86_SIZE_32: return 's';
	case X86_SIZE_64: return 'd';
	case X86_SIZE_8:
	case X86_SIZE_16:
	case X86_SIZE_80:
	case X86_SIZE_128:
		break;
263
	}
264
	panic("invalid XMM mode");
265
266
}

267
static void ia32_emit_xmm_mode_suffix(ir_node const *const node)
268
{
269
270
	ia32_attr_t const *const attr = get_ia32_attr_const(node);
	be_emit_char(get_xmm_mode_suffix(attr->size));
271
272
}

273
274
275
276
277
/**
 * Emits the target label for a control flow node.
 */
static void ia32_emit_cfop_target(const ir_node *node)
{
278
	ir_node *block = be_emit_get_cfop_target(node);
279
	be_gas_emit_block_name(block);
280
281
}

282
void x86_emit_condition_code(x86_condition_code_t cc)
283
284
{
	switch (cc) {
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
	case x86_cc_overflow:      be_emit_cstring("o");  return;
	case x86_cc_not_overflow:  be_emit_cstring("no"); return;
	case x86_cc_float_below:
	case x86_cc_float_unordered_below:
	case x86_cc_below:         be_emit_cstring("b");  return;
	case x86_cc_float_above_equal:
	case x86_cc_float_unordered_above_equal:
	case x86_cc_above_equal:   be_emit_cstring("ae"); return;
	case x86_cc_float_equal:
	case x86_cc_equal:         be_emit_cstring("e");  return;
	case x86_cc_float_not_equal:
	case x86_cc_not_equal:     be_emit_cstring("ne"); return;
	case x86_cc_float_below_equal:
	case x86_cc_float_unordered_below_equal:
	case x86_cc_below_equal:   be_emit_cstring("be"); return;
	case x86_cc_float_above:
	case x86_cc_float_unordered_above:
	case x86_cc_above:         be_emit_cstring("a");  return;
	case x86_cc_sign:          be_emit_cstring("s");  return;
	case x86_cc_not_sign:      be_emit_cstring("ns"); return;
	case x86_cc_parity:        be_emit_cstring("p");  return;
	case x86_cc_not_parity:    be_emit_cstring("np"); return;
	case x86_cc_less:          be_emit_cstring("l");  return;
	case x86_cc_greater_equal: be_emit_cstring("ge"); return;
	case x86_cc_less_equal:    be_emit_cstring("le"); return;
	case x86_cc_greater:       be_emit_cstring("g");  return;
	case x86_cc_float_parity_cases:
	case x86_cc_additional_float_cases:
313
		break;
314
	}
315
	panic("invalid ia32 condition code");
316
317
}

318
typedef enum ia32_emit_mod_t {
319
	EMIT_NONE         = 0,
320
321
322
	EMIT_ALTERNATE_AM = 1U << 0,
	EMIT_LONG         = 1U << 1,
	EMIT_LOW_REG      = 1U << 2,
323
	EMIT_HIGH_REG     = 1U << 3,
324
325
	EMIT_16BIT_REG    = 1U << 4,
	EMIT_32BIT_REG    = 1U << 5,
326
	EMIT_SHIFT_COMMA  = 1U << 6,
327
} ia32_emit_mod_t;
328
ENUM_BITSET(ia32_emit_mod_t)
329

330
331
332
/**
 * Emits address mode.
 */
333
static void ia32_emit_am(ir_node const *const node)
334
{
335
	ia32_attr_t const *const attr = get_ia32_attr_const(node);
336
337
338
339
340
341
342
	/* Prepare a temporary x86_addr_t with input numbers set until the ia32
	 * backend sets them properly earlier. */
	x86_addr_t addr = attr->addr;
	addr.base_input  = n_ia32_base;
	addr.index_input = n_ia32_index;
	addr.mem_input   = n_ia32_mem;
	x86_emit_addr(node, &addr);
343
344
}

345
void ia32_emitf(ir_node const *const node, char const *fmt, ...)
346
347
348
349
{
	va_list ap;
	va_start(ap, fmt);

350
	be_emit_char('\t');
351
	for (;;) {
352
		const char      *start = fmt;
353
		ia32_emit_mod_t  mod   = EMIT_NONE;
354
355
356
357
358
359
360
361

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

		if (*fmt == '\n') {
362
363
364
			be_emit_char('\n');
			be_emit_write_line();
			be_emit_char('\t');
365
366
367
368
369
370
371
			++fmt;
			if (*fmt == '\0')
				break;
			continue;
		}

		if (*fmt == '\0')
Christian Würdig's avatar
Christian Würdig committed
372
			break;
373
374

		++fmt;
375
376
		for (;;) {
			switch (*fmt) {
377
378
			case '*': mod |= EMIT_ALTERNATE_AM; break;
			case 'l': mod |= EMIT_LONG;         break;
379
			case '<': mod |= EMIT_LOW_REG;      break;
380
			case '>': mod |= EMIT_HIGH_REG;     break;
381
			case '^': mod |= EMIT_16BIT_REG;    break;
382
			case '#': mod |= EMIT_32BIT_REG;    break;
383
			case ',': mod |= EMIT_SHIFT_COMMA;  break;
384
385
386
			default:
				goto end_of_mods;
			}
387
388
			++fmt;
		}
389
end_of_mods:
390

391
		switch (*fmt++) {
392
393
394
			arch_register_t const *reg;
			ir_node         const *imm;

395
396
397
398
399
400
			case '%':
				be_emit_char('%');
				break;

			case 'A': {
				switch (*fmt++) {
401
					case 'F':
402
						if (get_ia32_op_type(node) == ia32_Normal) {
403
							ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
404
405
							char            const *const fmt  = attr->x87.res_in_reg ? "%%st, %%%s" : "%%%s, %%st";
							be_emit_irprintf(fmt, attr->x87.reg->name);
406
							break;
407
408
						} else {
							goto emit_AM;
409
410
						}

411
emit_AM:
412
					case 'M':
413
414
						if (mod & EMIT_ALTERNATE_AM)
							be_emit_char('*');
415
416
417
						ia32_emit_am(node);
						break;

418
419
					case 'R':
						reg = va_arg(ap, const arch_register_t*);
420
						if (get_ia32_op_type(node) == ia32_Normal) {
421
							goto emit_R;
422
423
						} else {
							goto emit_AM;
424
425
426
						}

					case 'S':
427
428
429
						if (get_ia32_op_type(node) == ia32_Normal) {
							goto emit_S;
						} else {
430
							++fmt;
431
							goto emit_AM;
432
433
434
435
436
437
438
						}

					default: goto unknown;
				}
				break;
			}

439
			case 'B': {
440
				ia32_attr_t const *const attr = get_ia32_attr_const(node);
441
442
				ir_node const *const src = get_irn_n(node, n_ia32_binary_right);
				if (is_ia32_Immediate(src)) {
443
					emit_ia32_immediate_attr(true, src);
444
					be_emit_cstring(", ");
445
					if (attr->tp == ia32_Normal) {
446
						goto destination_operand;
447
					} else {
448
						ia32_emit_am(node);
449
450
					}
				} else {
451
					if (attr->tp == ia32_Normal) {
452
						reg = arch_get_irn_register(src);
453
						emit_register(reg, attr->size, attr->use_8bit_high);
454
455
					} else {
						ia32_emit_am(node);
456
457
					}
					be_emit_cstring(", ");
458
destination_operand:
459
					reg = arch_get_irn_register_in(node, n_ia32_binary_left);
460
					emit_register(reg, attr->size, attr->use_8bit_high);
461
462
				}
				break;
463
			}
464

465
			case 'D':
466
				if (!is_digit(*fmt))
467
					goto unknown;
468
				reg = arch_get_irn_register_out(node, *fmt++ - '0');
469
				goto emit_R;
470

471
472
473
474
475
476
			case 'E': {
				const ir_entity *const entity = va_arg(ap, const ir_entity*);
				be_gas_emit_entity(entity);
				break;
			}

477
478
479
			case 'F':
				if (*fmt == 'M') {
					ia32_emit_x87_mode_suffix(node);
480
481
				} else if (*fmt == 'I') {
					ia32_emit_x87_mode_suffix_int(node);
482
483
				} else if (*fmt == 'P') {
					ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
484
					if (attr->x87.pop)
485
						be_emit_char('p');
486
487
488
489
490
491
492
493
494
495
496
497
				} 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).
498
499
500
					 * 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. */
501
					if (get_ia32_x87_attr_const(node)->x87.reverse)
502
						be_emit_char('r');
503
504
				} else if (*fmt == 'X') {
					ia32_emit_xmm_mode_suffix(node);
505
				} else if (*fmt == '0') {
506
					be_emit_char('%');
507
					be_emit_string(get_ia32_x87_attr_const(node)->x87.reg->name);
508
509
510
				} else {
					goto unknown;
				}
511
				++fmt;
512
513
				break;

514
			case 'I':
515
516
				imm = node;
emit_I:
517
518
519
				if (mod & EMIT_SHIFT_COMMA) {
					const ia32_immediate_attr_t *attr
						= get_ia32_immediate_attr_const(imm);
520
					if (attr->imm.entity == NULL && attr->imm.offset == 1)
521
522
						break;
				}
523
				emit_ia32_immediate_attr(!(mod & EMIT_ALTERNATE_AM), imm);
524
525
526
				if (mod & EMIT_SHIFT_COMMA) {
					be_emit_char(',');
				}
527
528
529
530
531
532
				break;

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

533
			case 'M': {
534
				ia32_attr_t const *const attr = get_ia32_attr_const(node);
535
				if (mod & EMIT_32BIT_REG) {
536
537
					assert(is_ia32_Load(node) || is_ia32_Conv_I2I(node));
					if (attr->size == X86_SIZE_32)
538
						break;
539
					be_emit_char(attr->sign_extend ? 's' : 'z');
540
				}
541
				ia32_emit_mode_suffix(attr->size);
542
				break;
543
			}
544
545

			case 'P': {
546
				x86_condition_code_t cc;
547
548
				if (*fmt == 'X') {
					++fmt;
549
					cc = (x86_condition_code_t)va_arg(ap, int);
550
				} else if (is_digit(*fmt)) {
551
					cc = ia32_determine_final_cc(node, *fmt - '0');
552
					++fmt;
553
554
555
				} else {
					goto unknown;
				}
556
				x86_emit_condition_code(cc);
557
558
559
				break;
			}

560
561
562
563
564
			case 'R':
				reg = va_arg(ap, const arch_register_t*);
emit_R:
				if (mod & EMIT_ALTERNATE_AM)
					be_emit_char('*');
565
				const char *name;
566
				if (mod & EMIT_HIGH_REG) {
567
					name = get_register_name_8bit_high(reg);
568
				} else if (mod & EMIT_LOW_REG) {
569
					name = get_register_name_8bit_low(reg);
570
				} else if (mod & EMIT_16BIT_REG) {
571
					name = get_register_name_16bit(reg);
572
573
				} else if (mod & EMIT_32BIT_REG) {
					name = reg->name;
574
				} else {
575
576
577
					ia32_attr_t const *const attr = get_ia32_attr_const(node);
					name = get_register_name_size(reg, attr->size,
					                              attr->use_8bit_high);
578
				}
579
580
				be_emit_char('%');
				be_emit_string(name);
581
582
583
				if (mod & EMIT_SHIFT_COMMA) {
					be_emit_char(',');
				}
584
585
586
587
				break;

emit_S:
			case 'S': {
588
				if (!is_digit(*fmt))
589
590
					goto unknown;

591
				unsigned pos = *fmt++ - '0';
592
593
594
				ir_node const *const src = get_irn_n(node, pos);
				if (is_ia32_Immediate(src)) {
					imm = src;
595
					goto emit_I;
596
				} else {
597
					reg = arch_get_irn_register(src);
598
					goto emit_R;
599
600
601
602
603
604
605
606
607
				}
			}

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

608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
			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);
				}
626
627
628
629
				break;

			default:
unknown:
630
				panic("unknown format conversion");
631
		}
632
633
	}

634
	be_emit_finish_line_gas(node);
635
636
637
	va_end(ap);
}

638
639
640
/**
 * walks up a tree of copies/perms/spills/reloads to find the original value
 * that is moved around
641
 */
642
643
static ir_node *find_original_value(ir_node *node)
{
644
645
646
647
648
649
650
651
652
653
654
	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)) {
655
			return find_original_value(get_irn_n(pred, get_Proj_num(node)));
656
		} else if (be_is_MemPerm(pred)) {
657
			return find_original_value(get_irn_n(pred, get_Proj_num(node)));
658
659
		} 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
660
661
		} else if (is_ia32_Store(pred)) {
			return find_original_value(get_irn_n(pred, n_ia32_Store_val));
662
663
664
		} else {
			return node;
		}
665
	} else if (is_Phi(node)) {
666
		foreach_irn_in(node, i, in) {
667
668
669
670
671
672
673
			ir_node *res = find_original_value(in);
			if (res != NULL)
				return res;
		}
		return NULL;
	} else {
		return node;
674
675
676
	}
}

677
678
x86_condition_code_t ia32_determine_final_cc(ir_node const *const node,
                                             int const flags_pos)
679
{
680
681
682
683
684
	ia32_condcode_attr_t const *const attr = get_ia32_condcode_attr_const(node);
	x86_condition_code_t              cc   = attr->condition_code;
	if (attr->attr.ins_permuted)
		cc = x86_negate_condition_code(cc);

685
	ir_node *flags = skip_Proj(get_irn_n(node, flags_pos));
686

687
	/* Permuted operands of a test instruction do not change the result. */
688
	if (is_ia32_Test(flags))
689
690
		return cc;

Christoph Mallon's avatar
Christoph Mallon committed
691
	if (is_ia32_Sahf(flags)) {
692
693
694
		flags = get_irn_n(flags, n_ia32_Sahf_val);
		if (!is_ia32_FucomFnstsw(flags) && !is_ia32_FucomppFnstsw(flags) && !is_ia32_FtstFnstsw(flags)) {
			ir_graph *const irg = get_irn_irg(node);
695
			inc_irg_visited(irg);
696
697
			flags = find_original_value(flags);
			assert(is_ia32_FucomFnstsw(flags) || is_ia32_FucomppFnstsw(flags) || is_ia32_FtstFnstsw(flags));
698
		}
699
	}
700

701
	ia32_attr_t const *const flags_attr = get_ia32_attr_const(flags);
702
	if (flags_attr->ins_permuted)
703
		cc = x86_invert_condition_code(cc);
704
	return cc;
705
706
}

707
708
709
710
711
712
/**
 * 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());
713
	be_emit_irprintf("%lu", get_ia32_exc_label_id(node));
714
715
}

716
static bool fallthrough_possible(const ir_node *block, const ir_node *target)
717
{
718
	return be_emit_get_prev_block(target) == block;
719
720
}

Christian Würdig's avatar
Christian Würdig committed
721
722
723
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
724
static void emit_ia32_Jcc(const ir_node *node)
725
{
726
	x86_condition_code_t cc = ia32_determine_final_cc(node, n_ia32_Jcc_eflags);
Christian Würdig's avatar
Christian Würdig committed
727

728
	/* get both Projs */
729
	ir_node const *proj_true   = get_Proj_for_pn(node, pn_ia32_Jcc_true);
730
	ir_node const *target_true = be_emit_get_cfop_target(proj_true);
731
	ir_node const *proj_false  = get_Proj_for_pn(node, pn_ia32_Jcc_false);
732
733
	ir_node const *block       = get_nodes_block(node);
	if (fallthrough_possible(block, target_true)) {
734
		/* exchange both proj's so the second one can be omitted */
735
736
		const ir_node *t = proj_true;

737
738
		proj_true  = proj_false;
		proj_false = t;
739
		cc         = x86_negate_condition_code(cc);
740
	}
741
	const ir_node *target_false = be_emit_get_cfop_target(proj_false);
742
743
744
745
746
747
748
749
750
751
752
753
754
755
	bool           fallthrough  = fallthrough_possible(block, target_false);
	/* if we can't have a fallthrough anyway, put the more likely case first */
	if (!fallthrough) {
		/* We would need execfreq for the concrete edge, but don't have it
		 * available here, so we use the block execfreq :-( */
		double freq_true  = get_block_execfreq(target_true);
		double freq_false = get_block_execfreq(target_false);
		if (freq_false > freq_true) {
			const ir_node *t = proj_true;
			proj_true  = proj_false;
			proj_false = t;
			cc         = x86_negate_condition_code(cc);
		}
	}
756

757
	bool need_parity_label = false;
758
	if (cc & x86_cc_float_parity_cases) {
759
760
		/* Some floating point comparisons require a test of the parity flag,
		 * which indicates that the result is unordered */
761
		if (cc & x86_cc_negated) {
762
			ia32_emitf(proj_true, "jp %L");
763
		} else {
764
765
			/* we need a local label if the false proj is a fallthrough
			 * as the falseblock might have no label emitted then */
766
767
			if (fallthrough) {
				need_parity_label = true;
768
				ia32_emitf(proj_false, "jp 1f");
769
			} else {
770
				ia32_emitf(proj_false, "jp %L");
771
			}
772
		}
773
	}
774
	ia32_emitf(proj_true, "j%PX %L", (int)cc);
Christoph Mallon's avatar
Christoph Mallon committed
775
	if (need_parity_label) {
776
777
		be_emit_cstring("1:\n");
		be_emit_write_line();
778
779
	}

780
	/* the second Proj might be a fallthrough */
781
	if (!fallthrough) {
782
		ia32_emitf(proj_false, "jmp %L");
783
784
	} else if (be_options.verbose_asm) {
		ia32_emitf(proj_false, "/* fallthrough to %L */");
785
	}
Michael Beck's avatar
Michael Beck committed
786
787
}

788
789
790
791
792
793
/**
 * Emits an ia32 Setcc. This is mostly easy but some floating point compares
 * are tricky.
 */
static void emit_ia32_Setcc(const ir_node *node)
{
794
	const arch_register_t *dreg = arch_get_irn_register_out(node, pn_ia32_Setcc_res);
795

796
797
	x86_condition_code_t const cc
		= ia32_determine_final_cc(node, n_ia32_Setcc_eflags);
798
799
	if (cc & x86_cc_float_parity_cases) {
		if (cc & x86_cc_negated) {
800
801
802
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setp %>R", dreg);
			ia32_emitf(node, "orb %>R, %<R", dreg, dreg);
803
		} else {
804
805
806
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setnp %>R", dreg);
			ia32_emitf(node, "andb %>R, %<R", dreg, dreg);
807
		}
808
	} else {
809
		ia32_emitf(node, "set%PX %R", (int)cc, dreg);
810
811
812
	}
}

813
814
void ia32_emit_jumptable_target(ir_entity const *const table,
                                ir_node const *const proj_x)
815
816
{
	(void)table;
817
	ir_node const *const block = be_emit_get_cfop_target(proj_x);
818
	be_gas_emit_block_name(block);
819
820
821
822
823
824
	switch (be_options.pic_style) {
	case BE_PIC_NONE:
		break;

	case BE_PIC_ELF_NO_PLT:
	case BE_PIC_ELF_PLT:
825
		be_emit_cstring("@GOTOFF");
826
827
828
		break;

	case BE_PIC_MACH_O:
829
830
		be_emit_char('-');
		be_emit_string(pic_base_label);
831
		break;
832
833
834
	}
}

835
/**
836
 * Emits code for a SwitchJmp
837
838
839
 */
static void emit_ia32_SwitchJmp(const ir_node *node)
{
840
841
	ia32_switch_attr_t const *const attr = get_ia32_switch_attr_const(node);
	ia32_emitf(node, "jmp %*AS0");
842
	be_emit_jump_table(node, attr->table, attr->table_entity, mode_P,
843
	                   ia32_emit_jumptable_target);
Christian Würdig's avatar
Christian Würdig committed
844
845
846
847
848
}

/**
 * Emits code for a unconditional jump.
 */
849
static void emit_ia32_Jmp(const ir_node *node)
850
{
851
	/* we have a block schedule */
852
	ir_node *block  = get_nodes_block(node);
853
	ir_node *target = be_emit_get_cfop_target(node);
854
	if (!fallthrough_possible(block, target)) {
855
		ia32_emitf(node, "jmp %L");
856
857
	} else if (be_options.verbose_asm) {
		ia32_emitf(node, "/* fallthrough to %L */");
Christian Würdig's avatar
Christian Würdig committed
858
859
860
	}
}

861
862
863
864
865
static void emit_ia32_asm_register(const arch_register_t *reg, char modifier,
                                   ir_mode *mode)
{
	const char *name;
	switch (modifier) {
866
867
868
869
870
871
872
873
874
875
876
877
878
	case '\0': {
		if (mode_is_float(mode)) {
			name = reg->name;
		} else {
			x86_insn_size_t const size = x86_size_from_mode(mode);
			name = get_register_name_size(reg, size, false);
		}
		break;
	}
	case 'b': name = get_register_name_8bit_low(reg); break;
	case 'h': name = get_register_name_8bit_high(reg); break;
	case 'w': name = get_register_name_16bit(reg); break;
	case 'k': name = reg->name; break;
879
	default:
880
		panic("invalid asm op modifier");
881
	}
882
883
	be_emit_char('%');
	be_emit_string(name);
884
885
}

886
887
static void emit_ia32_asm_operand(ir_node const *const node, char const modifier, unsigned const pos)
{
888
	x86_asm_operand_kind_t required;
889
890
891
892
893
894
	switch (modifier) {
	case '\0':
	case 'b':
	case 'h':
	case 'k':
	case 'w':
895
896
897
898
899
		required = ASM_OP_INVALID;
		break;

	case 'c':
		required = ASM_OP_IMMEDIATE;
900
901
902
903
904
905
906
		break;

	default:
		be_errorf(node, "asm contains unknown modifier '%c'", modifier);
		return;
	}

907
908
	be_asm_attr_t     const *const attr = get_be_asm_attr_const(node);
	x86_asm_operand_t const *const op   = &((x86_asm_operand_t const*)attr->operands)[pos];
909
910

	if (required != ASM_OP_INVALID && required != op->kind) {
911
912
913
		char const *const want = x86_get_constraint_name(required);
		char const *const have = x86_get_constraint_name(op->kind);
		be_errorf(node, "modifier of operand '%%%c%u' requires an operand of type '%s', but got '%s'", modifier, pos, want, have);
914
915
916
		return;
	}

917
918
919
920
921
	switch ((x86_asm_operand_kind_t)op->kind) {
	case ASM_OP_INVALID:
		panic("invalid asm operand");

	case ASM_OP_IN_REG: {
Matthias Braun's avatar
Cleanup    
Matthias Braun committed
922
923
		arch_register_t const *const reg
			= arch_get_irn_register_in(node, op->inout_pos);
924
925
926
927
928
		emit_ia32_asm_register(reg, modifier, op->u.mode);
		return;
	}

	case ASM_OP_OUT_REG: {
Matthias Braun's avatar
Cleanup    
Matthias Braun committed
929
930
		arch_register_t const *const reg
			= arch_get_irn_register_out(node, op->inout_pos);
931
932
933
934
935
		emit_ia32_asm_register(reg, modifier, op->u.mode);
		return;
	}

	case ASM_OP_MEMORY: {
Matthias Braun's avatar
Cleanup    
Matthias Braun committed
936
937
		arch_register_t const *const reg
			= arch_get_irn_register_in(node, op->inout_pos);
938
939
940
941
942
		be_emit_irprintf("(%%%s)", reg->name);
		return;
	}

	case ASM_OP_IMMEDIATE:
943
944
945
		if (modifier != 'c')
			be_emit_char('$');
		x86_emit_imm32(&op->u.imm32);
946
947
948
949
950
		return;
	}
	panic("invalid asm operand kind");
}

951
952
953
/**
 * Emits code for an ASM pseudo op.
 */
954
static void emit_ia32_Asm(const ir_node *node)
955
{
956
	be_emit_asm(node, emit_ia32_asm_operand);