ia32_emitter.c 96.4 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;
}

Christian Würdig's avatar
Christian Würdig committed
140
/**
Christian Würdig's avatar
Christian Würdig committed
141
 * Returns the register at in position pos.
Christian Würdig's avatar
Christian Würdig committed
142
 */
143
static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
144
{
145
146
	ir_node *op = get_irn_n(irn, pos);
	return arch_get_irn_register(op);
Christian Würdig's avatar
Christian Würdig committed
147
148
}

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

Michael Beck's avatar
Michael Beck committed
159
160
161
/**
 * Emit the name of the 8bit low register
 */
162
163
static void emit_8bit_register(const arch_register_t *reg)
{
164
	const char *reg_name = arch_register_get_name(reg);
165
166
	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
167

168
	be_emit_char('%');
169
	be_emit_char(reg_name[1]); /* get the basic name of the register */
170
171
172
	be_emit_char('l');
}

Michael Beck's avatar
Michael Beck committed
173
174
175
176
177
178
/**
 * 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);
179
180
	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
181
182

	be_emit_char('%');
183
	be_emit_char(reg_name[1]); /* get the basic name of the register */
Michael Beck's avatar
Michael Beck committed
184
185
186
	be_emit_char('h');
}

187
188
static void emit_16bit_register(const arch_register_t *reg)
{
189
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
190

191
	be_emit_char('%');
192
	be_emit_string(reg_name+1); /* skip the 'e' prefix of the 32bit names */
193
194
}

195
196
197
198
199
200
/**
 * emit a register, possible shortened by a mode
 *
 * @param reg   the register
 * @param mode  the mode of the register or NULL for full register
 */
201
202
203
204
static void emit_register(const arch_register_t *reg, const ir_mode *mode)
{
	const char *reg_name;

Christoph Mallon's avatar
Christoph Mallon committed
205
	if (mode != NULL) {
206
		int size = get_mode_size_bits(mode);
Christoph Mallon's avatar
Christoph Mallon committed
207
208
209
		switch (size) {
			case  8: emit_8bit_register(reg);  return;
			case 16: emit_16bit_register(reg); return;
210
		}
Christoph Mallon's avatar
Christoph Mallon committed
211
		assert(mode_is_float(mode) || size == 32);
212
213
214
	}

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

216
217
	be_emit_char('%');
	be_emit_string(reg_name);
Christian Würdig's avatar
Christian Würdig committed
218
219
}

220
void ia32_emit_source_register(const ir_node *node, int pos)
221
{
Christoph Mallon's avatar
Christoph Mallon committed
222
	const arch_register_t *reg = get_in_reg(node, pos);
223

224
	emit_register(reg, NULL);
225
226
}

227
228
static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
{
229
	be_gas_emit_entity(entity);
230
231

	if (get_entity_owner(entity) == get_tls_type()) {
232
		if (get_entity_visibility(entity) == ir_visibility_external) {
233
234
235
236
237
238
			be_emit_cstring("@INDNTPOFF");
		} else {
			be_emit_cstring("@NTPOFF");
		}
	}

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

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
272
	const ir_node         *in = get_irn_n(node, pos);
Christoph Mallon's avatar
Christoph Mallon committed
273
	if (is_ia32_Immediate(in)) {
274
275
276
277
278
279
280
281
		emit_ia32_Immediate(in);
		return;
	}

	reg = get_in_reg(node, pos);
	emit_8bit_register(reg);
}

Michael Beck's avatar
Michael Beck committed
282
283
284
285
286
287
void ia32_emit_8bit_high_source_register(const ir_node *node, int pos)
{
	const arch_register_t *reg = get_in_reg(node, pos);
	emit_8bit_register_high(reg);
}

288
289
290
291
292
293
294
295
296
297
298
299
300
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;
	}

	reg = get_in_reg(node, pos);
	emit_16bit_register(reg);
}

301
302
void ia32_emit_dest_register(const ir_node *node, int pos)
{
303
	const arch_register_t *reg  = arch_irn_get_register(node, pos);
304
305
306
307

	emit_register(reg, NULL);
}

308
309
void ia32_emit_dest_register_size(const ir_node *node, int pos)
{
310
	const arch_register_t *reg  = arch_irn_get_register(node, pos);
311
312
313
314

	emit_register(reg, get_ia32_ls_mode(node));
}

