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

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

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

65
#include "../besched.h"
66
#include "../benode.h"
Michael Beck's avatar
Michael Beck committed
67
#include "../beabi.h"
68
#include "../be_dbgout.h"
Matthias Braun's avatar
Matthias Braun committed
69
70
#include "../beemitter.h"
#include "../begnuas.h"
71
#include "../beirg.h"
72
#include "../be_dbgout.h"
Christian Würdig's avatar
Christian Würdig committed
73

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

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

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

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

93
94
95
/** Return the next block in Block schedule */
static ir_node *get_prev_block_sched(const ir_node *block)
{
96
	return (ir_node*)get_irn_link(block);
97
98
}

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

Christoph Mallon's avatar
Christoph Mallon committed
104
	if (!is_Proj(cfgpred))
105
		return 1;
106
	pred = get_Proj_pred(cfgpred);
Christoph Mallon's avatar
Christoph Mallon committed
107
	if (is_ia32_SwitchJmp(pred))
108
		return 0;
109

110
	return 1;
111
112
}

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

122
123
124
	if (has_Block_entity(block))
		return 1;

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

		if (get_prev_block_sched(block) == cfgpred_block
				&& is_fallthrough(cfgpred)) {
133
			need_label = 0;
134
135
136
137
138
139
		}
	}

	return need_label;
}

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

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

159
	be_emit_char('%');
160
	be_emit_char(reg_name[1]); /* get the basic name of the register */
161
162
163
	be_emit_char('l');
}

Michael Beck's avatar
Michael Beck committed
164
165
166
167
168
169
/**
 * 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);
170
171
	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
172
173

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

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

182
	be_emit_char('%');
183
	be_emit_string(reg_name+1); /* skip the 'e' prefix of the 32bit names */
184
185
}

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

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

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

207
208
	be_emit_char('%');
	be_emit_string(reg_name);
Christian Würdig's avatar
Christian Würdig committed
209
210
}

211
void ia32_emit_source_register(const ir_node *node, int pos)
212
{
213
	const arch_register_t *reg = arch_get_irn_register_in(node, pos);
214

215
	emit_register(reg, NULL);
216
217
}

218
219
static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
{
220
	be_gas_emit_entity(entity);
221
222

	if (get_entity_owner(entity) == get_tls_type()) {
223
		if (get_entity_visibility(entity) == ir_visibility_external) {
224
225
226
227
228
229
			be_emit_cstring("@INDNTPOFF");
		} else {
			be_emit_cstring("@NTPOFF");
		}
	}

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

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
263
	const ir_node         *in = get_irn_n(node, pos);
Christoph Mallon's avatar
Christoph Mallon committed
264
	if (is_ia32_Immediate(in)) {
265
266
267
268
		emit_ia32_Immediate(in);
		return;
	}

269
	reg = arch_get_irn_register_in(node, pos);
270
271
272
	emit_8bit_register(reg);
}

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

279
280
281
282
283
284
285
286
287
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;
	}

288
	reg = arch_get_irn_register_in(node, pos);
289
290
291
	emit_16bit_register(reg);
}

292
293
void ia32_emit_dest_register(const ir_node *node, int pos)
{
294
	const arch_register_t *reg  = arch_get_irn_register_out(node, pos);
295
296
297
298

	emit_register(reg, NULL);
}

299
300
void ia32_emit_dest_register_size(const ir_node *node, int pos)
{
301
	const arch_register_t *reg  = arch_get_irn_register_out(node, pos);
302
303
304
305

	emit_register(reg, get_ia32_ls_mode(node));
}

306
307
void ia32_emit_8bit_dest_register(const ir_node *node, int pos)
{
308
	const arch_register_t *reg  = arch_get_irn_register_out(node, pos);
309
310
311
312
313

	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
314
{
315
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
316

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

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

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

342
	ia32_emit_mode_suffix_mode(mode);
343
344
}

345
void ia32_emit_x87_mode_suffix(const ir_node *node)
346
{
347
348
	ir_mode *mode;

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

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

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

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

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

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

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

434
435
436
437
438
439
/**
 * 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);
440
	be_gas_emit_block_name(block);
441
442
}

Michael Beck's avatar
Michael Beck committed
443
444
445
/**
 * Emit the suffix for a compare instruction.
 */
446
447
448
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
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;
478
	}
479
	panic("Invalid ia32 condition code");
480
481
}

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

