ia32_emitter.c 98.9 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
2
 * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
/**
21
 * @file
Christian Würdig's avatar
Christian Würdig committed
22
23
 * @brief       This file implements the ia32 node emitter.
 * @author      Christian Wuerdig, Matthias Braun
24
25
 *
 * Summary table for x86 floatingpoint compares:
26
27
 * (remember effect of unordered on x86: ZF=1, PF=1, CF=1)
 *
28
29
30
31
32
 *   pnc_Eq  => !P && E
 *   pnc_Lt  => !P && B
 *   pnc_Le  => !P && BE
 *   pnc_Gt  => A
 *   pnc_Ge  => AE
33
 *   pnc_Lg  => NE
34
35
36
37
38
39
40
 *   pnc_Leg => NP  (ordered)
 *   pnc_Uo  => P
 *   pnc_Ue  => E
 *   pnc_Ul  => B
 *   pnc_Ule => BE
 *   pnc_Ug  => P || A
 *   pnc_Uge => P || AE
41
 *   pnc_Ne  => P || NE
42
 */
43
#include "config.h"
Christian Würdig's avatar
Christian Würdig committed
44

Christian Würdig's avatar
Christian Würdig committed
45
46
#include <limits.h>

47
#include "xmalloc.h"
48
49
#include "tv.h"
#include "iredges.h"
Christian Würdig's avatar
Christian Würdig committed
50
51
52
53
#include "debug.h"
#include "irgwalk.h"
#include "irprintf.h"
#include "irop_t.h"
Christian Würdig's avatar
Christian Würdig committed
54
#include "irargs_t.h"
55
#include "irprog_t.h"
56
#include "iredges_t.h"
57
#include "irtools.h"
58
#include "execfreq.h"
59
#include "error.h"
Matthias Braun's avatar
Matthias Braun committed
60
#include "raw_bitset.h"
61
#include "dbginfo.h"
62
#include "lc_opts.h"
63
#include "ircons.h"
Christian Würdig's avatar
Christian Würdig committed
64

65
66
67
#include "besched.h"
#include "benode.h"
#include "beabi.h"
68
#include "bedwarf.h"
69
70
71
#include "beemitter.h"
#include "begnuas.h"
#include "beirg.h"
Christian Würdig's avatar
Christian Würdig committed
72

73
#include "ia32_emitter.h"
74
#include "ia32_common_transform.h"
Christian Würdig's avatar
Christian Würdig committed
75
#include "gen_ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
76
#include "gen_ia32_regalloc_if.h"
77
78
#include "ia32_nodes_attr.h"
#include "ia32_new_nodes.h"
79
#include "ia32_architecture.h"
Christian Würdig's avatar
Christian Würdig committed
80
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
81

82
83
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

Christian Würdig's avatar
Christian Würdig committed
84
85
#define SNPRINTF_BUF_LEN 128

86
static const ia32_isa_t *isa;
87
static char              pic_base_label[128];
88
static ir_label_t        exc_label_id;
89
static int               mark_spill_reload = 0;
90
static int               do_pic;
91

92
93
94
95
static bool              sp_relative;
static int               frame_type_size;
static int               callframe_offset;

96
97
98
/** Return the next block in Block schedule */
static ir_node *get_prev_block_sched(const ir_node *block)
{
99
	return (ir_node*)get_irn_link(block);
100
101
}

102
/** Checks if the current block is a fall-through target. */
103
static int is_fallthrough(const ir_node *cfgpred)
104
105
106
{
	ir_node *pred;

Christoph Mallon's avatar
Christoph Mallon committed
107
	if (!is_Proj(cfgpred))
108
		return 1;
109
	pred = get_Proj_pred(cfgpred);
Christoph Mallon's avatar
Christoph Mallon committed
110
	if (is_ia32_SwitchJmp(pred))
111
		return 0;
112

113
	return 1;
114
115
}

116
117
118
119
/**
 * returns non-zero if the given block needs a label
 * because of being a jump-target (and not a fall-through)
 */
