ia32_emitter.c 88.6 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
	EMIT_LOW_REG      = 1U << 4,
358
359
	EMIT_16BIT_REG    = 1U << 5,
	EMIT_SHIFT_COMMA  = 1U << 6,
360
} ia32_emit_mod_t;
361
ENUM_BITSET(ia32_emit_mod_t)
362

363
364
365
/**
 * Emits address mode.
 */
366
static void ia32_emit_am(ir_node const *const node)
367
368
369
370
371
{
	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);
372
373
	ir_node   *idx       = get_irn_n(node, n_ia32_index);
	int        has_index = !is_ia32_NoReg_GP(idx);
374
375
376
377

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

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

381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
	/* 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) {
403
			const arch_register_t *reg = arch_get_irn_register_in(node, n_ia32_base);
404
405
406
407
408
			emit_register(reg, NULL);
		}

		/* emit index + scale */
		if (has_index) {
409
			const arch_register_t *reg = arch_get_irn_register_in(node, n_ia32_index);
410
411
412
413
414
415
416
417
418
419
420
421
422
			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(')');
	}
}

423
424
425
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, ...)
426
427
428
429
{
	va_list ap;
	va_start(ap, fmt);

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

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

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

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

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

471
		switch (*fmt++) {
472
473
474
			arch_register_t const *reg;
			ir_node         const *imm;

475
476
477
478
479
480
			case '%':
				be_emit_char('%');
				break;

			case 'A': {
				switch (*fmt++) {
481
					case 'F':
482
						if (get_ia32_op_type(node) == ia32_Normal) {
483
484
485
							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);
486
							break;
487
488
						} else {
							goto emit_AM;
489
490
						}

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

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

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

					default: goto unknown;
				}
				break;
			}

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

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

549
550
551
			case 'F':
				if (*fmt == 'M') {
					ia32_emit_x87_mode_suffix(node);
552
553
554
555
				} else if (*fmt == 'P') {
					ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(node);
					if (attr->pop)
						be_emit_char('p');
556
557
558
559
560
561
562
563
564
565
566
567
				} 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).
568
569
570
571
					 * 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)
572
						be_emit_char('r');
573
574
				} else if (*fmt == 'X') {
					ia32_emit_xmm_mode_suffix(node);
575
				} else if (*fmt == '0') {
576
					be_emit_char('%');
577
					be_emit_string(get_ia32_x87_attr_const(node)->reg->name);
578
579
580
				} else {
					goto unknown;
				}
581
				++fmt;
582
583
				break;

584
			case 'I':
585
586
				imm = node;
emit_I:
587
588
589
590
591
592
				if (mod & EMIT_SHIFT_COMMA) {
					const ia32_immediate_attr_t *attr
						= get_ia32_immediate_attr_const(imm);
					if (attr->symconst == NULL && attr->offset == 1)
						break;
				}
593
594
				if (!(mod & EMIT_ALTERNATE_AM))
					be_emit_char('$');
595
				emit_ia32_Immediate_no_prefix(imm);
596
597
598
				if (mod & EMIT_SHIFT_COMMA) {
					be_emit_char(',');
				}
599
600
601
602
603
604
				break;

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

605
606
607
608
609
610
611
612
613
614
			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);
615
				break;
616
			}
617
618

			case 'P': {
619
620
621
622
623
624
625
				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
626
					++fmt;
627
628
629
				} else {
					goto unknown;
				}
630
				ia32_emit_condition_code(cc);
631
632
633
				break;
			}

634
635
636
637
638
			case 'R':
				reg = va_arg(ap, const arch_register_t*);
emit_R:
				if (mod & EMIT_ALTERNATE_AM)
					be_emit_char('*');
639
640
641
642
				if (mod & EMIT_HIGH_REG) {
					emit_8bit_register_high(reg);
				} else if (mod & EMIT_LOW_REG) {
					emit_8bit_register(reg);
643
644
				} else if (mod & EMIT_16BIT_REG) {
					emit_16bit_register(reg);
645
646
647
				} else {
					emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
				}
648
649
650
				if (mod & EMIT_SHIFT_COMMA) {
					be_emit_char(',');
				}
651
652
653
654
				break;

emit_S:
			case 'S': {
655
				unsigned pos;
656

657
				if (*fmt < '0' || '9' < *fmt)
658
659
660
					goto unknown;

				pos = *fmt++ - '0';
661
662
663
				imm = get_irn_n(node, pos);
				if (is_ia32_Immediate(imm)) {
					goto emit_I;
664
				} else {
665
					reg = arch_get_irn_register_in(node, pos);
666
					goto emit_R;
667
668
669
670
671
672
673
674
675
				}
			}

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