492
493
494
495
496
497
498
499
500
/**
 * 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);
501
502
	ir_node   *idx       = get_irn_n(node, n_ia32_index);
	int        has_index = !is_ia32_NoReg_GP(idx);
503
504
505
506

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

507
508
509
	if (get_ia32_am_tls_segment(node))
		be_emit_cstring("%gs:");

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

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

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
/**
 * 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
568
 * %d   signed int              signed int
569
570
 *
 * x starts at 0
571
 * # modifier for %ASx, %D, %R, and %S uses ls mode of node to alter register width
572
 * * modifier does not prefix immediates with $, but AM with *
573
 * l modifier for %lu and %ld
574
575
 * > modifier to output high 8bit register (ah, bh)
 * < modifier to output low 8bit register (al, bl)
576
577
578
579
580
581
582
 */
static void ia32_emitf(const ir_node *node, const char *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);

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

		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
601
			break;
602
603

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

618
		switch (*fmt++) {
619
620
621
			arch_register_t const *reg;
			ir_node         const *imm;

622
623
624
625
626
627
			case '%':
				be_emit_char('%');
				break;

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

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

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

					default: goto unknown;
				}
				break;
			}

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

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

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

675
			case 'M':
676
677
678
679
				ia32_emit_mode_suffix_mode(get_ia32_ls_mode(node));
				break;

			case 'P': {
680
681
				ia32_condition_code_t cc = va_arg(ap, ia32_condition_code_t);
				ia32_emit_condition_code(cc);
682
683
684
				break;
			}

685
686
687
688
689
			case 'R':
				reg = va_arg(ap, const arch_register_t*);
emit_R:
				if (mod & EMIT_ALTERNATE_AM)
					be_emit_char('*');
690
691
692
693
694
695
696
				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);
				}
697
698
699
700
				break;

emit_S:
			case 'S': {
701
				unsigned pos;
702
703
704
705
706

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

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

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

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

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

	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
760
	}
761
762
}

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

776
777
778
779
780
				if (out == NULL) {
					out = in1;
				} else if (out == in) {
					in = in1;
				}
781

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

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

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

	/* do we need the 3-address form? */
Christoph Mallon's avatar
Christoph Mallon committed
813
	if (is_ia32_NoReg_GP(left) ||
814
			arch_get_irn_register_in(node, n_ia32_IMul_left) != out_reg) {
815
816
817
		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
818
819
820
	}
}

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

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

881
		flags_attr = get_ia32_attr_const(cmp);
882
	} else {
883
		flags_attr = get_ia32_attr_const(flags);
884
	}
885

886
887
888
	if (flags_attr->data.ins_permuted)
		cc = ia32_invert_condition_code(cc);
	return cc;
889
890
}

891
void ia32_emit_cmp_suffix_node(const ir_node *node, int flags_pos)
892
{
893
894
	ia32_condition_code_t cc = get_ia32_condcode(node);
	cc = determine_final_cc(node, flags_pos, cc);
895

896
	ia32_emit_condition_code(cc);
897
}
898

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

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

916
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
917

918
	foreach_out_edge(node, edge) {
919
920
921
922
923
924
925
926
927
928
929
930
		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;
}

931
static int can_be_fallthrough(const ir_node *node)
932
933
934
935
936
937
{
	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
938
939
940
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
941
static void emit_ia32_Jcc(const ir_node *node)
942
{
943
944
945
946
	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
947

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

950
951
952
	/* get both Projs */
	proj_true = get_proj(node, pn_ia32_Jcc_true);
	assert(proj_true && "Jcc without true Proj");
953

954
955
	proj_false = get_proj(node, pn_ia32_Jcc_false);
	assert(proj_false && "Jcc without false Proj");
956

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

961
962
		proj_true  = proj_false;
		proj_false = t;
963
		cc         = ia32_negate_condition_code(cc);
964
965
	}

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

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

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

1003
1004
1005
1006
1007
	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);