ia32_new_nodes.c 28.7 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
10
 * @file
 * @brief       Handling of ia32 specific firm opcodes.
 * @author      Christian Wuerdig
 *
yb9976's avatar
yb9976 committed
11
 * This file implements the creation of the architecture specific firm opcodes
Christoph Mallon's avatar
Christoph Mallon committed
12
 * and the corresponding node constructors for the ia32 assembler irg.
13
14
 */
#include <stdlib.h>
15
#include <stdbool.h>
16
#include <inttypes.h>
17

18
#include "irargs_t.h"
19
20
21
22
23
24
#include "irprog_t.h"
#include "irgraph_t.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "ircons_t.h"
#include "iropt_t.h"
Christian Würdig's avatar
Christian Würdig committed
25
#include "irop.h"
26
#include "irverify_t.h"
27
#include "irprintf.h"
28
#include "iredges.h"
Matthias Braun's avatar
Matthias Braun committed
29
#include "panic.h"
30
#include "xmalloc.h"
31

32
#include "bearch.h"
33
#include "bedump.h"
34
#include "beinfo.h"
35

36
#include "bearch_ia32_t.h"
37
#include "ia32_common_transform.h"
38
39
#include "ia32_nodes_attr.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
40
#include "gen_ia32_regalloc_if.h"
41

Matthias Braun's avatar
Matthias Braun committed
42
43
struct obstack opcodes_obst;

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
static const char *condition_code_name(x86_condition_code_t cc)
{
	switch (cc) {
	case x86_cc_overflow:                    return "overflow";
	case x86_cc_not_overflow:                return "not overflow";
	case x86_cc_float_below:                 return "float below";
	case x86_cc_float_unordered_below:       return "float unordered or below";
	case x86_cc_below:                       return "below";
	case x86_cc_float_above_equal:           return "float above or equal";
	case x86_cc_float_unordered_above_equal: return "float unordered or above or equal";
	case x86_cc_above_equal:                 return "above or equal";
	case x86_cc_float_equal:                 return "float equal";
	case x86_cc_equal:                       return "equal";
	case x86_cc_float_not_equal:             return "float not equal";
	case x86_cc_not_equal:                   return "not equal";
	case x86_cc_float_below_equal:           return "float below or equal";
	case x86_cc_float_unordered_below_equal: return "float unordered or below or equal";
	case x86_cc_below_equal:                 return "below or equal";
	case x86_cc_float_above:                 return "float above";
	case x86_cc_float_unordered_above:       return "float unordered or above";
	case x86_cc_above:                       return "above";
	case x86_cc_sign:                        return "sign";
	case x86_cc_not_sign:                    return "no sign";
	case x86_cc_parity:                      return "parity";
	case x86_cc_not_parity:                  return "no parity";
	case x86_cc_less:                        return "less";
	case x86_cc_greater_equal:               return "greater or equal";
	case x86_cc_less_equal:                  return "less or equal";
	case x86_cc_greater:                     return "greater";
	case x86_cc_float_parity_cases:          return "float parity cases";
	case x86_cc_additional_float_cases:      return "additional float cases";
	default:                                 return NULL;
	}
}

79
80
81
82
83
84
85
static bool has_ia32_condcode_attr(const ir_node *node)
{
	return is_ia32_Setcc(node) || is_ia32_SetccMem(node) || is_ia32_CMovcc(node)
	    || is_ia32_Jcc(node) || is_ia32_Adc(node) || is_ia32_Sbb(node)
	    || is_ia32_Sbb0(node) || is_ia32_Cmc(node);
}

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
static bool has_ia32_x87_attr(ir_node const *const node)
{
	switch ((ia32_opcodes)get_ia32_irn_opcode(node)) {
	case iro_ia32_FucomFnstsw:
	case iro_ia32_Fucomi:
	case iro_ia32_FucomppFnstsw:
	case iro_ia32_fadd:
	case iro_ia32_fdiv:
	case iro_ia32_ffreep:
	case iro_ia32_fist:
	case iro_ia32_fisttp:
	case iro_ia32_fmul:
	case iro_ia32_fpop:
	case iro_ia32_fpush:
	case iro_ia32_fpushCopy:
	case iro_ia32_fst:
	case iro_ia32_fsub:
	case iro_ia32_fxch:
		return true;

	default:
		return false;
	}
}

111
112
113
114
115
116
117
118
119
120
121
static char const *get_frame_use_str(ir_node const *const node)
{
	switch (get_ia32_frame_use(node)) {
	case IA32_FRAME_USE_NONE:  return "none";
	case IA32_FRAME_USE_32BIT: return "32bit";
	case IA32_FRAME_USE_64BIT: return "64bit";
	case IA32_FRAME_USE_AUTO:  return "auto";
	}
	return "invalid";
}

122
123
124
125
126
127
128
/**
 * Dumper interface for dumping ia32 nodes in vcg.
 * @param n        the node to dump
 * @param F        the output file
 * @param reason   indicates which kind of information should be dumped
 * @return 0 on success or != 0 on failure
 */
