ia32_emitter.c 60.6 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
 *
 * 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"
Christian Würdig's avatar
Christian Würdig committed
45

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

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

62
63
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

64
#define BLOCK_PREFIX ".L"
Michael Beck's avatar
Michael Beck committed
65

Christian Würdig's avatar
Christian Würdig committed
66
67
68
#define SNPRINTF_BUF_LEN 128

/**
Christian Würdig's avatar
Christian Würdig committed
69
 * Returns the register at in position pos.
Christian Würdig's avatar
Christian Würdig committed
70
 */
71
72
73
74
75
static
const arch_register_t *get_in_reg(ia32_emit_env_t *env, const ir_node *irn,
                                  int pos)
{
	const arch_env_t       *arch_env = env->arch_env;
Christian Würdig's avatar
Christian Würdig committed
76
77
78
79
80
81
82
83
84
	ir_node                *op;
	const arch_register_t  *reg = NULL;

	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
85
	reg = arch_get_irn_register(arch_env, op);
Christian Würdig's avatar
Christian Würdig committed
86

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

89
	if(reg == &ia32_gp_regs[REG_GP_NOREG])
90
		panic("trying to emit noreg for %+F input %d", irn, pos);
91
92
93

	/* 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
94
		const arch_register_req_t *req;
95
96

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

Matthias Braun's avatar
Matthias Braun committed
99
		if (arch_register_req_is(req, limited)) {
100
			/* in case of limited requirements: get the first allowed register */
Matthias Braun's avatar
Matthias Braun committed
101
102
			unsigned idx = rbitset_next(req->limited, 0, 1);
			reg = arch_register_for_index(req->cls, idx);
103
		} else {
104
			/* otherwise get first register in class */
Matthias Braun's avatar
Matthias Braun committed
105
			reg = arch_register_for_index(req->cls, 0);
106
107
		}
	}
108

Christian Würdig's avatar
Christian Würdig committed
109
110
111
112
113
114
	return reg;
}

/**
 * Returns the register at out position pos.
 */
115
116
117
118
119
120
121
static
const arch_register_t *get_out_reg(ia32_emit_env_t *env, const ir_node *irn,
                                   int pos)
{
	const arch_env_t      *arch_env = env->arch_env;
	ir_node               *proj;
	const arch_register_t *reg = NULL;
Christian Würdig's avatar
Christian Würdig committed
122
123
124
125
126
127
128
129

	/* 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) {
		reg = arch_get_irn_register(arch_env, irn);
130
	} else if (is_ia32_irn(irn)) {
Christian Würdig's avatar
Christian Würdig committed
131
		reg = get_ia32_out_reg(irn, pos);
132
	} else {
Christian Würdig's avatar
Christian Würdig committed
133
134
135
136
137
138
139
140
141
142
143
144
145
		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
146
147
148
	return reg;
}

149
150
151
/**
 * Determine the gnu assembler suffix that indicates a mode
 */
152
153
static
char get_mode_suffix(const ir_mode *mode) {
154
155
156
157
158
159
160
	if(mode_is_float(mode)) {
		switch(get_mode_size_bits(mode)) {
		case 32:
			return 's';
		case 64:
			return 'l';
		case 80:
161
		case 96:
162
			return 't';
163
		}
164
	} else {
165
		assert(mode_is_int(mode) || mode_is_reference(mode));
166
167
168
169
170
171
172
173
174
		switch(get_mode_size_bits(mode)) {
		case 64:
			return 'q';
		case 32:
			return 'l';
		case 16:
			return 'w';
		case 8:
			return 'b';
Christian Würdig's avatar
Christian Würdig committed
175
		}
176
177
178
	}
	panic("Can't output mode_suffix for %+F\n", mode);
}
Christian Würdig's avatar
Christian Würdig committed
179

180
181
182
static
const char *ia32_get_reg_name_for_mode(ia32_emit_env_t *env, ir_mode *mode,
                                       const arch_register_t *reg) {
183
184
185
186
187
188
189
	switch(get_mode_size_bits(mode)) {
		case 8:
			return ia32_get_mapped_reg_name(env->isa->regs_8bit, reg);
		case 16:
			return ia32_get_mapped_reg_name(env->isa->regs_16bit, reg);
		default:
			return (char *)arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
190
	}
Christian Würdig's avatar
Christian Würdig committed
191
192
}

Michael Beck's avatar
Michael Beck committed
193
/**
194
 * Add a number to a prefix. This number will not be used a second time.
Michael Beck's avatar
Michael Beck committed
195
 */
196
197
static
char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
	static unsigned long id = 0;
	snprintf(buf, buflen, "%s%lu", prefix, ++id);
	return buf;
}

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