315
316
void ia32_emit_8bit_dest_register(const ir_node *node, int pos)
{
317
	const arch_register_t *reg  = arch_irn_get_register(node, pos);
318
319
320
321
322

	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
323
{
324
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
325

Matthias Braun's avatar
Matthias Braun committed
326
	assert(pos < 3);
327
328
	be_emit_char('%');
	be_emit_string(attr->x87[pos]->name);
329
}
Christian Würdig's avatar
Christian Würdig committed
330

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

345
void ia32_emit_mode_suffix(const ir_node *node)
346
347
{
	ir_mode *mode = get_ia32_ls_mode(node);
Christoph Mallon's avatar
Christoph Mallon committed
348
	if (mode == NULL)
Matthias Braun's avatar
Matthias Braun committed
349
350
		mode = mode_Iu;

351
	ia32_emit_mode_suffix_mode(mode);
352
353
}

354
void ia32_emit_x87_mode_suffix(const ir_node *node)
355
{
356
357
	ir_mode *mode;

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

388
static char get_xmm_mode_suffix(ir_mode *mode)
389
390
{
	assert(mode_is_float(mode));
391
	switch (get_mode_size_bits(mode)) {
Christoph Mallon's avatar
Christoph Mallon committed
392
393
394
	case 32: return 's';
	case 64: return 'd';
	default: panic("Invalid XMM mode");
395
396
397
	}
}

398
void ia32_emit_xmm_mode_suffix(const ir_node *node)
399
400
{
	ir_mode *mode = get_ia32_ls_mode(node);
401
	assert(mode != NULL);
402
403
	be_emit_char('s');
	be_emit_char(get_xmm_mode_suffix(mode));
404
405
}

406
void ia32_emit_xmm_mode_suffix_s(const ir_node *node)
407
408
409
{
	ir_mode *mode = get_ia32_ls_mode(node);
	assert(mode != NULL);
410
	be_emit_char(get_xmm_mode_suffix(mode));
411
412
}

413
void ia32_emit_extend_suffix(const ir_node *node)
414
{
415
	ir_mode *mode = get_ia32_ls_mode(node);
Christoph Mallon's avatar
Christoph Mallon committed
416
	if (get_mode_size_bits(mode) == 32)
417
		return;
Christoph Mallon's avatar
Christoph Mallon committed
418
	be_emit_char(mode_is_signed(mode) ? 's' : 'z');
419
	ia32_emit_mode_suffix_mode(mode);
Matthias Braun's avatar
Matthias Braun committed
420
421
}

422
void ia32_emit_source_register_or_immediate(const ir_node *node, int pos)
423
424
{
	ir_node *in = get_irn_n(node, pos);
Christoph Mallon's avatar
Christoph Mallon committed
425
	if (is_ia32_Immediate(in)) {
426
		emit_ia32_Immediate(in);
427
	} else {
428
429
430
		const ir_mode         *mode = get_ia32_ls_mode(node);
		const arch_register_t *reg  = get_in_reg(node, pos);
		emit_register(reg, mode);
431
432
433
	}
}

Christian Würdig's avatar
Christian Würdig committed
434
/**
435
 * Returns the target block for a control flow node.
Christian Würdig's avatar
Christian Würdig committed
436
 */
437
static ir_node *get_cfop_target_block(const ir_node *irn)
Christoph Mallon's avatar
Christoph Mallon committed
438
{
439
	assert(get_irn_mode(irn) == mode_X);
440
	return (ir_node*)get_irn_link(irn);
441
}
Christian Würdig's avatar
Christian Würdig committed
442

443
444
445
446
447
448
/**
 * 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);
449
	be_gas_emit_block_name(block);
450
451
}

Michael Beck's avatar
Michael Beck committed
452
453
454
/**
 * Emit the suffix for a compare instruction.
 */
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
481
482
483
484
485
486
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;
487
	}
488
	panic("Invalid ia32 condition code");
489
490
}

491
typedef enum ia32_emit_mod_t {
492
	EMIT_NONE         = 0,
493
	EMIT_RESPECT_LS   = 1U << 0,
494
	EMIT_ALTERNATE_AM = 1U << 1,
495
496
497
	EMIT_LONG         = 1U << 2,
	EMIT_HIGH_REG     = 1U << 3,
	EMIT_LOW_REG      = 1U << 4
498
} ia32_emit_mod_t;
499
ENUM_BITSET(ia32_emit_mod_t)
500