129
static void ia32_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
130
{
131
	ir_mode *mode = NULL;
Christian Würdig's avatar
Christian Würdig committed
132
133
134

	switch (reason) {
		case dump_node_opcode_txt:
135
			fprintf(F, "%s", get_irn_opname(n));
136

137
			if (is_ia32_Immediate(n) || is_ia32_Const(n)) {
138
139
140
141
				const ia32_immediate_attr_t *attr
					= get_ia32_immediate_attr_const(n);

				fputc(' ', F);
142
143
				if (attr->entity) {
					fputs(get_entity_name(attr->entity), F);
144
				}
145
146
				if (attr->offset != 0 || attr->entity == NULL) {
					if (attr->offset > 0 && attr->entity != NULL) {
147
148
						fputc('+', F);
					}
149
					fprintf(F, "%"PRId32, attr->offset);
150
151
152
					if (attr->no_pic_adjust) {
						fputs("(no_pic_adjust)", F);
					}
153
				}
154
			} else {
155
156
				const ia32_attr_t *attr = get_ia32_attr_const(n);

157
				if (attr->am_ent != NULL || attr->am_offs != 0) {
158
159
					fputs(" [", F);

160
161
					if (attr->am_ent != NULL) {
						fputs(get_entity_name(attr->am_ent), F);
162
						if (attr->am_sc_no_pic_adjust) {
163
164
							fputs("(no_pic_adjust)", F);
						}
165
					}
166
167
168
169
170
					if (attr->am_offs != 0) {
						if (attr->am_offs > 0 && attr->am_ent != NULL) {
							fputc('+', F);
						}
						fprintf(F, "%d", attr->am_offs);
171
172
173
					}

					fputc(']', F);
174
				}
175
			}
Christian Würdig's avatar
Christian Würdig committed
176
177
			break;

178
		case dump_node_mode_txt:
179
180
181
			mode = get_ia32_ls_mode(n);
			if (mode != NULL)
				fprintf(F, "[%s]", get_mode_name(mode));
182
			break;
Christian Würdig's avatar
Christian Würdig committed
183

184
		case dump_node_nodeattr_txt:
185
			if (! is_ia32_Lea(n)) {
186
187
188
189
				switch (get_ia32_op_type(n)) {
				case ia32_Normal:    break;
				case ia32_AddrModeS: fprintf(F, "[AM S] "); break;
				case ia32_AddrModeD: fprintf(F, "[AM D] "); break;
190
				}
Christian Würdig's avatar
Christian Würdig committed
191
192
193
194
			}
			break;

		case dump_node_info_txt:
195
			be_dump_reqs_and_registers(F, n);
196
197
198

			/* dump op type */
			fprintf(F, "op = ");
199
			switch (get_ia32_op_type(n)) {
200
201
202
203
204
205
206
207
208
				case ia32_Normal:
					fprintf(F, "Normal");
					break;
				case ia32_AddrModeD:
					fprintf(F, "AM Dest (Load+Store)");
					break;
				case ia32_AddrModeS:
					fprintf(F, "AM Source (Load)");
					break;
Christian Würdig's avatar
Christian Würdig committed
209
				default:
Matthias Braun's avatar
Matthias Braun committed
210
					fprintf(F, "unknown (%d)", (int)get_ia32_op_type(n));
Christian Würdig's avatar
Christian Würdig committed
211
					break;
212
213
214
215
216
			}
			fprintf(F, "\n");

			/* dump supported am */
			fprintf(F, "AM support = ");
217
			switch (get_ia32_am_support(n)) {
218
219
220
221
				case ia32_am_none:   fputs("none\n",            F); break;
				case ia32_am_unary:  fputs("source (unary)\n",  F); break;
				case ia32_am_binary: fputs("source (binary)\n", F); break;

Christian Würdig's avatar
Christian Würdig committed
222
				default:
Matthias Braun's avatar
Matthias Braun committed
223
					fprintf(F, "unknown (%d)\n", (int)get_ia32_am_support(n));
Christian Würdig's avatar
Christian Würdig committed
224
					break;
225
			}
Christian Würdig's avatar
Christian Würdig committed
226

227
			/* dump AM offset */
228
			if (get_ia32_am_offs_int(n) != 0) {
229
				fprintf(F, "AM offset = %d\n", get_ia32_am_offs_int(n));
230
			}
Christian Würdig's avatar
Christian Würdig committed
231

232
233
234
			/* dump AM entity */
			ir_entity *ent = get_ia32_am_ent(n);
			if (ent != NULL) {
235
				ident *id = get_entity_ld_ident(ent);
236
				fprintf(F, "AM entity = %s\n", get_id_str(id));
Matthias Braun's avatar
Matthias Braun committed
237
238
			}

239
			/* dump AM scale */
240
			fprintf(F, "AM scale = %u\n", get_ia32_am_scale(n));
Christian Würdig's avatar
Christian Würdig committed
241

242
			/* dump pn code */
243
			if (has_ia32_condcode_attr(n)) {
244
				const ia32_attr_t *attr = get_ia32_attr_const(n);
245
246
247
248
249
250
251
				const char *cc_name = condition_code_name(get_ia32_condcode(n));
				if (cc_name) {
					fprintf(F, "condition_code = %s\n", cc_name);
				} else {
					fprintf(F, "condition_code = <invalid (0x%X)>\n",
					        (unsigned)get_ia32_condcode(n));
				}
252
				fprintf(F, "ins_permuted = %s\n", be_dump_yesno(attr->ins_permuted));
253
			} else if (is_ia32_CopyB(n) || is_ia32_CopyB_i(n)) {
Michael Beck's avatar
Michael Beck committed
254
				fprintf(F, "size = %u\n", get_ia32_copyb_size(n));
255
256
257
258
259
			} else if (has_ia32_x87_attr(n)) {
				ia32_x87_attr_t const *const attr = get_ia32_x87_attr_const(n);
				fprintf(F, "explicit operand = %s\n", be_dump_reg_name(attr->reg));
				fprintf(F, "result to explicit operand = %s\n", be_dump_yesno(attr->res_in_reg));
				fprintf(F, "pop = %s\n", be_dump_yesno(attr->pop));
260
			}
Christian Würdig's avatar
Christian Würdig committed
261

262
263
			fprintf(F, "commutative = %s\n", be_dump_yesno(is_ia32_commutative(n)));
			fprintf(F, "is reload = %s\n", be_dump_yesno(is_ia32_is_reload(n)));
264
			fprintf(F, "latency = %u\n", get_ia32_latency(n));
Christian Würdig's avatar
Christian Würdig committed
265

266
			/* dump frame entity */
267
			fprintf(F, "frame use = %s\n", get_frame_use_str(n));
268
269
270
			fprintf(F, "frame entity = ");
			if (get_ia32_frame_ent(n)) {
				ir_fprintf(F, "%+F", get_ia32_frame_ent(n));
271
			} else {
272
273
274
				fprintf(F, "n/a");
			}
			fprintf(F, "\n");
275

276
277
278
279
			/* dump modes */
			fprintf(F, "ls_mode = ");
			if (get_ia32_ls_mode(n)) {
				ir_fprintf(F, "%+F", get_ia32_ls_mode(n));
280
			} else {
281
282
283
284
				fprintf(F, "n/a");
			}
			fprintf(F, "\n");

Christian Würdig's avatar
Christian Würdig committed
285
286
#ifndef NDEBUG
			/* dump original ir node name */
287
288
			char const *orig = get_ia32_attr_const(n)->orig_node;
			fprintf(F, "orig node = %s\n", orig ? orig : "n/a");
Christian Würdig's avatar
Christian Würdig committed
289
290
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
291
			break;
292
	}
293
294
295
296
}