Matthias Braun's avatar
Matthias Braun committed
214
215
216
217
218
219
220
// we have no C++ and can't define an implicit ia32_emit_env_t* cast to
// be_emit_env_t* so we cheat a bit...
#define be_emit_char(env,c)             be_emit_char(env->emit,c)
#define be_emit_string(env,s)           be_emit_string(env->emit,s)
#undef be_emit_cstring
#define be_emit_cstring(env,x)          { be_emit_string_len(env->emit, x, sizeof(x)-1); }
#define be_emit_ident(env,i)            be_emit_ident(env->emit,i)
221
#define be_emit_tarval(env,tv)          be_emit_tarval(env->emit,tv)
Matthias Braun's avatar
Matthias Braun committed
222
223
224
#define be_emit_write_line(env)         be_emit_write_line(env->emit)
#define be_emit_finish_line_gas(env,n)  be_emit_finish_line_gas(env->emit,n)
#define be_emit_pad_comment(env)        be_emit_pad_comment(env->emit)
Michael Beck's avatar
Michael Beck committed
225

226
void ia32_emit_source_register(ia32_emit_env_t *env, const ir_node *node, int pos)
Christian Würdig's avatar
Christian Würdig committed
227
{
228
	const arch_register_t *reg = get_in_reg(env, node, pos);
229
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
230

231
	assert(pos < get_irn_arity(node));
Christian Würdig's avatar
Christian Würdig committed
232

Matthias Braun's avatar
Matthias Braun committed
233
234
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
235
236
237
}

void ia32_emit_dest_register(ia32_emit_env_t *env, const ir_node *node, int pos) {
238
	const arch_register_t *reg = get_out_reg(env, node, pos);
239
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
240

Matthias Braun's avatar
Matthias Braun committed
241
242
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
Christian Würdig's avatar
Christian Würdig committed
243
244
}

245
246
247
248
249
250
251
252
static void ia32_emit_register(ia32_emit_env_t *env, const arch_register_t *reg)
{
	const char *reg_name = arch_register_get_name(reg);

	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
}

253
void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos)
Christian Würdig's avatar
Christian Würdig committed
254
{
255
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
256

Matthias Braun's avatar
Matthias Braun committed
257
	assert(pos < 3);
Matthias Braun's avatar
Matthias Braun committed
258
259
	be_emit_char(env, '%');
	be_emit_string(env, attr->x87[pos]->name);
260
}
Christian Würdig's avatar
Christian Würdig committed
261

Matthias Braun's avatar
Matthias Braun committed
262
263
static
void ia32_emit_mode_suffix_mode(ia32_emit_env_t *env, const ir_mode *mode)
264
{
Matthias Braun's avatar
Matthias Braun committed
265
	be_emit_char(env, get_mode_suffix(mode));
Christian Würdig's avatar
Christian Würdig committed
266
267
}

Matthias Braun's avatar
Matthias Braun committed
268
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
269
270
{
	ir_mode *mode = get_ia32_ls_mode(node);
Matthias Braun's avatar
Matthias Braun committed
271
272
273
274
	if(mode == NULL)
		mode = mode_Iu;

	ia32_emit_mode_suffix_mode(env, mode);
275
276
}

277
278
279
280
281
282
283
void ia32_emit_x87_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
{
	ir_mode *mode = get_ia32_ls_mode(node);
	if(mode != NULL)
		ia32_emit_mode_suffix_mode(env, mode);
}

284
285
static
char get_xmm_mode_suffix(ir_mode *mode)
286
287
288
289
290
291
292
293
294
295
296
297
298
{
	assert(mode_is_float(mode));
	switch(get_mode_size_bits(mode)) {
	case 32:
		return 's';
	case 64:
		return 'd';
	default:
		assert(0);
	}
	return '%';
}

299
300
301
void ia32_emit_xmm_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
{
	ir_mode *mode = get_ia32_ls_mode(node);
302
	assert(mode != NULL);
Matthias Braun's avatar
Matthias Braun committed
303
304
	be_emit_char(env, 's');
	be_emit_char(env, get_xmm_mode_suffix(mode));
305
306
307
308
309
310
}

