ia32_emitter.c 52 KB
Newer Older
<
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 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
 */
Christian Würdig's avatar
Christian Würdig committed
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
Christian Würdig's avatar
Christian Würdig committed
28
29
#endif

Christian Würdig's avatar
Christian Würdig committed
30
31
#include <limits.h>

32
#include "xmalloc.h"
33
34
#include "tv.h"
#include "iredges.h"
Christian Würdig's avatar
Christian Würdig committed
35
36
37
38
#include "debug.h"
#include "irgwalk.h"
#include "irprintf.h"
#include "irop_t.h"
Christian Würdig's avatar
Christian Würdig committed
39
#include "irargs_t.h"
40
#include "irprog_t.h"
41
#include "iredges_t.h"
42
#include "execfreq.h"
43
#include "error.h"
Matthias Braun's avatar
Matthias Braun committed
44
#include "raw_bitset.h"
45
#include "dbginfo.h"
Christian Würdig's avatar
Christian Würdig committed
46

47
#include "../besched_t.h"
Christian Würdig's avatar
Christian Würdig committed
48
#include "../benode_t.h"
Michael Beck's avatar
Michael Beck committed
49
#include "../beabi.h"
50
#include "../be_dbgout.h"
Matthias Braun's avatar
Matthias Braun committed
51
52
#include "../beemitter.h"
#include "../begnuas.h"
53
#include "../beirg_t.h"
54
#include "../be_dbgout.h"
Christian Würdig's avatar
Christian Würdig committed
55

56
#include "ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
57
#include "gen_ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
58
#include "gen_ia32_regalloc_if.h"
59
60
#include "ia32_nodes_attr.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
61
#include "ia32_map_regs.h"
62
#include "ia32_architecture.h"
Christian Würdig's avatar
Christian Würdig committed
63
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
64

65
66
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

67
#define BLOCK_PREFIX ".L"
Michael Beck's avatar
Michael Beck committed
68

Christian Würdig's avatar
Christian Würdig committed
69
70
#define SNPRINTF_BUF_LEN 128

71
72
73
static const arch_env_t *arch_env;
static const ia32_isa_t *isa;
static ia32_code_gen_t  *cg;
74
75
static int               do_pic;
static char              pic_base_label[128];
76

Christian Würdig's avatar
Christian Würdig committed
77
/**
Christian Würdig's avatar
Christian Würdig committed
78
 * Returns the register at in position pos.
Christian Würdig's avatar
Christian Würdig committed
79
 */
80
static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
81
{
82
83
	ir_node               *op;
	const arch_register_t *reg = NULL;
Christian Würdig's avatar
Christian Würdig committed
84
85
86
87
88
89
90

	assert(get_irn_arity(irn) > pos && "Invalid IN position");

	/* The out register of the operator at position pos is the
	   in register we need. */
	op = get_irn_n(irn, pos);

Christian Würdig's avatar
Christian Würdig committed
91
	reg = arch_get_irn_register(arch_env, op);
Christian Würdig's avatar
Christian Würdig committed
92

Christian Würdig's avatar
Christian Würdig committed
93
	assert(reg && "no in register found");
94

95
	if(reg == &ia32_gp_regs[REG_GP_NOREG])
96
		panic("trying to emit noreg for %+F input %d", irn, pos);
97
98
99

	/* in case of unknown register: just return a valid register */
	if (reg == &ia32_gp_regs[REG_GP_UKNWN]) {
Matthias Braun's avatar
Matthias Braun committed
100
		const arch_register_req_t *req;
101
102

		/* ask for the requirements */
Matthias Braun's avatar
Matthias Braun committed
103
		req = arch_get_register_req(arch_env, irn, pos);
104

Matthias Braun's avatar
Matthias Braun committed
105
		if (arch_register_req_is(req, limited)) {
106
			/* in case of limited requirements: get the first allowed register */
Matthias Braun's avatar
Matthias Braun committed
107
108
			unsigned idx = rbitset_next(req->limited, 0, 1);
			reg = arch_register_for_index(req->cls, idx);
109
		} else {
110
			/* otherwise get first register in class */
Matthias Braun's avatar
Matthias Braun committed
111
			reg = arch_register_for_index(req->cls, 0);
112
113
		}
	}
114

Christian Würdig's avatar
Christian Würdig committed
115
116
117
118
119
120
	return reg;
}

/**
 * Returns the register at out position pos.
 */
