ia32_emitter.c 60.5 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 {
Michael Beck's avatar
Michael Beck committed
165
		assert(mode_is_int(mode) || mode_is_reference(mode) || mode_is_character(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
189
	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)   &&
		!is_ia32_xCondJmp(node);
190
191
}

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

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

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

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

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

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

Matthias Braun's avatar
Matthias Braun committed
245
246
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
247
248
249
}

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

Matthias Braun's avatar
Matthias Braun committed
253
254
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
Christian Würdig's avatar
Christian Würdig committed
255
256
}

257
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
258
{
259
	const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
260

Matthias Braun's avatar
Matthias Braun committed
261
	assert(pos < 3);
Matthias Braun's avatar
Matthias Braun committed
262
263
	be_emit_char(env, '%');
	be_emit_string(env, attr->x87[pos]->name);
264
}
Christian Würdig's avatar
Christian Würdig committed
265

266
267
268
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node)
{
	tarval *tv;
269
	ir_entity *ent;
270
	ident *id;
Christian Würdig's avatar
Christian Würdig committed
271

272
273
	be_emit_char(env, '$');

274
275
276
	switch(get_ia32_immop_type(node)) {
	case ia32_ImmConst:
		tv = get_ia32_Immop_tarval(node);
277
		be_emit_tarval(env, tv);
278
		return;
279
	case ia32_ImmSymConst:
280
		ent = get_ia32_Immop_symconst(node);
Michael Beck's avatar
Michael Beck committed
281
		set_entity_backend_marked(ent, 1);
282
		id = get_entity_ld_ident(ent);
283
		be_emit_ident(env, id);
284
		return;
285
286
	case ia32_ImmNone:
		break;
Christian Würdig's avatar
Christian Würdig committed
287
	}
Christian Würdig's avatar
Christian Würdig committed
288

289
290
291
	assert(0);
	be_emit_string(env, "BAD");
	return;
292
}
Christian Würdig's avatar
Christian Würdig committed
293

Matthias Braun's avatar
Matthias Braun committed
294
295
static
void ia32_emit_mode_suffix_mode(ia32_emit_env_t *env, const ir_mode *mode)
296
{
Matthias Braun's avatar
Matthias Braun committed
297
	be_emit_char(env, get_mode_suffix(mode));
Christian Würdig's avatar
Christian Würdig committed
298
299
}

Matthias Braun's avatar
Matthias Braun committed
300
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
301
302
{
	ir_mode *mode = get_ia32_ls_mode(node);
Matthias Braun's avatar
Matthias Braun committed
303
304
305
306
	if(mode == NULL)
		mode = mode_Iu;

	ia32_emit_mode_suffix_mode(env, mode);
307
308
}

309
310
311
312
313
314
315
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);
}

316
317
static
char get_xmm_mode_suffix(ir_mode *mode)
318
319
320
321
322
323
324
325
326
327
328
329
330
{
	assert(mode_is_float(mode));
	switch(get_mode_size_bits(mode)) {
	case 32:
		return 's';
	case 64:
		return 'd';
	default:
		assert(0);
	}
	return '%';
}

331
332
333
void ia32_emit_xmm_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
{
	ir_mode *mode = get_ia32_ls_mode(node);
334
	assert(mode != NULL);
Matthias Braun's avatar
Matthias Braun committed
335
336
	be_emit_char(env, 's');
	be_emit_char(env, get_xmm_mode_suffix(mode));
337
338
339
340
341
342
}

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
343
	be_emit_char(env, get_xmm_mode_suffix(mode));
344
345
}

346
347
348
349
350
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
351
		be_emit_char(env, 's');
352
	} else {
Matthias Braun's avatar
Matthias Braun committed
353
354
355
356
		be_emit_char(env, 'z');
	}
}

357
358
static
void ia32_emit_function_object(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
{
	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;
	}
}

378
379
static
void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
380
381
382
383
384
385
386
387
388
389
390
391
{
	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
392
393
394
	}
}

Matthias Braun's avatar
Matthias Braun committed
395

396
397
static
void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node);
Matthias Braun's avatar
Matthias Braun committed
398

Christian Würdig's avatar
Christian Würdig committed
399
400
401
/**
 * Emits registers and/or address mode of a binary operation.
 */
402
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
403
	int            right_pos;
404
	const ir_node *right_op = get_irn_n(node, 3);
Christian Würdig's avatar
Christian Würdig committed
405

406
407
408
409
410
411
	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
412
			break;
413
414
		} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
			ia32_emit_immediate(env, node);
415
			be_emit_cstring(env, ", ");
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
			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";
431
			}
Christian Würdig's avatar
Christian Würdig committed
432