297
298
ia32_attr_t *get_ia32_attr(ir_node *node)
{
299
	assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes");
300
	return (ia32_attr_t *)get_irn_generic_attr(node);
301
302
}

303
304
const ia32_attr_t *get_ia32_attr_const(const ir_node *node)
{
305
306
307
308
	assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes");
	return (const ia32_attr_t*) get_irn_generic_attr_const(node);
}

309
310
ia32_x87_attr_t *get_ia32_x87_attr(ir_node *node)
{
311
312
313
314
315
	ia32_attr_t     *attr     = get_ia32_attr(node);
	ia32_x87_attr_t *x87_attr = CAST_IA32_ATTR(ia32_x87_attr_t, attr);
	return x87_attr;
}

316
317
const ia32_x87_attr_t *get_ia32_x87_attr_const(const ir_node *node)
{
318
319
320
321
322
	const ia32_attr_t     *attr     = get_ia32_attr_const(node);
	const ia32_x87_attr_t *x87_attr = CONST_CAST_IA32_ATTR(ia32_x87_attr_t, attr);
	return x87_attr;
}

323
324
const ia32_asm_attr_t *get_ia32_asm_attr_const(const ir_node *node)
{
325
326
327
328
329
330
	const ia32_attr_t     *attr     = get_ia32_attr_const(node);
	const ia32_asm_attr_t *asm_attr = CONST_CAST_IA32_ATTR(ia32_asm_attr_t, attr);

	return asm_attr;
}

331
332
ia32_immediate_attr_t *get_ia32_immediate_attr(ir_node *node)
{
333
334
335
336
337
338
	ia32_attr_t           *attr      = get_ia32_attr(node);
	ia32_immediate_attr_t *imm_attr  = CAST_IA32_ATTR(ia32_immediate_attr_t, attr);

	return imm_attr;
}

339
340
const ia32_immediate_attr_t *get_ia32_immediate_attr_const(const ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
341
342
	const ia32_attr_t           *attr     = get_ia32_attr_const(node);
	const ia32_immediate_attr_t *imm_attr = CONST_CAST_IA32_ATTR(ia32_immediate_attr_t, attr);
343

Michael Beck's avatar
Michael Beck committed
344
345
346
	return imm_attr;
}