121
static const arch_register_t *get_out_reg(const ir_node *irn, int pos)
122
123
124
{
	ir_node               *proj;
	const arch_register_t *reg = NULL;
Christian Würdig's avatar
Christian Würdig committed
125
126
127
128
129
130
131

	/* 1st case: irn is not of mode_T, so it has only                 */
	/*           one OUT register -> good                             */
	/* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
	/*           Proj with the corresponding projnum for the register */

	if (get_irn_mode(irn) != mode_T) {
132
		assert(pos == 0);
Christian Würdig's avatar
Christian Würdig committed
133
		reg = arch_get_irn_register(arch_env, irn);
134
	} else if (is_ia32_irn(irn)) {
Christian Würdig's avatar
Christian Würdig committed
135
		reg = get_ia32_out_reg(irn, pos);
136
	} else {
Christian Würdig's avatar
Christian Würdig committed
137
138
139
140
141
142
143
144
145
146
147
148
149
		const ir_edge_t *edge;

		foreach_out_edge(irn, edge) {
			proj = get_edge_src_irn(edge);
			assert(is_Proj(proj) && "non-Proj from mode_T node");
			if (get_Proj_proj(proj) == pos) {
				reg = arch_get_irn_register(arch_env, proj);
				break;
			}
		}
	}

	assert(reg && "no out register found");
Christian Würdig's avatar
Christian Würdig committed
150
151
152
	return reg;
}

Michael Beck's avatar
Michael Beck committed
153
/**
154
 * Add a number to a prefix. This number will not be used a second time.
Michael Beck's avatar
Michael Beck committed
155
 */
156
157
static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
{
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
	static unsigned long id = 0;
	snprintf(buf, buflen, "%s%lu", prefix, ++id);
	return buf;
}

/*************************************************************
 *             _       _    __   _          _
 *            (_)     | |  / _| | |        | |
 *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
 * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
 * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
 * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
 * | |                                       | |
 * |_|                                       |_|
 *************************************************************/

174
175
static void emit_8bit_register(const arch_register_t *reg)
{
176
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
177

178
179
180
181
182
183
184
185
	be_emit_char('%');
	be_emit_char(reg_name[1]);
	be_emit_char('l');
}

static void emit_16bit_register(const arch_register_t *reg)
{
	const char *reg_name = ia32_get_mapped_reg_name(isa->regs_16bit, reg);
Christian Würdig's avatar
Christian Würdig committed
186

187
188
	be_emit_char('%');
	be_emit_string(reg_name);
189
190
}

