ia32_emitter.c 62.4 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
90
91
92
93
	if(reg == &ia32_gp_regs[REG_GP_NOREG])
		panic("trying to emit noreg");

	/* 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
static
int produces_result(const ir_node *node) {
182
	return
Matthias Braun's avatar
Matthias Braun committed
183
184
185
		!is_ia32_CmpSet(node)       &&
		!is_ia32_CmpSet8Bit(node)   &&
		!is_ia32_CmpJmp(node)       &&
186
		!is_ia32_CmpJmp8Bit(node)   &&
Matthias Braun's avatar
Matthias Braun committed
187
188
189
190
191
192
193
194
195
196
197
		!is_ia32_St(node)           &&
		!is_ia32_SwitchJmp(node)    &&
		!is_ia32_TestJmp(node)      &&
		!is_ia32_TestJmp8Bit(node)  &&
		!is_ia32_xCmpSet(node)      &&
		!is_ia32_xCmpJmp(node)      &&
		!is_ia32_CmpCMov(node)      &&
		!is_ia32_CmpCMov8Bit(node)  &&
		!is_ia32_TestCMov(node)     &&
		!is_ia32_TestCMov8Bit(node) &&
		!is_ia32_CmpSet(node)       &&
198
		!is_ia32_TestSet(node);
199
200
}

201
202
203
static
const char *ia32_get_reg_name_for_mode(ia32_emit_env_t *env, ir_mode *mode,
                                       const arch_register_t *reg) {
204
205
206
207
208
209
210
	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
211
	}
Christian Würdig's avatar
Christian Würdig committed
212
213
}

Michael Beck's avatar
Michael Beck committed
214
/**
215
 * Add a number to a prefix. This number will not be used a second time.
Michael Beck's avatar
Michael Beck committed
216
 */
217
218
static
char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	static unsigned long id = 0;
	snprintf(buf, buflen, "%s%lu", prefix, ++id);
	return buf;
}

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

Matthias Braun's avatar
Matthias Braun committed
235
236
237
238
239
240
241
// 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)
242
#define be_emit_tarval(env,tv)          be_emit_tarval(env->emit,tv)
Matthias Braun's avatar
Matthias Braun committed
243
244
245
#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
246

247
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
248
{
249
	const arch_register_t *reg = get_in_reg(env, node, pos);
250
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
251

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

Matthias Braun's avatar
Matthias Braun committed
254
255
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
256
257
258
}

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

Matthias Braun's avatar
Matthias Braun committed
262
263
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
Christian Würdig's avatar
Christian Würdig committed
264
265
}

266
267
268
269
270
271
272
273
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);
}

274
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
275
{
276
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
277

Matthias Braun's avatar
Matthias Braun committed
278
	assert(pos < 3);
Matthias Braun's avatar
Matthias Braun committed
279
280
	be_emit_char(env, '%');
	be_emit_string(env, attr->x87[pos]->name);
281
}
Christian Würdig's avatar
Christian Würdig committed
282

Matthias Braun's avatar
Matthias Braun committed
283
284
static
void ia32_emit_mode_suffix_mode(ia32_emit_env_t *env, const ir_mode *mode)
285
{
Matthias Braun's avatar
Matthias Braun committed
286
	be_emit_char(env, get_mode_suffix(mode));
Christian Würdig's avatar
Christian Würdig committed
287
288
}

Matthias Braun's avatar
Matthias Braun committed
289
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
290
291
{
	ir_mode *mode = get_ia32_ls_mode(node);
Matthias Braun's avatar
Matthias Braun committed
292
293
294
295
	if(mode == NULL)
		mode = mode_Iu;

	ia32_emit_mode_suffix_mode(env, mode);
296
297
}

298
299
300
301
302
303
304
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);
}

305
306
static
char get_xmm_mode_suffix(ir_mode *mode)
307
308
309
310
311
312
313
314
315
316
317
318
319
{
	assert(mode_is_float(mode));
	switch(get_mode_size_bits(mode)) {
	case 32:
		return 's';
	case 64:
		return 'd';
	default:
		assert(0);
	}
	return '%';
}

