ia32_emitter.c 59.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
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
183
184
185
186
187
188
	return
		!is_ia32_CmpSet(node)    &&
		!is_ia32_CondJmp(node)   &&
		!is_ia32_St(node)        &&
		!is_ia32_SwitchJmp(node) &&
		!is_ia32_TestJmp(node)   &&
		!is_ia32_xCmpSet(node)   &&
189
190
191
192
193
		!is_ia32_xCondJmp(node)  &&
		!is_ia32_CmpCMov(node)   &&
		!is_ia32_TestCMov(node)  &&
		!is_ia32_CmpSet(node)    && /* this is correct, the Cmp has no result */
		!is_ia32_TestSet(node);
194
195
}

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

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

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

Matthias Braun's avatar
Matthias Braun committed
230
231
232
233
234
235
236
// 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)
237
#define be_emit_tarval(env,tv)          be_emit_tarval(env->emit,tv)
Matthias Braun's avatar
Matthias Braun committed
238
239
240
#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
241

242
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
243
{
244
	const arch_register_t *reg = get_in_reg(env, node, pos);
245
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
246

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

Matthias Braun's avatar
Matthias Braun committed
249
250
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
251
252
253
}

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

Matthias Braun's avatar
Matthias Braun committed
257
258
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
Christian Würdig's avatar
Christian Würdig committed
259
260
}

261
262
263
264
265
266
267
268
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);
}

269
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
270
{
271
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
272

Matthias Braun's avatar
Matthias Braun committed
273
	assert(pos < 3);
Matthias Braun's avatar
Matthias Braun committed
274
275
	be_emit_char(env, '%');
	be_emit_string(env, attr->x87[pos]->name);
276
}
Christian Würdig's avatar
Christian Würdig committed
277

278
279
280
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node)
{
	tarval *tv;
281
	ir_entity *ent;
282
	ident *id;
Christian Würdig's avatar
Christian Würdig committed
283

284
285
	be_emit_char(env, '$');

286
287
288
	switch(get_ia32_immop_type(node)) {
	case ia32_ImmConst:
		tv = get_ia32_Immop_tarval(node);
289
		be_emit_tarval(env, tv);
290
		return;
291
	case ia32_ImmSymConst:
292
		ent = get_ia32_Immop_symconst(node);
Michael Beck's avatar
Michael Beck committed
293
		set_entity_backend_marked(ent, 1);
294
		id = get_entity_ld_ident(ent);
295
		be_emit_ident(env, id);
296
		return;
297
298
	case ia32_ImmNone:
		break;
Christian Würdig's avatar
Christian Würdig committed
299
	}
Christian Würdig's avatar
Christian Würdig committed
300

301
302
303
	assert(0);
	be_emit_string(env, "BAD");
	return;
304
}
Christian Würdig's avatar
Christian Würdig committed
305

Matthias Braun's avatar
Matthias Braun committed
306
307
static
void ia32_emit_mode_suffix_mode(ia32_emit_env_t *env, const ir_mode *mode)
308
{
Matthias Braun's avatar
Matthias Braun committed
309
	be_emit_char(env, get_mode_suffix(mode));
Christian Würdig's avatar
Christian Würdig committed
310
311
}

Matthias Braun's avatar
Matthias Braun committed
312
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
313
314
{
	ir_mode *mode = get_ia32_ls_mode(node);
Matthias Braun's avatar
Matthias Braun committed
315
316
317
318
	if(mode == NULL)
		mode = mode_Iu;

	ia32_emit_mode_suffix_mode(env, mode);
319
320
}

321
322
323
324
325
326
327
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);
}

328
329
static
char get_xmm_mode_suffix(ir_mode *mode)
330
331
332
333
334
335
336
337
338
339
340
341
342
{
	assert(mode_is_float(mode));
	switch(get_mode_size_bits(mode)) {
	case 32:
		return 's';
	case 64:
		return 'd';
	default:
		assert(0);
	}
	return '%';
}

343
344
345
void ia32_emit_xmm_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
{
	ir_mode *mode = get_ia32_ls_mode(node);
346
	assert(mode != NULL);
Matthias Braun's avatar
Matthias Braun committed
347
348
	be_emit_char(env, 's');
	be_emit_char(env, get_xmm_mode_suffix(mode));
349
350
351
352
353
354
}

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
355
	be_emit_char(env, get_xmm_mode_suffix(mode));
