ia32_emitter.c 55.3 KB
Newer Older
1
/**
2
3
4
5
 * @file
 * @brief   This file implements the node emitter.
 * @author  Christian Wuerdig, Matthias Braun
 * @version $Id$
6
 */
Christian Würdig's avatar
Christian Würdig committed
7
#ifdef HAVE_CONFIG_H
8
#include "config.h"
Christian Würdig's avatar
Christian Würdig committed
9
10
#endif

Christian Würdig's avatar
Christian Würdig committed
11
12
#include <limits.h>

13
#include "xmalloc.h"
14
15
#include "tv.h"
#include "iredges.h"
Christian Würdig's avatar
Christian Würdig committed
16
17
18
19
#include "debug.h"
#include "irgwalk.h"
#include "irprintf.h"
#include "irop_t.h"
Christian Würdig's avatar
Christian Würdig committed
20
#include "irargs_t.h"
21
#include "irprog_t.h"
22
#include "iredges_t.h"
23
#include "execfreq.h"
24
#include "error.h"
Matthias Braun's avatar
Matthias Braun committed
25
#include "raw_bitset.h"
Christian Würdig's avatar
Christian Würdig committed
26

27
#include "../besched_t.h"
Christian Würdig's avatar
Christian Würdig committed
28
#include "../benode_t.h"
Michael Beck's avatar
Michael Beck committed
29
#include "../beabi.h"
30
#include "../be_dbgout.h"
Matthias Braun's avatar
Matthias Braun committed
31
32
#include "../beemitter.h"
#include "../begnuas.h"
Christian Würdig's avatar
Christian Würdig committed
33

34
#include "ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
35
#include "gen_ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
36
#include "gen_ia32_regalloc_if.h"
37
38
#include "ia32_nodes_attr.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
39
#include "ia32_map_regs.h"
Christian Würdig's avatar
Christian Würdig committed
40
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
41

42
43
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

44
#define BLOCK_PREFIX ".L"
Michael Beck's avatar
Michael Beck committed
45

Christian Würdig's avatar
Christian Würdig committed
46
47
48
#define SNPRINTF_BUF_LEN 128

/**
Christian Würdig's avatar
Christian Würdig committed
49
 * Returns the register at in position pos.
Christian Würdig's avatar
Christian Würdig committed
50
 */
51
52
53
54
55
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
56
57
58
59
60
61
62
63
64
	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
65
	reg = arch_get_irn_register(arch_env, op);
Christian Würdig's avatar
Christian Würdig committed
66

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

69
70
	/* 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
71
		const arch_register_req_t *req;
72
73

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

Matthias Braun's avatar
Matthias Braun committed
76
		if (arch_register_req_is(req, limited)) {
77
			/* in case of limited requirements: get the first allowed register */
Matthias Braun's avatar
Matthias Braun committed
78
79
			unsigned idx = rbitset_next(req->limited, 0, 1);
			reg = arch_register_for_index(req->cls, idx);
80
		} else {
81
			/* otherwise get first register in class */
Matthias Braun's avatar
Matthias Braun committed
82
			reg = arch_register_for_index(req->cls, 0);
83
84
		}
	}
85

Christian Würdig's avatar
Christian Würdig committed
86
87
88
89
90
91
	return reg;
}

/**
 * Returns the register at out position pos.
 */
92
93
94
95
96
97
98
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
99
100
101
102
103
104
105
106

	/* 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);
107
	} else if (is_ia32_irn(irn)) {
Christian Würdig's avatar
Christian Würdig committed
108
		reg = get_ia32_out_reg(irn, pos);
109
	} else {
Christian Würdig's avatar
Christian Würdig committed
110
111
112
113
114
115
116
117
118
119
120
121
122
		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
123
124
125
126
	return reg;
}

/**
127
 * Returns an ident for the given tarval tv.
Christian Würdig's avatar
Christian Würdig committed
128
 */
129
130
static
ident *get_ident_for_tv(tarval *tv) {
131
	char buf[256];
132
	tarval_snprintf(buf, sizeof(buf), tv);
133
134
	return new_id_from_str(buf);
}
135

136
137
138
/**
 * Determine the gnu assembler suffix that indicates a mode
 */
