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

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

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

25
#include "../besched_t.h"
Christian Würdig's avatar
Christian Würdig committed
26
#include "../benode_t.h"
Michael Beck's avatar
Michael Beck committed
27
#include "../beabi.h"
28
#include "../be_dbgout.h"
Christian Würdig's avatar
Christian Würdig committed
29

30
#include "ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
31
#include "gen_ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
32
#include "gen_ia32_regalloc_if.h"
33
34
#include "ia32_nodes_attr.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
35
#include "ia32_map_regs.h"
Christian Würdig's avatar
Christian Würdig committed
36
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
37

38
#define BLOCK_PREFIX ".L"
Michael Beck's avatar
Michael Beck committed
39

Christian Würdig's avatar
Christian Würdig committed
40
41
#define SNPRINTF_BUF_LEN 128

42
/* global arch_env for lc_printf functions */
Christian Würdig's avatar
Christian Würdig committed
43
static const arch_env_t *arch_env = NULL;
44

Michael Beck's avatar
Michael Beck committed
45
46
47
48
49
50
51
52
/** by default, we generate assembler code for the Linux gas */
asm_flavour_t asm_flavour = ASM_LINUX_GAS;

/**
 * Switch to a new section
 */
void ia32_switch_section(FILE *F, section_t sec) {
	static section_t curr_sec = NO_SECTION;
53
	static const char *text[ASM_MAX][SECTION_MAX] = {
Michael Beck's avatar
Michael Beck committed
54
		{
Michael Beck's avatar
Michael Beck committed
55
56
57
			".section\t.text",
			".section\t.data",
			".section\t.rodata",
58
			".section\t.bss",
Christian Würdig's avatar
Christian Würdig committed
59
60
			".section\t.tbss,\"awT\",@nobits",
			".section\t.ctors,\"aw\",@progbits"
Michael Beck's avatar
Michael Beck committed
61
62
		},
		{
Michael Beck's avatar
Michael Beck committed
63
64
65
			".section\t.text",
			".section\t.data",
			".section .rdata,\"dr\"",
66
			".section\t.bss",
Christian Würdig's avatar
Christian Würdig committed
67
68
			".section\t.tbss,\"awT\",@nobits",
			".section\t.ctors,\"aw\",@progbits"
Michael Beck's avatar
Michael Beck committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
		}
	};

	if (curr_sec == sec)
		return;

	curr_sec = sec;
	switch (sec) {

	case NO_SECTION:
		break;

	case SECTION_TEXT:
	case SECTION_DATA:
	case SECTION_RODATA:
	case SECTION_COMMON:
Michael Beck's avatar
Michael Beck committed
85
	case SECTION_TLS:
Christian Würdig's avatar
Christian Würdig committed
86
	case SECTION_CTOR:
Michael Beck's avatar
Michael Beck committed
87
		fprintf(F, "\t%s\n", text[asm_flavour][sec]);
88
89
90
91
		break;

	default:
		break;
Michael Beck's avatar
Michael Beck committed
92
93
94
95
96
97
98
99
100
101
102
103
	}
}

static void ia32_dump_function_object(FILE *F, const char *name)
{
	switch (asm_flavour) {
	case ASM_LINUX_GAS:
		fprintf(F, "\t.type\t%s, @function\n", name);
		break;
	case ASM_MINGW_GAS:
		fprintf(F, "\t.def\t%s;\t.scl\t2;\t.type\t32;\t.endef\n", name);
		break;
104
105
	default:
		break;
Michael Beck's avatar
Michael Beck committed
106
107
108
109
110
111
112
113
114
	}
}

static void ia32_dump_function_size(FILE *F, const char *name)
{
	switch (asm_flavour) {
	case ASM_LINUX_GAS:
		fprintf(F, "\t.size\t%s, .-%s\n", name, name);
		break;
115
116
	default:
		break;
Michael Beck's avatar
Michael Beck committed
117
118
119
	}
}

Christian Würdig's avatar
Christian Würdig committed
120
/**
Christian Würdig's avatar
Christian Würdig committed
121
 * Returns the register at in position pos.
Christian Würdig's avatar
Christian Würdig committed
122
 */
Christian Würdig's avatar
Christian Würdig committed
123
static const arch_register_t *get_in_reg(const ir_node *irn, int pos) {
Christian Würdig's avatar
Christian Würdig committed
124
125
126
127
128
129
130
131
132
	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
133
	reg = arch_get_irn_register(arch_env, op);
Christian Würdig's avatar
Christian Würdig committed
134

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

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
	/* in case of a joker register: just return a valid register */
	if (arch_register_type_is(reg, joker)) {
		arch_register_req_t       req;
		const arch_register_req_t *p_req;

		/* ask for the requirements */
		p_req = arch_get_register_req(arch_env, &req, irn, pos);

		if (arch_register_req_is(p_req, limited)) {
			/* in case of limited requirements: get the first allowed register */

			bitset_t *bs = bitset_alloca(arch_register_class_n_regs(p_req->cls));
			int      idx;

			p_req->limited(p_req->limited_env, bs);
			idx = bitset_next_set(bs, 0);
			reg = arch_register_for_index(p_req->cls, idx);
154
		} else {
155
156
157
158
			/* otherwise get first register in class */
			reg = arch_register_for_index(p_req->cls, 0);
		}
	}
159

Christian Würdig's avatar
Christian Würdig committed
160
161
162
163
164
165
	return reg;
}