191
192
193
194
195
196
197
198
199
200
201
202
203
static void emit_register(const arch_register_t *reg, const ir_mode *mode)
{
	const char *reg_name;

	if(mode != NULL) {
		int size = get_mode_size_bits(mode);
		if(size == 8) {
			emit_8bit_register(reg);
			return;
		} else if(size == 16) {
			emit_16bit_register(reg);
			return;
		} else {
204
			assert(mode_is_float(mode) || size == 32);
205
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      = get_in_reg(node, pos);
217

218
	emit_register(reg, NULL);
219
220
}

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
static void emit_ia32_Immediate(const ir_node *node);

void ia32_emit_8bit_source_register_or_immediate(const ir_node *node, int pos)
{
	const arch_register_t *reg;
	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_8bit_register(reg);
}

void ia32_emit_dest_register(const ir_node *node, int pos)
{
	const arch_register_t *reg  = get_out_reg(node, pos);

	emit_register(reg, NULL);
}

void ia32_emit_8bit_dest_register(const ir_node *node, int pos)
{
	const arch_register_t *reg  = get_out_reg(node, pos);

	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
251
{
252
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
253

Matthias Braun's avatar
Matthias Braun committed
254
	assert(pos < 3);
255
256
	be_emit_char('%');
	be_emit_string(attr->x87[pos]->name);
257
}
Christian Würdig's avatar
Christian Würdig committed
258

Matthias Braun's avatar
Matthias Braun committed
259
static void ia32_emit_mode_suffix_mode(const ir_mode *mode)
260
{
Matthias Braun's avatar
Matthias Braun committed
261
262
263
264
	if(mode_is_float(mode)) {
		switch(get_mode_size_bits(mode)) {
		case 32: be_emit_char('s'); return;
		case 64: be_emit_char('l'); return;
265
266
		case 80:
		case 96: be_emit_char('t'); return;
Matthias Braun's avatar
Matthias Braun committed
267
268
269
270
271
272
273
274
275
276
277
278
279
		}
	} else {
		assert(mode_is_int(mode) || mode_is_reference(mode));
		switch(get_mode_size_bits(mode)) {
		case 64: be_emit_cstring("ll"); return;
				 /* gas docu says q is the suffix but gcc, objdump and icc use
				 	ll apparently */
		case 32: be_emit_char('l'); return;
		case 16: be_emit_char('w'); return;
		case 8:  be_emit_char('b'); return;
		}
	}
	panic("Can't output mode_suffix for %+F\n", mode);
Christian Würdig's avatar
Christian Würdig committed
280
281
}

282
void ia32_emit_mode_suffix(const ir_node *node)
283
284
{
	ir_mode *mode = get_ia32_ls_mode(node);
Matthias Braun's avatar
Matthias Braun committed
285
286
287
	if(mode == NULL)
		mode = mode_Iu;

288
	ia32_emit_mode_suffix_mode(mode);
289
290
}

291
void ia32_emit_x87_mode_suffix(const ir_node *node)
292
293
{
	ir_mode *mode = get_ia32_ls_mode(node);
294
295
296
	assert(mode != NULL);
	/* we only need to emit the mode on address mode */
	if(get_ia32_op_type(node) != ia32_Normal)
297
		ia32_emit_mode_suffix_mode(mode);
298
299
}

300
static char get_xmm_mode_suffix(ir_mode *mode)
301
302
303
304
305
306
307
308
309
310
311
312
313
{
	assert(mode_is_float(mode));
	switch(get_mode_size_bits(mode)) {
	case 32:
		return 's';
	case 64:
		return 'd';
	default:
		assert(0);
	}
	return '%';
}

314
void ia32_emit_xmm_mode_suffix(const ir_node *node)
315
316
{
	ir_mode *mode = get_ia32_ls_mode(node);
317
	assert(mode != NULL);
318
319
	be_emit_char('s');
	be_emit_char(get_xmm_mode_suffix(mode));
320
321
}

322
void ia32_emit_xmm_mode_suffix_s(const ir_node *node)
323
324
325
{
	ir_mode *mode = get_ia32_ls_mode(node);
	assert(mode != NULL);
326
	be_emit_char(get_xmm_mode_suffix(mode));
327
328
}

329
void ia32_emit_extend_suffix(const ir_mode *mode)
330
331
332
333
{
	if(get_mode_size_bits(mode) == 32)
		return;
	if(mode_is_signed(mode)) {
334
		be_emit_char('s');
335
	} else {
336
		be_emit_char('z');
Matthias Braun's avatar
Matthias Braun committed
337
338
339
	}
}

340
void ia32_emit_source_register_or_immediate(const ir_node *node, int pos)
341
342
343
{
	ir_node *in = get_irn_n(node, pos);
	if(is_ia32_Immediate(in)) {
344
		emit_ia32_Immediate(in);
345
	} else {
346
347
348
		const ir_mode         *mode = get_ia32_ls_mode(node);
		const arch_register_t *reg  = get_in_reg(node, pos);
		emit_register(reg, mode);
349
350
351
	}
}

Christian Würdig's avatar
Christian Würdig committed
352
353
354
/**
 * Emits registers and/or address mode of a binary operation.
 */
355
void ia32_emit_binop(const ir_node *node) {
356
357
358
	const ir_node         *right_op  = get_irn_n(node, n_ia32_binary_right);
	const ir_mode         *mode      = get_ia32_ls_mode(node);
	const arch_register_t *reg_left;
Christian Würdig's avatar
Christian Würdig committed
359

360
361
	switch(get_ia32_op_type(node)) {
	case ia32_Normal:
362
		reg_left = get_in_reg(node, n_ia32_binary_left);
363
		if(is_ia32_Immediate(right_op)) {
364
365
366
			emit_ia32_Immediate(right_op);
			be_emit_cstring(", ");
			emit_register(reg_left, mode);
Christian Würdig's avatar
Christian Würdig committed
367
			break;
368
		} else {
369
370
371
372
373
			const arch_register_t *reg_right
				= get_in_reg(node, n_ia32_binary_right);
			emit_register(reg_right, mode);
			be_emit_cstring(", ");
			emit_register(reg_left, mode);
374
375
376
		}
		break;
	case ia32_AddrModeS:
377
		if(is_ia32_Immediate(right_op)) {
378
379
380
			emit_ia32_Immediate(right_op);
			be_emit_cstring(", ");
			ia32_emit_am(node);
381
		} else {
382
383
384
385
			reg_left = get_in_reg(node, n_ia32_binary_left);
			ia32_emit_am(node);
			be_emit_cstring(", ");
			emit_register(reg_left, mode);
386
387
388
		}
		break;
	case ia32_AddrModeD:
389
		panic("DestMode can't be output by %%binop anymore");
390
391
392
		break;
	default:
		assert(0 && "unsupported op type");
Christian Würdig's avatar
Christian Würdig committed
393
	}
394
395
}

396
397
398
/**
 * Emits registers and/or address mode of a binary operation.
 */
399
void ia32_emit_x87_binop(const ir_node *node) {
400
	switch(get_ia32_op_type(node)) {
401
		case ia32_Normal:
402
			{
403
404
405
406
				const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
				const arch_register_t *in1      = x87_attr->x87[0];
				const arch_register_t *in2      = x87_attr->x87[1];
				const arch_register_t *out      = x87_attr->x87[2];
407
408
				const arch_register_t *in;

409
				in  = out ? ((out == in2) ? in1 : in2) : in2;
410
				out = out ? out : in1;
411

412
413
414
415
				be_emit_char('%');
				be_emit_string(arch_register_get_name(in));
				be_emit_cstring(", %");
				be_emit_string(arch_register_get_name(out));
416
417
418
			}
			break;
		case ia32_AddrModeS:
419
			ia32_emit_am(node);
420
			break;
421
		case ia32_AddrModeD:
422
423
424
425
426
		default:
			assert(0 && "unsupported op type");
	}
}

427
void ia32_emit_am_or_dest_register(const ir_node *node,
428
429
                                   int pos) {
	if(get_ia32_op_type(node) == ia32_Normal) {
430
		ia32_emit_dest_register(node, pos);
431
432
	} else {
		assert(get_ia32_op_type(node) == ia32_AddrModeD);
433
		ia32_emit_am(node);
434
435
436
	}
}

Christian Würdig's avatar
Christian Würdig committed
437
438
439
/**
 * Emits registers and/or address mode of a unary operation.
 */
440
void ia32_emit_unop(const ir_node *node, int pos) {
441
442
	const ir_node *op;

443
	switch(get_ia32_op_type(node)) {
444
445
446
	case ia32_Normal:
		op = get_irn_n(node, pos);
		if (is_ia32_Immediate(op)) {
447
			emit_ia32_Immediate(op);
448
		} else {
449
			ia32_emit_source_register(node, pos);
450
451
452
453
		}
		break;
	case ia32_AddrModeS:
	case ia32_AddrModeD:
454
		ia32_emit_am(node);
455
456
457
		break;
	default:
		assert(0 && "unsupported op type");
Christian Würdig's avatar
Christian Würdig committed
458
459
460
	}
}

461
static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
462
463
464
465
466
467
468
{
	ident *id;

	set_entity_backend_marked(entity, 1);
	id = get_entity_ld_ident(entity);
	be_emit_ident(id);

469
	if (get_entity_owner(entity) == get_tls_type()) {
470
471
472
473
474
475
		if (get_entity_visibility(entity) == visibility_external_allocated) {
			be_emit_cstring("@INDNTPOFF");
		} else {
			be_emit_cstring("@NTPOFF");
		}
	}
476
477
478
479
480
481

	if (!no_pic_adjust && do_pic) {
		/* TODO: only do this when necessary */
		be_emit_char('-');
		be_emit_string(pic_base_label);
	}
482
483
}

Christian Würdig's avatar
Christian Würdig committed
484
/**
485
 * Emits address mode.
Christian Würdig's avatar
Christian Würdig committed
486
 */
487
void ia32_emit_am(const ir_node *node) {
488
489
490
491
492
493
	ir_entity *ent       = get_ia32_am_sc(node);
	int        offs      = get_ia32_am_offs_int(node);
	ir_node   *base      = get_irn_n(node, 0);
	int        has_base  = !is_ia32_NoReg_GP(base);
	ir_node   *index     = get_irn_n(node, 1);
	int        has_index = !is_ia32_NoReg_GP(index);
Christian Würdig's avatar
Christian Würdig committed
494

495
	/* just to be sure... */
496
	assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
Christian Würdig's avatar
Christian Würdig committed
497

498
	/* emit offset */
499
	if (ent != NULL) {
500
		if (is_ia32_am_sc_sign(node))
501
			be_emit_char('-');
502
		ia32_emit_entity(ent, 0);
Christian Würdig's avatar
Christian Würdig committed
503
504
	}

505
	if(offs != 0) {
506
		if(ent != NULL) {
507
			be_emit_irprintf("%+d", offs);
508
		} else {
509
			be_emit_irprintf("%d", offs);
510
		}
511
	}
Christian Würdig's avatar
Christian Würdig committed
512

513
	if (has_base || has_index) {
514
		be_emit_char('(');
Christian Würdig's avatar
Christian Würdig committed
515

516
		/* emit base */
517
		if (has_base) {
518
519
			const arch_register_t *reg = get_in_reg(node, n_ia32_base);
			emit_register(reg, NULL);
Christian Würdig's avatar
Christian Würdig committed
520
521
		}

522
		/* emit index + scale */
523
		if (has_index) {
524
			const arch_register_t *reg = get_in_reg(node, n_ia32_index);
525
			int scale;
526
527
			be_emit_char(',');
			emit_register(reg, NULL);
528

529
530
			scale = get_ia32_am_scale(node);
			if (scale > 0) {
531
				be_emit_irprintf(",%d", 1 << get_ia32_am_scale(node));
532
533
			}
		}
534
		be_emit_char(')');
Christian Würdig's avatar
Christian Würdig committed
535
	}
536
537
538

	/* special case if nothing is set */
	if(ent == NULL && offs == 0 && !has_base && !has_index) {
539
		be_emit_char('0');
540
	}
541
}
Christian Würdig's avatar
Christian Würdig committed
542

Matthias Braun's avatar
Matthias Braun committed
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
static void emit_ia32_IMul(const ir_node *node)
{
	ir_node               *left    = get_irn_n(node, n_ia32_IMul_left);
	const arch_register_t *out_reg = get_out_reg(node, pn_ia32_IMul_res);

	be_emit_cstring("\timul");
	ia32_emit_mode_suffix(node);
	be_emit_char(' ');

	ia32_emit_binop(node);

	/* do we need the 3-address form? */
	if(is_ia32_NoReg_GP(left) ||
			get_in_reg(node, n_ia32_IMul_left) != out_reg) {
		be_emit_cstring(", ");
		emit_register(out_reg, get_ia32_ls_mode(node));
	}
	be_emit_finish_line_gas(node);
}

Christian Würdig's avatar
Christian Würdig committed
563
564
565
566
567
568
569
570
571
572
/*************************************************
 *                 _ _                         _
 *                (_) |                       | |
 *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
 *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
 * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
 *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
 *
 *************************************************/

Christian Würdig's avatar
Christian Würdig committed
573
#undef IA32_DO_EMIT
Christian Würdig's avatar
Christian Würdig committed
574
#define IA32_DO_EMIT(irn) ia32_fprintf_format(F, irn, cmd_buf, cmnt_buf)
Christian Würdig's avatar
Christian Würdig committed
575

576
577
578
579
/*
 * coding of conditions
 */
struct cmp2conditon_t {
Christian Würdig's avatar
Christian Würdig committed
580
	const char *name;
581
	int         num;
582
583
584
585
586
};

/*
 * positive conditions for signed compares
 */
587
static const struct cmp2conditon_t cmp2condition_s[] = {
588
589
590
591
592
593
594
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "l",               pn_Cmp_Lt },     /* < */
	{ "le",              pn_Cmp_Le },     /* <= */
	{ "g",               pn_Cmp_Gt },     /* > */
	{ "ge",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
595
	{ NULL,              pn_Cmp_Leg},     /* always true */
596
597
598
599
600
};

/*
 * positive conditions for unsigned compares
 */
601
static const struct cmp2conditon_t cmp2condition_u[] = {
Christian Würdig's avatar
Christian Würdig committed
602
603
604
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "b",               pn_Cmp_Lt },     /* < */
Christian Würdig's avatar
Christian Würdig committed
605
	{ "be",              pn_Cmp_Le },     /* <= */
Christian Würdig's avatar
Christian Würdig committed
606
607
608
	{ "a",               pn_Cmp_Gt },     /* > */
	{ "ae",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
609
	{ NULL,              pn_Cmp_Leg },   /* always true  */
610
611
};

612
613
614
615
616
617
618
619
enum {
	ia32_pn_Cmp_unsigned = 0x1000,
	ia32_pn_Cmp_float    = 0x2000,
};

/**
 * walks up a tree of copies/perms/spills/reloads to find the original value
 * that is moved around
620
 */
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
static ir_node *find_original_value(ir_node *node)
{
	inc_irg_visited(current_ir_graph);
	while(1) {
		mark_irn_visited(node);
		if(be_is_Copy(node)) {
			node = be_get_Copy_op(node);
		} else if(be_is_CopyKeep(node)) {
			node = be_get_CopyKeep_op(node);
		} else if(is_Proj(node)) {
			ir_node *pred = get_Proj_pred(node);
			if(be_is_Perm(pred)) {
				node = get_irn_n(pred, get_Proj_proj(node));
			} else if(be_is_MemPerm(pred)) {
				node = get_irn_n(pred, get_Proj_proj(node) + 1);
			} else if(is_ia32_Load(pred)) {
				node = get_irn_n(pred, n_ia32_Load_mem);
			} else {
				return node;
			}
641
		} else if(is_ia32_Store(node)) {
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
			node = get_irn_n(node, n_ia32_Store_val);
		} 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);
				if(irn_visited(in))
					continue;
				node = in;
				break;
			}
			assert(i < arity);
		} else {
			return node;
		}
	}
}