347
348
ia32_condcode_attr_t *get_ia32_condcode_attr(ir_node *node)
{
349
	assert(has_ia32_condcode_attr(node));
Michael Beck's avatar
Michael Beck committed
350
351
352
353
354
355
	ia32_attr_t          *attr    = get_ia32_attr(node);
	ia32_condcode_attr_t *cc_attr = CAST_IA32_ATTR(ia32_condcode_attr_t, attr);

	return cc_attr;
}

356
357
const ia32_condcode_attr_t *get_ia32_condcode_attr_const(const ir_node *node)
{
358
	assert(has_ia32_condcode_attr(node));
Michael Beck's avatar
Michael Beck committed
359
360
361
362
363
364
	const ia32_attr_t          *attr    = get_ia32_attr_const(node);
	const ia32_condcode_attr_t *cc_attr = CONST_CAST_IA32_ATTR(ia32_condcode_attr_t, attr);

	return cc_attr;
}

365
366
367
368
369
370
371
372
373
374
375
376
377
378
ia32_switch_attr_t *get_ia32_switch_attr(ir_node *node)
{
	ia32_attr_t        *attr        = get_ia32_attr(node);
	ia32_switch_attr_t *switch_attr = CAST_IA32_ATTR(ia32_switch_attr_t, attr);
	return switch_attr;
}

const ia32_switch_attr_t *get_ia32_switch_attr_const(const ir_node *node)
{
	const ia32_attr_t        *attr        = get_ia32_attr_const(node);
	const ia32_switch_attr_t *switch_attr = CONST_CAST_IA32_ATTR(ia32_switch_attr_t, attr);
	return switch_attr;
}

379
380
381
382
383
384
385
386
387
388
389
390
391
392
ia32_return_attr_t *get_ia32_return_attr(ir_node *node)
{
	ia32_attr_t        *attr        = get_ia32_attr(node);
	ia32_return_attr_t *return_attr = CAST_IA32_ATTR(ia32_return_attr_t, attr);
	return return_attr;
}

const ia32_return_attr_t *get_ia32_return_attr_const(const ir_node *node)
{
	const ia32_attr_t        *attr        = get_ia32_attr_const(node);
	const ia32_return_attr_t *return_attr = CONST_CAST_IA32_ATTR(ia32_return_attr_t, attr);
	return return_attr;
}

393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
ia32_call_attr_t *get_ia32_call_attr(ir_node *node)
{
	ia32_attr_t      *attr      = get_ia32_attr(node);
	ia32_call_attr_t *call_attr = CAST_IA32_ATTR(ia32_call_attr_t, attr);

	return call_attr;
}

const ia32_call_attr_t *get_ia32_call_attr_const(const ir_node *node)
{
	const ia32_attr_t      *attr      = get_ia32_attr_const(node);
	const ia32_call_attr_t *call_attr = CONST_CAST_IA32_ATTR(ia32_call_attr_t, attr);

	return call_attr;
}

409
410
ia32_copyb_attr_t *get_ia32_copyb_attr(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
411
412
413
414
415
416
	ia32_attr_t       *attr       = get_ia32_attr(node);
	ia32_copyb_attr_t *copyb_attr = CAST_IA32_ATTR(ia32_copyb_attr_t, attr);

	return copyb_attr;
}

417
418
const ia32_copyb_attr_t *get_ia32_copyb_attr_const(const ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
419
420
421
422
	const ia32_attr_t       *attr       = get_ia32_attr_const(node);
	const ia32_copyb_attr_t *copyb_attr = CONST_CAST_IA32_ATTR(ia32_copyb_attr_t, attr);

	return copyb_attr;
423
424
}

425
426
ia32_climbframe_attr_t *get_ia32_climbframe_attr(ir_node *node)
{
427
428
429
430
431
432
	ia32_attr_t            *attr            = get_ia32_attr(node);
	ia32_climbframe_attr_t *climbframe_attr = CAST_IA32_ATTR(ia32_climbframe_attr_t, attr);

	return climbframe_attr;
}

433
434
const ia32_climbframe_attr_t *get_ia32_climbframe_attr_const(const ir_node *node)
{
435
436
437
438
439
440
	const ia32_attr_t            *attr            = get_ia32_attr_const(node);
	const ia32_climbframe_attr_t *climbframe_attr = CONST_CAST_IA32_ATTR(ia32_climbframe_attr_t, attr);

	return climbframe_attr;
}

441
/**
442
 * Gets the type of an ia32 node.
443
 */
444
445
ia32_op_type_t get_ia32_op_type(const ir_node *node)
{
446
	const ia32_attr_t *attr = get_ia32_attr_const(node);
447
	return (ia32_op_type_t)attr->tp;
448
449
450
}

/**
451
 * Sets the type of an ia32 node.
452
 */
453
454
void set_ia32_op_type(ir_node *node, ia32_op_type_t tp)
{
455
	ia32_attr_t *attr = get_ia32_attr(node);
456
	attr->tp = tp;
457
458
}

