ia32_emitter.c 60.7 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
	/* in case of a joker register: just return a valid register */
	if (arch_register_type_is(reg, joker)) {
Matthias Braun's avatar
Matthias Braun committed
91
		const arch_register_req_t *req;
92
93

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

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

Christian Würdig's avatar
Christian Würdig committed
106
107
108
109
110
111
	return reg;
}

/**
 * Returns the register at out position pos.
 */
112
113
114
115
116
117
118
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
119
120
121
122
123
124
125
126

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

146
147
148
/**
 * Determine the gnu assembler suffix that indicates a mode
 */
149
150
static
char get_mode_suffix(const ir_mode *mode) {
151
152
153
154
155
156
157
158
	if(mode_is_float(mode)) {
		switch(get_mode_size_bits(mode)) {
		case 32:
			return 's';
		case 64:
			return 'l';
		case 80:
			return 't';
159
		}
160
	} else {
Michael Beck's avatar
Michael Beck committed
161
		assert(mode_is_int(mode) || mode_is_reference(mode) || mode_is_character(mode));
162
163
164
165
166
167
168
169
170
		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
171
		}
172
173
174
	}
	panic("Can't output mode_suffix for %+F\n", mode);
}
Christian Würdig's avatar
Christian Würdig committed
175

176
177
static
int produces_result(const ir_node *node) {
178
179
180
181
182
183
184
185
	return !(is_ia32_St(node) ||
		is_ia32_CondJmp(node) ||
		is_ia32_xCondJmp(node) ||
		is_ia32_CmpSet(node) ||
		is_ia32_xCmpSet(node) ||
		is_ia32_SwitchJmp(node));
}

186
187
188
static
const char *ia32_get_reg_name_for_mode(ia32_emit_env_t *env, ir_mode *mode,
                                       const arch_register_t *reg) {
189
190
191
192
193
194
195
	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
196
	}
Christian Würdig's avatar
Christian Würdig committed
197
198
}

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

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

Matthias Braun's avatar
Matthias Braun committed
220
221
222
223
224
225
226
// 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)
227
#define be_emit_tarval(env,tv)          be_emit_tarval(env->emit,tv)
Matthias Braun's avatar
Matthias Braun committed
228
229
230
#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
231

232
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
233
{
234
	const arch_register_t *reg = get_in_reg(env, node, pos);
235
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
236

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

Matthias Braun's avatar
Matthias Braun committed
239
240
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
241
242
243
}

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

Matthias Braun's avatar
Matthias Braun committed
247
248
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
Christian Würdig's avatar
Christian Würdig committed
249
250
}

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

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

260
261
262
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node)
{
	tarval *tv;
263
	ir_entity *ent;
264
	ident *id;
Christian Würdig's avatar
Christian Würdig committed
265

266
267
	be_emit_char(env, '$');

268
269
270
	switch(get_ia32_immop_type(node)) {
	case ia32_ImmConst:
		tv = get_ia32_Immop_tarval(node);
271
		be_emit_tarval(env, tv);
272
		return;
273
	case ia32_ImmSymConst:
274
275
276
		ent = get_ia32_Immop_symconst(node);
		mark_entity_visited(ent);
		id = get_entity_ld_ident(ent);
277
		be_emit_ident(env, id);
278
		return;
279
280
	case ia32_ImmNone:
		break;
Christian Würdig's avatar
Christian Würdig committed
281
	}
Christian Würdig's avatar
Christian Würdig committed
282

283
284
285
	assert(0);
	be_emit_string(env, "BAD");
	return;
286
}
Christian Würdig's avatar
Christian Würdig committed
287

Matthias Braun's avatar
Matthias Braun committed
288
289
static
void ia32_emit_mode_suffix_mode(ia32_emit_env_t *env, const ir_mode *mode)
290
{
Matthias Braun's avatar
Matthias Braun committed
291
	be_emit_char(env, get_mode_suffix(mode));
Christian Würdig's avatar
Christian Würdig committed
292
293
}

