ia32_emitter.c 44.2 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
static const char *get_register_name_mode(const arch_register_t *reg,
                                          ir_mode *mode)
161
{
162
163
	if (mode == NULL)
		return reg->name;
164
165
	if (mode == ia32_mode_8h)
		return get_register_name_8bit_high(reg);
166
167
168
169
170
171
172
	unsigned size = get_mode_size_bits(mode);
	if (size == 8)
		return get_register_name_8bit_low(reg);
	else if (size == 16)
		return get_register_name_16bit(reg);
	else
		return reg->name;
173
174
}

175
176
177
178
179
/**
 * emit a register, possible shortened by a mode
 * @param reg   the register
 * @param mode  the mode of the register or NULL for full register
 */
180
static void emit_register(const arch_register_t *reg, ir_mode *mode)
181
{
182
	const char *name = get_register_name_mode(reg, mode);
183
	be_emit_char('%');
184
	be_emit_string(name);
Christian Würdig's avatar
Christian Würdig committed
185
186
}

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

Matthias Braun's avatar
Matthias Braun committed
197
static void ia32_emit_mode_suffix_mode(const ir_mode *mode)
198
{
199
	assert(mode_is_int(mode) || mode_is_reference(mode) || mode == ia32_mode_8h);
200
201
202
203
	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
204
205
		/* gas docu says q is the suffix but gcc, objdump and icc use ll
		 * apparently */
Matthias Braun's avatar
Matthias Braun committed
206
207
		case 64: be_emit_cstring("ll"); return;
	}
208
	panic("cannot output mode_suffix for %+F", mode);
Christian Würdig's avatar
Christian Würdig committed
209
210
}

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

217
	ir_mode *mode = get_ia32_ls_mode(node);
218
219
220
221
222
223
224
225
226
227
228
229
	assert(mode_is_float(mode));
	switch (get_mode_size_bits(mode)) {
		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;
	}
	panic("cannot output mode_suffix for %+F", mode);
}
230

231
232
233
234
235
236
237
238
239
240
241
static void ia32_emit_x87_mode_suffix_int(ir_node const *const node)
{
	assert(get_ia32_op_type(node) != ia32_Normal);
	ir_mode *mode = get_ia32_ls_mode(node);
	assert(mode_is_int(mode) || mode_is_reference(mode));
	switch (get_mode_size_bits(mode)) {
		case 16: be_emit_char('s');     return;
		case 32: be_emit_char('l');     return;
		/* gas docu says q is the suffix but gcc, objdump and icc use ll
		 * apparently */
		case 64: be_emit_cstring("ll"); return;
242
	}
243
	panic("cannot output mode_suffix for %+F", mode);
244
245
}

246
static char get_xmm_mode_suffix(ir_mode *mode)
247
248
{
	assert(mode_is_float(mode));
249
	switch (get_mode_size_bits(mode)) {
Christoph Mallon's avatar
Christoph Mallon committed
250
251
	case 32: return 's';
	case 64: return 'd';
252
	default: panic("invalid XMM mode");
253
254
255
	}
}

256
static void ia32_emit_xmm_mode_suffix(ir_node const *const node)
257
258
259
{
	ir_mode *mode = get_ia32_ls_mode(node);
	assert(mode != NULL);
260
	be_emit_char(get_xmm_mode_suffix(mode));
261
262
}

263
264
265
266
267
/**
 * Emits the target label for a control flow node.
 */
static void ia32_emit_cfop_target(const ir_node *node)
{
268
	ir_node *block = be_emit_get_cfop_target(node);
269
	be_gas_emit_block_name(block);
270
271
}

272
void x86_emit_condition_code(x86_condition_code_t cc)
273
274
{
	switch (cc) {
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
	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:
303
		break;
304
	}
305
	panic("invalid ia32 condition code");
306
307
}

308
typedef enum ia32_emit_mod_t {
309
	EMIT_NONE         = 0,
310
311
312
	EMIT_ALTERNATE_AM = 1U << 0,
	EMIT_LONG         = 1U << 1,
	EMIT_LOW_REG      = 1U << 2,
313
	EMIT_HIGH_REG     = 1U << 3,
314
315
	EMIT_16BIT_REG    = 1U << 4,
	EMIT_32BIT_REG    = 1U << 5,
316
	EMIT_SHIFT_COMMA  = 1U << 6,
317
} ia32_emit_mod_t;
318
ENUM_BITSET(ia32_emit_mod_t)
319