459
460
ia32_am_type_t get_ia32_am_support(const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
461
	const ia32_attr_t *attr = get_ia32_attr_const(node);
462
	return (ia32_am_type_t)attr->am_arity;
Matthias Braun's avatar
Matthias Braun committed
463
464
}

465
/**
466
 * Sets the supported address mode of an ia32 node
467
 */
468
469
void set_ia32_am_support(ir_node *node, ia32_am_type_t arity)
{
470
471
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->am_arity = arity;
Christian Würdig's avatar
Christian Würdig committed
472
473
}

474
/**
475
 * Gets the address mode offset as int.
476
 */
477
int32_t get_ia32_am_offs_int(const ir_node *node)
478
{
479
	const ia32_attr_t *attr = get_ia32_attr_const(node);
480
481
482
	return attr->am_offs;
}

483
/**
484
 * Sets the address mode offset from an int.
485
 */
486
void set_ia32_am_offs_int(ir_node *node, int32_t offset)
487
{
488
489
490
491
	ia32_attr_t *attr = get_ia32_attr(node);
	attr->am_offs = offset;
}

492
void add_ia32_am_offs_int(ir_node *node, int32_t offset)
493
{
494
495
496
497
	ia32_attr_t *attr = get_ia32_attr(node);
	attr->am_offs += offset;
}

498
ir_entity *get_ia32_am_ent(const ir_node *node)
499
{
500
	const ia32_attr_t *attr = get_ia32_attr_const(node);
501
	return attr->am_ent;
502
503
}

504
void set_ia32_am_ent(ir_node *node, ir_entity *entity)
505
{
506
	ia32_attr_t *attr = get_ia32_attr(node);
507
	attr->am_ent      = entity;
508
509
}

510
511
512
void set_ia32_am_tls_segment(ir_node *node, bool value)
{
	ia32_attr_t *attr = get_ia32_attr(node);
513
	attr->am_tls_segment = value;
514
515
516
517
518
}

bool get_ia32_am_tls_segment(const ir_node *node)
{
	const ia32_attr_t *attr = get_ia32_attr_const(node);
519
	return attr->am_tls_segment;
520
521
}

522
523
524
/**
 * Gets the addr mode const.
 */
525
526
unsigned get_ia32_am_scale(const ir_node *node)
{
527
	const ia32_attr_t *attr = get_ia32_attr_const(node);
528
	return attr->am_scale;
529
530
}

Christian Würdig's avatar
Christian Würdig committed
531
/**
532
 * Sets the index register scale for address mode.
Christian Würdig's avatar
Christian Würdig committed
533
 */
534
535
void set_ia32_am_scale(ir_node *node, unsigned scale)
{
536
	ia32_attr_t *attr = get_ia32_attr(node);
Michael Beck's avatar
Michael Beck committed
537
	assert(scale <= 3 && "AM scale out of range [0 ... 3]");
538
	attr->am_scale = scale;
Christian Würdig's avatar
Christian Würdig committed
539
540
}

541
542
543
544
void ia32_copy_am_attrs(ir_node *to, const ir_node *from)
{
	set_ia32_ls_mode(to, get_ia32_ls_mode(from));
	set_ia32_am_scale(to, get_ia32_am_scale(from));
545
	set_ia32_am_ent(to, get_ia32_am_ent(from));
546
547
	add_ia32_am_offs_int(to, get_ia32_am_offs_int(from));
	set_ia32_frame_ent(to, get_ia32_frame_ent(from));
548
	set_ia32_frame_use(to, get_ia32_frame_use(from));
549
550
551
552
553
}

/**
 * Sets node to commutative.
 */
554
555
void set_ia32_commutative(ir_node *node)
{
556
557
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->is_commutative = 1;
558
559
560
561
562
}

/**
 * Sets node to non-commutative.
 */
563
564
void clear_ia32_commutative(ir_node *node)
{
565
566
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->is_commutative = 0;
567
568
569
}

/**
570
 * Checks if node is commutative.
571
 */
572
573
int is_ia32_commutative(const ir_node *node)
{
574
	const ia32_attr_t *attr = get_ia32_attr_const(node);
575
	return attr->is_commutative;
576
577
}

578
579
void set_ia32_is_reload(ir_node *node)
{
580
	ia32_attr_t *attr = get_ia32_attr(node);
581
	attr->is_reload = 1;
582
583
}

584
585
int is_ia32_is_reload(const ir_node *node)
{
586
	const ia32_attr_t *attr = get_ia32_attr_const(node);
587
	return attr->is_reload;
588
589
}

590
591
void set_ia32_is_spill(ir_node *node)
{
592
	ia32_attr_t *attr = get_ia32_attr(node);
593
	attr->is_spill = 1;
594
595
}

596
597
int is_ia32_is_spill(const ir_node *node)
{
598
	const ia32_attr_t *attr = get_ia32_attr_const(node);
599
	return attr->is_spill;
600
601
}

602
603
void set_ia32_is_remat(ir_node *node)
{
604
	ia32_attr_t *attr = get_ia32_attr(node);
605
	attr->is_remat = 1;
606
607
}