Matthias Braun's avatar
Matthias Braun committed
294
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
295
296
{
	ir_mode *mode = get_ia32_ls_mode(node);
Matthias Braun's avatar
Matthias Braun committed
297
298
299
300
	if(mode == NULL)
		mode = mode_Iu;

	ia32_emit_mode_suffix_mode(env, mode);
301
302
}

303
304
305
306
307
308
309
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);
}

310
311
static
char get_xmm_mode_suffix(ir_mode *mode)
312
313
314
315
316
317
318
319
320
321
322
323
324
{
	assert(mode_is_float(mode));
	switch(get_mode_size_bits(mode)) {
	case 32:
		return 's';
	case 64:
		return 'd';
	default:
		assert(0);
	}
	return '%';
}

325
326
327
void ia32_emit_xmm_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
{
	ir_mode *mode = get_ia32_ls_mode(node);
328
	assert(mode != NULL);
Matthias Braun's avatar
Matthias Braun committed
329
330
	be_emit_char(env, 's');
	be_emit_char(env, get_xmm_mode_suffix(mode));
331
332
333
334
335
336
}

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
337
	be_emit_char(env, get_xmm_mode_suffix(mode));
338
339
}

340
341
342
343
344
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
345
		be_emit_char(env, 's');
346
	} else {
Matthias Braun's avatar
Matthias Braun committed
347
348
349
350
		be_emit_char(env, 'z');
	}
}

351
352
static
void ia32_emit_function_object(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
{
	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;
	}
}

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

Matthias Braun's avatar
Matthias Braun committed
389

390
391
static
void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node);
Matthias Braun's avatar
Matthias Braun committed
392

Christian Würdig's avatar
Christian Würdig committed
393
394
395
/**
 * Emits registers and/or address mode of a binary operation.
 */
396
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
397
	const ir_node *right_op;
Christian Würdig's avatar
Christian Würdig committed
398

399
400
401
402
403
404
405
	switch(get_ia32_op_type(node)) {
	case ia32_Normal:
		right_op = get_irn_n(node, 3);
		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
406
			break;
407
408
		} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
			ia32_emit_immediate(env, node);
409
			be_emit_cstring(env, ", ");
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
			ia32_emit_source_register(env, node, 2);
		} 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;

			in      = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
			out     = out ? out : in1;
			in_name = arch_register_get_name(in);

			if (is_ia32_emit_cl(node)) {
				assert(REGS_ARE_EQUAL(&ia32_gp_regs[REG_ECX], in) && "shift operation needs ecx");
				in_name = "cl";
425
			}
Christian Würdig's avatar
Christian Würdig committed
426

427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
			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:
		ia32_emit_am(env, node);
		be_emit_cstring(env, ", ");
		if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
			assert(!produces_result(node) && "Source AM with Const must not produce result");
			ia32_emit_immediate(env, node);
		} else if (produces_result(node)) {
			ia32_emit_dest_register(env, node, 0);
		} else {
			ia32_emit_source_register(env, node, 2);
		}
		break;
	case ia32_AddrModeD:
		right_op = get_irn_n(node, 3);
		if(is_ia32_Immediate(right_op)) {
			emit_ia32_Immediate(env, right_op);
			be_emit_cstring(env, ", ");
			ia32_emit_am(env, node);
			break;
		} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
			ia32_emit_immediate(env, node);
			be_emit_cstring(env, ", ");
			ia32_emit_am(env, node);
		} else {
			const arch_register_t *in1 = get_in_reg(env, node,
				                                    get_irn_arity(node) == 5 ? 3 : 2);
			ir_mode               *mode = get_ia32_ls_mode(node);
			const char            *in_name;
Christian Würdig's avatar
Christian Würdig committed
461

462
			in_name = ia32_get_reg_name_for_mode(env, mode, in1);
463

464
465
466
			if (is_ia32_emit_cl(node)) {
				assert(REGS_ARE_EQUAL(&ia32_gp_regs[REG_ECX], in1) && "shift operation needs ecx");
				in_name = "cl";
Christian Würdig's avatar
Christian Würdig committed
467
			}
468
469
470
471
472
473
474
475
476

			be_emit_char(env, '%');
			be_emit_string(env, in_name);
			be_emit_cstring(env, ", ");
			ia32_emit_am(env, node);
		}
		break;
	default:
		assert(0 && "unsupported op type");