356
357
}

358
359
360
361
362
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
363
		be_emit_char(env, 's');
364
	} else {
Matthias Braun's avatar
Matthias Braun committed
365
366
367
368
		be_emit_char(env, 'z');
	}
}

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

390
391
static
void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
392
393
394
395
396
397
398
399
400
401
402
403
{
	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
404
405
406
	}
}

Matthias Braun's avatar
Matthias Braun committed
407

408
409
static
void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node);
Matthias Braun's avatar
Matthias Braun committed
410

Christian Würdig's avatar
Christian Würdig committed
411
412
413
/**
 * Emits registers and/or address mode of a binary operation.
 */
414
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
415
	int            right_pos;
416
	const ir_node *right_op = get_irn_n(node, 3);
Christian Würdig's avatar
Christian Würdig committed
417

418
419
420
421
422
423
	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
424
			break;
425
426
		} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
			ia32_emit_immediate(env, node);
427
			be_emit_cstring(env, ", ");
428
429
430
431
432
433
434
435
			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;

436
			in      = out ? ((out == in2) ? in1 : in2) : in2;
437
438
439
440
			out     = out ? out : in1;
			in_name = arch_register_get_name(in);

			if (is_ia32_emit_cl(node)) {
441
				assert(in == &ia32_gp_regs[REG_ECX]);
442
				in_name = "cl";
443
			}
Christian Würdig's avatar
Christian Würdig committed
444

445
446
447
448
449
450
451
452
			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:
		if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
453
454
			assert(!produces_result(node) &&
					"Source AM with Const must not produce result");
455
			ia32_emit_immediate(env, node);
456
457
458
459
460
461
462
463
464
			be_emit_cstring(env, ", ");
			ia32_emit_am(env, node);
		} else if(is_ia32_Immediate(right_op)) {
			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);
465
		} else if (produces_result(node)) {
466
467
			ia32_emit_am(env, node);
			be_emit_cstring(env, ", ");
468
469
			ia32_emit_dest_register(env, node, 0);
		} else {
470
471
			ia32_emit_am(env, node);
			be_emit_cstring(env, ", ");
472
473
474
475
			ia32_emit_source_register(env, node, 2);
		}
		break;
	case ia32_AddrModeD:
476
		right_pos = get_irn_arity(node) >= 5 ? 3 : 2;
477
		right_op  = get_irn_n(node, right_pos);
478
479
480
481
482
483
484
485
486
487
		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 {
488
			const arch_register_t *in1 = get_in_reg(env, node, right_pos);
489
490
			ir_mode               *mode = get_ia32_ls_mode(node);
			const char            *in_name;
Christian Würdig's avatar
Christian Würdig committed
491

492
			in_name = ia32_get_reg_name_for_mode(env, mode, in1);
493

494
			if (is_ia32_emit_cl(node)) {
495
				assert(in1 == &ia32_gp_regs[REG_ECX]);
496
				in_name = "cl";
Christian Würdig's avatar
Christian Würdig committed
497
			}
498
499
500
501
502
503
504
505
506

			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
507
	}
508
509
}

510
511
512
/**
 * Emits registers and/or address mode of a binary operation.
 */
513
514
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
515
		case ia32_Normal:
516
517
518
519
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				// should not happen...
				assert(0);
			} else {
520
521
522
523
				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];
524
525
				const arch_register_t *in;

526
				in  = out ? ((out == in2) ? in1 : in2) : in2;
527
				out = out ? out : in1;
528

Matthias Braun's avatar
Matthias Braun committed
529
530
531
532
				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));
533
534
535
536
			}
			break;
		case ia32_AddrModeS:
		case ia32_AddrModeD:
537
			ia32_emit_am(env, node);
538
539
540
541
542
543
			break;
		default:
			assert(0 && "unsupported op type");
	}
}

544
545
546
547
548
549
550
551
552
553
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
554
555
556
/**
 * Emits registers and/or address mode of a unary operation.
 */
557
558
559
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node, int pos) {
	const ir_node *op;

560
	switch(get_ia32_op_type(node)) {
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
	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
577
578
579
580
	}
}

/**
581
 * Emits address mode.
Christian Würdig's avatar
Christian Würdig committed
582
 */