433
434
435
436
437
438
439
440
			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)) {
441
442
			assert(!produces_result(node) &&
					"Source AM with Const must not produce result");
443
			ia32_emit_immediate(env, node);
444
445
446
447
448
449
450
451
452
			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);
453
		} else if (produces_result(node)) {
454
455
			ia32_emit_am(env, node);
			be_emit_cstring(env, ", ");
456
457
			ia32_emit_dest_register(env, node, 0);
		} else {
458
459
			ia32_emit_am(env, node);
			be_emit_cstring(env, ", ");
460
461
462
463
			ia32_emit_source_register(env, node, 2);
		}
		break;
	case ia32_AddrModeD:
464
		right_pos = get_irn_arity(node) >= 5 ? 3 : 2;
465
		right_op  = get_irn_n(node, right_pos);
466
467
468
469
470
471
472
473
474
475
		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 {
476
			const arch_register_t *in1 = get_in_reg(env, node, right_pos);
477
478
			ir_mode               *mode = get_ia32_ls_mode(node);
			const char            *in_name;
Christian Würdig's avatar
Christian Würdig committed
479

480
			in_name = ia32_get_reg_name_for_mode(env, mode, in1);
481

482
483
484
			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
485
			}
486
487
488
489
490
491
492
493
494

			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
495
	}
496
497
}

498
499
500
/**
 * Emits registers and/or address mode of a binary operation.
 */
501
502
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
503
		case ia32_Normal:
504
505
506
507
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				// should not happen...
				assert(0);
			} else {
508
509
510
511
				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];
512
513
				const arch_register_t *in;

514
515
				in  = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
				out = out ? out : in1;
516

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

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

548
	switch(get_ia32_op_type(node)) {
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
	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
565
566
567
568
	}
}

/**
569
 * Emits address mode.
Christian Würdig's avatar
Christian Würdig committed
570
 */
571
void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
572
573
574
575
576
577
	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
578

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

582
	/* emit offset */
583
584
585
	if (ent != NULL) {
		ident *id;

Michael Beck's avatar
Michael Beck committed
586
		set_entity_backend_marked(ent, 1);
587
		id = get_entity_ld_ident(ent);
588
		if (is_ia32_am_sc_sign(node))
Matthias Braun's avatar
Matthias Braun committed
589
590
			be_emit_char(env, '-');
		be_emit_ident(env, id);
Matthias Braun's avatar
Matthias Braun committed
591
592
593
594
595
596
597
598

		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
599
600
	}

601
	if(offs != 0) {
602
		if(ent != NULL) {
Matthias Braun's avatar
Matthias Braun committed
603
			be_emit_irprintf(env->emit, "%+d", offs);
604
		} else {
Matthias Braun's avatar
Matthias Braun committed
605
			be_emit_irprintf(env->emit, "%d", offs);
606
		}
607
	}
Christian Würdig's avatar
Christian Würdig committed
608