Christian Würdig's avatar
Christian Würdig committed
477
	}
478
479
}

480
481
482
/**
 * Emits registers and/or address mode of a binary operation.
 */
483
484
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
485
		case ia32_Normal:
486
487
488
489
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				// should not happen...
				assert(0);
			} else {
490
491
492
493
				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];
494
495
				const arch_register_t *in;

496
497
				in  = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
				out = out ? out : in1;
498

Matthias Braun's avatar
Matthias Braun committed
499
500
501
502
				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));
503
504
505
506
			}
			break;
		case ia32_AddrModeS:
		case ia32_AddrModeD:
507
			ia32_emit_am(env, node);
508
509
510
511
512
513
			break;
		default:
			assert(0 && "unsupported op type");
	}
}

514
515
516
517
518
519
520
521
522
523
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
524
525
526
/**
 * Emits registers and/or address mode of a unary operation.
 */
527
528
529
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node, int pos) {
	const ir_node *op;

530
	switch(get_ia32_op_type(node)) {
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
	case ia32_Normal:
		op = get_irn_n(node, pos);
		if (is_ia32_Immediate(op)) {
			emit_ia32_Immediate(env, op);
		} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
			ia32_emit_immediate(env, node);
		} 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
547
548
549
550
	}
}

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

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

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

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

		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
581
582
	}

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

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

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

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

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

Christian Würdig's avatar
Christian Würdig committed
614
615
616
617
618
619
620
621
622
623
/*************************************************
 *                 _ _                         _
 *                (_) |                       | |
 *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
 *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
 * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
 *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
 *
 *************************************************/

Christian Würdig's avatar
Christian Würdig committed
624
#undef IA32_DO_EMIT
Christian Würdig's avatar
Christian Würdig committed
625
#define IA32_DO_EMIT(irn) ia32_fprintf_format(F, irn, cmd_buf, cmnt_buf)
Christian Würdig's avatar
Christian Würdig committed
626

627
628
629
630
/*
 * coding of conditions
 */
struct cmp2conditon_t {
Christian Würdig's avatar
Christian Würdig committed
631
632
	const char *name;
	pn_Cmp      num;
633
634
635
636
637
};

/*
 * positive conditions for signed compares
 */