583
void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
584
585
586
587
588
589
	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
590

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

594
	/* emit offset */
595
596
597
	if (ent != NULL) {
		ident *id;

Michael Beck's avatar
Michael Beck committed
598
		set_entity_backend_marked(ent, 1);
599
		id = get_entity_ld_ident(ent);
600
		if (is_ia32_am_sc_sign(node))
Matthias Braun's avatar
Matthias Braun committed
601
602
			be_emit_char(env, '-');
		be_emit_ident(env, id);
Matthias Braun's avatar
Matthias Braun committed
603
604
605
606
607
608
609
610

		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
611
612
	}

613
	if(offs != 0) {
614
		if(ent != NULL) {
Matthias Braun's avatar
Matthias Braun committed
615
			be_emit_irprintf(env->emit, "%+d", offs);
616
		} else {
Matthias Braun's avatar
Matthias Braun committed
617
			be_emit_irprintf(env->emit, "%d", offs);
618
		}
619
	}
Christian Würdig's avatar
Christian Würdig committed
620

621
	if (has_base || has_index) {
Matthias Braun's avatar
Matthias Braun committed
622
		be_emit_char(env, '(');
Christian Würdig's avatar
Christian Würdig committed
623

624
		/* emit base */
625
		if (has_base) {
626
			ia32_emit_source_register(env, node, 0);
Christian Würdig's avatar
Christian Würdig committed
627
628
		}

629
		/* emit index + scale */
630
631
		if (has_index) {
			int scale;
Matthias Braun's avatar
Matthias Braun committed
632
			be_emit_char(env, ',');
633
			ia32_emit_source_register(env, node, 1);
634

635
636
			scale = get_ia32_am_scale(node);
			if (scale > 0) {
Matthias Braun's avatar
Matthias Braun committed
637
				be_emit_irprintf(env->emit, ",%d", 1 << get_ia32_am_scale(node));
638
639
			}
		}
Matthias Braun's avatar
Matthias Braun committed
640
		be_emit_char(env, ')');
Christian Würdig's avatar
Christian Würdig committed
641
	}
642
}
Christian Würdig's avatar
Christian Würdig committed
643

Christian Würdig's avatar
Christian Würdig committed
644
645
646
647
648
649
650
651
652
653
/*************************************************
 *                 _ _                         _
 *                (_) |                       | |
 *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
 *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
 * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
 *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
 *
 *************************************************/

Christian Würdig's avatar
Christian Würdig committed
654
#undef IA32_DO_EMIT
Christian Würdig's avatar
Christian Würdig committed
655
#define IA32_DO_EMIT(irn) ia32_fprintf_format(F, irn, cmd_buf, cmnt_buf)
Christian Würdig's avatar
Christian Würdig committed
656

657
658
659
660
/*
 * coding of conditions
 */
struct cmp2conditon_t {
Christian Würdig's avatar
Christian Würdig committed
661
662
	const char *name;
	pn_Cmp      num;
663
664
665
666
667
};

/*
 * positive conditions for signed compares
 */