static int determine_final_pnc(const ir_node *node, int flags_pos,
                               int pnc)
662
{
663
664
665
666
667
668
	ir_node           *flags = get_irn_n(node, flags_pos);
	const ia32_attr_t *flags_attr;
	flags = skip_Proj(flags);

	if(is_ia32_Sahf(flags)) {
		ir_node *cmp = get_irn_n(flags, n_ia32_Sahf_val);
669
670
		if(!(is_ia32_FucomFnstsw(cmp) || is_ia32_FucompFnstsw(cmp)
				|| is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp))) {
671
672
			cmp = find_original_value(cmp);
			assert(is_ia32_FucomFnstsw(cmp) || is_ia32_FucompFnstsw(cmp)
673
			       || is_ia32_FucomppFnstsw(cmp) || is_ia32_FtstFnstsw(cmp));
674
		}
675

676
		flags_attr = get_ia32_attr_const(cmp);
677
		if(flags_attr->data.ins_permuted)
678
679
			pnc = get_mirrored_pnc(pnc);
		pnc |= ia32_pn_Cmp_float;
Matthias Braun's avatar
Matthias Braun committed
680
681
	} else if(is_ia32_Ucomi(flags) || is_ia32_Fucomi(flags)
			|| is_ia32_Fucompi(flags)) {
682
683
		flags_attr = get_ia32_attr_const(flags);

684
		if(flags_attr->data.ins_permuted)
685
686
			pnc = get_mirrored_pnc(pnc);
		pnc |= ia32_pn_Cmp_float;
687
	} else {
688
#if 0
689
690
		assert(is_ia32_Cmp(flags) || is_ia32_Test(flags)
				|| is_ia32_Cmp8Bit(flags) || is_ia32_Test8Bit(flags));
691
#endif
692
693
		flags_attr = get_ia32_attr_const(flags);

694
		if(flags_attr->data.ins_permuted)
695
696
697
			pnc = get_mirrored_pnc(pnc);
		if(flags_attr->data.cmp_unsigned)
			pnc |= ia32_pn_Cmp_unsigned;
698
	}