/**
 * Returns the register at out position pos.
 */
Christian Würdig's avatar
Christian Würdig committed
166
static const arch_register_t *get_out_reg(const ir_node *irn, int pos) {
Christian Würdig's avatar
Christian Würdig committed
167
168
169
170
171
172
173
174
175
176
	ir_node                *proj;
	const arch_register_t  *reg = NULL;

	/* 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);
177
	} else if (is_ia32_irn(irn)) {
Christian Würdig's avatar
Christian Würdig committed
178
		reg = get_ia32_out_reg(irn, pos);
179
	} else {
Christian Würdig's avatar
Christian Würdig committed
180
181
182
183
184
185
186
187
188
189
190
191
192
		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
193
194
195
196
	return reg;
}

/**
197
 * Returns an ident for the given tarval tv.
Christian Würdig's avatar
Christian Würdig committed
198
 */
199
200
201
202
203
204
static ident *get_ident_for_tv(tarval *tv) {
	char buf[256];
	int len = tarval_snprintf(buf, sizeof(buf), tv);
	assert(len);
	return new_id_from_str(buf);
}
205

206
207
208
209
210
211
212
213
214
215
216
217
/**
 * Determine the gnu assembler suffix that indicates a mode
 */
static char get_mode_suffix(const ir_mode *mode) {
	if(mode_is_float(mode)) {
		switch(get_mode_size_bits(mode)) {
		case 32:
			return 's';
		case 64:
			return 'l';
		case 80:
			return 't';
218
		}
219
220
221
222
223
224
225
226
227
228
229
	} 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
230
		}
231
232
233
	}
	panic("Can't output mode_suffix for %+F\n", mode);
}
Christian Würdig's avatar
Christian Würdig committed
234

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
static int produces_result(const ir_node *node) {
	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));
}

static const char *ia32_get_reg_name_for_mode(ia32_emit_env_t *env, ir_mode *mode, const arch_register_t *reg) {
	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
253
	}
Christian Würdig's avatar
Christian Würdig committed
254
255
}

256
#if 0
Christian Würdig's avatar
Christian Würdig committed
257
/**
258
 * Determines the SSE suffix depending on the mode.
Christian Würdig's avatar
Christian Würdig committed
259
 */
260
static int ia32_print_mode_suffix(lc_appendable_t *app,
Christian Würdig's avatar
Christian Würdig committed
261
262
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
{
263
264
	ir_node *irn  = arg->v_ptr;
	ir_mode *mode = get_ia32_ls_mode(irn);
Christian Würdig's avatar
Christian Würdig committed
265

266
267
268
269
270
	if (mode_is_float(mode)) {
		return lc_appendable_chadd(app, get_mode_size_bits(mode) == 32 ? 's' : 'd');
	} else {
		if(get_mode_size_bits(mode) == 32)
			return 0;
Christian Würdig's avatar
Christian Würdig committed
271

272
273
274
275
		if(mode_is_signed(mode))
			lc_appendable_chadd(app, 's');
		else
			lc_appendable_chadd(app, 'z');
Christian Würdig's avatar
Christian Würdig committed
276

277
278
279
		lc_appendable_chadd(app, get_mode_suffix(mode));
		return 2;
	}
280
}
281
#endif
282

Michael Beck's avatar
Michael Beck committed
283
/**
284
 * Add a number to a prefix. This number will not be used a second time.
Michael Beck's avatar
Michael Beck committed
285
 */
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
static char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
	static unsigned long id = 0;
	snprintf(buf, buflen, "%s%lu", prefix, ++id);
	return buf;
}

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

void ia32_emit_ident(ia32_emit_env_t *env, ident *id)
Michael Beck's avatar
Michael Beck committed
304
{
305
306
	size_t len = get_id_strlen(id);
	const char* str = get_id_str(id);
Michael Beck's avatar
Michael Beck committed
307

308
309
	ia32_emit_string_len(env, str, len);
}
Michael Beck's avatar
Michael Beck committed
310

311
312
313
314
void ia32_emit_irprintf(ia32_emit_env_t *env, const char *fmt, ...)
{
	char buf[128];
	va_list ap;
315

316
317
318
	va_start(ap, fmt);
	ir_vsnprintf(buf, sizeof(buf), fmt, ap);
	va_end(ap);
319

320
	ia32_emit_string(env, buf);
Michael Beck's avatar
Michael Beck committed
321
322
}