120
static int block_needs_label(const ir_node *block)
121
{
122
	int need_label = 1;
123
124
	int  n_cfgpreds = get_Block_n_cfgpreds(block);

125
	if (get_Block_entity(block) != NULL)
126
127
		return 1;

128
	if (n_cfgpreds == 0) {
129
		need_label = 0;
130
	} else if (n_cfgpreds == 1) {
Christoph Mallon's avatar
Christoph Mallon committed
131
132
		ir_node *cfgpred       = get_Block_cfgpred(block, 0);
		ir_node *cfgpred_block = get_nodes_block(cfgpred);
133
134
135

		if (get_prev_block_sched(block) == cfgpred_block
				&& is_fallthrough(cfgpred)) {
136
			need_label = 0;
137
138
139
140
141
142
		}
	}

	return need_label;
}

Michael Beck's avatar
Michael Beck committed
143
/**
144
 * Add a number to a prefix. This number will not be used a second time.
Michael Beck's avatar
Michael Beck committed
145
 */
146
147
static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
{
148
	static unsigned long id = 0;
149
	snprintf(buf, buflen, "%s%s%lu", be_gas_get_private_prefix(), prefix, ++id);
150
151
152
	return buf;
}

Michael Beck's avatar
Michael Beck committed
153
154
155
/**
 * Emit the name of the 8bit low register
 */
156
157
static void emit_8bit_register(const arch_register_t *reg)
{
158
	const char *reg_name = arch_register_get_name(reg);
159
160
	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
161

162
	be_emit_char('%');
163
	be_emit_char(reg_name[1]); /* get the basic name of the register */
164
165
166
	be_emit_char('l');
}

Michael Beck's avatar
Michael Beck committed
167
168
169
170
171
172
/**
 * Emit the name of the 8bit high register
 */
static void emit_8bit_register_high(const arch_register_t *reg)
{
	const char *reg_name = arch_register_get_name(reg);
173
174
	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
175
176

	be_emit_char('%');
177
	be_emit_char(reg_name[1]); /* get the basic name of the register */
Michael Beck's avatar
Michael Beck committed
178
179
180
	be_emit_char('h');
}

181
182
static void emit_16bit_register(const arch_register_t *reg)
{
183
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
184

185
	be_emit_char('%');
186
	be_emit_string(reg_name+1); /* skip the 'e' prefix of the 32bit names */
187
188
}

189
190
191
192
193
194
/**
 * emit a register, possible shortened by a mode
 *
 * @param reg   the register
 * @param mode  the mode of the register or NULL for full register
 */
195
196
197
198
static void emit_register(const arch_register_t *reg, const ir_mode *mode)
{
	const char *reg_name;

Christoph Mallon's avatar
Christoph Mallon committed
199
	if (mode != NULL) {
200
		int size = get_mode_size_bits(mode);
Christoph Mallon's avatar
Christoph Mallon committed
201
202
203
		switch (size) {
			case  8: emit_8bit_register(reg);  return;
			case 16: emit_16bit_register(reg); return;
204
		}
Christoph Mallon's avatar
Christoph Mallon committed
205
		assert(mode_is_float(mode) || size == 32);
206
207
208
	}

	reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
209

210
211
	be_emit_char('%');
	be_emit_string(reg_name);
Christian Würdig's avatar
Christian Würdig committed
212
213
}

214
void ia32_emit_source_register(const ir_node *node, int pos)
215
{
216
	const arch_register_t *reg = arch_get_irn_register_in(node, pos);
217

218
	emit_register(reg, NULL);
219
220
}

221
222
static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
{
223
	be_gas_emit_entity(entity);
224
225

	if (get_entity_owner(entity) == get_tls_type()) {
226
		if (get_entity_visibility(entity) == ir_visibility_external) {
227
228
229
230
231
232
			be_emit_cstring("@INDNTPOFF");
		} else {
			be_emit_cstring("@NTPOFF");
		}
	}

233
	if (do_pic && !no_pic_adjust) {
234
235
236
237
238
239
240
241
242
243
244
245
		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('-');
246
		ia32_emit_entity(attr->symconst, attr->no_pic_adjust);
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
	}
	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);
}
262
263
264
265

void ia32_emit_8bit_source_register_or_immediate(const ir_node *node, int pos)
{
	const arch_register_t *reg;
Michael Beck's avatar
Michael Beck committed
266
	const ir_node         *in = get_irn_n(node, pos);
Christoph Mallon's avatar
Christoph Mallon committed
267
	if (is_ia32_Immediate(in)) {
268
269
270
271
		emit_ia32_Immediate(in);
		return;
	}

272
	reg = arch_get_irn_register_in(node, pos);
273
274
275
	emit_8bit_register(reg);
}