void ia32_emit_xmm_mode_suffix_s(ia32_emit_env_t *env, const ir_node *node)
{
	ir_mode *mode = get_ia32_ls_mode(node);
	assert(mode != NULL);
Matthias Braun's avatar
Matthias Braun committed
311
	be_emit_char(env, get_xmm_mode_suffix(mode));
312
313
}

314
315
316
317
318
void ia32_emit_extend_suffix(ia32_emit_env_t *env, const ir_mode *mode)
{
	if(get_mode_size_bits(mode) == 32)
		return;
	if(mode_is_signed(mode)) {
Matthias Braun's avatar
Matthias Braun committed
319
		be_emit_char(env, 's');
320
	} else {
Matthias Braun's avatar
Matthias Braun committed
321
322
323
324
		be_emit_char(env, 'z');
	}
}

325
326
static
void ia32_emit_function_object(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
{
	switch (be_gas_flavour) {
	case GAS_FLAVOUR_NORMAL:
		be_emit_cstring(env, "\t.type\t");
		be_emit_string(env, name);
		be_emit_cstring(env, ", @function\n");
		be_emit_write_line(env);
		break;
	case GAS_FLAVOUR_MINGW:
		be_emit_cstring(env, "\t.def\t");
		be_emit_string(env, name);
		be_emit_cstring(env, ";\t.scl\t2;\t.type\t32;\t.endef\n");
		be_emit_write_line(env);
		break;
	default:
		break;
	}
}

346
347
static
void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
348
349
350
351
352
353
354
355
356
357
358
359
{
	switch (be_gas_flavour) {
	case GAS_FLAVOUR_NORMAL:
		be_emit_cstring(env, "\t.size\t");
		be_emit_string(env, name);
		be_emit_cstring(env, ", .-");
		be_emit_string(env, name);
		be_emit_char(env, '\n');
		be_emit_write_line(env);
		break;
	default:
		break;
Christian Würdig's avatar
Christian Würdig committed
360
361
362
	}
}

Matthias Braun's avatar
Matthias Braun committed
363

364
365
static
void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node);
Matthias Braun's avatar
Matthias Braun committed
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
void ia32_emit_8bit_source_register(ia32_emit_env_t *env, const ir_node *node,
                                    int pos)
{
	const arch_register_t *reg;
	const char            *reg_name;
	ir_node               *in;

	in = get_irn_n(node, pos);
	if(is_ia32_Immediate(in)) {
		emit_ia32_Immediate(env, in);
		return;
	}

	reg      = get_in_reg(env, node, pos);
	reg_name = arch_register_get_name(reg);

	be_emit_char(env, '%');
	be_emit_char(env, reg_name[1]);
	be_emit_char(env, 'l');
}

void ia32_emit_16bit_source_register(ia32_emit_env_t *env, const ir_node *node,
                                     int pos)
{
	const arch_register_t *reg;
	const char            *reg_name;
	ir_node               *in;

	in = get_irn_n(node, pos);
	if(is_ia32_Immediate(in)) {
		emit_ia32_Immediate(env, in);
		return;
	}

	reg      = get_in_reg(env, node, pos);
	reg_name = arch_register_get_name(reg);

	be_emit_char(env, '%');
	be_emit_string(env, &reg_name[1]);
	be_emit_char(env, 'x');
}

409
410
411
412
413
414
415
416
417
418
419
void ia32_emit_8bit_dest_register(ia32_emit_env_t *env, const ir_node *node,
                                  int pos)
{
	const arch_register_t *reg      = get_out_reg(env, node, pos);
	const char            *reg_name = arch_register_get_name(reg);

	be_emit_char(env, '%');
	be_emit_char(env, reg_name[1]);
	be_emit_char(env, 'l');
}

420
421
422
423
424
425
426
427
428
429
430
void ia32_emit_source_register_or_immediate(ia32_emit_env_t *env,
                                            const ir_node *node, int pos)
{
	ir_node *in = get_irn_n(node, pos);
	if(is_ia32_Immediate(in)) {
		emit_ia32_Immediate(env, in);
	} else {
		ia32_emit_source_register(env, node, pos);
	}
}

Christian Würdig's avatar
Christian Würdig committed
431
432
433
/**
 * Emits registers and/or address mode of a binary operation.
 */