139
140
static
char get_mode_suffix(const ir_mode *mode) {
141
142
143
144
145
146
147
148
	if(mode_is_float(mode)) {
		switch(get_mode_size_bits(mode)) {
		case 32:
			return 's';
		case 64:
			return 'l';
		case 80:
			return 't';
149
		}
150
151
152
153
154
155
156
157
158
159
160
	} else {
		assert(mode_is_int(mode) || mode_is_reference(mode));
		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
161
		}
162
163
164
	}
	panic("Can't output mode_suffix for %+F\n", mode);
}
Christian Würdig's avatar
Christian Würdig committed
165

166
167
static
int produces_result(const ir_node *node) {
168
169
170
171
172
173
174
175
176
	return !(is_ia32_St(node) ||
		is_ia32_Store8Bit(node) ||
		is_ia32_CondJmp(node) ||
		is_ia32_xCondJmp(node) ||
		is_ia32_CmpSet(node) ||
		is_ia32_xCmpSet(node) ||
		is_ia32_SwitchJmp(node));
}

177
178
179
static
const char *ia32_get_reg_name_for_mode(ia32_emit_env_t *env, ir_mode *mode,
                                       const arch_register_t *reg) {
180
181
182
183
184
185
186
	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
187
	}
Christian Würdig's avatar
Christian Würdig committed
188
189
}

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

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

Matthias Braun's avatar
Matthias Braun committed
211
212
213
214
215
216
217
218
219
220
// we have no C++ and can't define an implicit ia32_emit_env_t* cast to
// be_emit_env_t* so we cheat a bit...
#define be_emit_char(env,c)             be_emit_char(env->emit,c)
#define be_emit_string(env,s)           be_emit_string(env->emit,s)
#undef be_emit_cstring
#define be_emit_cstring(env,x)          { be_emit_string_len(env->emit, x, sizeof(x)-1); }
#define be_emit_ident(env,i)            be_emit_ident(env->emit,i)
#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
221

222
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
223
{
224
	const arch_register_t *reg = get_in_reg(env, node, pos);
225
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
226

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

Matthias Braun's avatar
Matthias Braun committed
229
230
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
231
232
233
}

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

Matthias Braun's avatar
Matthias Braun committed
237
238
	be_emit_char(env, '%');
	be_emit_string(env, reg_name);
Christian Würdig's avatar
Christian Würdig committed
239
240
}

241
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
242
{
243
	ia32_attr_t *attr = get_ia32_attr(node);
244

Matthias Braun's avatar
Matthias Braun committed
245
	assert(pos < 3);
Matthias Braun's avatar
Matthias Braun committed
246
247
	be_emit_char(env, '%');
	be_emit_string(env, attr->x87[pos]->name);
248
}
Christian Würdig's avatar
Christian Würdig committed
249

250
251
252
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node)
{
	tarval *tv;
253
	ir_entity *ent;
254
	ident *id;
Christian Würdig's avatar
Christian Würdig committed
255

256
257
258
259
260
261
	switch(get_ia32_immop_type(node)) {
	case ia32_ImmConst:
		tv = get_ia32_Immop_tarval(node);
		id = get_ident_for_tv(tv);
		break;
	case ia32_ImmSymConst:
262
263
264
		ent = get_ia32_Immop_symconst(node);
		mark_entity_visited(ent);
		id = get_entity_ld_ident(ent);
265
266
267
		break;
	default:
		assert(0);
Matthias Braun's avatar
Matthias Braun committed
268
		be_emit_string(env, "BAD");
269
		return;
Christian Würdig's avatar
Christian Würdig committed
270
	}
Christian Würdig's avatar
Christian Würdig committed
271

Matthias Braun's avatar
Matthias Braun committed
272
	be_emit_ident(env, id);
273
}
Christian Würdig's avatar
Christian Würdig committed
274

275
276
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_mode *mode)
{
Matthias Braun's avatar
Matthias Braun committed
277
	be_emit_char(env, get_mode_suffix(mode));
Christian Würdig's avatar
Christian Würdig committed
278
279
}

280
281
282
283
284
285
286
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(env, mode);
}

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

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

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
314
	be_emit_char(env, get_xmm_mode_suffix(mode));
315
316
}

317
318
319
320
321
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
322
		be_emit_char(env, 's');
323
	} else {
Matthias Braun's avatar
Matthias Braun committed
324
325
326
327
		be_emit_char(env, 'z');
	}
}

328
329
static
void ia32_emit_function_object(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
{
	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;
	}
}

349
350
static
void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
Matthias Braun's avatar
Matthias Braun committed
351
352
353
354
355
356
357
358
359
360
361
362
{
	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
363
364
365
	}
}