501
502
503
504
505
506
507
508
509
/**
 * 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);
510
511
	ir_node   *idx       = get_irn_n(node, n_ia32_index);
	int        has_index = !is_ia32_NoReg_GP(idx);
512
513
514
515

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

516
517
518
	if (get_ia32_am_tls_segment(node))
		be_emit_cstring("%gs:");

519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
	/* 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) {
			const arch_register_t *reg = get_in_reg(node, n_ia32_base);
			emit_register(reg, NULL);
		}

		/* emit index + scale */
		if (has_index) {
			const arch_register_t *reg = get_in_reg(node, n_ia32_index);
			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(')');
	}
}

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

	for (;;) {
592
		const char      *start = fmt;
593
		ia32_emit_mod_t  mod   = EMIT_NONE;
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

		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
610
			break;
611
612

		++fmt;
613
614
		for (;;) {
			switch (*fmt) {
615
616
617
			case '*': mod |= EMIT_ALTERNATE_AM; break;
			case '#': mod |= EMIT_RESPECT_LS;   break;
			case 'l': mod |= EMIT_LONG;         break;
618
619
			case '>': mod |= EMIT_HIGH_REG;     break;
			case '<': mod |= EMIT_LOW_REG;      break;
620
621
622
			default:
				goto end_of_mods;
			}
623
624
			++fmt;
		}
625
end_of_mods:
626

627
		switch (*fmt++) {
628
629
630
			arch_register_t const *reg;
			ir_node         const *imm;

631
632
633
634
635
636
			case '%':
				be_emit_char('%');
				break;

			case 'A': {
				switch (*fmt++) {
637
emit_AM:
638
					case 'M':
639
640
						if (mod & EMIT_ALTERNATE_AM)
							be_emit_char('*');
641
642
643
						ia32_emit_am(node);
						break;

644
645
					case 'R':
						reg = va_arg(ap, const arch_register_t*);
646
						if (get_ia32_op_type(node) == ia32_AddrModeS) {
647
							goto emit_AM;
648
						} else {
649
							goto emit_R;
650
651
652
653
654
						}

					case 'S':
						if (get_ia32_op_type(node) == ia32_AddrModeS) {
							++fmt;
655
							goto emit_AM;
656
657
658
659
660
661
662
663
664
665
						} else {
							assert(get_ia32_op_type(node) == ia32_Normal);
							goto emit_S;
						}

					default: goto unknown;
				}
				break;
			}

666
			case 'D':
667
668
				if (*fmt < '0' || '9' <= *fmt)
					goto unknown;
669
				reg = arch_irn_get_register(node, *fmt++ - '0');
670
				goto emit_R;
671
672

			case 'I':
673
674
				imm = node;
emit_I:
675
676
				if (!(mod & EMIT_ALTERNATE_AM))
					be_emit_char('$');
677
				emit_ia32_Immediate_no_prefix(imm);
678
679
680
681
682
683
				break;

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

684
			case 'M':
685
686
687
688
				ia32_emit_mode_suffix_mode(get_ia32_ls_mode(node));
				break;

			case 'P': {
689
690
				ia32_condition_code_t cc = va_arg(ap, ia32_condition_code_t);
				ia32_emit_condition_code(cc);
691
692
693
				break;
			}

694
695
696
697
698
			case 'R':
				reg = va_arg(ap, const arch_register_t*);
emit_R:
				if (mod & EMIT_ALTERNATE_AM)
					be_emit_char('*');
699
700
701
702
703
704
705
				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);
				}
706
707
708
709
				break;

emit_S:
			case 'S': {
710
				unsigned pos;
711
712
713
714
715

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

				pos = *fmt++ - '0';
716
717
718
				imm = get_irn_n(node, pos);
				if (is_ia32_Immediate(imm)) {
					goto emit_I;
719
				} else {
Michael Beck's avatar
Michael Beck committed
720
					reg = get_in_reg(node, pos);
721
					goto emit_R;
722
723
724
725
726
727
728
729
730
				}
			}

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

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
			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);
				}
749
750
751
752
				break;

			default:
unknown:
753
				panic("unknown format conversion in ia32_emitf()");
754
		}
755
756
757
758
759
760
761
762
763
764
765
766
767
768
	}

	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
769
	}
770
771
}

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

785
786
787
788
789
				if (out == NULL) {
					out = in1;
				} else if (out == in) {
					in = in1;
				}