434
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node, int produces_result) {
435
	const ir_node *right_op = get_irn_n(node, n_ia32_binary_right);
Christian Würdig's avatar
Christian Würdig committed
436

437
438
439
440
441
	switch(get_ia32_op_type(node)) {
	case ia32_Normal:
		if(is_ia32_Immediate(right_op)) {
			emit_ia32_Immediate(env, right_op);
			be_emit_cstring(env, ", ");
442
			ia32_emit_source_register(env, node, n_ia32_binary_left);
Christian Würdig's avatar
Christian Würdig committed
443
			break;
444
		} else {
445
446
			const arch_register_t *in1 = get_in_reg(env, node, n_ia32_binary_left);
			const arch_register_t *in2 = get_in_reg(env, node, n_ia32_binary_right);
447
			const arch_register_t *out = produces_result ? get_out_reg(env, node, 0) : NULL;
448
449
450
			const arch_register_t *in;
			const char            *in_name;

451
			in      = out ? ((out == in2) ? in1 : in2) : in2;
452
453
454
455
456
457
458
459
460
461
			out     = out ? out : in1;
			in_name = arch_register_get_name(in);

			be_emit_char(env, '%');
			be_emit_string(env, in_name);
			be_emit_cstring(env, ", %");
			be_emit_string(env, arch_register_get_name(out));
		}
		break;
	case ia32_AddrModeS:
462
		if(is_ia32_Immediate(right_op)) {
463
			assert(!produces_result && "Source AM with Const must not produce result");
464
465
466
467

			emit_ia32_Immediate(env, right_op);
			be_emit_cstring(env, ", ");
			ia32_emit_am(env, node);
468
		} else if (produces_result) {
469
470
			ia32_emit_am(env, node);
			be_emit_cstring(env, ", ");
471
472
			ia32_emit_dest_register(env, node, 0);
		} else {
473
474
			ia32_emit_am(env, node);
			be_emit_cstring(env, ", ");
475
			ia32_emit_source_register(env, node, n_ia32_binary_left);
476
477
478
		}
		break;
	case ia32_AddrModeD:
479
		panic("DestMode can't be output by %%binop anymore");
480
481
482
		break;
	default:
		assert(0 && "unsupported op type");
Christian Würdig's avatar
Christian Würdig committed
483
	}
484
485
}

486
487
488
/**
 * Emits registers and/or address mode of a binary operation.
 */
489
490
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
491
		case ia32_Normal:
492
			{
493
494
495
496
				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];
497
498
				const arch_register_t *in;

499
				in  = out ? ((out == in2) ? in1 : in2) : in2;
500
				out = out ? out : in1;
501

Matthias Braun's avatar
Matthias Braun committed
502
503
504
505
				be_emit_char(env, '%');
				be_emit_string(env, arch_register_get_name(in));
				be_emit_cstring(env, ", %");
				be_emit_string(env, arch_register_get_name(out));
506
507
508
			}
			break;
		case ia32_AddrModeS:
509
			ia32_emit_am(env, node);
510
			break;
511
		case ia32_AddrModeD:
512
513
514
515
516
		default:
			assert(0 && "unsupported op type");
	}
}

517
518
519
520
521
522
523
524
525
526
void ia32_emit_am_or_dest_register(ia32_emit_env_t *env, const ir_node *node,
                                   int pos) {
	if(get_ia32_op_type(node) == ia32_Normal) {
		ia32_emit_dest_register(env, node, pos);
	} else {
		assert(get_ia32_op_type(node) == ia32_AddrModeD);
		ia32_emit_am(env, node);
	}
}

Christian Würdig's avatar
Christian Würdig committed
527
528
529
/**
 * Emits registers and/or address mode of a unary operation.
 */
530
531
532
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node, int pos) {
	const ir_node *op;

533
	switch(get_ia32_op_type(node)) {
534
535
536
537
538
539
540
541
542
543
544
545
546
547
	case ia32_Normal:
		op = get_irn_n(node, pos);
		if (is_ia32_Immediate(op)) {
			emit_ia32_Immediate(env, op);
		} else {
			ia32_emit_source_register(env, node, pos);
		}
		break;
	case ia32_AddrModeS:
	case ia32_AddrModeD:
		ia32_emit_am(env, node);
		break;
	default:
		assert(0 && "unsupported op type");
Christian Würdig's avatar
Christian Würdig committed
548
549
550
551
	}
}

/**
552
 * Emits address mode.
Christian Würdig's avatar
Christian Würdig committed
553
 */
554
void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
555
556
557
558
559
560
	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
561

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

565
	/* emit offset */