699
700

	return pnc;
701
702
}

703
static void ia32_emit_cmp_suffix(int pnc)
704
{
705
706
707
708
709
710
711
712
713
714
715
716
	const char        *str;

	if((pnc & ia32_pn_Cmp_float) || (pnc & ia32_pn_Cmp_unsigned)) {
		pnc = pnc & 7;
		assert(cmp2condition_u[pnc].num == pnc);
		str = cmp2condition_u[pnc].name;
	} else {
		pnc = pnc & 7;
		assert(cmp2condition_s[pnc].num == pnc);
		str = cmp2condition_s[pnc].name;
	}

717
	be_emit_string(str);
718
719
}

720
void ia32_emit_cmp_suffix_node(const ir_node *node,
721
722
                               int flags_pos)
{
723
724
	const ia32_attr_t *attr = get_ia32_attr_const(node);

Michael Beck's avatar
Michael Beck committed
725
	pn_Cmp pnc = get_ia32_condcode(node);
726
727

	pnc = determine_final_pnc(node, flags_pos, pnc);
728
729
730
731
732
733
734
735
	if(attr->data.ins_permuted) {
		if(pnc & ia32_pn_Cmp_float) {
			pnc = get_negated_pnc(pnc, mode_F);
		} else {
			pnc = get_negated_pnc(pnc, mode_Iu);
		}
	}

736
	ia32_emit_cmp_suffix(pnc);
737
}
738