676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
			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);
				}
694
695
696
697
				break;

			default:
unknown:
698
				panic("unknown format conversion");
699
		}
700
701
	}

702
	be_emit_finish_line_gas(node);
703
704
705
	va_end(ap);
}

Matthias Braun's avatar
Matthias Braun committed
706
707
708
static void emit_ia32_IMul(const ir_node *node)
{
	ir_node               *left    = get_irn_n(node, n_ia32_IMul_left);
709
	const arch_register_t *out_reg = arch_get_irn_register_out(node, pn_ia32_IMul_res);
Matthias Braun's avatar
Matthias Braun committed
710
711

	/* do we need the 3-address form? */
Christoph Mallon's avatar
Christoph Mallon committed
712
	if (is_ia32_NoReg_GP(left) ||
713
			arch_get_irn_register_in(node, n_ia32_IMul_left) != out_reg) {
714
		ia32_emitf(node, "imul%M %#S4, %#AS3, %#D0");
715
	} else {
716
		ia32_emitf(node, "imul%M %#AS4, %#S3");
Matthias Braun's avatar
Matthias Braun committed
717
718
719
	}
}

720
721
722
/**
 * walks up a tree of copies/perms/spills/reloads to find the original value
 * that is moved around
723
 */
724
725
static ir_node *find_original_value(ir_node *node)
{
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
	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
742
743
		} else if (is_ia32_Store(pred)) {
			return find_original_value(get_irn_n(pred, n_ia32_Store_val));
744
745
746
		} else {
			return node;
		}
747
748
749
750
751
752
753
754
755
756
757
758
759
	} 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;
760
761
762
	}
}

763
764
static ia32_condition_code_t determine_final_cc(const ir_node *node,
		int flags_pos, ia32_condition_code_t cc)
765
{
766
767
768
769
	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
770
	if (is_ia32_Sahf(flags)) {
771
		ir_node *cmp = get_irn_n(flags, n_ia32_Sahf_val);
772
		if (!(is_ia32_FucomFnstsw(cmp) || is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp))) {
773
774
			ir_graph *irg = get_irn_irg(node);
			inc_irg_visited(irg);
775
			cmp = find_original_value(cmp);
776
			assert(cmp != NULL);
777
			assert(is_ia32_FucomFnstsw(cmp) || is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp));
778
		}
779

780
		flags_attr = get_ia32_attr_const(cmp);
781
	} else {
782
		flags_attr = get_ia32_attr_const(flags);
783
	}
784

785
786
787
	if (flags_attr->data.ins_permuted)
		cc = ia32_invert_condition_code(cc);
	return cc;
788
789
}

790
791
792
793
794
795
/**
 * 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());
796
	be_emit_irprintf("%lu", get_ia32_exc_label_id(node));
797
798
}

799
static int can_be_fallthrough(const ir_node *node)
800
801
802
803
804
805
{
	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
806
807
808
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
809
static void emit_ia32_Jcc(const ir_node *node)
810
{
811
812
	int                   need_parity_label = 0;
	ia32_condition_code_t cc                = get_ia32_condcode(node);
Christian Würdig's avatar
Christian Würdig committed
813

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

816
	/* get both Projs */
817
	ir_node const *proj_true = be_get_Proj_for_pn(node, pn_ia32_Jcc_true);
818
	assert(proj_true && "Jcc without true Proj");
819

820
	ir_node const *proj_false = be_get_Proj_for_pn(node, pn_ia32_Jcc_false);
821
	assert(proj_false && "Jcc without false Proj");
822

823
	if (can_be_fallthrough(proj_true)) {
824
		/* exchange both proj's so the second one can be omitted */
825
826
		const ir_node *t = proj_true;

827
828
		proj_true  = proj_false;
		proj_false = t;
829
		cc         = ia32_negate_condition_code(cc);
830
831
	}