323
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
324
{
325
326
	const arch_register_t *reg = get_in_reg(node, pos);
	const char *reg_name = arch_register_get_name(reg);
Christian Würdig's avatar
Christian Würdig committed
327

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

330
331
332
333
334
335
336
	ia32_emit_char(env, '%');
	ia32_emit_string(env, reg_name);
}

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

338
339
	ia32_emit_char(env, '%');
	ia32_emit_string(env, reg_name);
Christian Würdig's avatar
Christian Würdig committed
340
341
}

342
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
343
{
344
	ia32_attr_t *attr = get_ia32_attr(node);
345

Matthias Braun's avatar
Matthias Braun committed
346
	assert(pos < 3);
347
348
349
	ia32_emit_char(env, '%');
	ia32_emit_string(env, attr->x87[pos]->name);
}
Christian Würdig's avatar
Christian Würdig committed
350

351
352
353
354
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node)
{
	tarval *tv;
	ident *id;
Christian Würdig's avatar
Christian Würdig committed
355

356
357
358
359
360
361
362
363
364
365
366
367
	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:
		id = get_ia32_Immop_symconst(node);
		break;
	default:
		assert(0);
		ia32_emit_string(env, "BAD");
		return;
Christian Würdig's avatar
Christian Würdig committed
368
	}
Christian Würdig's avatar
Christian Würdig committed
369

370
371
	ia32_emit_ident(env, id);
}
Christian Würdig's avatar
Christian Würdig committed
372

373
374
375
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_mode *mode)
{
	ia32_emit_char(env, get_mode_suffix(mode));
Christian Würdig's avatar
Christian Würdig committed
376
377
}

378
379
380
381
382
383
384
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);
}

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
void ia32_emit_xmm_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
{
	ir_mode *mode = get_ia32_ls_mode(node);
	ia32_emit_char(env, 's');
	if(mode != NULL) {
		assert(mode_is_float(mode));
		switch(get_mode_size_bits(mode)) {
		case 32:
			ia32_emit_char(env, 's');
			break;
		case 64:
			ia32_emit_char(env, 'd');
			break;
		default:
			assert(0);
		}
	}
}

404
405
406
407
408
409
410
411
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)) {
		ia32_emit_char(env, 's');
	} else {
		ia32_emit_char(env, 'z');
Christian Würdig's avatar
Christian Würdig committed
412
413
414
	}
}

Christian Würdig's avatar
Christian Würdig committed
415
416
417
/**
 * Emits registers and/or address mode of a binary operation.
 */
418
419
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
420
		case ia32_Normal:
421
422
423
424
425
426
427
428
429
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				ia32_emit_char(env, '$');
				ia32_emit_immediate(env, node);
				ia32_emit_cstring(env, ", ");
				ia32_emit_source_register(env, node, 2);
			} else {
				const arch_register_t *in1 = get_in_reg(node, 2);
				const arch_register_t *in2 = get_in_reg(node, 3);
				const arch_register_t *out = produces_result(node) ? get_out_reg(node, 0) : NULL;
Christian Würdig's avatar
Christian Würdig committed
430
				const arch_register_t *in;
Christian Würdig's avatar
Christian Würdig committed
431
				const char            *in_name;
Christian Würdig's avatar
Christian Würdig committed
432

Christian Würdig's avatar
Christian Würdig committed
433
434
435
				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
436

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

442
443
444
445
				ia32_emit_char(env, '%');
				ia32_emit_string(env, in_name);
				ia32_emit_cstring(env, ", %");
				ia32_emit_string(env, arch_register_get_name(out));
Christian Würdig's avatar
Christian Würdig committed
446
447
448
			}
			break;
		case ia32_AddrModeS:
449
450
451
452
453
454
455
456
457
458
459
460
461
			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);
				ia32_emit_cstring(env, ", $");
				ia32_emit_immediate(env, node);
			} else if (produces_result(node)) {
				ia32_emit_am(env, node);
				ia32_emit_cstring(env, ", ");
				ia32_emit_dest_register(env, node, 0);
			} else {
				ia32_emit_am(env, node);
				ia32_emit_cstring(env, ", ");
				ia32_emit_source_register(env, node, 2);
462
			}
Christian Würdig's avatar
Christian Würdig committed
463
464
			break;
		case ia32_AddrModeD:
465
466
467
468
469
470
471
472
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				ia32_emit_char(env, '$');
				ia32_emit_immediate(env, node);
				ia32_emit_cstring(env, ", ");
				ia32_emit_am(env, node);
			} else {
				const arch_register_t *in1 = get_in_reg(node, get_irn_arity(node) == 5 ? 3 : 2);
				ir_mode               *mode = get_ia32_ls_mode(node);
Christian Würdig's avatar
Christian Würdig committed
473
				const char            *in_name;
Christian Würdig's avatar
Christian Würdig committed
474
475
476

				in_name = ia32_get_reg_name_for_mode(env, mode, in1);

477
				if (is_ia32_emit_cl(node)) {
Christian Würdig's avatar
Christian Würdig committed
478
479
480
					assert(REGS_ARE_EQUAL(&ia32_gp_regs[REG_ECX], in1) && "shift operation needs ecx");
					in_name = "cl";
				}
481

482
483
484
485
				ia32_emit_char(env, '%');
				ia32_emit_string(env, in_name);
				ia32_emit_cstring(env, ", ");
				ia32_emit_am(env, node);
Christian Würdig's avatar
Christian Würdig committed
486
487
488
489
490
			}
			break;
		default:
			assert(0 && "unsupported op type");
	}
491
492
}

493
494
495
/**
 * Emits registers and/or address mode of a binary operation.
 */
496
497
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
	switch(get_ia32_op_type(node)) {
498
		case ia32_Normal:
499
500
501
502
503
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				// should not happen...
				assert(0);
			} else {
				ia32_attr_t *attr = get_ia32_attr(node);
504
505
506
507
508
				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;

509
510
				in  = out ? (REGS_ARE_EQUAL(out, in2) ? in1 : in2) : in2;
				out = out ? out : in1;
511

512
513
514
515
				ia32_emit_char(env, '%');
				ia32_emit_string(env, arch_register_get_name(in));
				ia32_emit_cstring(env, ", %");
				ia32_emit_string(env, arch_register_get_name(out));
516
517
518
519
			}
			break;
		case ia32_AddrModeS:
		case ia32_AddrModeD:
520
			ia32_emit_am(env, node);
521
522
523
524
525
526
			break;
		default:
			assert(0 && "unsupported op type");
	}
}

Christian Würdig's avatar
Christian Würdig committed
527
528
529
/**
 * Emits registers and/or address mode of a unary operation.
 */
530
531
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
532
		case ia32_Normal:
533
534
535
536
			if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
				ia32_emit_char(env, '$');
				ia32_emit_immediate(env, node);
			} else {
Matthias Braun's avatar
Matthias Braun committed
537
				if (is_ia32_Mul(node) || is_ia32_IMul1OP(node)) {
538
					ia32_emit_source_register(env, node, 3);
Matthias Braun's avatar
Matthias Braun committed
539
540
				} else if(is_ia32_IDiv(node) || is_ia32_Div(node)) {
					ia32_emit_source_register(env, node, 4);
541
542
543
544
				} 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);
545
				} else {
546
					ia32_emit_dest_register(env, node, 0);
547
				}
548
			}
Christian Würdig's avatar
Christian Würdig committed
549
			break;
550
		case ia32_AddrModeS:
551
552
		case ia32_AddrModeD:
			ia32_emit_am(env, node);
553
			break;
Christian Würdig's avatar
Christian Würdig committed
554
555
556
557
558
559
		default:
			assert(0 && "unsupported op type");
	}
}

/**
560
 * Emits address mode.
Christian Würdig's avatar
Christian Würdig committed
561
 */
562
563
564
565
void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node) {
	ia32_am_flavour_t am_flav = get_ia32_am_flavour(node);
	ident *id = get_ia32_am_sc(node);
	int offs = get_ia32_am_offs_int(node);
Christian Würdig's avatar
Christian Würdig committed
566

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

570
571
572
573
574
	/* emit offset */
	if (id != NULL) {
		if (is_ia32_am_sc_sign(node))
			ia32_emit_char(env, '-');
		ia32_emit_ident(env, id);
Christian Würdig's avatar
Christian Würdig committed
575
576
	}

577
578
579
580
581
	if(offs != 0) {
		if(id != NULL) {
			ia32_emit_irprintf(env, "%+d", offs);
		} else {
			ia32_emit_irprintf(env, "%d", offs);
582
		}
583
	}
Christian Würdig's avatar
Christian Würdig committed
584

585
586
	if (am_flav & (ia32_B | ia32_I)) {
		ia32_emit_char(env, '(');
Christian Würdig's avatar
Christian Würdig committed
587

588
589
590
		/* emit base */
		if (am_flav & ia32_B) {
			ia32_emit_source_register(env, node, 0);
Christian Würdig's avatar
Christian Würdig committed
591
592
		}

593
594
595
596
		/* emit index + scale */
		if (am_flav & ia32_I) {
			ia32_emit_char(env, ',');
			ia32_emit_source_register(env, node, 1);
597

598
599
			if (am_flav & ia32_S) {
				ia32_emit_irprintf(env, ",%d", 1 << get_ia32_am_scale(node));
600
601
			}
		}
602
		ia32_emit_char(env, ')');
Christian Würdig's avatar
Christian Würdig committed
603
	}
604
}
Christian Würdig's avatar
Christian Würdig committed
605

606
#if 0
Christian Würdig's avatar
Christian Würdig committed
607
608
609
/**
 * Formated print of commands and comments.
 */