739
740
741
/**
 * Returns the target block for a control flow node.
 */
742
static ir_node *get_cfop_target_block(const ir_node *irn) {
743
744
745
	return get_irn_link(irn);
}

746
747
748
/**
 * Emits a block label for the given block.
 */
749
static void ia32_emit_block_name(const ir_node *block)
750
{
Michael Beck's avatar
Michael Beck committed
751
	if (has_Block_label(block)) {
752
753
		be_emit_string(be_gas_label_prefix());
		be_emit_irprintf("%u", (unsigned)get_Block_label(block));
Michael Beck's avatar
Michael Beck committed
754
	} else {
755
756
		be_emit_cstring(BLOCK_PREFIX);
		be_emit_irprintf("%d", get_irn_node_nr(block));
Michael Beck's avatar
Michael Beck committed
757
	}
758
759
}

Christian Würdig's avatar
Christian Würdig committed
760
/**
761
 * Emits the target label for a control flow node.
Christian Würdig's avatar
Christian Würdig committed
762
 */
763
764
static void ia32_emit_cfop_target(const ir_node *node)
{
765
	ir_node *block = get_cfop_target_block(node);
766

767
	ia32_emit_block_name(block);
Christian Würdig's avatar
Christian Würdig committed
768
}
769

770
/** Return the next block in Block schedule */
771
772
static ir_node *next_blk_sched(const ir_node *block)
{
Michael Beck's avatar
Michael Beck committed
773
	return get_irn_link(block);
774
775
}