320
321
322
void ia32_emit_xmm_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
{
	ir_mode *mode = get_ia32_ls_mode(node);
323
	assert(mode != NULL);
Matthias Braun's avatar
Matthias Braun committed
324
325
	be_emit_char(env, 's');
	be_emit_char(env, get_xmm_mode_suffix(mode));
326
327
328
329
330
331
}

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
332
	be_emit_char(env, get_xmm_mode_suffix(mode));
333
334
}

335
336
337
338
339
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
340
		be_emit_char(env, 's');
341
	} else {
Matthias Braun's avatar
Matthias Braun committed
342
343
344
345
		be_emit_char(env, 'z');
	}
}

346
347
static
void ia32_emit_function_object(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
360
361
362
363
364
365
366
{
	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;
	}
}

367
368
static
void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
369
370
371
372
373
374
375
376
377
378
379
380
{
	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
381
382
383
	}
}

Matthias Braun's avatar
Matthias Braun committed
384

385
386
static
void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node);
Matthias Braun's avatar
Matthias Braun committed
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
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');
}

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
441
442
443
/**
 * Emits registers and/or address mode of a binary operation.
 */
444
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
445
	const ir_node *right_op = get_irn_n(node, 3);
Christian Würdig's avatar
Christian Würdig committed
446

447
448
449
450
451
452
	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, ", ");
			ia32_emit_source_register(env, node, 2);
Christian Würdig's avatar
Christian Würdig committed
453
			break;
454
455
456
457
458
459
460
		} else {
			const arch_register_t *in1 = get_in_reg(env, node, 2);
			const arch_register_t *in2 = get_in_reg(env, node, 3);
			const arch_register_t *out = produces_result(node) ? get_out_reg(env, node, 0) : NULL;
			const arch_register_t *in;
			const char            *in_name;

461
			in      = out ? ((out == in2) ? in1 : in2) : in2;
462
463
464
465
466
467
468
469
470
471
			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:
472
		if(is_ia32_Immediate(right_op)) {
473
474
475
476
477
478
			assert(!produces_result(node) &&
					"Source AM with Const must not produce result");

			emit_ia32_Immediate(env, right_op);
			be_emit_cstring(env, ", ");
			ia32_emit_am(env, node);
479
		} else if (produces_result(node)) {
480
481
			ia32_emit_am(env, node);
			be_emit_cstring(env, ", ");
482
483
			ia32_emit_dest_register(env, node, 0);
		} else {
484
485
			ia32_emit_am(env, node);
			be_emit_cstring(env, ", ");
486
487
488
489
			ia32_emit_source_register(env, node, 2);
		}
		break;
	case ia32_AddrModeD:
490
		panic("DestMode can't be output by %%binop anymore");
491
492
493
		break;
	default:
		assert(0 && "unsupported op type");
Christian Würdig's avatar
Christian Würdig committed
494
	}
495
496
}

497
498
499
/**
 * Emits registers and/or address mode of a binary operation.
 */
500
501
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
502
		case ia32_Normal:
503
			{
504
505
506
507
				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];
508
509
				const arch_register_t *in;

510
				in  = out ? ((out == in2) ? in1 : in2) : in2;
511
				out = out ? out : in1;
512

Matthias Braun's avatar
Matthias Braun committed
513
514
515
516
				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));
517
518
519
520
			}
			break;
		case ia32_AddrModeS:
		case ia32_AddrModeD:
521
			ia32_emit_am(env, node);
522
523
524
525
526
527
			break;
		default:
			assert(0 && "unsupported op type");
	}
}

528
529
530
531
532
533
534
535
536
537
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
538
539
540
/**
 * Emits registers and/or address mode of a unary operation.
 */
541
542
543
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node, int pos) {
	const ir_node *op;

544
	switch(get_ia32_op_type(node)) {
545
546
547
548
549
550
551
552
553
554
555
556
557
558
	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
559
560
561
562
	}
}

