ia32_common_transform.c 24.4 KB
Newer Older
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
4
5
6
7
8
9
 */

/**
 * @file
 * @brief       This file implements the common parts of IR transformation from
 *              firm into ia32-Firm.
Matthias Braun's avatar
Matthias Braun committed
10
 * @author      Matthias Braun, Sebastian Buchwald
11
 */
12
#include "config.h"
13
14
15
16
17

#include "error.h"
#include "ircons.h"
#include "irprintf.h"
#include "typerep.h"
18
#include "bitset.h"
19
#include "heights.h"
20

21
22
#include "betranshlp.h"
#include "beabi.h"
23
24
25
26
27
28
29
30

#include "ia32_architecture.h"
#include "ia32_common_transform.h"
#include "ia32_new_nodes.h"

#include "gen_ia32_new_nodes.h"
#include "gen_ia32_regalloc_if.h"

31
ir_heights_t *ia32_heights = NULL;
32
33
34
35

static int check_immediate_constraint(long val, char immediate_constraint_type)
{
	switch (immediate_constraint_type) {
36
37
38
39
40
41
42
43
44
45
46
		case 'i': return 1;

		case 'I': return    0 <= val && val <=  31;
		case 'J': return    0 <= val && val <=  63;
		case 'K': return -128 <= val && val <= 127;
		case 'L': return val == 0xff || val == 0xffff;
		case 'M': return    0 <= val && val <=   3;
		case 'N': return    0 <= val && val <= 255;
		case 'O': return    0 <= val && val <= 127;

		default: panic("Invalid immediate constraint found");
47
48
49
	}
}

50
ir_type *ia32_get_prim_type(const ir_mode *mode)
51
{
52
53
54
55
	if (mode == ia32_mode_E) {
		return ia32_type_E;
	} else {
		return get_type_for_mode(mode);
56
57
58
	}
}

59
60
ir_entity *ia32_create_float_const_entity(ia32_isa_t *isa, ir_tarval *tv,
                                          ident *name)
61
{
62
	ir_entity        *res = pmap_get(ir_entity, isa->tv_ent, tv);
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
	ir_initializer_t *initializer;
	ir_mode          *mode;
	ir_type          *tp;

	if (res != NULL)
		return res;

	mode = get_tarval_mode(tv);

	if (! ia32_cg_config.use_sse2) {
		/* try to reduce the mode to produce smaller sized entities */
		if (mode != mode_F) {
			if (tarval_ieee754_can_conv_lossless(tv, mode_F)) {
				mode = mode_F;
				tv = tarval_convert_to(tv, mode);
			} else if (mode != mode_D) {
				if (tarval_ieee754_can_conv_lossless(tv, mode_D)) {
					mode = mode_D;
81
82
83
84
85
86
					tv = tarval_convert_to(tv, mode);
				}
			}
		}
	}

87
88
89
90
91
	if (name == NULL)
		name = id_unique("C%u");

	tp  = ia32_get_prim_type(mode);
	res = new_entity(get_glob_type(), name, tp);
92
93
94
95
96
97
98
99
	set_entity_ld_ident(res, get_entity_ident(res));
	set_entity_visibility(res, ir_visibility_private);
	add_entity_linkage(res, IR_LINKAGE_CONSTANT);

	initializer = create_initializer_tarval(tv);
	set_entity_initializer(res, initializer);

	pmap_insert(isa->tv_ent, tv, res);
100
101
102
	return res;
}

103
ir_node *ia32_create_Immediate(ir_graph *const irg, ir_entity *const symconst, int const symconst_sign, long const val)
104
105
{
	ir_node  *start_block = get_irg_start_block(irg);
106
	ir_node  *immediate   = new_bd_ia32_Immediate(NULL, start_block, symconst,
107
			symconst_sign, ia32_no_pic_adjust, val);
108
	arch_set_irn_register(immediate, &ia32_registers[REG_GP_NOREG]);
109
110
111
112
113
114
115
116
117
118
119
120
121

	return immediate;
}