320
321
322
/**
 * Emits address mode.
 */
323
static void ia32_emit_am(ir_node const *const node)
324
{
325
	ia32_attr_t const *const attr = get_ia32_attr_const(node);
326
327
328
329
330
331
332
	/* 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);
333
334
}

335
void ia32_emitf(ir_node const *const node, char const *fmt, ...)
336
337
338
339
{
	va_list ap;
	va_start(ap, fmt);

340
	be_emit_char('\t');
341
	for (;;) {
342
		const char      *start = fmt;
343
		ia32_emit_mod_t  mod   = EMIT_NONE;
344
345
346
347
348
349
350
351

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

		if (*fmt == '\n') {
352
353
354
			be_emit_char('\n');
			be_emit_write_line();
			be_emit_char('\t');
355
356
357
358
359
360
361
			++fmt;
			if (*fmt == '\0')
				break;
			continue;
		}

		if (*fmt == '\0')
Christian Würdig's avatar
Christian Würdig committed
362
			break;
363
364

		++fmt;
365
366
		for (;;) {
			switch (*fmt) {
367
368
			case '*': mod |= EMIT_ALTERNATE_AM; break;
			case 'l': mod |= EMIT_LONG;         break;
369
			case '<': mod |= EMIT_LOW_REG;      break;
370
			case '>': mod |= EMIT_HIGH_REG;     break;
371
			case '^': mod |= EMIT_16BIT_REG;    break;
372
			case '#': mod |= EMIT_32BIT_REG;    break;
373
			case ',': mod |= EMIT_SHIFT_COMMA;  break;
374
375
376
			default:
				goto end_of_mods;
			}
377
378
			++fmt;
		}
379
end_of_mods:
380

381
		switch (*fmt++) {
382
383
384
			arch_register_t const *reg;
			ir_node         const *imm;

385
386
387
388
389
390
			case '%':
				be_emit_char('%');
				break;

			case 'A': {
				switch (*fmt++) {
391
					case 'F':
392
						if (get_ia32_op_type(node) == ia32_Normal) {
393
							ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
394
395
							char            const *const fmt  = attr->x87.res_in_reg ? "%%st, %%%s" : "%%%s, %%st";
							be_emit_irprintf(fmt, attr->x87.reg->name);
396
							break;
397
398
						} else {
							goto emit_AM;
399
400
						}

401
emit_AM:
402
					case 'M':
403
404
						if (mod & EMIT_ALTERNATE_AM)
							be_emit_char('*');
405
406
407
						ia32_emit_am(node);
						break;

408
409
					case 'R':
						reg = va_arg(ap, const arch_register_t*);
410
						if (get_ia32_op_type(node) == ia32_Normal) {
411
							goto emit_R;
412
413
						} else {
							goto emit_AM;
414
415
416
						}

					case 'S':
417
418
419
						if (get_ia32_op_type(node) == ia32_Normal) {
							goto emit_S;
						} else {
420
							++fmt;
421
							goto emit_AM;
422
423
424
425
426
427
428
						}

					default: goto unknown;
				}
				break;
			}

429
430
431
			case 'B': {
				ir_node const *const src = get_irn_n(node, n_ia32_binary_right);
				if (is_ia32_Immediate(src)) {
432
					emit_ia32_immediate_attr(true, src);
433
					be_emit_cstring(", ");
434
435
					if (get_ia32_op_type(node) == ia32_Normal) {
						goto destination_operand;
436
					} else {
437
						ia32_emit_am(node);
438
439
					}
				} else {
440
					if (get_ia32_op_type(node) == ia32_Normal) {
441
						reg = arch_get_irn_register(src);
442
						emit_register(reg, get_ia32_ls_mode(node));
443
444
					} else {
						ia32_emit_am(node);
445
446
					}
					be_emit_cstring(", ");
447
destination_operand:
448
449
450
451
					reg = arch_get_irn_register_in(node, n_ia32_binary_left);
					emit_register(reg, get_ia32_ls_mode(node));
				}
				break;
452
			}
453

454
			case 'D':
455
				if (!is_digit(*fmt))
456
					goto unknown;
457
				reg = arch_get_irn_register_out(node, *fmt++ - '0');
458
				goto emit_R;
459

460
461
462
463
464
465
			case 'E': {
				const ir_entity *const entity = va_arg(ap, const ir_entity*);
				be_gas_emit_entity(entity);
				break;
			}

466
467
468
			case 'F':
				if (*fmt == 'M') {
					ia32_emit_x87_mode_suffix(node);
469
470
				} else if (*fmt == 'I') {
					ia32_emit_x87_mode_suffix_int(node);
471
472
				} else if (*fmt == 'P') {
					ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
473
					if (attr->x87.pop)
474
						be_emit_char('p');
475
476
477
478
479
480
481
482
483
484
485
486
				} 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).
487
488
489
					 * 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. */
490
					if (get_ia32_x87_attr_const(node)->x87.reverse)
491
						be_emit_char('r');
492
493
				} else if (*fmt == 'X') {
					ia32_emit_xmm_mode_suffix(node);
494
				} else if (*fmt == '0') {
495
					be_emit_char('%');
496
					be_emit_string(get_ia32_x87_attr_const(node)->x87.reg->name);
497
498
499
				} else {
					goto unknown;
				}