Christian Würdig's avatar
Christian Würdig committed
610
611
612
613
614
615
616
617
static void ia32_fprintf_format(FILE *F, const ir_node *irn, char *cmd_buf, char *cmnt_buf) {
	unsigned lineno;
	const char *name = irn ? be_retrieve_dbg_info(get_irn_dbg_info((ir_node *)irn), &lineno) : NULL;

	if (name)
		fprintf(F, "\t%-35s %-60s /* %s:%u */\n", cmd_buf, cmnt_buf, name, lineno);
	else
		fprintf(F, "\t%-35s %-60s\n", cmd_buf, cmnt_buf);
Christian Würdig's avatar
Christian Würdig committed
618
}
619
#endif
Christian Würdig's avatar
Christian Würdig committed
620

621
622
623
void ia32_write_line(ia32_emit_env_t *env)
{
	char *finished_line = obstack_finish(env->obst);
Christian Würdig's avatar
Christian Würdig committed
624

625
626
627
628
	fwrite(finished_line, env->linelength, 1, env->out);
	env->linelength = 0;
	obstack_free(env->obst, finished_line);
}
Christian Würdig's avatar
Christian Würdig committed
629

630
631
632
633
634
635
void ia32_pad_comment(ia32_emit_env_t *env)
{
	while(env->linelength <= 30) {
		ia32_emit_char(env, ' ');
	}
	ia32_emit_cstring(env, "    ");
636
637
}

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
void ia32_emit_finish_line(ia32_emit_env_t *env, const ir_node *node)
{
	dbg_info *dbg;
	const char *sourcefile;
	unsigned lineno;

	if(node == NULL) {
		ia32_emit_char(env, '\n');
		ia32_write_line(env);
		return;
	}

	ia32_pad_comment(env);
	ia32_emit_cstring(env, "/* ");
	ia32_emit_irprintf(env, "%+F ", node);

	dbg = get_irn_dbg_info(node);
	sourcefile = be_retrieve_dbg_info(dbg, &lineno);
	if(sourcefile != NULL) {
		ia32_emit_string(env, sourcefile);
		ia32_emit_irprintf(env, ":%u", lineno);
	}
	ia32_emit_cstring(env, " */\n");
	ia32_write_line(env);
}
Christian Würdig's avatar
Christian Würdig committed
663

Christian Würdig's avatar
Christian Würdig committed
664

Christian Würdig's avatar
Christian Würdig committed
665
666
667
668
669
670
671
672
673
674
/*************************************************
 *                 _ _                         _
 *                (_) |                       | |
 *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
 *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
 * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
 *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
 *
 *************************************************/

Christian Würdig's avatar
Christian Würdig committed
675
#undef IA32_DO_EMIT
Christian Würdig's avatar
Christian Würdig committed
676
#define IA32_DO_EMIT(irn) ia32_fprintf_format(F, irn, cmd_buf, cmnt_buf)
Christian Würdig's avatar
Christian Würdig committed
677

678
679
680
681
/*
 * coding of conditions
 */
struct cmp2conditon_t {
Christian Würdig's avatar
Christian Würdig committed
682
683
	const char *name;
	pn_Cmp      num;
684
685
686
687
688
689
};

/*
 * positive conditions for signed compares
 */