const arch_register_t *ia32_get_clobber_register(const char *clobber)
{
	const arch_register_t       *reg = NULL;
	int                          c;
	size_t                       r;
	const arch_register_class_t *cls;

	/* TODO: construct a hashmap instead of doing linear search for clobber
	 * register */
122
	for (c = 0; c < N_IA32_CLASSES; ++c) {
123
		cls = & ia32_reg_classes[c];
124
		for (r = 0; r < cls->n_regs; ++r) {
125
			const arch_register_t *temp_reg = arch_register_for_index(cls, r);
Michael Beck's avatar
Michael Beck committed
126
			if (strcmp(temp_reg->name, clobber) == 0
127
128
129
130
131
					|| (c == CLASS_ia32_gp && strcmp(temp_reg->name+1, clobber) == 0)) {
				reg = temp_reg;
				break;
			}
		}
Michael Beck's avatar
Michael Beck committed
132
		if (reg != NULL)
133
134
135
136
137
138
			break;
	}

	return reg;
}

139
140
int ia32_mode_needs_gp_reg(ir_mode *mode)
{
141
	if (mode == ia32_mode_fpcw)
142
		return 0;
Michael Beck's avatar
Michael Beck committed
143
	if (get_mode_size_bits(mode) > 32)
144
145
146
147
		return 0;
	return mode_is_int(mode) || mode_is_reference(mode) || mode == mode_b;
}

148
149
150
151
152
153
154
155
156
157
158
159
/**
 * An assembler constraint.
 */
typedef struct constraint_t {
	const arch_register_class_t *cls;
	unsigned                     allowed_registers;
	char                         all_registers_allowed;
	char                         memory_possible;
	char                         immediate_type;
	int                          same_as;
} constraint_t;