500
				++fmt;
501
502
				break;

503
			case 'I':
504
505
				imm = node;
emit_I:
506
507
508
				if (mod & EMIT_SHIFT_COMMA) {
					const ia32_immediate_attr_t *attr
						= get_ia32_immediate_attr_const(imm);
509
					if (attr->imm.entity == NULL && attr->imm.offset == 1)
510
511
						break;
				}
512
				emit_ia32_immediate_attr(!(mod & EMIT_ALTERNATE_AM), imm);
513
514
515
				if (mod & EMIT_SHIFT_COMMA) {
					be_emit_char(',');
				}
516
517
518
519
520
521
				break;

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

522
523
524
			case 'M': {
				ir_mode *mode = get_ia32_ls_mode(node);
				if (!mode)
525
					mode = ia32_mode_gp;
526
				if (mod & EMIT_32BIT_REG) {
527
528
529
530
531
					if (get_mode_size_bits(mode) == 32)
						break;
					be_emit_char(mode_is_signed(mode) ? 's' : 'z');
				}
				ia32_emit_mode_suffix_mode(mode);
532
				break;
533
			}
534
535

			case 'P': {
536
				x86_condition_code_t cc;
537
538
				if (*fmt == 'X') {
					++fmt;
539
					cc = (x86_condition_code_t)va_arg(ap, int);
540
				} else if (is_digit(*fmt)) {
541
					cc = ia32_determine_final_cc(node, *fmt - '0');
yb9976's avatar
yb9976 committed
542
					++fmt;
543
544
545
				} else {
					goto unknown;
				}
546
				x86_emit_condition_code(cc);
547
548
549
				break;
			}

550
551
552
553
554
			case 'R':
				reg = va_arg(ap, const arch_register_t*);
emit_R:
				if (mod & EMIT_ALTERNATE_AM)
					be_emit_char('*');
555
				const char *name;
556
				if (mod & EMIT_HIGH_REG) {
557
					name = get_register_name_8bit_high(reg);
558
				} else if (mod & EMIT_LOW_REG) {
559
					name = get_register_name_8bit_low(reg);
560
				} else if (mod & EMIT_16BIT_REG) {
561
					name = get_register_name_16bit(reg);
562
563
				} else if (mod & EMIT_32BIT_REG) {
					name = reg->name;
564
				} else {
565
					name = get_register_name_mode(reg, get_ia32_ls_mode(node));
566
				}
567
568
				be_emit_char('%');
				be_emit_string(name);
569
570
571
				if (mod & EMIT_SHIFT_COMMA) {
					be_emit_char(',');
				}
572
573
574
575
				break;

emit_S:
			case 'S': {
576
				if (!is_digit(*fmt))
577
578
					goto unknown;

579
				unsigned pos = *fmt++ - '0';
580
581
582
				ir_node const *const src = get_irn_n(node, pos);
				if (is_ia32_Immediate(src)) {
					imm = src;
583
					goto emit_I;
584
				} else {
585
					reg = arch_get_irn_register(src);
586
					goto emit_R;
587
588
589
590
591
592
593
594
595
				}
			}

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

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
			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);
				}
614
615
616
617
				break;

			default:
unknown:
618
				panic("unknown format conversion");
619
		}
620
621
	}

622
	be_emit_finish_line_gas(node);
623
624
625
	va_end(ap);
}

626
627
628
/**
 * walks up a tree of copies/perms/spills/reloads to find the original value
 * that is moved around
629
 */