Michael Beck's avatar
Michael Beck committed
276
277
void ia32_emit_8bit_high_source_register(const ir_node *node, int pos)
{
278
	const arch_register_t *reg = arch_get_irn_register_in(node, pos);
Michael Beck's avatar
Michael Beck committed
279
280
281
	emit_8bit_register_high(reg);
}

282
283
284
285
286
287
288
289
290
void ia32_emit_16bit_source_register_or_immediate(const ir_node *node, int pos)
{
	const arch_register_t *reg;
	const ir_node         *in = get_irn_n(node, pos);
	if (is_ia32_Immediate(in)) {
		emit_ia32_Immediate(in);
		return;
	}

291
	reg = arch_get_irn_register_in(node, pos);
292
293
294
	emit_16bit_register(reg);
}

295
296
void ia32_emit_dest_register(const ir_node *node, int pos)
{
297
	const arch_register_t *reg  = arch_get_irn_register_out(node, pos);
298
299
300
301

	emit_register(reg, NULL);
}

302
303
void ia32_emit_dest_register_size(const ir_node *node, int pos)
{
304
	const arch_register_t *reg  = arch_get_irn_register_out(node, pos);
305
306
307
308

	emit_register(reg, get_ia32_ls_mode(node));
}

309
310
void ia32_emit_8bit_dest_register(const ir_node *node, int pos)
{
311
	const arch_register_t *reg  = arch_get_irn_register_out(node, pos);
312
313
314
315
316

	emit_register(reg, mode_Bu);
}

void ia32_emit_x87_register(const ir_node *node, int pos)
Christian Würdig's avatar
Christian Würdig committed
317
{
318
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
319

Matthias Braun's avatar
Matthias Braun committed
320
	assert(pos < 3);
321
322
	be_emit_char('%');
	be_emit_string(attr->x87[pos]->name);
323
}
Christian Würdig's avatar
Christian Würdig committed
324

Matthias Braun's avatar
Matthias Braun committed
325
static void ia32_emit_mode_suffix_mode(const ir_mode *mode)
326
{
327
328
329
330
331
	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
332
333
		/* gas docu says q is the suffix but gcc, objdump and icc use ll
		 * apparently */
Matthias Braun's avatar
Matthias Braun committed
334
335
		case 64: be_emit_cstring("ll"); return;
	}
336
	panic("Can't output mode_suffix for %+F", mode);
Christian Würdig's avatar
Christian Würdig committed
337
338
}

339
void ia32_emit_mode_suffix(const ir_node *node)
340
341
{
	ir_mode *mode = get_ia32_ls_mode(node);
Christoph Mallon's avatar
Christoph Mallon committed
342
	if (mode == NULL)
Matthias Braun's avatar
Matthias Braun committed
343
344
		mode = mode_Iu;

345
	ia32_emit_mode_suffix_mode(mode);
346
347
}

348
void ia32_emit_x87_mode_suffix(const ir_node *node)
349
{
350
351
	ir_mode *mode;

352
	/* we only need to emit the mode on address mode */
353
354
355
356
357
358
359
360
	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)) {
361
362
363
364
365
366
367
			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;
368
369
		}
	} else {
370
		assert(mode_is_int(mode) || mode_is_reference(mode));
371
372
373
374
375
376
377
		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;
		}
378
	}
379
	panic("Can't output mode_suffix for %+F", mode);
380
381
}

382
static char get_xmm_mode_suffix(ir_mode *mode)
383
384
{
	assert(mode_is_float(mode));
385
	switch (get_mode_size_bits(mode)) {
Christoph Mallon's avatar
Christoph Mallon committed
386
387
388
	case 32: return 's';
	case 64: return 'd';
	default: panic("Invalid XMM mode");
389
390
391
	}
}

392
void ia32_emit_xmm_mode_suffix(const ir_node *node)
393
394
{
	ir_mode *mode = get_ia32_ls_mode(node);
395
	assert(mode != NULL);
396
397
	be_emit_char('s');
	be_emit_char(get_xmm_mode_suffix(mode));
398
399
}