776
777
778
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
779
static ir_node *get_proj(const ir_node *node, long proj) {
780
781
782
	const ir_edge_t *edge;
	ir_node         *src;

783
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
784

785
	foreach_out_edge(node, edge) {
786
787
788
789
790
791
792
793
794
795
796
797
		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;
}

Christian Würdig's avatar
Christian Würdig committed
798
799
800
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
801
static void emit_ia32_Jcc(const ir_node *node)
802
{
803
	int            need_parity_label = 0;
804
805
806
807
	const ir_node *proj_true;
	const ir_node *proj_false;
	const ir_node *block;
	const ir_node *next_block;
Michael Beck's avatar
Michael Beck committed
808
	pn_Cmp         pnc = get_ia32_condcode(node);
Christian Würdig's avatar
Christian Würdig committed
809

810
	pnc = determine_final_pnc(node, 0, pnc);
Christian Würdig's avatar
Christian Würdig committed
811

812
813
814
	/* get both Projs */
	proj_true = get_proj(node, pn_ia32_Jcc_true);
	assert(proj_true && "Jcc without true Proj");
815

816
817
	proj_false = get_proj(node, pn_ia32_Jcc_false);
	assert(proj_false && "Jcc without false Proj");
818

819
	block      = get_nodes_block(node);
820
	next_block = next_blk_sched(block);
821

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

826
827
		proj_true  = proj_false;
		proj_false = t;
828
829
830
831
832
		if(pnc & ia32_pn_Cmp_float) {
			pnc = get_negated_pnc(pnc, mode_F);
		} else {
			pnc = get_negated_pnc(pnc, mode_Iu);
		}
833
834
	}

835
836
837
838
	if (pnc & ia32_pn_Cmp_float) {
		/* Some floating point comparisons require a test of the parity flag,
		 * which indicates that the result is unordered */
		switch (pnc & 15) {
839
			case pn_Cmp_Uo: {
840
841
842
				be_emit_cstring("\tjp ");
				ia32_emit_cfop_target(proj_true);
				be_emit_finish_line_gas(proj_true);
843
				break;
844
			}
845
846

			case pn_Cmp_Leg:
847
848
849
				be_emit_cstring("\tjnp ");
				ia32_emit_cfop_target(proj_true);
				be_emit_finish_line_gas(proj_true);
850
851
852
853
				break;

			case pn_Cmp_Eq:
			case pn_Cmp_Lt:
854
855
856
857
858
859
860
861
862
863
			case pn_Cmp_Le:
				/* we need a local label if the false proj is a fallthrough
				 * as the falseblock might have no label emitted then */
				if (get_cfop_target_block(proj_false) == next_block) {
					need_parity_label = 1;
					be_emit_cstring("\tjp 1f");
				} else {
					be_emit_cstring("\tjp ");
					ia32_emit_cfop_target(proj_false);
				}
864
				be_emit_finish_line_gas(proj_false);
865
				goto emit_jcc;
866
867
868

			case pn_Cmp_Ug:
			case pn_Cmp_Uge:
869
			case pn_Cmp_Ne:
870
871
872
				be_emit_cstring("\tjp ");
				ia32_emit_cfop_target(proj_true);
				be_emit_finish_line_gas(proj_true);
873
				goto emit_jcc;
874
875
876
877
878
879

			default:
				goto emit_jcc;
		}
	} else {
emit_jcc:
880
881
882
883
884
		be_emit_cstring("\tj");
		ia32_emit_cmp_suffix(pnc);
		be_emit_char(' ');
		ia32_emit_cfop_target(proj_true);
		be_emit_finish_line_gas(proj_true);
885
886
	}

887
888
889
890
891
	if(need_parity_label) {
		be_emit_cstring("1:");
		be_emit_write_line();
	}

892
	/* the second Proj might be a fallthrough */
893
	if (get_cfop_target_block(proj_false) != next_block) {
894
895
896
		be_emit_cstring("\tjmp ");
		ia32_emit_cfop_target(proj_false);
		be_emit_finish_line_gas(proj_false);
897
	} else {
898
899
900
901
		be_emit_cstring("\t/* fallthrough to ");
		ia32_emit_cfop_target(proj_false);
		be_emit_cstring(" */");
		be_emit_finish_line_gas(proj_false);
902
	}
Michael Beck's avatar
Michael Beck committed
903
904
}