668
669
static
const struct cmp2conditon_t cmp2condition_s[] = {
670
671
672
673
674
675
676
677
	{ 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 */
678
679
680
681
682
};

/*
 * positive conditions for unsigned compares
 */
683
684
static
const struct cmp2conditon_t cmp2condition_u[] = {
Christian Würdig's avatar
Christian Würdig committed
685
686
687
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "b",               pn_Cmp_Lt },     /* < */
Christian Würdig's avatar
Christian Würdig committed
688
	{ "be",              pn_Cmp_Le },     /* <= */
Christian Würdig's avatar
Christian Würdig committed
689
690
691
692
	{ "a",               pn_Cmp_Gt },     /* > */
	{ "ae",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
	{ NULL,              pn_Cmp_True },   /* always true */
693
694
695
696
697
};

/*
 * returns the condition code
 */
698
static
Matthias Braun's avatar
Matthias Braun committed
699
const char *get_cmp_suffix(pn_Cmp cmp_code)
700
{
701
	assert( (cmp2condition_s[cmp_code & 7].num) == (cmp_code & 7));
702
	assert( (cmp2condition_u[cmp_code & 7].num) == (cmp_code & 7));
703

704
705
706
	if((cmp_code & ia32_pn_Cmp_Unsigned)) {
		return cmp2condition_u[cmp_code & 7].name;
	} else {
707
		return cmp2condition_s[cmp_code & 7].name;
708
	}
709
710
}

711
712
void ia32_emit_cmp_suffix(ia32_emit_env_t *env, long pnc)
{
Matthias Braun's avatar
Matthias Braun committed
713
	be_emit_string(env, get_cmp_suffix(pnc));
714
715
716
}


717
718
719
/**
 * Returns the target block for a control flow node.
 */
720
721
static
ir_node *get_cfop_target_block(const ir_node *irn) {
722
723
724
	return get_irn_link(irn);
}

725
726
727
/**
 * Emits a block label for the given block.
 */
728
729
730
731
732
733
734
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
735
/**
736
 * Emits the target label for a control flow node.
Christian Würdig's avatar
Christian Würdig committed
737
 */
738
static
739
740
void ia32_emit_cfop_target(ia32_emit_env_t * env, const ir_node *node) {
	ir_node *block = get_cfop_target_block(node);
741

742
	ia32_emit_block_name(env, block);
Christian Würdig's avatar
Christian Würdig committed
743
}
744

745
746
/** Return the next block in Block schedule */
static ir_node *next_blk_sched(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
747
	return get_irn_link(block);
748
749
}

750
751
752
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
753
754
static
ir_node *get_proj(const ir_node *node, long proj) {
755
756
757
	const ir_edge_t *edge;
	ir_node         *src;

758
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
759

760
	foreach_out_edge(node, edge) {
761
762
763
764
765
766
767
768
769
770
771
772
		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
773
774
775
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
776
777
778
static
void finish_CondJmp(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode,
                    long pnc) {
779
780
781
782
783
	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
784

785
	/* get both Proj's */
786
	proj_true = get_proj(node, pn_Cond_true);
787
	assert(proj_true && "CondJmp without true Proj");
Christian Würdig's avatar
Christian Würdig committed
788

789
	proj_false = get_proj(node, pn_Cond_false);
790
791
	assert(proj_false && "CondJmp without false Proj");

792
	/* for now, the code works for scheduled and non-schedules blocks */
793
	block = get_nodes_block(node);
794
795

	/* we have a block schedule */
796
	next_block = next_blk_sched(block);
797

798
	if (get_cfop_target_block(proj_true) == next_block) {
799
		/* exchange both proj's so the second one can be omitted */
800
801
		const ir_node *t = proj_true;

802
803
804
805
		proj_true  = proj_false;
		proj_false = t;
		flipped    = 1;
		pnc        = get_negated_pnc(pnc, mode);
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
844
845
846
847
848
849
850
851
	if (mode_is_float(mode)) {
		/* Some floating point comparisons require a test of the parity flag, which
		 * indicates that the result is unordered */
		switch (pnc) {
			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, ' ');
852
		ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
853
		be_emit_finish_line_gas(env, proj_true);
854
855
	}

856
	/* the second Proj might be a fallthrough */
857
	if (get_cfop_target_block(proj_false) != next_block) {
Matthias Braun's avatar
Matthias Braun committed
858
		be_emit_cstring(env, "\tjmp ");
859
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
860
		be_emit_finish_line_gas(env, proj_false);
861
	} else {
862
		be_emit_cstring(env, "\t/* fallthrough to ");
863
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
864
865
		be_emit_cstring(env, " */");
		be_emit_finish_line_gas(env, proj_false);
866
	}
Christian Würdig's avatar
Christian Würdig committed
867
868
869
}

/**
Christian Würdig's avatar
Christian Würdig committed
870
 * Emits code for conditional jump.
Christian Würdig's avatar
Christian Würdig committed
871
 */
872
873
static
void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
874
875
876
	be_emit_cstring(env, "\tcmp");
	ia32_emit_mode_suffix(env, node);
	be_emit_char(env, ' ');
877
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
878
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
879

880
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
881
882
}

Christian Würdig's avatar
Christian Würdig committed
883
884
885
/**
 * Emits code for conditional jump with two variables.
 */
886
887
static
void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
888
	CondJmp_emitter(env, node);
Christian Würdig's avatar
Christian Würdig committed
889
890
}

891
892
893
/**
 * Emits code for conditional test and jump.
 */
894
895
static
void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
896
897
898
899
	be_emit_cstring(env, "\ttest");
	ia32_emit_mode_suffix(env, node);
	be_emit_char(env, ' ');

900
901
902
	ia32_emit_binop(env, node);
	be_emit_finish_line_gas(env, node);

903
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
904
905
906
907
908
}

/**
 * Emits code for conditional test and jump with two variables.
 */
909
910
static
void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
911
	TestJmp_emitter(env, node);
912
913
}