630
631
static ir_node *find_original_value(ir_node *node)
{
632
633
634
635
636
637
638
639
640
641
642
	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)) {
643
			return find_original_value(get_irn_n(pred, get_Proj_num(node)));
644
		} else if (be_is_MemPerm(pred)) {
645
			return find_original_value(get_irn_n(pred, get_Proj_num(node)));
646
647
		} 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
648
649
		} else if (is_ia32_Store(pred)) {
			return find_original_value(get_irn_n(pred, n_ia32_Store_val));
650
651
652
		} else {
			return node;
		}
653
	} else if (is_Phi(node)) {
654
		foreach_irn_in(node, i, in) {
655
656
657
658
659
660
661
			ir_node *res = find_original_value(in);
			if (res != NULL)
				return res;
		}
		return NULL;
	} else {
		return node;
662
663
664
	}
}

665
666
x86_condition_code_t ia32_determine_final_cc(ir_node const *const node,
                                             int const flags_pos)
667
{
668
669
670
671
672
	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);

673
	ir_node *flags = skip_Proj(get_irn_n(node, flags_pos));
674

675
	/* Permuted operands of a test instruction do not change the result. */
676
	if (is_ia32_Test(flags))
677
678
		return cc;

Christoph Mallon's avatar
Christoph Mallon committed
679
	if (is_ia32_Sahf(flags)) {
680
681
682
		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);
683
			inc_irg_visited(irg);
684
685
			flags = find_original_value(flags);
			assert(is_ia32_FucomFnstsw(flags) || is_ia32_FucomppFnstsw(flags) || is_ia32_FtstFnstsw(flags));
686
		}
687
	}
688

689
	ia32_attr_t const *const flags_attr = get_ia32_attr_const(flags);
690
	if (flags_attr->ins_permuted)
691
		cc = x86_invert_condition_code(cc);
692
	return cc;
693
694
}

695
696
697
698
699
700
/**
 * 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());
701
	be_emit_irprintf("%lu", get_ia32_exc_label_id(node));
702
703
}

704
static bool fallthrough_possible(const ir_node *block, const ir_node *target)
705
{
706
	return be_emit_get_prev_block(target) == block;
707
708
}

Christian Würdig's avatar
Christian Würdig committed
709
710
711
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
712
static void emit_ia32_Jcc(const ir_node *node)
713
{
714
	x86_condition_code_t cc = ia32_determine_final_cc(node, n_ia32_Jcc_eflags);
Christian Würdig's avatar
Christian Würdig committed
715

716
	/* get both Projs */
717
	ir_node const *proj_true   = get_Proj_for_pn(node, pn_ia32_Jcc_true);
718
	ir_node const *target_true = be_emit_get_cfop_target(proj_true);
719
	ir_node const *proj_false  = get_Proj_for_pn(node, pn_ia32_Jcc_false);
720
721
	ir_node const *block       = get_nodes_block(node);
	if (fallthrough_possible(block, target_true)) {
722
		/* exchange both proj's so the second one can be omitted */
723
724
		const ir_node *t = proj_true;

725
726
		proj_true  = proj_false;
		proj_false = t;
727
		cc         = x86_negate_condition_code(cc);
728
	}
729
	const ir_node *target_false = be_emit_get_cfop_target(proj_false);
730
731
732
733
734
735
736
737
738
739
740
741
742
743
	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);
		}
	}
744

745
	bool need_parity_label = false;
746
	if (cc & x86_cc_float_parity_cases) {
747
748
		/* Some floating point comparisons require a test of the parity flag,
		 * which indicates that the result is unordered */
749
		if (cc & x86_cc_negated) {
750
			ia32_emitf(proj_true, "jp %L");
751
		} else {
752
753
			/* we need a local label if the false proj is a fallthrough
			 * as the falseblock might have no label emitted then */
754
755
			if (fallthrough) {
				need_parity_label = true;
756
				ia32_emitf(proj_false, "jp 1f");
757
			} else {
758
				ia32_emitf(proj_false, "jp %L");
759
			}
760
		}
761
	}
762
	ia32_emitf(proj_true, "j%PX %L", (int)cc);
Christoph Mallon's avatar
Christoph Mallon committed
763
	if (need_parity_label) {
764
765
		be_emit_cstring("1:\n");
		be_emit_write_line();
766
767
	}

768
	/* the second Proj might be a fallthrough */