566
567
568
	if (ent != NULL) {
		ident *id;

Michael Beck's avatar
Michael Beck committed
569
		set_entity_backend_marked(ent, 1);
570
		id = get_entity_ld_ident(ent);
571
		if (is_ia32_am_sc_sign(node))
Matthias Braun's avatar
Matthias Braun committed
572
573
			be_emit_char(env, '-');
		be_emit_ident(env, id);
Matthias Braun's avatar
Matthias Braun committed
574
575
576
577
578
579
580
581

		if(get_entity_owner(ent) == get_tls_type()) {
			if (get_entity_visibility(ent) == visibility_external_allocated) {
				be_emit_cstring(env, "@INDNTPOFF");
			} else {
				be_emit_cstring(env, "@NTPOFF");
			}
		}
Christian Würdig's avatar
Christian Würdig committed
582
583
	}

584
	if(offs != 0) {
585
		if(ent != NULL) {
Matthias Braun's avatar
Matthias Braun committed
586
			be_emit_irprintf(env->emit, "%+d", offs);
587
		} else {
Matthias Braun's avatar
Matthias Braun committed
588
			be_emit_irprintf(env->emit, "%d", offs);
589
		}
590
	}
Christian Würdig's avatar
Christian Würdig committed
591

592
	if (has_base || has_index) {
Matthias Braun's avatar
Matthias Braun committed
593
		be_emit_char(env, '(');
Christian Würdig's avatar
Christian Würdig committed
594

595
		/* emit base */
596
		if (has_base) {
597
			ia32_emit_source_register(env, node, n_ia32_base);
Christian Würdig's avatar
Christian Würdig committed
598
599
		}

600
		/* emit index + scale */
601
602
		if (has_index) {
			int scale;
Matthias Braun's avatar
Matthias Braun committed
603
			be_emit_char(env, ',');
604
			ia32_emit_source_register(env, node, n_ia32_index);
605

606
607
			scale = get_ia32_am_scale(node);
			if (scale > 0) {
Matthias Braun's avatar
Matthias Braun committed
608
				be_emit_irprintf(env->emit, ",%d", 1 << get_ia32_am_scale(node));
609
610
			}
		}
Matthias Braun's avatar
Matthias Braun committed
611
		be_emit_char(env, ')');
Christian Würdig's avatar
Christian Würdig committed
612
	}
613
614
615
616
617

	/* special case if nothing is set */
	if(ent == NULL && offs == 0 && !has_base && !has_index) {
		be_emit_char(env, '0');
	}
618
}
Christian Würdig's avatar
Christian Würdig committed
619

Christian Würdig's avatar
Christian Würdig committed
620
621
622
623
624
625
626
627
628
629
/*************************************************
 *                 _ _                         _
 *                (_) |                       | |
 *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
 *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
 * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
 *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
 *
 *************************************************/

Christian Würdig's avatar
Christian Würdig committed
630
#undef IA32_DO_EMIT
Christian Würdig's avatar
Christian Würdig committed
631
#define IA32_DO_EMIT(irn) ia32_fprintf_format(F, irn, cmd_buf, cmnt_buf)
Christian Würdig's avatar
Christian Würdig committed
632

633
634
635
636
/*
 * coding of conditions
 */
struct cmp2conditon_t {
Christian Würdig's avatar
Christian Würdig committed
637
	const char *name;
638
	int         num;
639
640
641
642
643
};

/*
 * positive conditions for signed compares
 */
644
static const struct cmp2conditon_t cmp2condition_s[] = {
645
646
647
648
649
650
651
	{ 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 },     /* != */
652
	{ NULL,              pn_Cmp_Leg},     /* always true */
653
654
655
656
657
};

/*
 * positive conditions for unsigned compares
 */
658
static const struct cmp2conditon_t cmp2condition_u[] = {
Christian Würdig's avatar
Christian Würdig committed
659
660
661
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "b",               pn_Cmp_Lt },     /* < */
Christian Würdig's avatar
Christian Würdig committed
662
	{ "be",              pn_Cmp_Le },     /* <= */
Christian Würdig's avatar
Christian Würdig committed
663
664
665
	{ "a",               pn_Cmp_Gt },     /* > */
	{ "ae",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
666
	{ NULL,              pn_Cmp_Leg },   /* always true  */
667
668
};

669
670
671
672
673
674
675
676
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
677
 */
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
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;
			}
		} else if(is_Store(node)) {
			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)
719
{
720
721
722
723
724
725
726
727
728
729
730
731
	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);
		if(!is_ia32_FucomFnstsw(cmp) || is_ia32_FucompFnstsw(cmp)
				|| is_ia32_FucomppFnstsw(cmp)) {
			cmp = find_original_value(cmp);
			assert(is_ia32_FucomFnstsw(cmp) || is_ia32_FucompFnstsw(cmp)
			       || is_ia32_FucomppFnstsw(cmp));
		}