/**
563
 * Emits address mode.
Christian Würdig's avatar
Christian Würdig committed
564
 */
565
void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
566
567
568
569
570
571
	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
572

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

576
	/* emit offset */
577
578
579
	if (ent != NULL) {
		ident *id;

Michael Beck's avatar
Michael Beck committed
580
		set_entity_backend_marked(ent, 1);
581
		id = get_entity_ld_ident(ent);
582
		if (is_ia32_am_sc_sign(node))
Matthias Braun's avatar
Matthias Braun committed
583
584
			be_emit_char(env, '-');
		be_emit_ident(env, id);
Matthias Braun's avatar
Matthias Braun committed
585
586
587
588
589
590
591
592

		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
593
594
	}

595
	if(offs != 0) {
596
		if(ent != NULL) {
Matthias Braun's avatar
Matthias Braun committed
597
			be_emit_irprintf(env->emit, "%+d", offs);
598
		} else {
Matthias Braun's avatar
Matthias Braun committed
599
			be_emit_irprintf(env->emit, "%d", offs);
600
		}
601
	}
Christian Würdig's avatar
Christian Würdig committed
602

603
	if (has_base || has_index) {
Matthias Braun's avatar
Matthias Braun committed
604
		be_emit_char(env, '(');
Christian Würdig's avatar
Christian Würdig committed
605

606
		/* emit base */
607
		if (has_base) {
608
			ia32_emit_source_register(env, node, 0);
Christian Würdig's avatar
Christian Würdig committed
609
610
		}

611
		/* emit index + scale */
612
613
		if (has_index) {
			int scale;
Matthias Braun's avatar
Matthias Braun committed
614
			be_emit_char(env, ',');
615
			ia32_emit_source_register(env, node, 1);
616

617
618
			scale = get_ia32_am_scale(node);
			if (scale > 0) {
Matthias Braun's avatar
Matthias Braun committed
619
				be_emit_irprintf(env->emit, ",%d", 1 << get_ia32_am_scale(node));
620
621
			}
		}
Matthias Braun's avatar
Matthias Braun committed
622
		be_emit_char(env, ')');
Christian Würdig's avatar
Christian Würdig committed
623
	}
624
625
626
627
628

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

Christian Würdig's avatar
Christian Würdig committed
631
632
633
634
635
636
637
638
639
640
/*************************************************
 *                 _ _                         _
 *                (_) |                       | |
 *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
 *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
 * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
 *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
 *
 *************************************************/

Christian Würdig's avatar
Christian Würdig committed
641
#undef IA32_DO_EMIT
Christian Würdig's avatar
Christian Würdig committed
642
#define IA32_DO_EMIT(irn) ia32_fprintf_format(F, irn, cmd_buf, cmnt_buf)
Christian Würdig's avatar
Christian Würdig committed
643

644
645
646
647
/*
 * coding of conditions
 */
struct cmp2conditon_t {
Christian Würdig's avatar
Christian Würdig committed
648
649
	const char *name;
	pn_Cmp      num;
650
651
652
653
654
};

/*
 * positive conditions for signed compares
 */
655
656
static
const struct cmp2conditon_t cmp2condition_s[] = {
657
658
659
660
661
662
663
664
	{ 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 },     /* != */
	{ NULL,              pn_Cmp_Leg},     /* Floating point: ordered */
665
666
667
668
669
};

/*
 * positive conditions for unsigned compares
 */
670
671
static
const struct cmp2conditon_t cmp2condition_u[] = {
Christian Würdig's avatar
Christian Würdig committed
672
673
674
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "b",               pn_Cmp_Lt },     /* < */
Christian Würdig's avatar
Christian Würdig committed
675
	{ "be",              pn_Cmp_Le },     /* <= */
Christian Würdig's avatar
Christian Würdig committed
676
677
678
679
	{ "a",               pn_Cmp_Gt },     /* > */
	{ "ae",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
	{ NULL,              pn_Cmp_True },   /* always true */
680
681
682
683
684
};