400
void ia32_emit_xmm_mode_suffix_s(const ir_node *node)
401
402
403
{
	ir_mode *mode = get_ia32_ls_mode(node);
	assert(mode != NULL);
404
	be_emit_char(get_xmm_mode_suffix(mode));
405
406
}

407
void ia32_emit_extend_suffix(const ir_node *node)
408
{
409
	ir_mode *mode = get_ia32_ls_mode(node);
Christoph Mallon's avatar
Christoph Mallon committed
410
	if (get_mode_size_bits(mode) == 32)
411
		return;
Christoph Mallon's avatar
Christoph Mallon committed
412
	be_emit_char(mode_is_signed(mode) ? 's' : 'z');
413
	ia32_emit_mode_suffix_mode(mode);
Matthias Braun's avatar
Matthias Braun committed
414
415
}

416
void ia32_emit_source_register_or_immediate(const ir_node *node, int pos)
417
418
{
	ir_node *in = get_irn_n(node, pos);
Christoph Mallon's avatar
Christoph Mallon committed
419
	if (is_ia32_Immediate(in)) {
420
		emit_ia32_Immediate(in);
421
	} else {
422
		const ir_mode         *mode = get_ia32_ls_mode(node);
423
		const arch_register_t *reg  = arch_get_irn_register_in(node, pos);
424
		emit_register(reg, mode);
425
426
427
	}
}

Christian Würdig's avatar
Christian Würdig committed
428
/**
429
 * Returns the target block for a control flow node.
Christian Würdig's avatar
Christian Würdig committed
430
 */
431
static ir_node *get_cfop_target_block(const ir_node *irn)
Christoph Mallon's avatar
Christoph Mallon committed
432
{
433
	assert(get_irn_mode(irn) == mode_X);
434
	return (ir_node*)get_irn_link(irn);
435
}
Christian Würdig's avatar
Christian Würdig committed
436

437
438
439
440
441
442
/**
 * 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);
443
	be_gas_emit_block_name(block);
444
445
}

Michael Beck's avatar
Michael Beck committed
446
447
448
/**
 * Emit the suffix for a compare instruction.
 */
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
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;
481
	}
482
	panic("Invalid ia32 condition code");
483
484
}

485
typedef enum ia32_emit_mod_t {
486
	EMIT_NONE         = 0,
487
	EMIT_RESPECT_LS   = 1U << 0,
488
	EMIT_ALTERNATE_AM = 1U << 1,
489
490
491
	EMIT_LONG         = 1U << 2,
	EMIT_HIGH_REG     = 1U << 3,
	EMIT_LOW_REG      = 1U << 4
492
} ia32_emit_mod_t;
493
ENUM_BITSET(ia32_emit_mod_t)
494

495
496
497
498
499
500
501
502
503
/**
 * Emits address mode.
 */
void ia32_emit_am(const ir_node *node)
{
	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);
504
505
	ir_node   *idx       = get_irn_n(node, n_ia32_index);
	int        has_index = !is_ia32_NoReg_GP(idx);
506
507
508
509

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

510
511
512
	if (get_ia32_am_tls_segment(node))
		be_emit_cstring("%gs:");

513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
	/* 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) {
535
			const arch_register_t *reg = arch_get_irn_register_in(node, n_ia32_base);
536
537
538
539
540
			emit_register(reg, NULL);
		}

		/* emit index + scale */
		if (has_index) {
541
			const arch_register_t *reg = arch_get_irn_register_in(node, n_ia32_index);
542
543
544
545
546
547
548
549
550
551
552
553
554
			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(')');
	}
}

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
/**
 * fmt  parameter               output
 * ---- ----------------------  ---------------------------------------------
 * %%                           %
 * %AM  <node>                  address mode of the node
 * %AR  const arch_register_t*  address mode of the node or register
 * %ASx <node>                  address mode of the node or source register x
 * %Dx  <node>                  destination register x
 * %I   <node>                  immediate of the node
 * %L   <node>                  control flow target of the node
 * %M   <node>                  mode suffix of the node
 * %P   int                     condition code
 * %R   const arch_register_t*  register
 * %Sx  <node>                  source register x
 * %s   const char*             string
 * %u   unsigned int            unsigned int
571
 * %d   signed int              signed int
572
573
 *
 * x starts at 0
574
 * # modifier for %ASx, %D, %R, and %S uses ls mode of node to alter register width
575
 * * modifier does not prefix immediates with $, but AM with *
576
 * l modifier for %lu and %ld
577
578
 * > modifier to output high 8bit register (ah, bh)
 * < modifier to output low 8bit register (al, bl)
579
580
581
582
583
584
585
 */