static const struct cmp2conditon_t cmp2condition_s[] = {
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
	{ 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 */
706
707
708
709
710
711
};

/*
 * positive conditions for unsigned compares
 */
static const struct cmp2conditon_t cmp2condition_u[] = {
Christian Würdig's avatar
Christian Würdig committed
712
713
714
	{ NULL,              pn_Cmp_False },  /* always false */
	{ "e",               pn_Cmp_Eq },     /* == */
	{ "b",               pn_Cmp_Lt },     /* < */
Christian Würdig's avatar
Christian Würdig committed
715
	{ "be",              pn_Cmp_Le },     /* <= */
Christian Würdig's avatar
Christian Würdig committed
716
717
718
719
	{ "a",               pn_Cmp_Gt },     /* > */
	{ "ae",              pn_Cmp_Ge },     /* >= */
	{ "ne",              pn_Cmp_Lg },     /* != */
	{ NULL,              pn_Cmp_True },   /* always true */
720
721
722
723
724
};

/*
 * returns the condition code
 */
725
static const char *get_cmp_suffix(int cmp_code)
726
{
727
728
	assert( (cmp2condition_s[cmp_code & 15].num) == (cmp_code & 15));
	assert( (cmp2condition_u[cmp_code & 7].num) == (cmp_code & 7));
729

730
731
732
733
734
	if((cmp_code & ia32_pn_Cmp_Unsigned)) {
		return cmp2condition_u[cmp_code & 7].name;
	} else {
		return cmp2condition_s[cmp_code & 15].name;
	}
735
736
}

737
738
739
740
741
742
void ia32_emit_cmp_suffix(ia32_emit_env_t *env, long pnc)
{
	ia32_emit_string(env, get_cmp_suffix(pnc));
}


743
744
745
746
747
748
749
/**
 * Returns the target block for a control flow node.
 */
static ir_node *get_cfop_target_block(const ir_node *irn) {
	return get_irn_link(irn);
}

Christian Würdig's avatar
Christian Würdig committed
750
751
752
/**
 * Returns the target label for a control flow node.
 */
753
754
void ia32_emit_cfop_target(ia32_emit_env_t * env, const ir_node *node) {
	ir_node *block = get_cfop_target_block(node);
755

756
757
	ia32_emit_cstring(env, BLOCK_PREFIX);
	ia32_emit_irprintf(env, "%d", get_irn_node_nr(block));
Christian Würdig's avatar
Christian Würdig committed
758
}
759

760
761
/** Return the next block in Block schedule */
static ir_node *next_blk_sched(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
762
	return get_irn_link(block);
763
764
}

765
766
767
/**
 * Returns the Proj with projection number proj and NOT mode_M
 */
768
static ir_node *get_proj(const ir_node *node, long proj) {
769
770
771
	const ir_edge_t *edge;
	ir_node         *src;

772
	assert(get_irn_mode(node) == mode_T && "expected mode_T node");
773

774
	foreach_out_edge(node, edge) {
775
776
777
778
779
780
781
782
783
784
785
786
		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
787
788
789
/**
 * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
 */
790
791
static void finish_CondJmp(ia32_emit_env_t *env, const ir_node *node,
                           ir_mode *mode, long pnc) {
792
793
794
795
796
	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
797

798
	/* get both Proj's */
799
	proj_true = get_proj(node, pn_Cond_true);
800
	assert(proj_true && "CondJmp without true Proj");
Christian Würdig's avatar
Christian Würdig committed
801

802
	proj_false = get_proj(node, pn_Cond_false);
803
804
	assert(proj_false && "CondJmp without false Proj");

805
	/* for now, the code works for scheduled and non-schedules blocks */
806
	block = get_nodes_block(node);
807
808

	/* we have a block schedule */
809
	next_block = next_blk_sched(block);
810

811
	if (get_cfop_target_block(proj_true) == next_block) {
812
		/* exchange both proj's so the second one can be omitted */
813
814
		const ir_node *t = proj_true;

815
816
817
818
		proj_true  = proj_false;
		proj_false = t;
		flipped    = 1;
		pnc        = get_negated_pnc(pnc, mode);
819
820
	}

821
822
	/* in case of unordered compare, check for parity */
	if (pnc & pn_Cmp_Uo) {
823
824
825
		ia32_emit_cstring(env, "\tjp ");
		ia32_emit_cfop_target(env, proj_true);
		ia32_emit_finish_line(env, proj_true);
826
827
	}

828
829
830
831
832
	ia32_emit_cstring(env, "\tj");
	ia32_emit_cmp_suffix(env, pnc);
	ia32_emit_char(env, ' ');
	ia32_emit_cfop_target(env, proj_true);
	ia32_emit_finish_line(env, proj_true);
Christian Würdig's avatar
Christian Würdig committed
833

834
	/* the second Proj might be a fallthrough */
835
	if (get_cfop_target_block(proj_false) != next_block) {
836
837
838
839
840
841
842
843
		ia32_emit_cstring(env, "\tjmp ");
		ia32_emit_cfop_target(env, proj_false);
		ia32_emit_finish_line(env, proj_false);
	} else {
		ia32_emit_cstring(env, "\t/* fallthrough to");
		ia32_emit_cfop_target(env, proj_false);
		ia32_emit_cstring(env, " */");
		ia32_emit_finish_line(env, proj_false);
844
	}
Christian Würdig's avatar
Christian Würdig committed
845
846
847
}

/**
Christian Würdig's avatar
Christian Würdig committed
848
 * Emits code for conditional jump.
Christian Würdig's avatar
Christian Würdig committed
849
 */
850
851
852
853
static void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
	ia32_emit_cstring(env, "\tcmp ");
	ia32_emit_binop(env, node);
	ia32_emit_finish_line(env, node);
Christian Würdig's avatar
Christian Würdig committed
854

855
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
Christian Würdig's avatar
Christian Würdig committed
856
857
}

Christian Würdig's avatar
Christian Würdig committed
858
859
860
/**
 * Emits code for conditional jump with two variables.
 */
861
862
static void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
	CondJmp_emitter(env, node);
Christian Würdig's avatar
Christian Würdig committed
863
864
}

865
866
867
/**
 * Emits code for conditional test and jump.
 */
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
static void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
	if(is_ia32_ImmSymConst(node) || is_ia32_ImmConst(node)) {
		ia32_emit_cstring(env, "\ttest $");
		ia32_emit_immediate(env, node);
		ia32_emit_cstring(env, ", ");
		ia32_emit_source_register(env, node, 0);
		ia32_emit_finish_line(env, node);
	} else {
		ia32_emit_cstring(env, "\ttest ");
		ia32_emit_source_register(env, node, 1);
		ia32_emit_cstring(env, ", ");
		ia32_emit_source_register(env, node, 0);
		ia32_emit_finish_line(env, node);
	}
	finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
883
884
885
886
887
}