790

791
792
793
794
				be_emit_char('%');
				be_emit_string(arch_register_get_name(in));
				be_emit_cstring(", %");
				be_emit_string(arch_register_get_name(out));
795
796
797
			}
			break;
		case ia32_AddrModeS:
798
			ia32_emit_am(node);
799
			break;
800
		case ia32_AddrModeD:
801
802
803
804
805
		default:
			assert(0 && "unsupported op type");
	}
}

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

Matthias Braun's avatar
Matthias Braun committed
816
817
818
static void emit_ia32_IMul(const ir_node *node)
{
	ir_node               *left    = get_irn_n(node, n_ia32_IMul_left);
819
	const arch_register_t *out_reg = arch_irn_get_register(node, pn_ia32_IMul_res);
Matthias Braun's avatar
Matthias Braun committed
820
821

	/* do we need the 3-address form? */
Christoph Mallon's avatar
Christoph Mallon committed
822
	if (is_ia32_NoReg_GP(left) ||
Matthias Braun's avatar
Matthias Braun committed
823
			get_in_reg(node, n_ia32_IMul_left) != out_reg) {
824
825
826
		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
827
828
829
	}
}

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

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

890
		flags_attr = get_ia32_attr_const(cmp);
891
	} else {
892
		flags_attr = get_ia32_attr_const(flags);
893
	}
894

895
896
897
	if (flags_attr->data.ins_permuted)
		cc = ia32_invert_condition_code(cc);
	return cc;
898
899
}

900
void ia32_emit_cmp_suffix_node(const ir_node *node, int flags_pos)
901
{
902
903
	ia32_condition_code_t cc = get_ia32_condcode(node);
	cc = determine_final_cc(node, flags_pos, cc);
904

905
	ia32_emit_condition_code(cc);
906
}
907

908
909
910
911
912
913
/**
 * 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());
914
	be_emit_irprintf("%lu", get_ia32_exc_label_id(node));
915
916
}

917
918
919
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
Christoph Mallon's avatar
Christoph Mallon committed
920
921
static ir_node *get_proj(const ir_node *node, long proj)
{
922
923
924
	const ir_edge_t *edge;
	ir_node         *src;

925
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
926

927
	foreach_out_edge(node, edge) {
928
929
930
931
932
933
934
935
936
937
938
939
		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;
}

940
static int can_be_fallthrough(const ir_node *node)
941
942
943
944
945
946
{
	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
947
948
949
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
950
static void emit_ia32_Jcc(const ir_node *node)
951
{
952
953
954
955
	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
956

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

959
960
961
	/* get both Projs */
	proj_true = get_proj(node, pn_ia32_Jcc_true);
	assert(proj_true && "Jcc without true Proj");
962

963
964
	proj_false = get_proj(node, pn_ia32_Jcc_false);
	assert(proj_false && "Jcc without false Proj");
965

966
	if (can_be_fallthrough(proj_true)) {
967
		/* exchange both proj's so the second one can be omitted */
968
969
		const ir_node *t = proj_true;

970
971
		proj_true  = proj_false;
		proj_false = t;
972
		cc         = ia32_negate_condition_code(cc);
973
974
	}

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

996
	/* the second Proj might be a fallthrough */
Matthias Braun's avatar
Matthias Braun committed
997
	if (can_be_fallthrough(proj_false)) {
998
		ia32_emitf(proj_false, "\t/* fallthrough to %L */\n");
999
	} else {
1000
		ia32_emitf(proj_false, "\tjmp %L\n");
1001
	}
Michael Beck's avatar
Michael Beck committed
1002
1003
}

1004
1005
1006
1007
1008
1009
/**
 * Emits an ia32 Setcc. This is mostly easy but some floating point compares
 * are tricky.
 */
static void emit_ia32_Setcc(const ir_node *node)
{
1010
	const arch_register_t *dreg = arch_irn_get_register(node, pn_ia32_Setcc_res);
1011

1012
1013
1014
1015
1016
	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);
1017
1018
			ia32_emitf(node, "\tsetp %>R\n", dreg);
			ia32_emitf(node, "\torb %>R, %<R\n", dreg, dreg);
1019
1020
1021
1022
		} else {
			ia32_emitf(node, "\tset%P %<R\n", cc, dreg);
			ia32_emitf(node, "\tsetnp %>R\n", dreg);