static void ia32_emitf(const ir_node *node, const char *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);

	for (;;) {
586
		const char      *start = fmt;
587
		ia32_emit_mod_t  mod   = EMIT_NONE;
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

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

		if (*fmt == '\n') {
			be_emit_finish_line_gas(node);
			++fmt;
			if (*fmt == '\0')
				break;
			continue;
		}

		if (*fmt == '\0')
Christian Würdig's avatar
Christian Würdig committed
604
			break;
605
606

		++fmt;
607
608
		for (;;) {
			switch (*fmt) {
609
610
611
			case '*': mod |= EMIT_ALTERNATE_AM; break;
			case '#': mod |= EMIT_RESPECT_LS;   break;
			case 'l': mod |= EMIT_LONG;         break;
612
613
			case '>': mod |= EMIT_HIGH_REG;     break;
			case '<': mod |= EMIT_LOW_REG;      break;
614
615
616
			default:
				goto end_of_mods;
			}
617
618
			++fmt;
		}
619
end_of_mods:
620

621
		switch (*fmt++) {
622
623
624
			arch_register_t const *reg;
			ir_node         const *imm;

625
626
627
628
629
630
			case '%':
				be_emit_char('%');
				break;

			case 'A': {
				switch (*fmt++) {
631
emit_AM:
632
					case 'M':
633
634
						if (mod & EMIT_ALTERNATE_AM)
							be_emit_char('*');
635
636
637
						ia32_emit_am(node);
						break;

638
639
					case 'R':
						reg = va_arg(ap, const arch_register_t*);
640
						if (get_ia32_op_type(node) == ia32_AddrModeS) {
641
							goto emit_AM;
642
						} else {
643
							goto emit_R;
644
645
646
647
648
						}

					case 'S':
						if (get_ia32_op_type(node) == ia32_AddrModeS) {
							++fmt;
649
							goto emit_AM;
650
651
652
653
654
655
656
657
658
659
						} else {
							assert(get_ia32_op_type(node) == ia32_Normal);
							goto emit_S;
						}

					default: goto unknown;
				}
				break;
			}

660
			case 'D':
661
662
				if (*fmt < '0' || '9' <= *fmt)
					goto unknown;
663
				reg = arch_get_irn_register_out(node, *fmt++ - '0');
664
				goto emit_R;
665
666

			case 'I':
667
668
				imm = node;
emit_I:
669
670
				if (!(mod & EMIT_ALTERNATE_AM))
					be_emit_char('$');
671
				emit_ia32_Immediate_no_prefix(imm);
672
673
674
675
676
677
				break;

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

678
			case 'M':
679
680
681
682
				ia32_emit_mode_suffix_mode(get_ia32_ls_mode(node));
				break;

			case 'P': {
683
684
				ia32_condition_code_t cc = va_arg(ap, ia32_condition_code_t);
				ia32_emit_condition_code(cc);
685
686
687
				break;
			}

688
689
690
691
692
			case 'R':
				reg = va_arg(ap, const arch_register_t*);
emit_R:
				if (mod & EMIT_ALTERNATE_AM)
					be_emit_char('*');
693
694
695
696
697
698
699
				if (mod & EMIT_HIGH_REG) {
					emit_8bit_register_high(reg);
				} else if (mod & EMIT_LOW_REG) {
					emit_8bit_register(reg);
				} else {
					emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
				}
700
701
702
703
				break;

emit_S:
			case 'S': {
704
				unsigned pos;
705
706
707
708
709

				if (*fmt < '0' || '9' <= *fmt)
					goto unknown;

				pos = *fmt++ - '0';
710
711
712
				imm = get_irn_n(node, pos);
				if (is_ia32_Immediate(imm)) {
					goto emit_I;
713
				} else {
714
					reg = arch_get_irn_register_in(node, pos);
715
					goto emit_R;
716
717
718
719
720
721
722
723
724
				}
			}

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

725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
			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);
				}