160
static void parse_asm_constraints(constraint_t *const constraint, ident *const constraint_text, bool const is_output)
161
162
163
164
{
	memset(constraint, 0, sizeof(constraint[0]));
	constraint->same_as = -1;

165
	char const *c = get_id_str(constraint_text);
Michael Beck's avatar
Michael Beck committed
166
	if (*c == 0) {
167
168
169
170
171
172
		/* a memory constraint: no need to do anything in backend about it
		 * (the dependencies are already respected by the memory edge of
		 * the node) */
		return;
	}

173
174
	arch_register_class_t const *const gp = &ia32_reg_classes[CLASS_ia32_gp];

175
176
	/* TODO: improve error messages with node and source info. (As users can
	 * easily hit these) */
177
178
179
180
181
182
	char                         immediate_type        = '\0';
	unsigned                     limited               = 0;
	arch_register_class_t const *cls                   = NULL;
	bool                         memory_possible       = false;
	bool                         all_registers_allowed = false;
	int                          same_as               = -1;
183
	while (*c != 0) {
184
185
		arch_register_class_t const *new_cls = NULL;
		char                         new_imm = '\0';
186
		switch (*c) {
187
188
189
190
191
		case ' ':
		case '\t':
		case '\n':
			break;

192
193
194
		/* Skip out/in-out marker */
		case '=': break;
		case '+': break;
195

196
197
		case '&': break;

198
199
200
		case '*':
			++c;
			break;
201

202
		case '#':
203
			while (*c != 0 && *c != ',')
204
205
206
				++c;
			break;

207
208
209
210
211
212
213
		case 'a': new_cls = gp; limited |= 1 << REG_GP_EAX; break;
		case 'b': new_cls = gp; limited |= 1 << REG_GP_EBX; break;
		case 'c': new_cls = gp; limited |= 1 << REG_GP_ECX; break;
		case 'd': new_cls = gp; limited |= 1 << REG_GP_EDX; break;
		case 'D': new_cls = gp; limited |= 1 << REG_GP_EDI; break;
		case 'S': new_cls = gp; limited |= 1 << REG_GP_ESI; break;

214
215
216
217
		case 'Q':
		case 'q':
			/* q means lower part of the regs only, this makes no
			 * difference to Q for us (we only assign whole registers) */
218
			new_cls  = gp;
219
220
			limited |= 1 << REG_GP_EAX | 1 << REG_GP_EBX | 1 << REG_GP_ECX |
			           1 << REG_GP_EDX;
221
			break;
222

223
		case 'A':
224
			new_cls  = gp;
225
			limited |= 1 << REG_GP_EAX | 1 << REG_GP_EDX;
226
			break;
227

228
		case 'l':
229
			new_cls  = gp;
230
231
232
			limited |= 1 << REG_GP_EAX | 1 << REG_GP_EBX | 1 << REG_GP_ECX |
			           1 << REG_GP_EDX | 1 << REG_GP_ESI | 1 << REG_GP_EDI |
			           1 << REG_GP_EBP;
233
234
235
236
237
			break;

		case 'R':
		case 'r':
		case 'p':
238
239
			new_cls               = gp;
			all_registers_allowed = true;
240
241
242
243
244
245
			break;

		case 'f':
		case 't':
		case 'u':
			/* TODO: mark values so the x87 simulator knows about t and u */
246
247
			new_cls               = &ia32_reg_classes[CLASS_ia32_fp];
			all_registers_allowed = true;
248
249
250
251
			break;

		case 'Y':
		case 'x':
252
253
			new_cls               = &ia32_reg_classes[CLASS_ia32_xmm];
			all_registers_allowed = true;
254
255
256
257
258
259
260
261
262
			break;

		case 'I':
		case 'J':
		case 'K':
		case 'L':
		case 'M':
		case 'N':
		case 'O':
263
264
			new_cls = gp;
			new_imm = *c;
265
			break;
266

267
268
		case 'n':
		case 'i':
269
270
			new_cls = gp;
			new_imm = 'i';
271
272
273
274
			break;

		case 'X':
		case 'g':
275
276
277
278
			new_cls               = gp;
			new_imm               = 'i';
			all_registers_allowed = true;
			memory_possible       = true;
279
280
281
282
283
284
285
286
287
288
289
			break;

		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
290
		case '9': {
291
292
293
			if (is_output)
				panic("can only specify same constraint on input");

294
			int p;
295
			sscanf(c, "%d%n", &same_as, &p);
Michael Beck's avatar
Michael Beck committed
296
			if (same_as >= 0) {
297
298
299
300
				c += p;
				continue;
			}
			break;
301
		}
302
303
304
305
306
307
308

		case 'm':
		case 'o':
		case 'V':
			/* memory constraint no need to do anything in backend about it
			 * (the dependencies are already respected by the memory edge of
			 * the node) */
309
			memory_possible = true;
310
311
312
313
314
315
316
317
318
319
320
321
			break;

		case 'E': /* no float consts yet */
		case 'F': /* no float consts yet */
		case 's': /* makes no sense on x86 */
		case '<': /* no autodecrement on x86 */
		case '>': /* no autoincrement on x86 */
		case 'C': /* sse constant not supported yet */
		case 'G': /* 80387 constant not supported yet */
		case 'y': /* we don't support mmx registers yet */
		case 'Z': /* not available in 32 bit mode */
		case 'e': /* not available in 32 bit mode */
322
323
			panic("unsupported asm constraint '%c' found in (%+F)", *c, current_ir_graph);

324
		default:
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
			panic("unknown asm constraint '%c' found in (%+F)", *c, current_ir_graph);
		}

		if (new_cls) {
			if (!cls) {
				cls = new_cls;
			} else if (cls != new_cls) {
				panic("multiple register classes not supported");
			}
		}

		if (new_imm != '\0') {
			if (immediate_type == '\0') {
				immediate_type = new_imm;
			} else if (immediate_type != new_imm) {
				panic("multiple immediate types not supported");
			}
342
		}
343

344
345
346
		++c;
	}

Michael Beck's avatar
Michael Beck committed
347
	if (same_as >= 0) {
348
349
350
351
352
353
		if (cls != NULL)
			panic("same as and register constraint not supported");
		if (immediate_type != '\0')
			panic("same as and immediate constraint not supported");
	}

354
355
	if (!cls && same_as < 0 && !memory_possible)
		panic("no constraint specified for assembler input");
356
357
358
359
360
361
362
363
364

	constraint->same_as               = same_as;
	constraint->cls                   = cls;
	constraint->allowed_registers     = limited;
	constraint->all_registers_allowed = all_registers_allowed;
	constraint->memory_possible       = memory_possible;
	constraint->immediate_type        = immediate_type;
}