Matthias Braun's avatar
Matthias Braun committed
366
367


Christian Würdig's avatar
Christian Würdig committed
368
369
370
/**
 * Emits registers and/or address mode of a binary operation.
 */
371
372
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
Christian Würdig's avatar
Christian Würdig committed
373
		case ia32_Normal:
374
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
Matthias Braun's avatar
Matthias Braun committed
375
				be_emit_char(env, '$');
376
				ia32_emit_immediate(env, node);
Matthias Braun's avatar
Matthias Braun committed
377
				be_emit_cstring(env, ", ");
378
379
				ia32_emit_source_register(env, node, 2);
			} else {
380
381
382
				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;
Christian Würdig's avatar
Christian Würdig committed
383
				const arch_register_t *in;
Christian Würdig's avatar
Christian Würdig committed
384
				const char            *in_name;
Christian Würdig's avatar
Christian Würdig committed
385

Christian Würdig's avatar
Christian Würdig committed
386
387
388
				in      = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
				out     = out ? out : in1;
				in_name = arch_register_get_name(in);
Christian Würdig's avatar
Christian Würdig committed
389

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

Matthias Braun's avatar
Matthias Braun committed
395
396
397
398
				be_emit_char(env, '%');
				be_emit_string(env, in_name);
				be_emit_cstring(env, ", %");
				be_emit_string(env, arch_register_get_name(out));
Christian Würdig's avatar
Christian Würdig committed
399
400
401
			}
			break;
		case ia32_AddrModeS:
402
403
404
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				assert(!produces_result(node) && "Source AM with Const must not produce result");
				ia32_emit_am(env, node);
Matthias Braun's avatar
Matthias Braun committed
405
				be_emit_cstring(env, ", $");
406
407
408
				ia32_emit_immediate(env, node);
			} else if (produces_result(node)) {
				ia32_emit_am(env, node);
Matthias Braun's avatar
Matthias Braun committed
409
				be_emit_cstring(env, ", ");
410
411
412
				ia32_emit_dest_register(env, node, 0);
			} else {
				ia32_emit_am(env, node);
Matthias Braun's avatar
Matthias Braun committed
413
				be_emit_cstring(env, ", ");
414
				ia32_emit_source_register(env, node, 2);
415
			}
Christian Würdig's avatar
Christian Würdig committed
416
417
			break;
		case ia32_AddrModeD:
418
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
Matthias Braun's avatar
Matthias Braun committed
419
				be_emit_char(env, '$');
420
				ia32_emit_immediate(env, node);
Matthias Braun's avatar
Matthias Braun committed
421
				be_emit_cstring(env, ", ");
422
423
				ia32_emit_am(env, node);
			} else {
424
425
				const arch_register_t *in1 = get_in_reg(env, node,
				                                        get_irn_arity(node) == 5 ? 3 : 2);
426
				ir_mode               *mode = get_ia32_ls_mode(node);
Christian Würdig's avatar
Christian Würdig committed
427
				const char            *in_name;
Christian Würdig's avatar
Christian Würdig committed
428
429
430

				in_name = ia32_get_reg_name_for_mode(env, mode, in1);

431
				if (is_ia32_emit_cl(node)) {
Christian Würdig's avatar
Christian Würdig committed
432
433
434
					assert(REGS_ARE_EQUAL(&ia32_gp_regs[REG_ECX], in1) && "shift operation needs ecx");
					in_name = "cl";
				}
435

Matthias Braun's avatar
Matthias Braun committed
436
437
438
				be_emit_char(env, '%');
				be_emit_string(env, in_name);
				be_emit_cstring(env, ", ");
439
				ia32_emit_am(env, node);
Christian Würdig's avatar
Christian Würdig committed
440
441
442
443
444
			}
			break;
		default:
			assert(0 && "unsupported op type");
	}
445
446
}

447
448
449
/**
 * Emits registers and/or address mode of a binary operation.
 */
450
451
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
452
		case ia32_Normal:
453
454
455
456
457
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				// should not happen...
				assert(0);
			} else {
				ia32_attr_t *attr = get_ia32_attr(node);
458
459
460
461
462
				const arch_register_t *in1 = attr->x87[0];
				const arch_register_t *in2 = attr->x87[1];
				const arch_register_t *out = attr->x87[2];
				const arch_register_t *in;

463
464
				in  = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
				out = out ? out : in1;
465

Matthias Braun's avatar
Matthias Braun committed
466
467
468
469
				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));