608
609
int is_ia32_is_remat(const ir_node *node)
{
610
	const ia32_attr_t *attr = get_ia32_attr_const(node);
611
	return attr->is_remat;
612
613
}

614
615
616
/**
 * Gets the mode of the stored/loaded value (only set for Store/Load)
 */
617
618
ir_mode *get_ia32_ls_mode(const ir_node *node)
{
619
	const ia32_attr_t *attr = get_ia32_attr_const(node);
620
	return attr->ls_mode;
621
622
623
624
625
}

/**
 * Sets the mode of the stored/loaded value (only set for Store/Load)
 */
626
627
void set_ia32_ls_mode(ir_node *node, ir_mode *mode)
{
628
629
	ia32_attr_t *attr = get_ia32_attr(node);
	attr->ls_mode     = mode;
630
631
}

632
/**
633
 * Gets the frame entity assigned to this node.
634
 */
635
636
ir_entity *get_ia32_frame_ent(const ir_node *node)
{
637
	const ia32_attr_t *attr = get_ia32_attr_const(node);
638
639
640
641
	return attr->frame_ent;
}

/**
642
 * Sets the frame entity for this node.
643
 */
644
645
void set_ia32_frame_ent(ir_node *node, ir_entity *ent)
{
646
647
	ia32_attr_t *attr = get_ia32_attr(node);
	attr->frame_ent   = ent;
648
649
650
651
652
653
654
	if (!ent) {
		set_ia32_frame_use(node, IA32_FRAME_USE_NONE);
	} else if (get_ia32_frame_use(node) == IA32_FRAME_USE_NONE) {
		/* Only set frame use to auto, if it is not set to something more specific
		 * already. */
		set_ia32_frame_use(node, IA32_FRAME_USE_AUTO);
	}
655
656
}

Christian Würdig's avatar
Christian Würdig committed
657
658
659
660

/**
 * Gets the instruction latency.
 */
661
662
unsigned get_ia32_latency(const ir_node *node)
{
663
	assert(is_ia32_irn(node));
664
665
666
	const ir_op *op               = get_irn_op(node);
	const ia32_op_attr_t *op_attr = (ia32_op_attr_t*) get_op_attr(op);
	return op_attr->latency;
Christian Würdig's avatar
Christian Würdig committed
667
668
}

Matthias Braun's avatar
Matthias Braun committed
669
670
671
672
673
674
const ir_switch_table *get_ia32_switch_table(const ir_node *node)
{
	const ia32_switch_attr_t *attr = get_ia32_switch_attr_const(node);
	return attr->table;
}

675
x86_condition_code_t get_ia32_condcode(const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
676
{
Michael Beck's avatar
Michael Beck committed
677
	const ia32_condcode_attr_t *attr = get_ia32_condcode_attr_const(node);
678
	return attr->condition_code;
Christian Würdig's avatar
Christian Würdig committed
679
680
681
}

/**
Michael Beck's avatar
Michael Beck committed
682
 * Sets the condition code of a node
Christian Würdig's avatar
Christian Würdig committed
683
 */
684
void set_ia32_condcode(ir_node *node, x86_condition_code_t code)
Matthias Braun's avatar
Matthias Braun committed
685
{
Michael Beck's avatar
Michael Beck committed
686
	ia32_condcode_attr_t *attr = get_ia32_condcode_attr(node);
687
688
689
	attr->condition_code = code;
}

Michael Beck's avatar
Michael Beck committed
690
691
692
693
694
695
696
/**
 * Returns the condition code of a node.
 */
unsigned get_ia32_copyb_size(const ir_node *node)
{
	const ia32_copyb_attr_t *attr = get_ia32_copyb_attr_const(node);
	return attr->size;
697
698
}

699
700
701
/**
 * Get the exception label attribute.
 */
702
703
unsigned get_ia32_exc_label(const ir_node *node)
{
704
	const ia32_attr_t *attr = get_ia32_attr_const(node);
705
	return attr->has_except_label;
706
707
708
709
710
}

/**
 * Set the exception label attribute.
 */
711
712
void set_ia32_exc_label(ir_node *node, unsigned flag)
{
713
	ia32_attr_t *attr = get_ia32_attr(node);
714
	attr->has_except_label = flag;
715
716
717
718
719
}

/**
 * Return the exception label id.
 */
720
721
ir_label_t get_ia32_exc_label_id(const ir_node *node)
{
722
723
	const ia32_attr_t *attr = get_ia32_attr_const(node);

724
	assert(attr->has_except_label);
725
726
727
728
729
730
	return attr->exc_label;
}

/**
 * Assign the exception label id.
 */
731
732
void set_ia32_exc_label_id(ir_node *node, ir_label_t id)
{
733
734
	ia32_attr_t *attr = get_ia32_attr(node);

735
	assert(attr->has_except_label);
736
	attr->exc_label = id;
737
738
}

Christian Würdig's avatar
Christian Würdig committed
739
740
#ifndef NDEBUG

741
742
static const char *ia32_get_old_node_name(const ir_node *irn)
{
743
744
	ir_graph       *irg  = get_irn_irg(irn);
	struct obstack *obst = be_get_be_obst(irg);
745
746
747

	lc_eoprintf(firm_get_arg_env(), obst, "%+F", irn);
	obstack_1grow(obst, 0);
748
	return (const char*)obstack_finish(obst);
749
750
}

Christian Würdig's avatar
Christian Würdig committed
751
752
753
/**
 * Sets the name of the original ir node.
 */
754
755
756
void set_ia32_orig_node(ir_node *node, const ir_node *old)
{
	const char  *name = ia32_get_old_node_name(old);
Christian Würdig's avatar
Christian Würdig committed
757
758
759
760
761
	ia32_attr_t *attr = get_ia32_attr(node);
	attr->orig_node   = name;
}

#endif /* NDEBUG */
762

763
764
void ia32_swap_left_right(ir_node *node)
{
765
766
767
768
	ia32_attr_t *attr  = get_ia32_attr(node);
	ir_node     *left  = get_irn_n(node, n_ia32_binary_left);
	ir_node     *right = get_irn_n(node, n_ia32_binary_right);

Michael Beck's avatar
Michael Beck committed
769
	assert(is_ia32_commutative(node));
770
	attr->ins_permuted = !attr->ins_permuted;
771
772
	set_irn_n(node, n_ia32_binary_left,  right);
	set_irn_n(node, n_ia32_binary_right, left);
773
774
}

775
776
777
/**
 * Initializes the nodes attributes.
 */
778
779
780
static void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
                                 const arch_register_req_t **in_reqs,
                                 int n_res)