732

733
734
735
736
737
738
739
740
741
742
		flags_attr = get_ia32_attr_const(cmp);
		if(flags_attr->data.cmp_flipped)
			pnc = get_mirrored_pnc(pnc);
		pnc |= ia32_pn_Cmp_float;
	} else if(is_ia32_Ucomi(flags)) {
		flags_attr = get_ia32_attr_const(flags);

		if(flags_attr->data.cmp_flipped)
			pnc = get_mirrored_pnc(pnc);
		pnc |= ia32_pn_Cmp_float;
743
	} else {
744
745
746
747
748
749
750
751
		assert(is_ia32_Cmp(flags) || is_ia32_Test(flags)
				|| is_ia32_Cmp8Bit(flags) || is_ia32_Test8Bit(flags));
		flags_attr = get_ia32_attr_const(flags);

		if(flags_attr->data.cmp_flipped)
			pnc = get_mirrored_pnc(pnc);
		if(flags_attr->data.cmp_unsigned)
			pnc |= ia32_pn_Cmp_unsigned;
752
	}
753
754

	return pnc;
755
756
}

757
static void ia32_emit_cmp_suffix(ia32_emit_env_t *env, int pnc)
758
{
759
760
761
762
763
764
765
766
767
768
769
770
771
	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;
	}

	be_emit_string(env, str);
772
773
}

774
775
776
777
778
779
780
781
void ia32_emit_cmp_suffix_node(ia32_emit_env_t *env, const ir_node *node,
                               int flags_pos)
{
	pn_Cmp pnc = get_ia32_pncode(node);

	pnc = determine_final_pnc(node, flags_pos, pnc);
	ia32_emit_cmp_suffix(env, pnc);
}
782

783
784
785
/**
 * Returns the target block for a control flow node.
 */
786
787
static
ir_node *get_cfop_target_block(const ir_node *irn) {
788
789
790
	return get_irn_link(irn);
}

791
792
793
/**
 * Emits a block label for the given block.
 */
794
795
796
static
void ia32_emit_block_name(ia32_emit_env_t *env, const ir_node *block)
{
Michael Beck's avatar
Michael Beck committed
797
798
799
800
801
802
803
	if (has_Block_label(block)) {
		be_emit_string(env, be_gas_label_prefix());
		be_emit_irprintf(env->emit, "%u", (unsigned)get_Block_label(block));
	} else {
		be_emit_cstring(env, BLOCK_PREFIX);
		be_emit_irprintf(env->emit, "%d", get_irn_node_nr(block));
	}
804
805
}

Christian Würdig's avatar
Christian Würdig committed
806
/**
807
 * Emits the target label for a control flow node.
Christian Würdig's avatar
Christian Würdig committed
808
 */
809
static
810
811
void ia32_emit_cfop_target(ia32_emit_env_t * env, const ir_node *node) {
	ir_node *block = get_cfop_target_block(node);
812

813
	ia32_emit_block_name(env, block);
Christian Würdig's avatar
Christian Würdig committed
814
}
815

816
817
/** Return the next block in Block schedule */
static ir_node *next_blk_sched(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
818
	return get_irn_link(block);
819
820
}