/**
 * Emits code for conditional test and jump with two variables.
 */
888
889
static void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
	TestJmp_emitter(env, node);
890
891
}

892
893
894
static void emit_ia32_CJmp(ia32_emit_env_t *env, const ir_node *node) {
	ia32_emit_cstring(env, "/* omitted redundant test */");
	ia32_emit_finish_line(env, node);
895

896
	finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
897
}
898

899
900
901
static void emit_ia32_CJmpAM(ia32_emit_env_t *env, const ir_node *node) {
	ia32_emit_cstring(env, "/* omitted redundant test/cmp */");
	ia32_emit_finish_line(env, node);
902

903
	finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
904
}
Christian Würdig's avatar
Christian Würdig committed
905

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

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

Michael Beck's avatar
Michael Beck committed
919
920
921
/**
 * Emits code for conditional x87 floating point jump with two variables.
 */
922
923
static void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
	ia32_attr_t *attr = get_ia32_attr(node);
Michael Beck's avatar
Michael Beck committed
924
	const char *reg = attr->x87[1]->name;
925
	long pnc = get_ia32_pncode(node);
Michael Beck's avatar
Michael Beck committed
926

927
	switch (get_ia32_irn_opcode(node)) {
Michael Beck's avatar
Michael Beck committed
928
	case iro_ia32_fcomrJmp:
929
		pnc = get_inversed_pnc(pnc);
Michael Beck's avatar
Michael Beck committed
930
931
	case iro_ia32_fcomJmp:
	default:
932
		ia32_emit_cstring(env, "\tfucom ");
Michael Beck's avatar
Michael Beck committed
933
934
		break;
	case iro_ia32_fcomrpJmp:
935
		pnc = get_inversed_pnc(pnc);
Michael Beck's avatar
Michael Beck committed
936
	case iro_ia32_fcompJmp:
937
		ia32_emit_cstring(env, "\tfucomp ");
Michael Beck's avatar
Michael Beck committed
938
939
		break;
	case iro_ia32_fcomrppJmp:
940
		pnc = get_inversed_pnc(pnc);
Michael Beck's avatar
Michael Beck committed
941
	case iro_ia32_fcomppJmp:
942
		ia32_emit_cstring(env, "\tfucompp ");
Michael Beck's avatar
Michael Beck committed
943
944
945
946
		reg = "";
		break;
	}

947
948
949
950
951
	if(reg[0] != '\0') {
		ia32_emit_char(env, '%');
		ia32_emit_string(env, reg);
	}
	ia32_emit_finish_line(env, node);
Michael Beck's avatar
Michael Beck committed
952

953
954
955
956
	ia32_emit_cstring(env, "\tfnstsw %ax");
	ia32_emit_finish_line(env, node);
	ia32_emit_cstring(env, "\tsahf");
	ia32_emit_finish_line(env, node);
Michael Beck's avatar
Michael Beck committed
957

958
	finish_CondJmp(env, node, mode_E, pnc);
Michael Beck's avatar
Michael Beck committed
959
960
}

961
962
963
static void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
	long pnc = get_ia32_pncode(node);
	int is_PsiCondCMov = is_ia32_PsiCondCMov(node);
Matthias Braun's avatar
Matthias Braun committed
964
965
	int idx_left  = 2 - is_PsiCondCMov;
	int idx_right = 3 - is_PsiCondCMov;
Christian Würdig's avatar
Christian Würdig committed
966
967
	const arch_register_t *in1, *in2, *out;

968
969
970
	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
971

Christian Würdig's avatar
Christian Würdig committed
972
973
	/* we have to emit the cmp first, because the destination register */
	/* could be one of the compare registers                           */
974
975
976
977
978
979
980
981
982
983
984
985
986
	if (is_ia32_CmpCMov(node)) {
		ia32_emit_cstring(env, "\tcmp ");
		ia32_emit_source_register(env, node, 1);
		ia32_emit_cstring(env, ", ");
		ia32_emit_source_register(env, node, 0);
	} else if (is_ia32_xCmpCMov(node)) {
		ia32_emit_cstring(env, "\tucomis");
		ia32_emit_mode_suffix(env, get_irn_mode(node));
		ia32_emit_char(env, ' ');
		ia32_emit_source_register(env, node, 1);
		ia32_emit_cstring(env, ", ");
		ia32_emit_source_register(env, node, 0);
	} else if (is_PsiCondCMov) {
987
		/* omit compare because flags are already set by And/Or */
988
989
990
991
992
		ia32_emit_cstring(env, "\ttest ");
		ia32_emit_source_register(env, node, 0);
		ia32_emit_cstring(env, ", ");
		ia32_emit_source_register(env, node, 0);
	} else {
993
994
		assert(0 && "unsupported CMov");
	}