743
744
745
746
				break;

			default:
unknown:
747
				panic("unknown format conversion in ia32_emitf()");
748
		}
749
750
751
752
753
754
755
756
757
758
759
760
761
762
	}

	va_end(ap);
}

/**
 * Emits registers and/or address mode of a binary operation.
 */
void ia32_emit_binop(const ir_node *node)
{
	if (is_ia32_Immediate(get_irn_n(node, n_ia32_binary_right))) {
		ia32_emitf(node, "%#S4, %#AS3");
	} else {
		ia32_emitf(node, "%#AS4, %#S3");
Christian Würdig's avatar
Christian Würdig committed
763
	}
764
765
}

766
767
768
/**
 * Emits registers and/or address mode of a binary operation.
 */
Christoph Mallon's avatar
Christoph Mallon committed
769
770
void ia32_emit_x87_binop(const ir_node *node)
{
771
	switch (get_ia32_op_type(node)) {
772
		case ia32_Normal:
773
			{
774
775
				const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
				const arch_register_t *in1      = x87_attr->x87[0];
776
				const arch_register_t *in       = x87_attr->x87[1];
777
				const arch_register_t *out      = x87_attr->x87[2];
778

779
780
781
782
783
				if (out == NULL) {
					out = in1;
				} else if (out == in) {
					in = in1;
				}
784

785
786
787
788
				be_emit_char('%');
				be_emit_string(arch_register_get_name(in));
				be_emit_cstring(", %");
				be_emit_string(arch_register_get_name(out));
789
790
791
			}
			break;
		case ia32_AddrModeS:
792
			ia32_emit_am(node);
793
			break;
794
		case ia32_AddrModeD:
795
796
797
798
799
		default:
			assert(0 && "unsupported op type");
	}
}

Christian Würdig's avatar
Christian Würdig committed
800
801
802
/**
 * Emits registers and/or address mode of a unary operation.
 */
Christoph Mallon's avatar
Christoph Mallon committed
803
804
void ia32_emit_unop(const ir_node *node, int pos)
{
805
806
807
	char fmt[] = "%ASx";
	fmt[3] = '0' + pos;
	ia32_emitf(node, fmt);
Christian Würdig's avatar
Christian Würdig committed
808
809
}

Matthias Braun's avatar
Matthias Braun committed
810
811
812
static void emit_ia32_IMul(const ir_node *node)
{
	ir_node               *left    = get_irn_n(node, n_ia32_IMul_left);
813
	const arch_register_t *out_reg = arch_get_irn_register_out(node, pn_ia32_IMul_res);
Matthias Braun's avatar
Matthias Braun committed
814
815

	/* do we need the 3-address form? */
Christoph Mallon's avatar
Christoph Mallon committed
816
	if (is_ia32_NoReg_GP(left) ||
817
			arch_get_irn_register_in(node, n_ia32_IMul_left) != out_reg) {
818
819
820
		ia32_emitf(node, "\timul%M %#S4, %#AS3, %#D0\n");
	} else {
		ia32_emitf(node, "\timul%M %#AS4, %#S3\n");
Matthias Braun's avatar
Matthias Braun committed
821
822
823
	}
}

824
825
826
/**
 * walks up a tree of copies/perms/spills/reloads to find the original value
 * that is moved around
827
 */
828
829
static ir_node *find_original_value(ir_node *node)
{
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
	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
846
847
		} else if (is_ia32_Store(pred)) {
			return find_original_value(get_irn_n(pred, n_ia32_Store_val));
848
849
850
		} else {
			return node;
		}
851
852
853
854
855
856
857
858
859
860
861
862
863
	} 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;
864
865
866
	}
}

867
static int determine_final_cc(const ir_node *node, int flags_pos, int cc)
868
{
869
870
871
872
	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
873
	if (is_ia32_Sahf(flags)) {
874
		ir_node *cmp = get_irn_n(flags, n_ia32_Sahf_val);
Christoph Mallon's avatar
Christoph Mallon committed
875
		if (!(is_ia32_FucomFnstsw(cmp) || is_ia32_FucompFnstsw(cmp)
876
				|| is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp))) {
877
			inc_irg_visited(current_ir_graph);
878
			cmp = find_original_value(cmp);
879
			assert(cmp != NULL);
880
			assert(is_ia32_FucomFnstsw(cmp) || is_ia32_FucompFnstsw(cmp)
881
			       || is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp));
882
		}