905
static void emit_ia32_CMov(const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
906
{
907
908
909
	const ia32_attr_t     *attr         = get_ia32_attr_const(node);
	int                    ins_permuted = attr->data.ins_permuted;
	const arch_register_t *out          = arch_get_irn_register(arch_env, node);
Michael Beck's avatar
Michael Beck committed
910
	pn_Cmp                 pnc          = get_ia32_condcode(node);
911
912
913
914
915
	const arch_register_t *in_true;
	const arch_register_t *in_false;

	pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc);

916
	in_true  = arch_get_irn_register(arch_env,
917
	                                 get_irn_n(node, n_ia32_CMov_val_true));
918
	in_false = arch_get_irn_register(arch_env,
919
920
921
922
923
924
925
926
	                                 get_irn_n(node, n_ia32_CMov_val_false));

	/* should be same constraint fullfilled? */
	if(out == in_false) {
		/* yes -> nothing to do */
	} else if(out == in_true) {
		const arch_register_t *tmp;

927
928
929
		assert(get_ia32_op_type(node) == ia32_Normal);

		ins_permuted = !ins_permuted;
930
931
932
933

		tmp      = in_true;
		in_true  = in_false;
		in_false = tmp;
934
	} else {
935
		/* we need a mov */
936
937
938
939
940
		be_emit_cstring("\tmovl ");
		emit_register(in_false, NULL);
		be_emit_cstring(", ");
		emit_register(out, NULL);
		be_emit_finish_line_gas(node);
941
	}
942

943
944
945
946
947
948
949
950
	if(ins_permuted) {
		if(pnc & ia32_pn_Cmp_float) {
			pnc = get_negated_pnc(pnc, mode_F);
		} else {
			pnc = get_negated_pnc(pnc, mode_Iu);
		}
	}

951
952
	/* TODO: handling of Nans isn't correct yet */

953
954
955
	be_emit_cstring("\tcmov");
	ia32_emit_cmp_suffix(pnc);
	be_emit_char(' ');
956
	if(get_ia32_op_type(node) == ia32_AddrModeS) {
957
		ia32_emit_am(node);
958
	} else {
959
		emit_register(in_true, get_ia32_ls_mode(node));
960
	}
961
962
963
	be_emit_cstring(", ");
	emit_register(out, get_ia32_ls_mode(node));
	be_emit_finish_line_gas(node);
964
965
}

Christian Würdig's avatar
Christian Würdig committed
966
967
968
969
970
971
972
973
974
975
976
977
/*********************************************************
 *                 _ _       _
 *                (_) |     (_)
 *   ___ _ __ ___  _| |_     _ _   _ _ __ ___  _ __  ___
 *  / _ \ '_ ` _ \| | __|   | | | | | '_ ` _ \| '_ \/ __|
 * |  __/ | | | | | | |_    | | |_| | | | | | | |_) \__ \
 *  \___|_| |_| |_|_|\__|   | |\__,_|_| |_| |_| .__/|___/
 *                         _/ |               | |
 *                        |__/                |_|
 *********************************************************/

/* jump table entry (target and corresponding number) */
Christian Würdig's avatar
Christian Würdig committed
978
979
980
981
982
typedef struct _branch_t {
	ir_node *target;
	int      value;
} branch_t;

Christian Würdig's avatar
Christian Würdig committed
983
/* jump table for switch generation */
Christian Würdig's avatar
Christian Würdig committed
984
typedef struct _jmp_tbl_t {
Christian Würdig's avatar
Christian Würdig committed
985
	ir_node  *defProj;         /**< default target */
Matthias Braun's avatar
Matthias Braun committed
986
987
988
	long      min_value;       /**< smallest switch case */
	long      max_value;       /**< largest switch case */
	long      num_branches;    /**< number of jumps */
Christian Würdig's avatar
Christian Würdig committed
989
990
	char     *label;           /**< label of the jump table */
	branch_t *branches;        /**< jump array */
Christian Würdig's avatar
Christian Würdig committed
991
992
} jmp_tbl_t;

Christian Würdig's avatar
Christian Würdig committed
993
994
995
/**
 * Compare two variables of type branch_t. Used to sort all switch cases
 */
996
static int ia32_cmp_branch_t(const void *a, const void *b) {