995
	ia32_emit_finish_line(env, node);
Christian Würdig's avatar
Christian Würdig committed
996

Christian Würdig's avatar
Christian Würdig committed
997
998
	if (REGS_ARE_EQUAL(out, in2)) {
		/* best case: default in == out -> do nothing */
999
1000
	} else if (REGS_ARE_EQUAL(out, in1)) {
		ir_node *n = (ir_node*) node;
Christian Würdig's avatar
Christian Würdig committed
1001
		/* true in == out -> need complement compare and exchange true and default in */
1002
1003
1004
		ir_node *t = get_irn_n(n, idx_left);
		set_irn_n(n, idx_left, get_irn_n(n, idx_right));
		set_irn_n(n, idx_right, t);
Christian Würdig's avatar
Christian Würdig committed
1005

1006
1007
		pnc = get_negated_pnc(pnc, get_irn_mode(node));
	} else {
Christian Würdig's avatar
Christian Würdig committed
1008
		/* out is different from in: need copy default -> out */
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
		if (is_PsiCondCMov) {
			ia32_emit_cstring(env, "\tmovl ");
			ia32_emit_dest_register(env, node, 2);
			ia32_emit_cstring(env, ", ");
			ia32_emit_dest_register(env, node, 0);
		} else {
			ia32_emit_cstring(env, "\tmovl ");
			ia32_emit_source_register(env, node, 3);
			ia32_emit_cstring(env, ", ");
			ia32_emit_dest_register(env, node, 0);
		}
		ia32_emit_finish_line(env, node);
Christian Würdig's avatar
Christian Würdig committed
1021
	}
1022

1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
	if (is_PsiCondCMov) {
		ia32_emit_cstring(env, "\tcmov");
		ia32_emit_cmp_suffix(env, pnc);
		ia32_emit_cstring(env, "l ");
		ia32_emit_source_register(env, node, 1);
		ia32_emit_cstring(env, ", ");
		ia32_emit_dest_register(env, node, 0);
	} else {
		ia32_emit_cstring(env, "\tcmov");
		ia32_emit_cmp_suffix(env, pnc);
		ia32_emit_cstring(env, "l ");
		ia32_emit_source_register(env, node, 2);
		ia32_emit_cstring(env, ", ");
		ia32_emit_dest_register(env, node, 0);
	}
	ia32_emit_finish_line(env, node);
Christian Würdig's avatar
Christian Würdig committed
1039
1040
}

1041
1042
static void emit_ia32_CmpCMov(ia32_emit_env_t *env, const ir_node *node) {
	CMov_emitter(env, node);
1043
1044
}

1045
1046
static void emit_ia32_PsiCondCMov(ia32_emit_env_t *env, const ir_node *node) {
	CMov_emitter(env, node);
1047
1048
}

1049
1050
static void emit_ia32_xCmpCMov(ia32_emit_env_t *env, const ir_node *node) {
	CMov_emitter(env, node);
1051
1052
}

1053
1054
static void Set_emitter(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode) {
	int pnc = get_ia32_pncode(node);
Christian Würdig's avatar
Christian Würdig committed
1055
1056
1057
	const char *reg8bit;
	const arch_register_t *out;

1058
	out     = arch_get_irn_register(env->arch_env, node);
Christian Würdig's avatar
Christian Würdig committed
1059
1060
	reg8bit = ia32_get_mapped_reg_name(env->isa->regs_8bit, out);

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
	if (is_ia32_CmpSet(node)) {
		ia32_emit_cstring(env, "\tcmp ");
		ia32_emit_binop(env, node);
	} else if (is_ia32_xCmpSet(node)) {
		ia32_emit_cstring(env, "\tucomis");
		ia32_emit_mode_suffix(env, get_irn_mode(get_irn_n(node, 2)));
		ia32_emit_char(env, ' ');
		ia32_emit_binop(env, node);
	} else if (is_ia32_PsiCondSet(node)) {
		ia32_emit_cstring(env, "\tcmp $0, ");
		ia32_emit_source_register(env, node, 0);
	} else {
1073
1074
		assert(0 && "unsupported Set");
	}
1075
	ia32_emit_finish_line(env, node);
1076

1077
	/* use mov to clear target because it doesn't affect the eflags */
1078
1079
1080
	ia32_emit_cstring(env, "\tmovl $0, %");
	ia32_emit_string(env, arch_register_get_name(out));
	ia32_emit_finish_line(env, node);
1081

1082
1083
1084
1085
1086
	ia32_emit_cstring(env, "\tset");
	ia32_emit_cmp_suffix(env, pnc);
	ia32_emit_cstring(env, " %");
	ia32_emit_string(env, reg8bit);
	ia32_emit_finish_line(env, node);