365
366
367
368
369
static bool can_match(const arch_register_req_t *in,
                      const arch_register_req_t *out)
{
	if (in->cls != out->cls)
		return false;
370
371
	if (!arch_register_req_is(in,  limited) ||
	    !arch_register_req_is(out, limited))
372
373
374
375
376
		return true;

	return (*in->limited & *out->limited) != 0;
}

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
static bool match_requirement(arch_register_req_t const **reqs, size_t const n_reqs, bitset_t *const used, arch_register_req_t const *const req)
{
	if (!req->cls)
		return true;
	for (size_t i = 0; i != n_reqs; ++i) {
		if (bitset_is_set(used, i))
			continue;
		if (!can_match(req, reqs[i]))
			continue;
		bitset_set(used, i);
		return true;
	}
	return false;
}

392
393
394
395
396
397
398
399
400
401
402
403
404
static inline ir_node *get_new_node(ir_node *node)
{
#ifdef FIRM_GRGEN_BE
	if (be_transformer == TRANSFORMER_DEFAULT) {
		return be_transform_node(node);
	} else {
		return node;
	}
#else
	return be_transform_node(node);
#endif
}

405
static arch_register_req_t const *ia32_make_register_req(ir_graph *irg, constraint_t const *constraint, int n_outs, arch_register_req_t const **out_reqs, int pos);
406