/*
 * returns the condition code
 */
685
static
Matthias Braun's avatar
Matthias Braun committed
686
const char *get_cmp_suffix(pn_Cmp cmp_code)
687
{
688
	assert( (cmp2condition_s[cmp_code & 7].num) == (cmp_code & 7));
689
	assert( (cmp2condition_u[cmp_code & 7].num) == (cmp_code & 7));
690

691
692
693
	if((cmp_code & ia32_pn_Cmp_Unsigned)) {
		return cmp2condition_u[cmp_code & 7].name;
	} else {
694
		return cmp2condition_s[cmp_code & 7].name;
695
	}
696
697
}

698
699
void ia32_emit_cmp_suffix(ia32_emit_env_t *env, long pnc)
{
Matthias Braun's avatar
Matthias Braun committed
700
	be_emit_string(env, get_cmp_suffix(pnc));
701
702
703
}


704
705
706
/**
 * Returns the target block for a control flow node.
 */
707
708
static
ir_node *get_cfop_target_block(const ir_node *irn) {
709
710
711
	return get_irn_link(irn);
}

712
713
714
/**
 * Emits a block label for the given block.
 */
715
716
717
static
void ia32_emit_block_name(ia32_emit_env_t *env, const ir_node *block)
{
Michael Beck's avatar
Michael Beck committed
718
719
720
721
722
723
724
	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));
	}
725
726
}

Christian Würdig's avatar
Christian Würdig committed
727
/**
728
 * Emits the target label for a control flow node.
Christian Würdig's avatar
Christian Würdig committed
729
 */
730
static
731
732
void ia32_emit_cfop_target(ia32_emit_env_t * env, const ir_node *node) {
	ir_node *block = get_cfop_target_block(node);
733

734
	ia32_emit_block_name(env, block);
Christian Würdig's avatar
Christian Würdig committed
735
}
736

737
738
/** Return the next block in Block schedule */
static ir_node *next_blk_sched(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
739
	return get_irn_link(block);
740
741
}

742
743
744
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
745
746
static
ir_node *get_proj(const ir_node *node, long proj) {
747
748
749
	const ir_edge_t *edge;
	ir_node         *src;

750
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
751

752
	foreach_out_edge(node, edge) {
753
754
755
756
757
758
759
760
761
762
763
764
		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
765
766
767
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
768
769
770
static
void finish_CondJmp(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode,
                    long pnc) {
771
772
773
774
775
	const ir_node *proj_true;
	const ir_node *proj_false;
	const ir_node *block;
	const ir_node *next_block;
	int flipped = 0;
Christian Würdig's avatar
Christian Würdig committed
776

777
	/* get both Proj's */
778
	proj_true = get_proj(node, pn_Cond_true);
779
	assert(proj_true && "CondJmp without true Proj");
Christian Würdig's avatar
Christian Würdig committed
780

781
	proj_false = get_proj(node, pn_Cond_false);
782
783
	assert(proj_false && "CondJmp without false Proj");

784
	/* for now, the code works for scheduled and non-schedules blocks */
785
	block = get_nodes_block(node);
786
787

	/* we have a block schedule */
788
	next_block = next_blk_sched(block);
789

790
	if (get_cfop_target_block(proj_true) == next_block) {
791
		/* exchange both proj's so the second one can be omitted */
792
793
		const ir_node *t = proj_true;

794
795
796
797
		proj_true  = proj_false;
		proj_false = t;
		flipped    = 1;
		pnc        = get_negated_pnc(pnc, mode);
798
799
	}

800
801
802
	if (mode_is_float(mode)) {
		/* Some floating point comparisons require a test of the parity flag, which
		 * indicates that the result is unordered */
803
		switch (pnc & ~ia32_pn_Cmp_Unsigned) {
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
			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);
				goto float_jcc;

			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);
				goto float_jcc;

			default:
			float_jcc:
				/* The bits set by floating point compares correspond to unsigned
				 * comparisons */
				pnc |= ia32_pn_Cmp_Unsigned;
				goto emit_jcc;
		}
	} else {
emit_jcc:
		be_emit_cstring(env, "\tj");
		ia32_emit_cmp_suffix(env, pnc);
		be_emit_char(env, ' ');
844
		ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
845
		be_emit_finish_line_gas(env, proj_true);
846
847
	}

848
	/* the second Proj might be a fallthrough */
849
	if (get_cfop_target_block(proj_false) != next_block) {
Matthias Braun's avatar
Matthias Braun committed
850
		be_emit_cstring(env, "\tjmp ");
851
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
852
		be_emit_finish_line_gas(env, proj_false);
853
	} else {
854
		be_emit_cstring(env, "\t/* fallthrough to ");
855
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
856
857
		be_emit_cstring(env, " */");
		be_emit_finish_line_gas(env, proj_false);
858
	}
Christian Würdig's avatar
Christian Würdig committed
859
860
861
}