769
	if (fallthrough) {
770
		if (be_options.verbose_asm)
771
			ia32_emitf(proj_false, "/* fallthrough to %L */");
772
	} else {
773
		ia32_emitf(proj_false, "jmp %L");
774
	}
Michael Beck's avatar
Michael Beck committed
775
776
}

777
778
779
780
781
782
/**
 * Emits an ia32 Setcc. This is mostly easy but some floating point compares
 * are tricky.
 */
static void emit_ia32_Setcc(const ir_node *node)
{
783
	const arch_register_t *dreg = arch_get_irn_register_out(node, pn_ia32_Setcc_res);
784

785
786
	x86_condition_code_t const cc
		= ia32_determine_final_cc(node, n_ia32_Setcc_eflags);
787
788
	if (cc & x86_cc_float_parity_cases) {
		if (cc & x86_cc_negated) {
789
790
791
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setp %>R", dreg);
			ia32_emitf(node, "orb %>R, %<R", dreg, dreg);
792
		} else {
793
794
795
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setnp %>R", dreg);
			ia32_emitf(node, "andb %>R, %<R", dreg, dreg);
796
		}
797
	} else {
798
		ia32_emitf(node, "set%PX %R", (int)cc, dreg);
799
800
801
	}
}

802
803
void ia32_emit_jumptable_target(ir_entity const *const table,
                                ir_node const *const proj_x)
804
805
{
	(void)table;
806
	ir_node const *const block = be_emit_get_cfop_target(proj_x);
807
	be_gas_emit_block_name(block);
808
809
810
811
812
813
	switch (be_options.pic_style) {
	case BE_PIC_NONE:
		break;

	case BE_PIC_ELF_NO_PLT:
	case BE_PIC_ELF_PLT:
814
		be_emit_cstring("@GOTOFF");
815
816
817
		break;

	case BE_PIC_MACH_O:
818
819
		be_emit_char('-');
		be_emit_string(pic_base_label);
820
		break;
821
822
823
	}
}

824
/**
825
 * Emits code for a SwitchJmp
826
827
828
 */
static void emit_ia32_SwitchJmp(const ir_node *node)
{
829
830
	ia32_switch_attr_t const *const attr = get_ia32_switch_attr_const(node);
	ia32_emitf(node, "jmp %*AS0");
831
	be_emit_jump_table(node, attr->table, attr->table_entity, mode_P,
832
	                   ia32_emit_jumptable_target);
Christian Würdig's avatar
Christian Würdig committed
833
834
835
836
837
}

/**
 * Emits code for a unconditional jump.
 */
838
static void emit_ia32_Jmp(const ir_node *node)
839
{
840
	/* we have a block schedule */
841
	ir_node *block  = get_nodes_block(node);
842
	ir_node *target = be_emit_get_cfop_target(node);
843
	if (fallthrough_possible(block, target)) {
844
		if (be_options.verbose_asm)
845
			ia32_emitf(node, "/* fallthrough to %L */");
846
	} else {
847
		ia32_emitf(node, "jmp %L");
Christian Würdig's avatar
Christian Würdig committed
848
849
850
	}
}

851
852
853
854
855
856
857
858
859
static void emit_ia32_asm_register(const arch_register_t *reg, char modifier,
                                   ir_mode *mode)
{
	const char *name;
	switch (modifier) {
	case '\0': name = get_register_name_mode(reg, mode); 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;
860
	case  'k': name = reg->name; break;
861
	default:
862
		panic("invalid asm op modifier");
863
	}
864
865
	be_emit_char('%');
	be_emit_string(name);
866
867
}

868
869
static void emit_ia32_asm_operand(ir_node const *const node, char const modifier, unsigned const pos)
{
870
	x86_asm_operand_kind_t required;
871
872
873
874
875
876
	switch (modifier) {
	case '\0':
	case 'b':
	case 'h':
	case 'k':
	case 'w':
877
878
879
880
881
		required = ASM_OP_INVALID;
		break;

	case 'c':
		required = ASM_OP_IMMEDIATE;
882
883
884
885
886
887
888
		break;

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

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

	if (required != ASM_OP_INVALID && required != op->kind) {
893
894
895
		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);
896
897
898
		return;
	}

899
900
901
902
903
	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
904
905
		arch_register_t const *const reg
			= arch_get_irn_register_in(node, op->inout_pos);
906
907
908
909
910
		emit_ia32_asm_register(reg, modifier, op->u.mode);
		return;