609
	if (has_base || has_index) {
Matthias Braun's avatar
Matthias Braun committed
610
		be_emit_char(env, '(');
Christian Würdig's avatar
Christian Würdig committed
611

612
		/* emit base */
613
		if (has_base) {
614
			ia32_emit_source_register(env, node, 0);
Christian Würdig's avatar
Christian Würdig committed
615
616
		}

617
		/* emit index + scale */
618
619
		if (has_index) {
			int scale;
Matthias Braun's avatar
Matthias Braun committed
620
			be_emit_char(env, ',');
621
			ia32_emit_source_register(env, node, 1);
622

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

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

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

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

/*
 * positive conditions for signed compares
 */
656
657
static
const struct cmp2conditon_t cmp2condition_s[] = {
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
	{ 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 */
674
675
676
677
678
};

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

/*
 * returns the condition code
 */
694
static
Matthias Braun's avatar
Matthias Braun committed
695
const char *get_cmp_suffix(pn_Cmp cmp_code)
696
{
697
698
	assert( (cmp2condition_s[cmp_code & 15].num) == (cmp_code & 15));
	assert( (cmp2condition_u[cmp_code & 7].num) == (cmp_code & 7));
699

700
701
702
703
704
	if((cmp_code & ia32_pn_Cmp_Unsigned)) {
		return cmp2condition_u[cmp_code & 7].name;
	} else {
		return cmp2condition_s[cmp_code & 15].name;
	}
705
706
}

707
708
void ia32_emit_cmp_suffix(ia32_emit_env_t *env, long pnc)
{
Matthias Braun's avatar
Matthias Braun committed
709
	be_emit_string(env, get_cmp_suffix(pnc));
710
711
712
}


713
714
715
/**
 * Returns the target block for a control flow node.
 */
716
717
static
ir_node *get_cfop_target_block(const ir_node *irn) {
718
719
720
	return get_irn_link(irn);
}

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

738
	ia32_emit_block_name(env, block);
Christian Würdig's avatar
Christian Würdig committed
739
}
740

741
742
/** Return the next block in Block schedule */
static ir_node *next_blk_sched(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
743
	return get_irn_link(block);
744
745
}

746
747
748
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
749
750
static
ir_node *get_proj(const ir_node *node, long proj) {
751
752
753
	const ir_edge_t *edge;
	ir_node         *src;

754
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
755

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

781
	/* get both Proj's */
782
	proj_true = get_proj(node, pn_Cond_true);
783
	assert(proj_true && "CondJmp without true Proj");
Christian Würdig's avatar
Christian Würdig committed
784

785
	proj_false = get_proj(node, pn_Cond_false);
786
787
	assert(proj_false && "CondJmp without false Proj");

788
	/* for now, the code works for scheduled and non-schedules blocks */
789
	block = get_nodes_block(node);
790
791

	/* we have a block schedule */
792
	next_block = next_blk_sched(block);
793

794
	if (get_cfop_target_block(proj_true) == next_block) {
795
		/* exchange both proj's so the second one can be omitted */
796
797
		const ir_node *t = proj_true;

798
799
800
801
		proj_true  = proj_false;
		proj_false = t;
		flipped    = 1;
		pnc        = get_negated_pnc(pnc, mode);
802
803
	}

804
805
	/* in case of unordered compare, check for parity */
	if (pnc & pn_Cmp_Uo) {
Matthias Braun's avatar
Matthias Braun committed
806
		be_emit_cstring(env, "\tjp ");
807
		ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
808
		be_emit_finish_line_gas(env, proj_true);
809
810
	}

Matthias Braun's avatar
Matthias Braun committed
811
	be_emit_cstring(env, "\tj");
812
	ia32_emit_cmp_suffix(env, pnc);
Matthias Braun's avatar
Matthias Braun committed
813
	be_emit_char(env, ' ');
814
	ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
815
	be_emit_finish_line_gas(env, proj_true);
Christian Würdig's avatar
Christian Würdig committed
816

817
	/* the second Proj might be a fallthrough */
818
	if (get_cfop_target_block(proj_false) != next_block) {
Matthias Braun's avatar
Matthias Braun committed
819
		be_emit_cstring(env, "\tjmp ");
820
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
821
		be_emit_finish_line_gas(env, proj_false);
822
	} else {
823
		be_emit_cstring(env, "\t/* fallthrough to ");
824
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
825
826
		be_emit_cstring(env, " */");
		be_emit_finish_line_gas(env, proj_false);
827
	}
Christian Würdig's avatar
Christian Würdig committed
828
829
830
}

/**
Christian Würdig's avatar
Christian Würdig committed
831
 * Emits code for conditional jump.
Christian Würdig's avatar
Christian Würdig committed
832
 */
833
834
static
void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
835
836
837
	be_emit_cstring(env, "\tcmp");
	ia32_emit_mode_suffix(env, node);
	be_emit_char(env, ' ');
838
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
839
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
840

841
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
842
843
}

Christian Würdig's avatar
Christian Würdig committed
844
845
846
/**
 * Emits code for conditional jump with two variables.
 */
847
848
static
void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
849
	CondJmp_emitter(env, node);
Christian Würdig's avatar
Christian Würdig committed
850
851
}

852
853
854
/**
 * Emits code for conditional test and jump.
 */
855
856
static
void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
857
858
859
860
	be_emit_cstring(env, "\ttest");
	ia32_emit_mode_suffix(env, node);
	be_emit_char(env, ' ');

861
862
863
	ia32_emit_binop(env, node);
	be_emit_finish_line_gas(env, node);

864
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
865
866
867
868
869
}

/**
 * Emits code for conditional test and jump with two variables.
 */
870
871
static
void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
872
	TestJmp_emitter(env, node);
873
874
}

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

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

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

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

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

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

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

934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
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);

951
	return attr->offset == 0 && attr->symconst == NULL;
952
953
}

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

960
	out = arch_get_irn_register(env->arch_env, node);
961
962
	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
963

Christian Würdig's avatar
Christian Würdig committed
964
965
	/* we have to emit the cmp first, because the destination register */
	/* could be one of the compare registers                           */
966
	if (is_ia32_CmpCMov(node)) {
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
		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);
		}
983
	} else 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
990
		ia32_emit_source_register(env, node, 0);
	} else {
991
992
		assert(0 && "unsupported CMov"