638
639
static
const struct cmp2conditon_t cmp2condition_s[] = {
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
	{ 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 */
	{ NULL,              pn_Cmp_Uo },     /* Floating point: unordered */
	{ "e",               pn_Cmp_Ue },     /* Floating point: unordered or == */
	{ "b",               pn_Cmp_Ul },     /* Floating point: unordered or < */
	{ "be",              pn_Cmp_Ule },    /* Floating point: unordered or <= */
	{ "a",               pn_Cmp_Ug },     /* Floating point: unordered or > */
	{ "ae",              pn_Cmp_Uge },    /* Floating point: unordered or >= */
	{ "ne",              pn_Cmp_Ne },     /* Floating point: unordered or != */
	{ NULL,              pn_Cmp_True },   /* always true */
656
657
658
659
660
};

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

/*
 * returns the condition code
 */
676
static
Matthias Braun's avatar
Matthias Braun committed
677
const char *get_cmp_suffix(pn_Cmp cmp_code)
678
{
679
680
	assert( (cmp2condition_s[cmp_code & 15].num) == (cmp_code & 15));
	assert( (cmp2condition_u[cmp_code & 7].num) == (cmp_code & 7));
681

682
683
684
685
686
	if((cmp_code & ia32_pn_Cmp_Unsigned)) {
		return cmp2condition_u[cmp_code & 7].name;
	} else {
		return cmp2condition_s[cmp_code & 15].name;
	}
687
688
}

689
690
void ia32_emit_cmp_suffix(ia32_emit_env_t *env, long pnc)
{
Matthias Braun's avatar
Matthias Braun committed
691
	be_emit_string(env, get_cmp_suffix(pnc));
692
693
694
}


695
696
697
/**
 * Returns the target block for a control flow node.
 */
698
699
static
ir_node *get_cfop_target_block(const ir_node *irn) {
700
701
702
	return get_irn_link(irn);
}

703
704
705
706
707
708
709
static
void ia32_emit_block_name(ia32_emit_env_t *env, const ir_node *block)
{
	be_emit_cstring(env, BLOCK_PREFIX);
	be_emit_irprintf(env->emit, "%d", get_irn_node_nr(block));
}

Christian Würdig's avatar
Christian Würdig committed
710
711
712
/**
 * Returns the target label for a control flow node.
 */
713
static
714
715
void ia32_emit_cfop_target(ia32_emit_env_t * env, const ir_node *node) {
	ir_node *block = get_cfop_target_block(node);
716

717
	ia32_emit_block_name(env, block);
Christian Würdig's avatar
Christian Würdig committed
718
}
719

720
721
/** Return the next block in Block schedule */
static ir_node *next_blk_sched(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
722
	return get_irn_link(block);
723
724
}

725
726
727
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
728
729
static
ir_node *get_proj(const ir_node *node, long proj) {
730
731
732
	const ir_edge_t *edge;
	ir_node         *src;

733
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
734

735
	foreach_out_edge(node, edge) {
736
737
738
739
740
741
742
743
744
745
746
747
		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
748
749
750
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
751
752
753
static
void finish_CondJmp(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode,
                    long pnc) {
754
755
756
757
758
	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
759

760
	/* get both Proj's */
761
	proj_true = get_proj(node, pn_Cond_true);
762
	assert(proj_true && "CondJmp without true Proj");
Christian Würdig's avatar
Christian Würdig committed
763

764
	proj_false = get_proj(node, pn_Cond_false);
765
766
	assert(proj_false && "CondJmp without false Proj");

767
	/* for now, the code works for scheduled and non-schedules blocks */
768
	block = get_nodes_block(node);
769
770

	/* we have a block schedule */
771
	next_block = next_blk_sched(block);
772

773
	if (get_cfop_target_block(proj_true) == next_block) {
774
		/* exchange both proj's so the second one can be omitted */
775
776
		const ir_node *t = proj_true;

777
778
779
780
		proj_true  = proj_false;
		proj_false = t;
		flipped    = 1;
		pnc        = get_negated_pnc(pnc, mode);
781
782
	}

783
784
	/* in case of unordered compare, check for parity */
	if (pnc & pn_Cmp_Uo) {
Matthias Braun's avatar
Matthias Braun committed
785
		be_emit_cstring(env, "\tjp ");
786
		ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
787
		be_emit_finish_line_gas(env, proj_true);
788
789
	}

Matthias Braun's avatar
Matthias Braun committed
790
	be_emit_cstring(env, "\tj");
791
	ia32_emit_cmp_suffix(env, pnc);
Matthias Braun's avatar
Matthias Braun committed
792
	be_emit_char(env, ' ');
793
	ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
794
	be_emit_finish_line_gas(env, proj_true);
Christian Würdig's avatar
Christian Würdig committed
795

796
	/* the second Proj might be a fallthrough */
797
	if (get_cfop_target_block(proj_false) != next_block) {
Matthias Braun's avatar
Matthias Braun committed
798
		be_emit_cstring(env, "\tjmp ");
799
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
800
		be_emit_finish_line_gas(env, proj_false);
801
	} else {
802
		be_emit_cstring(env, "\t/* fallthrough to ");
803
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
804
805
		be_emit_cstring(env, " */");
		be_emit_finish_line_gas(env, proj_false);
806
	}
Christian Würdig's avatar
Christian Würdig committed
807
808
809
}

/**
Christian Würdig's avatar
Christian Würdig committed
810
 * Emits code for conditional jump.
Christian Würdig's avatar
Christian Würdig committed
811
 */
812
813
static
void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
814
	be_emit_cstring(env, "\tcmp ");
815
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
816
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
817

818
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
819
820
}

Christian Würdig's avatar
Christian Würdig committed
821
822
823
/**
 * Emits code for conditional jump with two variables.
 */
824
825
static
void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
826
	CondJmp_emitter(env, node);
Christian Würdig's avatar
Christian Würdig committed
827
828
}

829
830
831
/**
 * Emits code for conditional test and jump.
 */
832
833
static
void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
834
	if(is_ia32_ImmSymConst(node) || is_ia32_ImmConst(node)) {
835
		be_emit_cstring(env, "\ttest ");
836
		ia32_emit_immediate(env, node);
Matthias Braun's avatar
Matthias Braun committed
837
		be_emit_cstring(env, ", ");
838
		ia32_emit_source_register(env, node, 0);
Matthias Braun's avatar
Matthias Braun committed
839
		be_emit_finish_line_gas(env, node);
840
	} else {
Matthias Braun's avatar
Matthias Braun committed
841
		be_emit_cstring(env, "\ttest ");
842
		ia32_emit_source_register(env, node, 1);
Matthias Braun's avatar
Matthias Braun committed
843
		be_emit_cstring(env, ", ");
844
		ia32_emit_source_register(env, node, 0);
Matthias Braun's avatar
Matthias Braun committed
845
		be_emit_finish_line_gas(env, node);
846
847
	}
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
848
849
850
851
852
}