470
471
472
473
			}
			break;
		case ia32_AddrModeS:
		case ia32_AddrModeD:
474
			ia32_emit_am(env, node);
475
476
477
478
479
480
			break;
		default:
			assert(0 && "unsupported op type");
	}
}

Christian Würdig's avatar
Christian Würdig committed
481
482
483
/**
 * Emits registers and/or address mode of a unary operation.
 */
484
485
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
Christian Würdig's avatar
Christian Würdig committed
486
		case ia32_Normal:
487
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
Matthias Braun's avatar
Matthias Braun committed
488
				be_emit_char(env, '$');
489
490
				ia32_emit_immediate(env, node);
			} else {
Matthias Braun's avatar
Matthias Braun committed
491
				if (is_ia32_Mul(node) || is_ia32_IMul1OP(node)) {
492
					ia32_emit_source_register(env, node, 3);
Matthias Braun's avatar
Matthias Braun committed
493
494
				} else if(is_ia32_IDiv(node) || is_ia32_Div(node)) {
					ia32_emit_source_register(env, node, 4);
495
496
497
498
				} else if(is_ia32_Push(node)) {
					ia32_emit_source_register(env, node, 2);
				} else if(is_ia32_Pop(node)) {
					ia32_emit_dest_register(env, node, 1);
499
				} else {
500
					ia32_emit_dest_register(env, node, 0);
501
				}
502
			}
Christian Würdig's avatar
Christian Würdig committed
503
			break;
504
		case ia32_AddrModeS:
505
506
		case ia32_AddrModeD:
			ia32_emit_am(env, node);
507
			break;
Christian Würdig's avatar
Christian Würdig committed
508
509
510
511
512
513
		default:
			assert(0 && "unsupported op type");
	}
}

/**
514
 * Emits address mode.
Christian Würdig's avatar
Christian Würdig committed
515
 */
516
517
void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
	ia32_am_flavour_t am_flav = get_ia32_am_flavour(node);
518
	ir_entity *ent = get_ia32_am_sc(node);
519
	int offs = get_ia32_am_offs_int(node);
Christian Würdig's avatar
Christian Würdig committed
520

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

524
	/* emit offset */
525
526
527
528
529
	if (ent != NULL) {
		ident *id;

		mark_entity_visited(ent);
		id = get_entity_ld_ident(ent);
530
		if (is_ia32_am_sc_sign(node))
Matthias Braun's avatar
Matthias Braun committed
531
532
			be_emit_char(env, '-');
		be_emit_ident(env, id);
Christian Würdig's avatar
Christian Würdig committed
533
534
	}

535
	if(offs != 0) {
536
		if(ent != NULL) {
Matthias Braun's avatar
Matthias Braun committed
537
			be_emit_irprintf(env->emit, "%+d", offs);
538
		} else {
Matthias Braun's avatar
Matthias Braun committed
539
			be_emit_irprintf(env->emit, "%d", offs);
540
		}
541
	}
Christian Würdig's avatar
Christian Würdig committed
542

543
	if (am_flav & (ia32_B | ia32_I)) {
Matthias Braun's avatar
Matthias Braun committed
544
		be_emit_char(env, '(');
Christian Würdig's avatar
Christian Würdig committed
545

546
547
548
		/* emit base */
		if (am_flav & ia32_B) {
			ia32_emit_source_register(env, node, 0);
Christian Würdig's avatar
Christian Würdig committed
549
550
		}

551
552
		/* emit index + scale */
		if (am_flav & ia32_I) {
Matthias Braun's avatar
Matthias Braun committed
553
			be_emit_char(env, ',');
554
			ia32_emit_source_register(env, node, 1);
555

556
			if (am_flav & ia32_S) {
Matthias Braun's avatar
Matthias Braun committed
557
				be_emit_irprintf(env->emit, ",%d", 1 << get_ia32_am_scale(node));
558
559
			}
		}
Matthias Braun's avatar
Matthias Braun committed
560
		be_emit_char(env, ')');
Christian Würdig's avatar
Christian Würdig committed
561
	}
562
}
Christian Würdig's avatar
Christian Würdig committed
563

Christian Würdig's avatar
Christian Würdig committed
564
565
566
567
568
569
570
571
572
573
/*************************************************
 *                 _ _                         _
 *                (_) |                       | |
 *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
 *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
 * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
 *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
 *
 *************************************************/