407
ir_node *ia32_gen_ASM(ir_node *node)
408
{
409
410
411
412
413
414
415
416
417
418
419
420
	ir_node        *block        = get_nodes_block(node);
	ir_node        *new_block    = get_new_node(block);
	dbg_info       *dbgi         = get_irn_dbg_info(node);
	int             n_inputs     = get_ASM_n_inputs(node);
	int             n_ins        = n_inputs+1;
	ir_node       **in           = ALLOCANZ(ir_node*, n_ins);
	size_t          n_clobbers   = 0;
	ident         **clobbers     = get_ASM_clobbers(node);
	unsigned        reg_map_size = 0;
	ir_graph       *irg          = get_irn_irg(node);
	struct obstack *obst         = get_irg_obstack(irg);
	unsigned        clobber_bits[N_IA32_CLASSES];
421
	memset(&clobber_bits, 0, sizeof(clobber_bits));
422

423
	for (size_t c = 0; c < get_ASM_n_clobbers(node); ++c) {
424
		const char                *clobber = get_id_str(clobbers[c]);
425
426
		const arch_register_req_t *req     = ia32_parse_clobber(clobber);
		if (req == NULL)
427
			continue;
428

429
		clobber_bits[req->cls->index] |= *req->limited;
430
431
		assert(req->cls->n_regs <= sizeof(unsigned)*8);
		++n_clobbers;
432
	}
433
434
	size_t n_out_constraints = get_ASM_n_output_constraints(node);
	size_t out_arity         = n_out_constraints + n_clobbers;
435

436
437
	const ir_asm_constraint *in_constraints  = get_ASM_input_constraints(node);
	const ir_asm_constraint *out_constraints = get_ASM_output_constraints(node);
438
439

	/* determine size of register_map */
440
	for (size_t out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
441
		const ir_asm_constraint *constraint = &out_constraints[out_idx];
442
443
		if (constraint->pos+1 > reg_map_size)
			reg_map_size = constraint->pos+1;
444
	}
445
	for (int i = 0; i < n_inputs; ++i) {
446
		const ir_asm_constraint *constraint = &in_constraints[i];
447
448
		if (constraint->pos+1 > reg_map_size)
			reg_map_size = constraint->pos+1;
449
450
	}

451
	ia32_asm_reg_t *const register_map = NEW_ARR_DZ(ia32_asm_reg_t, obst, reg_map_size);
452
453

	/* construct output constraints */
454
455
456
	size_t                      out_size = out_arity + 1;
	const arch_register_req_t **out_reg_reqs
		= OALLOCN(obst, const arch_register_req_t*, out_size);
457

458
	size_t out_idx;
Michael Beck's avatar
Michael Beck committed
459
	for (out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
460
461
462
		constraint_t             parsed_constraint;
		const ir_asm_constraint *constraint = &out_constraints[out_idx];
		unsigned                 pos        = constraint->pos;
463
		parse_asm_constraints(&parsed_constraint, constraint->constraint, true);
464
		arch_register_req_t const *const req = ia32_make_register_req(irg, &parsed_constraint, n_out_constraints, out_reg_reqs, out_idx);
465
466
		out_reg_reqs[out_idx] = req;

467
468
469
470
471
472
		/* multiple constraints for same pos. This can happen for example when
		 * a =A constraint gets lowered to two constraints: =a and =d for the
		 * same pos */
		if (register_map[pos].valid)
			continue;

473
474
475
476
477
478
479
480
		register_map[pos].use_input = 0;
		register_map[pos].valid     = 1;
		register_map[pos].memory    = 0;
		register_map[pos].inout_pos = out_idx;
		register_map[pos].mode      = constraint->mode;
	}

	/* inputs + input constraints */
481
482
483
484
485
	const arch_register_req_t **in_reg_reqs
		= OALLOCN(obst, const arch_register_req_t*, n_ins);
	for (int i = 0; i < n_inputs; ++i) {
		constraint_t               parsed_constraint;
		ir_node                   *pred         = get_ASM_input(node, i);
486
487
488
489
490
		const ir_asm_constraint   *constraint   = &in_constraints[i];
		unsigned                   pos          = constraint->pos;
		int                        is_memory_op = 0;
		ir_node                   *input        = NULL;

491
		parse_asm_constraints(&parsed_constraint, constraint->constraint, false);
Matthias Braun's avatar
Matthias Braun committed
492
		if (parsed_constraint.cls != NULL) {
493
494
			unsigned r_clobber_bits
				= clobber_bits[parsed_constraint.cls->index];
Matthias Braun's avatar
Matthias Braun committed
495
496
497
			if (r_clobber_bits != 0) {
				if (parsed_constraint.all_registers_allowed) {
					parsed_constraint.all_registers_allowed = 0;
498
					be_get_allocatable_regs(irg, parsed_constraint.cls, &parsed_constraint.allowed_registers);
Matthias Braun's avatar
Matthias Braun committed
499
500
				}
				parsed_constraint.allowed_registers &= ~r_clobber_bits;
501
502
503
			}
		}

504
		arch_register_req_t const *const req = ia32_make_register_req(irg, &parsed_constraint, n_out_constraints, out_reg_reqs, i);
505
506
507
508
		in_reg_reqs[i] = req;

		if (parsed_constraint.immediate_type != '\0') {
			char imm_type = parsed_constraint.immediate_type;
509
			input = ia32_try_create_Immediate(pred, imm_type);
510
511
512
		}

		if (input == NULL) {
513
			input = get_new_node(pred);
514

515
516
517
			if (parsed_constraint.cls == NULL
					&& parsed_constraint.same_as < 0) {
				is_memory_op = 1;
518
				in_reg_reqs[i] = ia32_reg_classes[CLASS_ia32_gp].class_req;
Michael Beck's avatar
Michael Beck committed
519
			} else if (parsed_constraint.memory_possible) {
520
521
522
523
524
525
526
527
528
529
530
531
				/* TODO: match Load or Load/Store if memory possible is set */
			}
		}
		in[i] = input;

		register_map[pos].use_input = 1;
		register_map[pos].valid     = 1;
		register_map[pos].memory    = is_memory_op;
		register_map[pos].inout_pos = i;
		register_map[pos].mode      = constraint->mode;
	}

532
533
534
535
536
	assert(n_inputs == n_ins-1);
	ir_node *mem = get_ASM_mem(node);
	in[n_inputs]          = be_transform_node(mem);
	in_reg_reqs[n_inputs] = arch_no_register_req;

537
	/* parse clobbers */
538
	for (size_t c = 0; c < get_ASM_n_clobbers(node); ++c) {
539
		const char                *clobber = get_id_str(clobbers[c]);
540
541
		const arch_register_req_t *req     = ia32_parse_clobber(clobber);
		if (req == NULL)
542
543
544
545
546
			continue;
		out_reg_reqs[out_idx] = req;
		++out_idx;
	}

yb9976's avatar
typos    
yb9976 committed
547
	/* Attempt to make ASM node register pressure faithful.
548
549
550
551
552
553
554
555
556
557
558
	 * (This does not work for complicated cases yet!)
	 *
	 * Algorithm: Check if there are fewer inputs or outputs (I will call this
	 * the smaller list). Then try to match each constraint of the smaller list
	 * to 1 of the other list. If we can't match it, then we have to add a dummy
	 * input/output to the other list
	 *
	 * FIXME: This is still broken in lots of cases. But at least better than
	 *        before...
	 * FIXME: need to do this per register class...
	 */
559
560
561
562
563
	if (out_arity <= (size_t)n_inputs) {
		int       orig_inputs = n_ins;
		int       in_size     = n_ins;
		bitset_t *used_ins    = bitset_alloca(n_ins);
		for (size_t o = 0; o < out_arity; ++o) {
564
			const arch_register_req_t *outreq = out_reg_reqs[o];
565
			if (match_requirement(in_reg_reqs, orig_inputs, used_ins, outreq))
566
567
568
				continue;

			/* we might need more space in the input arrays */
569
			if (n_ins >= in_size) {
570
				in_size *= 2;
571
572
				const arch_register_req_t **new_in_reg_reqs
					= OALLOCN(obst, const arch_register_req_t*,
573
				                          in_size);
574
575
576
577
				memcpy(new_in_reg_reqs, in_reg_reqs,
				       n_ins*sizeof(new_in_reg_reqs[0]));
				ir_node **new_in = ALLOCANZ(ir_node*, in_size);
				memcpy(new_in, in, n_ins*sizeof(new_in[0]));
578
579
580
581
582
583

				in_reg_reqs = new_in_reg_reqs;
				in          = new_in;
			}

			/* add a new (dummy) input which occupies the register */
584
			assert(arch_register_req_is(outreq, limited));
585
586
587
			in_reg_reqs[n_ins] = outreq;
			in[n_ins]          = new_bd_ia32_ProduceVal(NULL, block);
			++n_ins;
588
589
		}
	} else {
590
591
		bitset_t *used_outs      = bitset_alloca(out_arity);
		size_t    orig_out_arity = out_arity;
592
		for (int i = 0; i < n_inputs; ++i) {
593
			const arch_register_req_t *inreq = in_reg_reqs[i];
594
			if (match_requirement(out_reg_reqs, orig_out_arity, used_outs, inreq))
595
596
597
598
599
600
601
602
				continue;

			/* we might need more space in the output arrays */
			if (out_arity >= out_size) {
				const arch_register_req_t **new_out_reg_reqs;

				out_size *= 2;
				new_out_reg_reqs
603
					= OALLOCN(obst, const arch_register_req_t*, out_size);
604
605
606
607
608
609
				memcpy(new_out_reg_reqs, out_reg_reqs,
				       out_arity * sizeof(new_out_reg_reqs[0]));
				out_reg_reqs = new_out_reg_reqs;
			}

			/* add a new (dummy) output which occupies the register */
610
			assert(arch_register_req_is(inreq, limited));
611
612
613
614
615
			out_reg_reqs[out_arity] = inreq;
			++out_arity;
		}
	}

616
617
618
619
620
621
	/* append none register requirement for the memory output */
	if (out_arity + 1 >= out_size) {
		const arch_register_req_t **new_out_reg_reqs;

		out_size = out_arity + 1;
		new_out_reg_reqs
622
			= OALLOCN(obst, const arch_register_req_t*, out_size);
623
624
625
626
627
628
629
630
631
		memcpy(new_out_reg_reqs, out_reg_reqs,
			   out_arity * sizeof(new_out_reg_reqs[0]));
		out_reg_reqs = new_out_reg_reqs;
	}

	/* add a new (dummy) output which occupies the register */
	out_reg_reqs[out_arity] = arch_no_register_req;
	++out_arity;

632
633
	ir_node *new_node = new_bd_ia32_Asm(dbgi, new_block, n_ins, in, out_arity,
	                                    get_ASM_text(node), register_map);
634

635
636
	backend_info_t *info = be_get_info(new_node);
	for (size_t o = 0; o < out_arity; ++o) {
637
		info->out_infos[o].req = out_reg_reqs[o];
638
	}
639
	arch_set_irn_register_reqs_in(new_node, in_reg_reqs);
640

641
	SET_IA32_ORIG_NODE(new_node, node);
642
643
644
645

	return new_node;
}