821
822
823
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
824
static ir_node *get_proj(const ir_node *node, long proj) {
825
826
827
	const ir_edge_t *edge;
	ir_node         *src;

828
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
829

830
	foreach_out_edge(node, edge) {
831
832
833
834
835
836
837
838
839
840
841
842
		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
843
844
845
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
846
847
static void emit_ia32_Jcc(ia32_emit_env_t *env, const ir_node *node)
{
848
849
850
851
	const ir_node *proj_true;
	const ir_node *proj_false;
	const ir_node *block;
	const ir_node *next_block;
852
	pn_Cmp         pnc = get_ia32_pncode(node);
Christian Würdig's avatar
Christian Würdig committed
853

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

856
857
858
	/* get both Projs */
	proj_true = get_proj(node, pn_ia32_Jcc_true);
	assert(proj_true && "Jcc without true Proj");
859

860
861
	proj_false = get_proj(node, pn_ia32_Jcc_false);
	assert(proj_false && "Jcc without false Proj");
862

863
	block      = get_nodes_block(node);
864
	next_block = next_blk_sched(block);
865

866
	if (get_cfop_target_block(proj_true) == next_block) {
867
		/* exchange both proj's so the second one can be omitted */
868
869
		const ir_node *t = proj_true;

870
871
		proj_true  = proj_false;
		proj_false = t;
872
873
874
875
876
		if(pnc & ia32_pn_Cmp_float) {
			pnc = get_negated_pnc(pnc, mode_F);
		} else {
			pnc = get_negated_pnc(pnc, mode_Iu);
		}
877
878
	}

879
880
881
882
	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) {
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
			case pn_Cmp_Uo:
				be_emit_cstring(env, "\tjp ");
				ia32_emit_cfop_target(env, proj_true);
				be_emit_finish_line_gas(env, proj_true);
				break;

			case pn_Cmp_Leg:
				be_emit_cstring(env, "\tjnp ");
				ia32_emit_cfop_target(env, proj_true);
				be_emit_finish_line_gas(env, proj_true);
				break;

			case pn_Cmp_Eq:
			case pn_Cmp_Lt:
			case pn_Cmp_Le:
				be_emit_cstring(env, "\tjp ");
				ia32_emit_cfop_target(env, proj_false);
				be_emit_finish_line_gas(env, proj_false);
901
				goto emit_jcc;
902
903
904
905
906
907
908

			case pn_Cmp_Ug:
			case pn_Cmp_Uge:
			case pn_Cmp_Ne:
				be_emit_cstring(env, "\tjp ");
				ia32_emit_cfop_target(env, proj_true);
				be_emit_finish_line_gas(env, proj_true);
909
				goto emit_jcc;
910
911
912
913
914
915
916
917
918

			default:
				goto emit_jcc;
		}
	} else {
emit_jcc:
		be_emit_cstring(env, "\tj");
		ia32_emit_cmp_suffix(env, pnc);
		be_emit_char(env, ' ');
919
		ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
920
		be_emit_finish_line_gas(env, proj_true);
921
922
	}

923
	/* the second Proj might be a fallthrough */
924
	if (get_cfop_target_block(proj_false) != next_block) {
Matthias Braun's avatar
Matthias Braun committed
925
		be_emit_cstring(env, "\tjmp ");
926
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
927
		be_emit_finish_line_gas(env, proj_false);
928
	} else {
929
		be_emit_cstring(env, "\t/* fallthrough to ");
930
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
931
932
		be_emit_cstring(env, " */");
		be_emit_finish_line_gas(env, proj_false);
933
	}
Christian Würdig's avatar
Christian Würdig committed
934
935
}

936
#if 0
Christian Würdig's avatar
Christian Würdig committed
937
938
939
/**
 * Emits code for conditional SSE floating point jump with two variables.
 */