883

884
		flags_attr = get_ia32_attr_const(cmp);
885
	} else {
886
		flags_attr = get_ia32_attr_const(flags);
887
	}
888

889
890
891
	if (flags_attr->data.ins_permuted)
		cc = ia32_invert_condition_code(cc);
	return cc;
892
893
}

894
void ia32_emit_cmp_suffix_node(const ir_node *node, int flags_pos)
895
{
896
897
	ia32_condition_code_t cc = get_ia32_condcode(node);
	cc = determine_final_cc(node, flags_pos, cc);
898

899
	ia32_emit_condition_code(cc);
900
}
901

902
903
904
905
906
907
/**
 * 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());
908
	be_emit_irprintf("%lu", get_ia32_exc_label_id(node));
909
910
}

911
912
913
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
Christoph Mallon's avatar
Christoph Mallon committed
914
915
static ir_node *get_proj(const ir_node *node, long proj)
{
916
917
918
	const ir_edge_t *edge;
	ir_node         *src;

919
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
920

921
	foreach_out_edge(node, edge) {
922
923
924
925
926
927
928
929
930
931
932
933
		src = get_edge_src_irn(edge);

		assert(is_Proj(src) && "Proj expected");
		if (get_irn_mode(src) == mode_M)
			continue;

		if (get_Proj_proj(src) == proj)
			return src;
	}
	return NULL;
}

934
static int can_be_fallthrough(const ir_node *node)
935
936
937
938
939
940
{
	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
941
942
943
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
944
static void emit_ia32_Jcc(const ir_node *node)
945
{
946
947
948
949
	int                   need_parity_label = 0;
	ia32_condition_code_t cc                = get_ia32_condcode(node);
	const ir_node        *proj_true;
	const ir_node        *proj_false;
Christian Würdig's avatar
Christian Würdig committed
950

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

953
954
955
	/* get both Projs */
	proj_true = get_proj(node, pn_ia32_Jcc_true);
	assert(proj_true && "Jcc without true Proj");
956

957
958
	proj_false = get_proj(node, pn_ia32_Jcc_false);
	assert(proj_false && "Jcc without false Proj");
959

960
	if (can_be_fallthrough(proj_true)) {
961
		/* exchange both proj's so the second one can be omitted */
962
963
		const ir_node *t = proj_true;

964
965
		proj_true  = proj_false;
		proj_false = t;
966
		cc         = ia32_negate_condition_code(cc);
967
968
	}

969
	if (cc & ia32_cc_float_parity_cases) {
970
971
		/* Some floating point comparisons require a test of the parity flag,
		 * which indicates that the result is unordered */
972
		if (cc & ia32_cc_negated) {
973
			ia32_emitf(proj_true, "\tjp %L\n");
974
		} else {
975
976
977
978
979
980
981
982
			/* 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;
				ia32_emitf(proj_false, "\tjp 1f\n");
			} else {
				ia32_emitf(proj_false, "\tjp %L\n");
			}
983
		}
984
	}
985
	ia32_emitf(proj_true, "\tj%P %L\n", cc);
Christoph Mallon's avatar
Christoph Mallon committed
986
	if (need_parity_label) {
987
		ia32_emitf(NULL, "1:\n");
988
989
	}

990
	/* the second Proj might be a fallthrough */
Matthias Braun's avatar
Matthias Braun committed
991
	if (can_be_fallthrough(proj_false)) {
992
		ia32_emitf(proj_false, "\t/* fallthrough to %L */\n");
993
	} else {
994
		ia32_emitf(proj_false, "\tjmp %L\n");
995
	}
Michael Beck's avatar
Michael Beck committed
996
997
}

998
999
1000
1001
1002
1003
/**
 * Emits an ia32 Setcc. This is mostly easy but some floating point compares
 * are tricky.
 */
static void emit_ia32_Setcc(const ir_node *node)
{
1004
	const arch_register_t *dreg = arch_get_irn_register_out(node, pn_ia32_Setcc_res);
1005

1006
1007
1008
1009
1010
	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) {
			ia32_emitf(node, "\tset%P %<R\n", cc, dreg);
1011
1012
			ia32_emitf(node