646
ir_node *ia32_gen_CopyB(ir_node *node)
647
{
648
649
650
651
652
653
654
	ir_node  *block    = get_new_node(get_nodes_block(node));
	ir_node  *src      = get_CopyB_src(node);
	ir_node  *new_src  = get_new_node(src);
	ir_node  *dst      = get_CopyB_dst(node);
	ir_node  *new_dst  = get_new_node(dst);
	ir_node  *mem      = get_CopyB_mem(node);
	ir_node  *new_mem  = get_new_node(mem);
655
656
657
	ir_node  *res      = NULL;
	dbg_info *dbgi     = get_irn_dbg_info(node);
	int      size      = get_type_size_bytes(get_CopyB_type(node));
658
	int      throws_exception = ir_throws_exception(node);
659
660
661
662
663
664
665
666
	int      rem;

	/* If we have to copy more than 32 bytes, we use REP MOVSx and */
	/* then we need the size explicitly in ECX.                    */
	if (size >= 32 * 4) {
		rem = size & 0x3; /* size % 4 */
		size >>= 2;

667
		res = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, size);
668

669
		res = new_bd_ia32_CopyB(dbgi, block, new_dst, new_src, res, new_mem, rem);
670
	} else {
Michael Beck's avatar
Michael Beck committed
671
		if (size == 0) {
672
673
674
			ir_fprintf(stderr, "Optimization warning copyb %+F with size <4\n",
			           node);
		}
675
		res = new_bd_ia32_CopyB_i(dbgi, block, new_dst, new_src, new_mem, size);
676
	}