940
static
941
void emit_ia32_xCmpJmp(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
942
	be_emit_cstring(env, "\tucomi");
Matthias Braun's avatar
Matthias Braun committed
943
	ia32_emit_xmm_mode_suffix(env, node);
Matthias Braun's avatar
Matthias Braun committed
944
	be_emit_char(env, ' ');
945
	ia32_emit_binop(env, node, 0);
Matthias Braun's avatar
Matthias Braun committed
946
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
947

948
	finish_CondJmp(env, node, mode_F, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
949
950
}

Michael Beck's avatar
Michael Beck committed
951
952
953
/**
 * Emits code for conditional x87 floating point jump with two variables.
 */
954
static
955
void emit_ia32_x87CmpJmp(ia32_emit_env_t *env, const ir_node *node) {
956
957
958
	const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
	const char            *reg      = x87_attr->x87[1]->name;
	long                   pnc      = get_ia32_pncode(node);
Michael Beck's avatar
Michael Beck committed
959

960
	switch (get_ia32_irn_opcode(node)) {
Michael Beck's avatar
Michael Beck committed
961
	case iro_ia32_fcomrJmp:
962
		pnc = get_inversed_pnc(pnc);
963
		reg = x87_attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
964
965
	case iro_ia32_fcomJmp:
	default:
Matthias Braun's avatar
Matthias Braun committed
966
		be_emit_cstring(env, "\tfucom ");
Michael Beck's avatar
Michael Beck committed
967
968
		break;
	case iro_ia32_fcomrpJmp:
969
		pnc = get_inversed_pnc(pnc);
970
		reg = x87_attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
971
	case iro_ia32_fcompJmp:
Matthias Braun's avatar
Matthias Braun committed
972
		be_emit_cstring(env, "\tfucomp ");
Michael Beck's avatar
Michael Beck committed
973
974
		break;
	case iro_ia32_fcomrppJmp:
975
		pnc = get_inversed_pnc(pnc);
Michael Beck's avatar
Michael Beck committed
976
	case iro_ia32_fcomppJmp:
Matthias Braun's avatar
Matthias Braun committed
977
		be_emit_cstring(env, "\tfucompp ");
Michael Beck's avatar
Michael Beck committed
978
979
980
981
		reg = "";
		break;
	}

982
	if(reg[0] != '\0') {
Matthias Braun's avatar
Matthias Braun committed
983
984
		be_emit_char(env, '%');
		be_emit_string(env, reg);
985
	}
Matthias Braun's avatar
Matthias Braun committed
986
	be_emit_finish_line_gas(env, node);
Michael Beck's avatar
Michael Beck committed
987

Matthias Braun's avatar
Matthias Braun committed
988
989
990
991
	be_emit_cstring(env, "\tfnstsw %ax");
	be_emit_finish_line_gas(env, node);
	be_emit_cstring(env, "\tsahf");
	be_emit_finish_line_gas(env, node);
Michael Beck's avatar
Michael Beck committed
992

993
	finish_CondJmp(env, node, mode_E, pnc);
Michael Beck's avatar
Michael Beck committed
994
}
995
#endif
Michael Beck's avatar
Michael Beck committed
996

997
static void emit_ia32_CMov(ia32_emit_env_t *env, const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
998
{
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
	const arch_register_t *out = arch_get_irn_register(env->arch_env, node);
	const arch_register_t *in_true;
	const arch_register_t *in_false;
	pn_Cmp                 pnc = get_ia32_pncode(node);

	pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc);

	in_true  = arch_get_irn_register(env->arch_env,
	                                 get_irn_n(node, n_ia32_CMov_val_true));
	in_false = arch_get_irn_register(env->arch_env,
	                                 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;

		/* swap left/right and negate pnc */
		pnc = get_negated_pnc(pnc, mode_Iu);

		tmp      = in_true;
		in_true  = in_false;
		in_false = tmp;
1023
	} else {
1024
		/* we need a mov */
1025
		be_emit_cstring(env, "\tmovl ");
1026
		ia32_emit_register(env, in_false);
Matthias Braun's avatar
Matthias Braun committed
1027
		be_emit_cstring(env, ", ");
1028
		ia32_emit_register(env, out);
1029
		be_emit_finish_line_gas(env, node);
1030
	}
1031
1032

	be_emit_cstring(env, "\tcmov");
1033
1034
1035
1036
	ia32_emit_cmp_suffix(env, pnc);
	be_emit_char(env, ' ');
	if(get_ia32_op_type(node) == ia32_AddrModeS) {
		ia32_emit_am(env, node);
1037
	} else {
1038
		ia32_emit_register(env, in_true);
1039
	}
1040
1041
	be_emit_cstring(env, ", ");
	ia32_emit_register(env, out);
Matthias Braun's avatar
Matthias Braun committed
1042
	be_emit_finish_line_gas(env, node);
1043
1044
}

1045
#if 0
1046
1047
static
void emit_ia32_xCmp(ia32_emit_env_t *env, const ir_node *node) {
1048
1049
1050
	int  sse_pnc  = -1;
	long pnc      = get_ia32_pncode(node);
	long unord    = pnc & pn_Cmp_Uo;
1051

Christian Würdig's avatar
Christian Würdig committed
1052
1053
	assert( (pnc & ia32_pn_Cmp_Unsigned) == 0);

Christian Würdig's avatar
Christian Würdig committed
1054
	switch (pnc) {
1055
1056
1057
1058
1059
1060
		case pn_Cmp_Leg: /* odered */
			sse_pnc = 7;
			break;
		case pn_Cmp_Uo:  /* unordered */
			sse_pnc = 3;
			break;
1061
		case pn_Cmp_Ue:
Christian Würdig's avatar
Christian Würdig committed
1062
		case pn_Cmp_Eq:  /* == */
1063
1064
			sse_pnc = 0;
			break;
1065
		case pn_Cmp_Ul:
Christian Würdig's avatar
Christian Würdig committed
1066
		case pn_Cmp_Lt:  /* < */
1067
1068
			sse_pnc = 1;
			break;
1069
		case pn_Cmp_Ule:
Christian Würdig's avatar
Christian Würdig committed
1070
		case pn_Cmp_Le: /* <= */
1071
1072
			sse_pnc = 2;
			break;