/**
Christian Würdig's avatar
Christian Würdig committed
862
 * Emits code for conditional jump.
Christian Würdig's avatar
Christian Würdig committed
863
 */
864
865
static
void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
866
867
868
	be_emit_cstring(env, "\tcmp");
	ia32_emit_mode_suffix(env, node);
	be_emit_char(env, ' ');
869
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
870
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
871

872
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
873
874
}

Christian Würdig's avatar
Christian Würdig committed
875
876
877
/**
 * Emits code for conditional jump with two variables.
 */
878
static
879
void emit_ia32_CmpJmp(ia32_emit_env_t *env, const ir_node *node) {
880
	CondJmp_emitter(env, node);
Christian Würdig's avatar
Christian Würdig committed
881
882
}

883
884
885
/**
 * Emits code for conditional test and jump.
 */
886
887
static
void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
888
889
890
891
	be_emit_cstring(env, "\ttest");
	ia32_emit_mode_suffix(env, node);
	be_emit_char(env, ' ');

892
893
894
	ia32_emit_binop(env, node);
	be_emit_finish_line_gas(env, node);

895
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
896
897
898
899
900
}

/**
 * Emits code for conditional test and jump with two variables.
 */
901
902
static
void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
903
	TestJmp_emitter(env, node);
904
905
}

Christian Würdig's avatar
Christian Würdig committed
906
907
908
/**
 * Emits code for conditional SSE floating point jump with two variables.
 */