677
	ir_set_throws_exception(res, throws_exception);
678

679
	SET_IA32_ORIG_NODE(res, node);
680
681
682
683

	return res;
}

684
ir_node *ia32_gen_Proj_tls(ir_node *node)
685
{
686
	ir_node *block = get_new_node(get_nodes_block(node));
687
	ir_node *res   = new_bd_ia32_LdTls(NULL, block);
688
689
690
	return res;
}

691
ir_node *ia32_gen_Unknown(ir_node *node)
692
{
693
694
695
696
697
	ir_mode  *mode  = get_irn_mode(node);
	ir_graph *irg   = current_ir_graph;
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_node  *block = get_irg_start_block(irg);
	ir_node  *res   = NULL;
698
699
700

	if (mode_is_float(mode)) {
		if (ia32_cg_config.use_sse2) {
701
			res = new_bd_ia32_xUnknown(dbgi, block);
702
		} else {
703
			res = new_bd_ia32_fldz(dbgi, block);
704
705
		}
	} else if (ia32_mode_needs_gp_reg(mode)) {
706
		res = new_bd_ia32_Unknown(dbgi, block);
707
708
709
	} else {
		panic("unsupported Unknown-Mode");
	}
710
711

	return res;
712
713
}

714
static arch_register_req_t const *ia32_make_register_req(ir_graph *const irg, constraint_t const *const c, int const n_outs, arch_register_req_t const **const out_reqs, int const pos)
715
{
716
	int const same_as = c->same_as;
717
718
719
720
	if (same_as >= 0) {
		if (same_as >= n_outs)
			panic("invalid output number in same_as constraint");

721
		struct obstack            *const obst  = get_irg_obstack(irg);
722
723
724
725
726
		arch_register_req_t       *const req   = OALLOC(obst, arch_register_req_t);
		arch_register_req_t const *const other = out_reqs[same_as];
		*req            = *other;
		req->type      |= arch_register_req_type_should_be_same;
		req->other_same = 1U << pos;
727

728
		/* Switch constraints. This is because in firm we have same_as
729
		 * constraints on the output constraints while in the gcc asm syntax
730
		 * they are specified on the input constraints. */
731
		out_reqs[same_as] = req;
732
		return other;
733
734
	}

735
736
	/* Pure memory ops. */
	if (!c->cls)
737
		return arch_no_register_req;
738

739
740
	if (c->allowed_registers == 0 || c->all_registers_allowed)
		return c->cls->class_req;
741

742
	struct obstack      *const obst    = get_irg_obstack(irg);
743
744
745
	arch_register_req_t *const req     = (arch_register_req_t*)obstack_alloc(obst, sizeof(req[0]) + sizeof(unsigned));
	unsigned            *const limited = (unsigned*)(req + 1);
	*limited = c->allowed_registers;
746

747
748
749
750
751
752
	memset(req, 0, sizeof(req[0]));
	req->type    = arch_register_req_type_limited;
	req->cls     = c->cls;
	req->limited = limited;
	req->width   = 1;
	return req;
753
754
}