/**
 * Emits code for conditional test and jump with two variables.
 */
853
854
static
void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
855
	TestJmp_emitter(env, node);
856
857
}

858
859
static
void emit_ia32_CJmp(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
860
861
	be_emit_cstring(env, "/* omitted redundant test */");
	be_emit_finish_line_gas(env, node);
862

863
	finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
864
}
865

866
867
static
void emit_ia32_CJmpAM(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
868
869
	be_emit_cstring(env, "/* omitted redundant test/cmp */");
	be_emit_finish_line_gas(env, node);
870

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

Christian Würdig's avatar
Christian Würdig committed
874
875
876
/**
 * Emits code for conditional SSE floating point jump with two variables.
 */
877
878
static
void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
879
	be_emit_cstring(env, "\tucomi");
Matthias Braun's avatar
Matthias Braun committed
880
	ia32_emit_xmm_mode_suffix(env, node);
Matthias Braun's avatar
Matthias Braun committed
881
	be_emit_char(env, ' ');
882
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
883
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
884

885
	finish_CondJmp(env, node, mode_F, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
886
887
}

Michael Beck's avatar
Michael Beck committed
888
889
890
/**
 * Emits code for conditional x87 floating point jump with two variables.
 */
891
892
static
void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
893
894
895
	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
896

897
	switch (get_ia32_irn_opcode(node)) {
Michael Beck's avatar
Michael Beck committed
898
	case iro_ia32_fcomrJmp:
899
		pnc = get_inversed_pnc(pnc);
900
		reg = x87_attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
901
902
	case iro_ia32_fcomJmp:
	default:
Matthias Braun's avatar
Matthias Braun committed
903
		be_emit_cstring(env, "\tfucom ");
Michael Beck's avatar
Michael Beck committed
904
905
		break;
	case iro_ia32_fcomrpJmp:
906
		pnc = get_inversed_pnc(pnc);
907
		reg = x87_attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
908
	case iro_ia32_fcompJmp:
Matthias Braun's avatar
Matthias Braun committed
909
		be_emit_cstring(env, "\tfucomp ");
Michael Beck's avatar
Michael Beck committed
910
911
		break;
	case iro_ia32_fcomrppJmp:
912
		pnc = get_inversed_pnc(pnc);
Michael Beck's avatar
Michael Beck committed
913
	case iro_ia32_fcomppJmp:
Matthias Braun's avatar
Matthias Braun committed
914
		be_emit_cstring(env, "\tfucompp ");
Michael Beck's avatar
Michael Beck committed
915
916
917
918
		reg = "";
		break;
	}

919
	if(reg[0] != '\0') {
Matthias Braun's avatar
Matthias Braun committed
920
921
		be_emit_char(env, '%');
		be_emit_string(env, reg);
922
	}
Matthias Braun's avatar
Matthias Braun committed
923
	be_emit_finish_line_gas(env, node);
Michael Beck's avatar
Michael Beck committed
924

Matthias Braun's avatar
Matthias Braun committed
925
926
927
928
	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
929

930
	finish_CondJmp(env, node, mode_E, pnc);
Michael Beck's avatar
Michael Beck committed
931
932
}