781
{
yb9976's avatar
yb9976 committed
782
783
784
	ir_graph       *irg  = get_irn_irg(node);
	struct obstack *obst = get_irg_obstack(irg);
	backend_info_t *info;
785

786
787
	arch_set_irn_flags(node, flags);
	arch_set_irn_register_reqs_in(node, in_reqs);
788

789
#ifndef NDEBUG
yb9976's avatar
yb9976 committed
790
791
	ia32_attr_t *attr  = get_ia32_attr(node);
	attr->attr_type   |= IA32_ATTR_ia32_attr_t;
792
#endif
793

794
	info            = be_get_info(node);
795
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_res);
796
797
}

798
static void init_ia32_x87_attributes(ir_node *res)
799
800
801
802
803
{
#ifndef NDEBUG
	ia32_attr_t *attr  = get_ia32_attr(res);
	attr->attr_type   |= IA32_ATTR_ia32_x87_attr_t;
#endif
804
805
	ir_graph *const irg = get_irn_irg(res);
	ia32_request_x87_sim(irg);
806
807
}

808
static void init_ia32_asm_attributes(ir_node *res)
809
810
811
812
813
{
#ifndef NDEBUG
	ia32_attr_t *attr  = get_ia32_attr(res);
	attr->attr_type   |= IA32_ATTR_ia32_asm_attr_t;
#endif
814
815
816

	ir_graph *const irg = get_irn_irg(res);
	ia32_request_x87_sim(irg); /* asm might have fp operands. */
817
818
}

819
static void init_ia32_immediate_attributes(ir_node *res, ir_entity *entity,
820
                                           bool no_pic_adjust, int32_t offset)
821
{
822
	ia32_immediate_attr_t *attr = (ia32_immediate_attr_t*)get_irn_generic_attr(res);
823

824
#ifndef NDEBUG
Michael Beck's avatar
Michael Beck committed
825
826
	attr->attr.attr_type  |= IA32_ATTR_ia32_immediate_attr_t;
#endif
827
	attr->entity        = entity;
828
829
	attr->no_pic_adjust = no_pic_adjust;
	attr->offset        = offset;
Michael Beck's avatar
Michael Beck committed
830
831
}

832
833
static void init_ia32_call_attributes(ir_node* res, unsigned pop,
                                      ir_type* call_tp)
834
{
835
	ia32_call_attr_t *attr = (ia32_call_attr_t*)get_irn_generic_attr(res);
836
837
838
839
840
841
842
843

#ifndef NDEBUG
	attr->attr.attr_type  |= IA32_ATTR_ia32_call_attr_t;
#endif
	attr->pop     = pop;
	attr->call_tp = call_tp;
}

844
static void init_ia32_copyb_attributes(ir_node *res, unsigned size)
845
{
846
	ia32_copyb_attr_t *attr = (ia32_copyb_attr_t*)get_irn_generic_attr(res);
Michael Beck's avatar
Michael Beck committed
847
848
849

#ifndef NDEBUG
	attr->attr.attr_type  |= IA32_ATTR_ia32_copyb_attr_t;
850
#endif
Michael Beck's avatar
Michael Beck committed
851
852
853
	attr->size = size;
}

854
static void init_ia32_condcode_attributes(ir_node *res,
855
                                          x86_condition_code_t cc)