909
static
910
void emit_ia32_xCmpJmp(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
911
	be_emit_cstring(env, "\tucomi");
Matthias Braun's avatar
Matthias Braun committed
912
	ia32_emit_xmm_mode_suffix(env, node);
Matthias Braun's avatar
Matthias Braun committed
913
	be_emit_char(env, ' ');
914
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
915
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
916

917
	finish_CondJmp(env, node, mode_F, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
918
919
}

Michael Beck's avatar
Michael Beck committed
920
921
922
/**
 * Emits code for conditional x87 floating point jump with two variables.
 */
923
static
924
void emit_ia32_x87CmpJmp(ia32_emit_env_t *env, const ir_node *node) {
925
926
927
	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
928

929
	switch (get_ia32_irn_opcode(node)) {
Michael Beck's avatar
Michael Beck committed
930
	case iro_ia32_fcomrJmp:
931
		pnc = get_inversed_pnc(pnc);
932
		reg = x87_attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
933
934
	case iro_ia32_fcomJmp:
	default:
Matthias Braun's avatar
Matthias Braun committed
935
		be_emit_cstring(env, "\tfucom ");
Michael Beck's avatar
Michael Beck committed
936
937
		break;
	case iro_ia32_fcomrpJmp:
938
		pnc = get_inversed_pnc(pnc);
939
		reg = x87_attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
940
	case iro_ia32_fcompJmp:
Matthias Braun's avatar
Matthias Braun committed
941
		be_emit_cstring(env, "\tfucomp ");
Michael Beck's avatar
Michael Beck committed
942
943
		break;
	case iro_ia32_fcomrppJmp:
944
		pnc = get_inversed_pnc(pnc);
Michael Beck's avatar
Michael Beck committed
945
	case iro_ia32_fcomppJmp:
Matthias Braun's avatar
Matthias Braun committed
946
		be_emit_cstring(env, "\tfucompp ");
Michael Beck's avatar
Michael Beck committed
947
948
949
950
		reg = "";
		break;
	}

951
	if(reg[0] != '\0') {
Matthias Braun's avatar
Matthias Braun committed
952
953
		be_emit_char(env, '%');
		be_emit_string(env, reg);
954
	}
Matthias Braun's avatar
Matthias Braun committed
955
	be_emit_finish_line_gas(env, node);
Michael Beck's avatar
Michael Beck committed
956

Matthias Braun's avatar
Matthias Braun committed
957
958
959
960
	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
961

962
	finish_CondJmp(env, node, mode_E, pnc);
Michael Beck's avatar
Michael Beck committed
963
964
}

965
static
Matthias Braun's avatar
Matthias Braun committed
966
967
void CMov_emitter(ia32_emit_env_t *env, const ir_node *node)
{
Christian Würdig's avatar
Christian Würdig committed
968
	const arch_register_t *in1, *in2, *out;
969
	long  pnc = get_ia32_pncode(node);
Christian Würdig's avatar
Christian Würdig committed
970

971
	out = arch_get_irn_register(env->arch_env, node);
Christian Würdig's avatar
Christian Würdig committed
972

Christian Würdig's avatar
Christian Würdig committed
973
974
	/* we have to emit the cmp first, because the destination register */
	/* could be one of the compare registers                           */
975
	if (is_ia32_xCmpCMov(node)) {
Matthias Braun's avatar
Matthias Braun committed
976
		be_emit_cstring(env, "\tucomis");
Matthias Braun's avatar
Matthias Braun committed
977
		ia32_emit_mode_suffix_mode(env, get_irn_mode(node));
Matthias Braun's avatar
Matthias Braun committed
978
		be_emit_char(env, ' ');
979
		ia32_emit_source_register(env, node, 1);
Matthias Braun's avatar
Matthias Braun committed
980
		be_emit_cstring(env, ", ");
981
		ia32_emit_source_register(env, node, 0);
982
983
984

		in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, 2));
		in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, 3));
985
	} else {
986
		if (is_ia32_CmpCMov(node) || is_ia32_CmpCMov8Bit(node)) {
987
988
			be_emit_cstring(env, "\tcmp ");
		} else {
989
			assert(is_ia32_TestCMov(node) || is_ia32_TestCMov8Bit(node));
990
991
992
993
994
995
			be_emit_cstring(env, "\ttest ");
		}
		ia32_emit_binop(env, node);

		in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, 5));
		in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, 6));
996
	}
Matthias Braun's avatar
Matthias Braun committed
997
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
998

999
	if (out == in2) {
Christian Würdig's avatar
Christian Würdig committed
1000
		/* best case: default in == out -> do nothing */
1001
1002
	} else if(in2 == &ia32_gp_regs[REG_GP_UKNWN]) {
		/* also nothign to do for unknown regs */
1003
1004
1005
1006
1007
1008
1009
	} else if (out == in1) {
		const arch_register_t *t;
		/* true in == out -> need complement compare and exchange true and
		 * default in */
		t   = in1;
		in1 = in2;
		in2 = t;
1010
1011
		pnc = get_negated_pnc(pnc, get_irn_mode(node));
	} else {
1012
		/* out is different from both ins: need copy default -> out */
1013
		be_emit_cstring(env, "\tmovl ");
1014
		ia32_emit_register(env, in2);
Matthias Braun's avatar
Matthias Braun committed
1015
		be_emit_cstring(env, ", ");
1016
		ia32_emit_register(env, out);
1017
		be_emit_finish_line_gas(env, node);
1018
	}
1019
1020

	be_emit_cstring(env, "\tcmov");
1021
	ia32_emit_cmp_suffix(env, pnc );
1022
	be_emit_cstring(env, "l ");
1023