Christian Würdig's avatar
Christian Würdig committed
574
#undef IA32_DO_EMIT
Christian Würdig's avatar
Christian Würdig committed
575
#define IA32_DO_EMIT(irn) ia32_fprintf_format(F, irn, cmd_buf, cmnt_buf)
Christian Würdig's avatar
Christian Würdig committed
576

577
578
579
580
/*
 * coding of conditions
 */
struct cmp2conditon_t {
Christian Würdig's avatar
Christian Würdig committed
581
582
	const char *name;
	pn_Cmp      num;
583
584
585
586
587
};

/*
 * positive conditions for signed compares
 */
588
589
static
const struct cmp2conditon_t cmp2condition_s[] = {
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
	{ 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 */
606
607
608
609
610
};

/*
 * positive conditions for unsigned compares
 */
611
612
static
const struct cmp2conditon_t cmp2condition_u[] = {
Christian Würdig's avatar
Christian Würdig committed
613
614
615
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "b",               pn_Cmp_Lt },     /* < */
Christian Würdig's avatar
Christian Würdig committed
616
	{ "be",              pn_Cmp_Le },     /* <= */
Christian Würdig's avatar
Christian Würdig committed
617
618
619
620
	{ "a",               pn_Cmp_Gt },     /* > */
	{ "ae",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
	{ NULL,              pn_Cmp_True },   /* always true */
621
622
623
624
625
};

/*
 * returns the condition code
 */
626
627
static
const char *get_cmp_suffix(int cmp_code)
628
{
629
630
	assert( (cmp2condition_s[cmp_code & 15].num) == (cmp_code & 15));
	assert( (cmp2condition_u[cmp_code & 7].num) == (cmp_code & 7));
631

632
633
634
635
636
	if((cmp_code & ia32_pn_Cmp_Unsigned)) {
		return cmp2condition_u[cmp_code & 7].name;
	} else {
		return cmp2condition_s[cmp_code & 15].name;
	}
637
638
}

639
640
void ia32_emit_cmp_suffix(ia32_emit_env_t *env, long pnc)
{
Matthias Braun's avatar
Matthias Braun committed
641
	be_emit_string(env, get_cmp_suffix(pnc));
642
643
644
}


645
646
647
/**
 * Returns the target block for a control flow node.
 */
648
649
static
ir_node *get_cfop_target_block(const ir_node *irn) {
650
651
652
	return get_irn_link(irn);
}

Christian Würdig's avatar
Christian Würdig committed
653
654
655
/**
 * Returns the target label for a control flow node.
 */
656
657
void ia32_emit_cfop_target(ia32_emit_env_t * env, const ir_node *node) {
	ir_node *block = get_cfop_target_block(node);
658

Matthias Braun's avatar
Matthias Braun committed
659
660
	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
661
}
662

663
664
/** Return the next block in Block schedule */
static ir_node *next_blk_sched(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
665
	return get_irn_link(block);
666
667
}

668
669
670
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
671
672
static
ir_node *get_proj(const ir_node *node, long proj) {
673
674
675
	const ir_edge_t *edge;
	ir_node         *src;

676
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
677

678
	foreach_out_edge(node, edge) {
679
680
681
682
683
684
685
686
687
688
689
690
		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
691
692
693
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
694
695
696
static
void finish_CondJmp(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode,
                    long pnc) {
697
698
699
700
701
	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
702

703
	/* get both Proj's */
704
	proj_true = get_proj(node, pn_Cond_true);
705
	assert(proj_true && "CondJmp without true Proj");
Christian Würdig's avatar
Christian Würdig committed
706

707
	proj_false = get_proj(node, pn_Cond_false);
708
709
	assert(proj_false && "CondJmp without false Proj");

710
	/* for now, the code works for scheduled and non-schedules blocks */
711
	block = get_nodes_block(node);
712
713

	/* we have a block schedule */
714
	next_block = next_blk_sched(block);
715

716
	if (get_cfop_target_block(proj_true) == next_block) {
717
		/* exchange both proj's so the second one can be omitted */
718
719
		const ir_node *t = proj_true;

720
721
722
723
		proj_true  = proj_false;
		proj_false = t;
		flipped    = 1;
		pnc        = get_negated_pnc(pnc, mode);
724
725
	}

726
727
	/* in case of unordered compare, check for parity */
	if (pnc & pn_Cmp_Uo) {
Matthias Braun's avatar
Matthias Braun committed
728
		be_emit_cstring(env, "\tjp ");
729
		ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
730
		be_emit_finish_line_gas(env, proj_true);
731
732
	}

Matthias Braun's avatar
Matthias Braun committed
733
	be_emit_cstring(env, "\tj");
734
	ia32_emit_cmp_suffix(env, pnc);
Matthias Braun's avatar
Matthias Braun committed
735
	be_emit_char(env, ' ');
736
	ia32_emit_cfop_target(env, proj_true);
Matthias Braun's avatar
Matthias Braun committed
737
	be_emit_finish_line_gas(env, proj_true);
Christian Würdig's avatar
Christian Würdig committed
738

739
	/* the second Proj might be a fallthrough */
740
	if (get_cfop_target_block(proj_false) != next_block) {
Matthias Braun's avatar
Matthias Braun committed
741
		be_emit_cstring(env, "\tjmp ");
742
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
743
		be_emit_finish_line_gas(env, proj_false);
744
	} else {
Matthias Braun's avatar
Matthias Braun committed
745
		be_emit_cstring(env, "\t/* fallthrough to");
746
		ia32_emit_cfop_target(env, proj_false);
Matthias Braun's avatar
Matthias Braun committed
747
748
		be_emit_cstring(env, " */");
		be_emit_finish_line_gas(env, proj_false);
749
	}
Christian Würdig's avatar
Christian Würdig committed
750
751
752
}

/**
Christian Würdig's avatar
Christian Würdig committed
753
 * Emits code for conditional jump.
Christian Würdig's avatar
Christian Würdig committed
754
 */
755
756
static
void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
757
	be_emit_cstring(env, "\tcmp ");
758
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
759
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
760

761
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
762
763
}

Christian Würdig's avatar
Christian Würdig committed
764
765
766
/**
 * Emits code for conditional jump with two variables.
 */
767
768
static
void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
769
	CondJmp_emitter(env, node);
Christian Würdig's avatar
Christian Würdig committed
770
771
}

772
773
774
/**
 * Emits code for conditional test and jump.
 */
775
776
static
void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
777
	if(is_ia32_ImmSymConst(node) || is_ia32_ImmConst(node)) {
Matthias Braun's avatar
Matthias Braun committed
778
		be_emit_cstring(env, "\ttest $");
779
		ia32_emit_immediate(env, node);
Matthias Braun's avatar
Matthias Braun committed
780
		be_emit_cstring(env, ", ");
781
		ia32_emit_source_register(env, node, 0);
Matthias Braun's avatar
Matthias Braun committed
782
		be_emit_finish_line_gas(env, node);
783
	} else {
Matthias Braun's avatar
Matthias Braun committed
784
		be_emit_cstring(env, "\ttest ");
785
		ia32_emit_source_register(env, node, 1);
Matthias Braun's avatar
Matthias Braun committed
786
		be_emit_cstring(env, ", ");
787
		ia32_emit_source_register(env, node, 0);
Matthias Braun's avatar
Matthias Braun committed
788
		be_emit_finish_line_gas(env, node);
789
790
	}
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
791
792
793
794
795
}