832
	if (cc & ia32_cc_float_parity_cases) {
833
834
		/* Some floating point comparisons require a test of the parity flag,
		 * which indicates that the result is unordered */
835
		if (cc & ia32_cc_negated) {
836
			ia32_emitf(proj_true, "jp %L");
837
		} else {
838
839
840
841
			/* 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;
842
				ia32_emitf(proj_false, "jp 1f");
843
			} else {
844
				ia32_emitf(proj_false, "jp %L");
845
			}
846
		}
847
	}
848
	ia32_emitf(proj_true, "j%PX %L", (int)cc);
Christoph Mallon's avatar
Christoph Mallon committed
849
	if (need_parity_label) {
850
851
		be_emit_cstring("1:\n");
		be_emit_write_line();
852
853
	}

854
	/* the second Proj might be a fallthrough */
Matthias Braun's avatar
Matthias Braun committed
855
	if (can_be_fallthrough(proj_false)) {
856
		if (be_options.verbose_asm)
857
			ia32_emitf(proj_false, "/* fallthrough to %L */");
858
	} else {
859
		ia32_emitf(proj_false, "jmp %L");
860
	}
Michael Beck's avatar
Michael Beck committed
861
862
}

863
864
865
866
867
868
/**
 * Emits an ia32 Setcc. This is mostly easy but some floating point compares
 * are tricky.
 */
static void emit_ia32_Setcc(const ir_node *node)
{
869
	const arch_register_t *dreg = arch_get_irn_register_out(node, pn_ia32_Setcc_res);
870

871
872
873
874
	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) {
875
876
877
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setp %>R", dreg);
			ia32_emitf(node, "orb %>R, %<R", dreg, dreg);
878
		} else {
879
880
881
			ia32_emitf(node, "set%PX %<R", (int)cc, dreg);
			ia32_emitf(node, "setnp %>R", dreg);
			ia32_emitf(node, "andb %>R, %<R", dreg, dreg);
882
		}
883
	} else {
884
		ia32_emitf(node, "set%PX %#R", (int)cc, dreg);
885
886
887
888
	}
}

static void emit_ia32_CMovcc(const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
889
{
890
	const ia32_attr_t     *attr = get_ia32_attr_const(node);
891
	const arch_register_t *out  = arch_get_irn_register_out(node, pn_ia32_res);
892
	ia32_condition_code_t  cc   = get_ia32_condcode(node);
893
894
895
	const arch_register_t *in_true;
	const arch_register_t *in_false;

896
	cc = determine_final_cc(node, n_ia32_CMovcc_eflags, cc);
897
	/* although you can't set ins_permuted in the constructor it might still
898
899
900
	 * be set by memory operand folding
	 * Permuting inputs of a cmov means the condition is negated!
	 */
901
	if (attr->data.ins_permuted)
902
		cc = ia32_negate_condition_code(cc);
903

904
905
	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));
906
907

	/* should be same constraint fullfilled? */
Christoph Mallon's avatar
Christoph Mallon committed
908
	if (out == in_false) {
909
		/* yes -> nothing to do */
Christoph Mallon's avatar
Christoph Mallon committed
910
	} else if (out == in_true) {
911
912
		const arch_register_t *tmp;

913
914
		assert(get_ia32_op_type(node) == ia32_Normal);

915
		cc = ia32_negate_condition_code(cc);
916
917
918
919

		tmp      = in_true;
		in_true  = in_false;
		in_false = tmp;
920
	} else {
921
		/* we need a mov */
922
		ia32_emitf(node, "movl %R, %R", in_false, out);
923
	}
924

925
926
	if (cc & ia32_cc_float_parity_cases) {
		panic("CMov with floatingpoint compare/parity not supported yet");
927
	}
928

929
	ia32_emitf(node, "cmov%PX %#AR, %#R", (int)cc, in_true, out);
930
931
}

932
/**
933
 * Emits code for a SwitchJmp
934
935
936
 */
static void emit_ia32_SwitchJmp(const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
937
938
	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
939

940
	ia32_emitf(node, "jmp %*AM");
Matthias Braun's avatar
Matthias Braun committed
941
	be_emit_jump_table(node, table, jump_table, get_cfop_target_block);
Christian Würdig's avatar
Christian Würdig committed
942
943
944
945
946
}

/**
 * Emits code for a unconditional jump.
 */
947
static void emit_ia32_Jmp(const ir_node *node)
948
{
949
	/* we have a block schedule */
950
	if (can_be_fallthrough(node)) {
951
		if (be_options.verbose_asm)
952
			ia32_emitf(node, "/* fallthrough to %L */");
953
	} else {
954
		ia32_emitf(node, "jmp %L");
Christian Würdig's avatar
Christian Würdig committed
955
956
957
	}
}

Michael Beck's avatar
Michael Beck committed
958
959
960
961
962
963
964
965
/**
 * Emit an inline assembler operand.
 *
 * @param node  the ia32_ASM node
 * @param s     points to the operand (a %c)
 *