933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
static
void emit_register_or_immediate(ia32_emit_env_t *env, const ir_node *node,
                                int pos)
{
	ir_node *op = get_irn_n(node, pos);
	if(is_ia32_Immediate(op)) {
		emit_ia32_Immediate(env, op);
	} else {
		ia32_emit_source_register(env, node, pos);
	}
}

static
int is_ia32_Immediate_0(const ir_node *node)
{
	const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
	tarval                      *tv   = attr->offset;

	if(tv == NULL || attr->symconst != NULL)
		return 0;

	return classify_tarval(tv) == CNST_NULL;
}

957
static
Matthias Braun's avatar
Matthias Braun committed
958
959
void CMov_emitter(ia32_emit_env_t *env, const ir_node *node)
{
960
	long pnc = get_ia32_pncode(node);
Christian Würdig's avatar
Christian Würdig committed
961
962
	const arch_register_t *in1, *in2, *out;

963
	out = arch_get_irn_register(env->arch_env, node);
964
965
	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));
Christian Würdig's avatar
Christian Würdig committed
966

Christian Würdig's avatar
Christian Würdig committed
967
968
	/* we have to emit the cmp first, because the destination register */
	/* could be one of the compare registers                           */
969
	if (is_ia32_CmpCMov(node)) {
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
		long pncr = pnc & ~ia32_pn_Cmp_Unsigned;
		ir_node *cmp_right = get_irn_n(node, 1);

		if( (pncr == pn_Cmp_Eq || pncr == pn_Cmp_Lg)
				&& is_ia32_Immediate(cmp_right)
				&& is_ia32_Immediate_0(cmp_right)) {
			be_emit_cstring(env, "\ttest ");
			ia32_emit_source_register(env, node, 0);
			be_emit_cstring(env, ", ");
			ia32_emit_source_register(env, node, 0);
		} else {
			be_emit_cstring(env, "\tcmp ");
			emit_register_or_immediate(env, node, 1);
			be_emit_cstring(env, ", ");
			ia32_emit_source_register(env, node, 0);
		}
986
	} else if (is_ia32_xCmpCMov(node)) {
Matthias Braun's avatar
Matthias Braun committed
987
		be_emit_cstring(env, "\tucomis");
Matthias Braun's avatar
Matthias Braun committed
988
		ia32_emit_mode_suffix_mode(env, get_irn_mode(node));
Matthias Braun's avatar
Matthias Braun committed
989
		be_emit_char(env, ' ');
990
		ia32_emit_source_register(env, node, 1);
Matthias Braun's avatar
Matthias Braun committed
991
		be_emit_cstring(env, ", ");
992
993
		ia32_emit_source_register(env, node, 0);
	} else {
994
995
		assert(0 && "unsupported CMov");
	}
Matthias Braun's avatar
Matthias Braun committed
996
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
997

Christian Würdig's avatar