/**
 * Emits code for conditional test and jump with two variables.
 */
796
797
static
void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
798
	TestJmp_emitter(env, node);
799
800
}

801
802
static
void emit_ia32_CJmp(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
803
804
	be_emit_cstring(env, "/* omitted redundant test */");
	be_emit_finish_line_gas(env, node);
805

806
	finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
807
}
808

809
810
static
void emit_ia32_CJmpAM(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
811
812
	be_emit_cstring(env, "/* omitted redundant test/cmp */");
	be_emit_finish_line_gas(env, node);
813

814
	finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
815
}
Christian Würdig's avatar
Christian Würdig committed
816

Christian Würdig's avatar
Christian Würdig committed
817
818
819
/**
 * Emits code for conditional SSE floating point jump with two variables.
 */
820
821
static
void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
822
	be_emit_cstring(env, "\tucomi");
Matthias Braun's avatar
Matthias Braun committed
823
	ia32_emit_xmm_mode_suffix(env, node);
Matthias Braun's avatar
Matthias Braun committed
824
	be_emit_char(env, ' ');
825
	ia32_emit_binop(env, node);
Matthias Braun's avatar
Matthias Braun committed
826
	be_emit_finish_line_gas(env, node);
Christian Würdig's avatar
Christian Würdig committed
827