Christian Würdig's avatar
Christian Würdig committed
914
915
916
/**
 * Emits code for conditional SSE floating point jump with two variables.
 */
917
918
static
void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
919
	be_emit_cstring(env, "\tucomi");
Matthias Braun's avatar
Matthias Braun committed
920
	ia32_emit_xmm_mode_suffix(env, node);
Matthias Braun's avatar
Matthias Braun committed
921
	be_emit_char(env, ' ');
922
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
923
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
924

925
	finish_CondJmp(env, node, mode_F, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
926
927
}

Michael Beck's avatar
Michael Beck committed
928
929
930
/**
 * Emits code for conditional x87 floating point jump with two variables.
 */
931
932
static
void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
933
934
935
	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
936

937
	switch (get_ia32_irn_opcode(node)) {
Michael Beck's avatar
Michael Beck committed
938
	case iro_ia32_fcomrJmp:
939
		pnc = get_inversed_pnc(pnc);
940
		reg = x87_attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
941
942
	case iro_ia32_fcomJmp:
	default:
Matthias Braun's avatar
Matthias Braun committed
943
		be_emit_cstring(env, "\tfucom ");
Michael Beck's avatar
Michael Beck committed
944
945
		break;
	case iro_ia32_fcomrpJmp:
946
		pnc = get_inversed_pnc(pnc);
947
		reg = x87_attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
948
	case iro_ia32_fcompJmp:
Matthias Braun's avatar
Matthias Braun committed
949
		be_emit_cstring(env, "\tfucomp ");
Michael Beck's avatar
Michael Beck committed
950
951
		break;
	case iro_ia32_fcomrppJmp:
952
		pnc = get_inversed_pnc(pnc);
Michael Beck's avatar
Michael Beck committed
953
	case iro_ia32_fcomppJmp:
Matthias Braun's avatar
Matthias Braun committed
954
		be_emit_cstring(env, "\tfucompp ");
Michael Beck's avatar
Michael Beck committed
955
956
957
958
		reg = "";
		break;
	}

959
	if(reg[0] != '\0') {
Matthias Braun's avatar
Matthias Braun committed
960
961
		be_emit_char(env, '%');
		be_emit_string(env, reg);
962
	}
Matthias Braun's avatar
Matthias Braun committed
963
	be_emit_finish_line_gas(env, node);
Michael Beck's avatar
Michael Beck committed
964

Matthias Braun's avatar
Matthias Braun committed
965
966
967
968
	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
969

970
	finish_CondJmp(env, node, mode_E, pnc);
Michael Beck's avatar
Michael Beck committed
971
972
}

973
static
Matthias Braun's avatar
Matthias Braun committed
974
975
void CMov_emitter(ia32_emit_env_t *env, const ir_node *node)
{
Christian Würdig's avatar
Christian Würdig committed
976
	const arch_register_t *in1, *in2, *out;
977
	long  pnc = get_ia32_pncode(node);
Christian Würdig's avatar
Christian Würdig committed
978

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

Christian Würdig's avatar
Christian Würdig committed
981
982
	/* we have to emit the cmp first, because the destination register */
	/* could be one of the compare registers                           */
983
	if (is_ia32_xCmpCMov(node)) {
Matthias Braun's avatar
Matthias Braun committed
984
		be_emit_cstring(env, "\tucomis");
Matthias Braun's avatar
Matthias Braun committed
985
		ia32_emit_mode_suffix_mode(env, get_irn_mode(node));
Matthias Braun's avatar
Matthias Braun committed
986
		be_emit_char(env, ' ');
987
		ia32_emit_source_register(env, node, 1);
Matthias Braun's avatar
Matthias Braun committed
988
		be_emit_cstring(env, ", ");
989
		ia32_emit_source_register(env, node, 0);
990
991
992

		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));
993
	} else {