755
const arch_register_req_t *ia32_parse_clobber(const char *clobber)
756
{
757
758
759
	if (strcmp(clobber, "memory") == 0 || strcmp(clobber, "cc") == 0)
		return NULL;

760
761
	arch_register_t const *const reg = ia32_get_clobber_register(clobber);
	if (!reg)
762
		panic("Register '%s' mentioned in asm clobber is unknown", clobber);
763

764
	return reg->single_req;
765
766
}

767

768
int ia32_prevents_AM(ir_node *const block, ir_node *const am_candidate,
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
                       ir_node *const other)
{
	if (get_nodes_block(other) != block)
		return 0;

	if (is_Sync(other)) {
		int i;

		for (i = get_Sync_n_preds(other) - 1; i >= 0; --i) {
			ir_node *const pred = get_Sync_pred(other, i);

			if (get_nodes_block(pred) != block)
				continue;

			/* Do not block ourselves from getting eaten */
			if (is_Proj(pred) && get_Proj_pred(pred) == am_candidate)
				continue;

787
			if (!heights_reachable_in_block(ia32_heights, pred, am_candidate))
788
789
790
791
792
793
794
795
796
797
798
				continue;

			return 1;
		}

		return 0;
	} else {
		/* Do not block ourselves from getting eaten */
		if (is_Proj(other) && get_Proj_pred(other) == am_candidate)
			return 0;

799
		if (!heights_reachable_in_block(ia32_heights, other, am_candidate))
800
801
802
803
804
805
			return 0;

		return 1;
	}
}

806
ir_node *ia32_try_create_Immediate(ir_node *node, char immediate_constraint_type)
807
{
808
809
	ir_mode *const mode = get_irn_mode(node);
	if (!mode_is_int(mode) && !mode_is_reference(mode))
810
811
		return NULL;

812
813
	ir_node *cnst;
	ir_node *symconst;
Michael Beck's avatar
Michael Beck committed
814
	if (is_Const(node)) {
815
816
		cnst     = node;
		symconst = NULL;
817
818
	} else if (is_SymConst_addr_ent(node)
			&& get_entity_owner(get_SymConst_entity(node)) != get_tls_type()) {
819
820
		cnst     = NULL;
		symconst = node;
Michael Beck's avatar
Michael Beck committed
821
	} else if (is_Add(node)) {
822
823
		ir_node *left  = get_Add_left(node);
		ir_node *right = get_Add_right(node);
824
		if (is_Const(left) && is_SymConst_addr_ent(right)) {
825
826
			cnst     = left;
			symconst = right;
827
		} else if (is_SymConst_addr_ent(left) && is_Const(right)) {
828
829
			cnst     = right;
			symconst = left;
830
831
		} else {
			return NULL;
832
833
834
835
836
		}
	} else {
		return NULL;
	}

837
	long val = 0;
Michael Beck's avatar
Michael Beck committed
838
	if (cnst != NULL) {
Matthias Braun's avatar
Matthias Braun committed
839
		ir_tarval *offset = get_Const_tarval(cnst);
840
841
		if (!tarval_is_long(offset)) {
			ir_fprintf(stderr, "Optimisation Warning: tarval of %+F is not a long?\n", cnst);
842
843
844
			return NULL;
		}

845
		val = get_tarval_long(offset);
Michael Beck's avatar
Michael Beck committed
846
		if (!check_immediate_constraint(val, immediate_constraint_type))
847
848
			return NULL;
	}
849
850

	ir_entity *symconst_ent = NULL;
Michael Beck's avatar
Michael Beck committed
851
	if (symconst != NULL) {
852
853
		/* we need full 32bits for symconsts */
		if (immediate_constraint_type != 'i')
854
855
			return NULL;

856
		symconst_ent = get_SymConst_entity(symconst);
857
858
	}

859
860
	ir_graph *const irg = get_irn_irg(node);
	return ia32_create_Immediate(irg, symconst_ent, 0, val);
861
}