828
	finish_CondJmp(env, node, mode_F, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
829
830
}

Michael Beck's avatar
Michael Beck committed
831
832
833
/**
 * Emits code for conditional x87 floating point jump with two variables.
 */
834
835
static
void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
836
	ia32_attr_t *attr = get_ia32_attr(node);
Michael Beck's avatar
Michael Beck committed
837
	const char *reg = attr->x87[1]->name;
838
	long pnc = get_ia32_pncode(node);
Michael Beck's avatar
Michael Beck committed
839

840
	switch (get_ia32_irn_opcode(node)) {
Michael Beck's avatar
Michael Beck committed
841
	case iro_ia32_fcomrJmp:
842
		pnc = get_inversed_pnc(pnc);
843
		reg = attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
844
845
	case iro_ia32_fcomJmp:
	default:
Matthias Braun's avatar
Matthias Braun committed
846
		be_emit_cstring(env, "\tfucom ");
Michael Beck's avatar
Michael Beck committed
847
848
		break;
	case iro_ia32_fcomrpJmp:
849
		pnc = get_inversed_pnc(pnc);
850
		reg = attr->x87[0]->name;
Michael Beck's avatar
Michael Beck committed
851
	case iro_ia32_fcompJmp:
Matthias Braun's avatar
Matthias Braun committed
852
		be_emit_cstring(env, "\tfucomp ");
Michael Beck's avatar
Michael Beck committed
853
854
		break;
	case iro_ia32_fcomrppJmp:
855
		pnc = get_inversed_pnc(pnc);
Michael Beck's avatar
Michael Beck committed
856
	case iro_ia32_fcomppJmp:
Matthias Braun's avatar
Matthias Braun committed
857
		be_emit_cstring(env, "\tfucompp ");
Michael Beck's avatar
Michael Beck committed
858
859
860
861
		reg = "";
		break;
	}

862
	if(reg[0] != '\0') {
Matthias Braun's avatar
Matthias Braun committed
863
864
		be_emit_char(env, '%');
		be_emit_string(env, reg);
865
	}
Matthias Braun's avatar
Matthias Braun committed
866
	be_emit_finish_line_gas(env, node);
Michael Beck's avatar
Michael Beck committed
867

Matthias Braun's avatar
Matthias Braun committed
868
869
870
871
	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
872

873
	finish_CondJmp(env, node, mode_E, pnc);
Michael Beck's avatar
Michael Beck committed
874
875
}

876
877
static
void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
878
879
	long pnc = get_ia32_pncode(node);
	int is_PsiCondCMov = is_ia32_PsiCondCMov(node);
Matthias Braun's avatar
Matthias Braun committed
880
881
	int idx_left  = 2 - is_PsiCondCMov;
	int idx_right = 3 - is_PsiCondCMov;
Christian Würdig's avatar
Christian Würdig committed
882
883
	const arch_register_t *in1, *in2, *out;

884
885
886
	out = arch_get_irn_register(env->arch_env, node);
	in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, idx_left));
	in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, idx_right));
Christian Würdig's avatar
Christian Würdig committed
887

Christian Würdig's avatar
Christian Würdig committed
888
889
	/* we have to emit the cmp first, because the destination register */
	/* could be one of the compare registers                           */
890
	if (is_ia32_CmpCMov(node)) {
Matthias Braun's avatar
Matthias Braun committed
891
		be_emit_cstring(env, "\tcmp ");
892
		ia32_emit_source_register(env, node, 1);
Matthias Braun's avatar
Matthias Braun committed
893
		be_emit_cstring(env, ", ");
894
895
		ia32_emit_source_register(env, node, 0);
	} else if (is_ia32_xCmpCMov(node)) {
Matthias Braun's avatar
Matthias Braun committed
896
		be_emit_cstring(env, "\tucomis");
897
		ia32_emit_mode_suffix(env, get_irn_mode(node));
Matthias Braun's avatar
Matthias Braun committed
898
		be_emit_char(env, ' ');
899
		ia32_emit_source_register(env, node, 1);
Matthias Braun's avatar
Matthias Braun committed
900
		be_emit_cstring(env, ", ");
901
902
		ia32_emit_source_register(env, node, 0);
	} else if (is_PsiCondCMov) {
903
		/* omit compare because flags are already set by And/Or */
Matthias Braun's avatar
Matthias Braun committed
904
		be_emit_cstring(env, "\ttest ");