856
{
857
	ia32_condcode_attr_t *attr = (ia32_condcode_attr_t*)get_irn_generic_attr(res);
Michael Beck's avatar
Michael Beck committed
858
859
860
861

#ifndef NDEBUG
	attr->attr.attr_type  |= IA32_ATTR_ia32_condcode_attr_t;
#endif
862
	attr->condition_code = cc;
863
864
}

865
static void init_ia32_climbframe_attributes(ir_node *res, unsigned count)
866
{
867
	ia32_climbframe_attr_t *attr = (ia32_climbframe_attr_t*)get_irn_generic_attr(res);
868
869
870
871
872
873
874

#ifndef NDEBUG
	attr->attr.attr_type  |= IA32_ATTR_ia32_climbframe_attr_t;
#endif
	attr->count = count;
}

Matthias Braun's avatar
Matthias Braun committed
875
876
static void init_ia32_switch_attributes(ir_node *node,
                                        const ir_switch_table *table)
877
{
Matthias Braun's avatar
Matthias Braun committed
878
	ia32_switch_attr_t *attr = (ia32_switch_attr_t*) get_irn_generic_attr(node);
879
880
881
#ifndef NDEBUG
	attr->attr.attr_type |= IA32_ATTR_ia32_switch_attr_t;
#endif
Matthias Braun's avatar
Matthias Braun committed
882
	attr->table = table;
883

884
	be_foreach_out(node, o) {
Matthias Braun's avatar
Matthias Braun committed
885
886
887
		arch_set_irn_register_req_out(node, o, arch_no_register_req);
	}
}
Christian Würdig's avatar
Christian Würdig committed
888

889
890
891
892
893
894
895
896
897
static void init_ia32_return_attributes(ir_node *node, uint16_t pop)
{
	ia32_return_attr_t *attr = (ia32_return_attr_t*)get_irn_generic_attr(node);
#ifndef NDEBUG
	attr->attr.attr_type |= IA32_ATTR_ia32_return_attr_t;
#endif
	attr->pop = pop;
}

898
static int ia32_attrs_equal_(const ia32_attr_t *a, const ia32_attr_t *b)
Christoph Mallon's avatar
Christoph Mallon committed
899
{
900
901
	/* nodes with not yet assigned entities shouldn't be CSEd (important for
	 * unsigned int -> double conversions */
902
	if (a->frame_use != IA32_FRAME_USE_NONE && !a->frame_ent)
903
		return false;
904

905
906
	return a->tp == b->tp
	    && a->am_scale == b->am_scale
907
908
	    && a->am_offs == b->am_offs
	    && a->am_ent == b->am_ent
909
	    && a->am_sc_no_pic_adjust == b->am_sc_no_pic_adjust
910
	    && a->ls_mode == b->ls_mode
911
	    && a->frame_use == b->frame_use
912
	    && a->frame_ent == b->frame_ent
913
914
	    && a->has_except_label == b->has_except_label
	    && a->ins_permuted == b->ins_permuted;
Christian Würdig's avatar
Christian Würdig committed
915
916
}

Michael Beck's avatar
Michael Beck committed
917
/** Compare nodes attributes for all "normal" nodes. */
918
static int ia32_attrs_equal(const ir_node *a, const ir_node *b)
919
920
921
{
	const ia32_attr_t* attr_a = get_ia32_attr_const(a);
	const ia32_attr_t* attr_b = get_ia32_attr_const(b);
922
	return ia32_attrs_equal_(attr_a, attr_b);
923
924
}

Michael Beck's avatar
Michael Beck committed
925
/** Compare node attributes for nodes with condition code. */
926
static int ia32_condcode_attrs_equal(const ir_node *a, const ir_node *b)
927
{
928
929
930
931
	const ia32_condcode_attr_t *attr_a = get_ia32_condcode_attr_const(a);
	const ia32_condcode_attr_t *attr_b = get_ia32_condcode_attr_const(b);
	return ia32_attrs_equal_(&attr_a->attr, &attr_b->attr)
	    && attr_a->condition_code == attr_b->condition_code;
932
933
}

934
/** Compare node attributes for call nodes. */
935
static int ia32_call_attrs_equal(const ir_node *a, const ir_node *b)
936
{
937
938
939
940
	const ia32_call_attr_t *attr_a = get_ia32_call_attr_const(a);
	const ia32_call_attr_t *attr_b = get_ia32_call_attr_const(b);
	return ia32_attrs_equal_(&attr_a->attr, &attr_b->attr)
	    && attr_a->pop == attr_b->pop && attr_a->call_tp == attr_b->call_tp;
941
942
}

Michael Beck's avatar
Michael Beck committed
943
/** Compare node attributes for CopyB nodes. */
944
static int ia32_copyb_attrs_equal(const ir_node *a, const ir_node *b)
Michael Beck's avatar
Michael Beck committed
945
{
946
947
948
949
	const ia32_copyb_attr_t *attr_a = get_ia32_copyb_attr_const(a);
	const ia32_copyb_attr_t *attr_b = get_ia32_copyb_attr_const(b);
	return ia32_attrs_equal_(&attr_a->attr, &attr_b->attr)
	    && attr_a->size == attr_b->size;
Matthias Braun's avatar