ia32_transform.c 47.1 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
7
/**
 * This file implements the IR transformation from firm into
 * ia32-Firm.
 *
 * $Id$
 */

8
9
10
11
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

Christian Würdig's avatar
Christian Würdig committed
12
#include "irargs_t.h"
13
14
15
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
Christian Würdig's avatar
Christian Würdig committed
16
17
18
#include "iropt_t.h"
#include "irop_t.h"
#include "irprog_t.h"
Christian Würdig's avatar
Christian Würdig committed
19
#include "iredges_t.h"
20
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
21
#include "irvrfy.h"
22
23
24
25
#include "ircons.h"
#include "dbginfo.h"
#include "debug.h"

Christian Würdig's avatar
Christian Würdig committed
26
#include "../benode_t.h"
Christian Würdig's avatar
Christian Würdig committed
27
28
#include "../besched.h"

Christian Würdig's avatar
Christian Würdig committed
29
30
#include "bearch_ia32_t.h"

31
32
33
34
#include "ia32_nodes_attr.h"
#include "../arch/archop.h"     /* we need this for Min and Max nodes */
#include "ia32_transform.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
35
#include "ia32_map_regs.h"
36

Christian Würdig's avatar
Christian Würdig committed
37
38
#include "gen_ia32_regalloc_if.h"

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#define SFP_SIGN "0x80000000"
#define DFP_SIGN "0x8000000000000000"
#define SFP_ABS  "0x7FFFFFFF"
#define DFP_ABS  "0x7FFFFFFFFFFFFFFF"

#define TP_SFP_SIGN "ia32_sfp_sign"
#define TP_DFP_SIGN "ia32_dfp_sign"
#define TP_SFP_ABS  "ia32_sfp_abs"
#define TP_DFP_ABS  "ia32_dfp_abs"

#define ENT_SFP_SIGN "IA32_SFP_SIGN"
#define ENT_DFP_SIGN "IA32_DFP_SIGN"
#define ENT_SFP_ABS  "IA32_SFP_ABS"
#define ENT_DFP_ABS  "IA32_DFP_ABS"

54
55
extern ir_op *get_op_Mulh(void);

56
57
typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
									  ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode);
Christian Würdig's avatar
Christian Würdig committed
58

59
60
61
typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
									 ir_node *op, ir_node *mem, ir_mode *mode);

62
63
64
65
typedef enum {
	ia32_SSIGN, ia32_DSIGN, ia32_SABS, ia32_DABS
} ia32_known_const_t;

Christian Würdig's avatar
Christian Würdig committed
66
67
68
69
70
71
72
73
74
75
/****************************************************************************************************
 *                  _        _                        __                           _   _
 *                 | |      | |                      / _|                         | | (_)
 *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
 * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
 * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
 *
 ****************************************************************************************************/

76
77
78
79
80
81
82
83
84
85
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
struct tv_ent {
	entity *ent;
	tarval *tv;
};

/* Compares two (entity, tarval) combinations */
static int cmp_tv_ent(const void *a, const void *b, size_t len) {
	const struct tv_ent *e1 = a;
	const struct tv_ent *e2 = b;

	return !(e1->tv == e2->tv);
}

/* Generates an entity for a known FP const (used for FP Neg + Abs) */
static char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) {
	static set    *const_set = NULL;
	struct tv_ent  key;
	struct tv_ent *entry;
	char          *tp_name;
	char          *ent_name;
	char          *cnst_str;
	ir_type       *tp;
	ir_node       *cnst;
	ir_graph      *rem;
	entity        *ent;

	if (! const_set) {
		const_set = new_set(cmp_tv_ent, 10);
	}

	switch (kct) {
		case ia32_SSIGN:
			tp_name  = TP_SFP_SIGN;
			ent_name = ENT_SFP_SIGN;
			cnst_str = SFP_SIGN;
			break;
		case ia32_DSIGN:
			tp_name  = TP_DFP_SIGN;
			ent_name = ENT_DFP_SIGN;
			cnst_str = DFP_SIGN;
			break;
		case ia32_SABS:
			tp_name  = TP_SFP_ABS;
			ent_name = ENT_SFP_ABS;
			cnst_str = SFP_ABS;
			break;
		case ia32_DABS:
			tp_name  = TP_DFP_ABS;
			ent_name = ENT_DFP_ABS;
			cnst_str = DFP_ABS;
			break;
	}


	key.tv  = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
	key.ent = NULL;

	entry = set_insert(const_set, &key, sizeof(key), HASH_PTR(key.tv));

	if (! entry->ent) {
		tp  = new_type_primitive(new_id_from_str(tp_name), mode);
		ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);

		set_entity_ld_ident(ent, get_entity_ident(ent));
		set_entity_visibility(ent, visibility_local);
		set_entity_variability(ent, variability_constant);
		set_entity_allocation(ent, allocation_static);

		/* we create a new entity here: It's initialization must resist on the
		    const code irg */
		rem = current_ir_graph;
		current_ir_graph = get_const_code_irg();
		cnst = new_Const(mode, key.tv);
		current_ir_graph = rem;

		set_atomic_ent_value(ent, cnst);

		/* set the entry for hashmap */
		entry->ent = ent;
	}

	return ent_name;
}

Christian Würdig's avatar
Christian Würdig committed
160
161
162
163
164
#ifndef NDEBUG
/**
 * Prints the old node name on cg obst and returns a pointer to it.
 */
const char *get_old_node_name(ia32_transform_env_t *env) {
Christian Würdig's avatar
Christian Würdig committed
165
	static int name_cnt = 0;
Christian Würdig's avatar
Christian Würdig committed
166
	ia32_isa_t *isa = (ia32_isa_t *)env->cg->arch_env->isa;
167

Christian Würdig's avatar
Christian Würdig committed
168
169
	lc_eoprintf(firm_get_arg_env(), isa->name_obst, "%+F", env->irn);
	obstack_1grow(isa->name_obst, 0);
Christian Würdig's avatar
Christian Würdig committed
170
171
172
173
174
	isa->name_obst_size += obstack_object_size(isa->name_obst);
	name_cnt++;
	if (name_cnt % 1024 == 0) {
		printf("name obst size reached %d bytes after %d nodes\n", isa->name_obst_size, name_cnt);
	}
Christian Würdig's avatar
Christian Würdig committed
175
176
177
 	return obstack_finish(isa->name_obst);
}
#endif /* NDEBUG */
Christian Würdig's avatar
Christian Würdig committed
178

179
180
/* determine if one operator is an Imm */
static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
Christian Würdig's avatar
Christian Würdig committed
181
	if (op1)
Christian Würdig's avatar
Christian Würdig committed
182
183
		return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL);
	else return is_ia32_Cnst(op2) ? op2 : NULL;
184
185
186
187
}

/* determine if one operator is not an Imm */
static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
Christian Würdig's avatar
Christian Würdig committed
188
	return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL);
189
190
191
192
193
194
195
196
197
198
199
200
201
}


/**
 * Construct a standard binary operation, set AM and immediate if required.
 *
 * @param env   The transformation environment
 * @param op1   The first operand
 * @param op2   The second operand
 * @param func  The node constructor function
 * @return The constructed ia32 node.
 */
static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
202
203
204
205
206
207
208
209
210
	ir_node           *new_op   = NULL;
	ir_mode           *mode     = env->mode;
	dbg_info          *dbg      = env->dbg;
	ir_graph          *irg      = env->irg;
	ir_node           *block    = env->block;
	firm_dbg_module_t *mod      = env->mod;
	ir_node           *noreg_gp = ia32_new_NoReg_gp(env->cg);
	ir_node           *noreg_fp = ia32_new_NoReg_fp(env->cg);
	ir_node           *nomem    = new_NoMem();
211
212
	ir_node           *expr_op, *imm_op;

213
214
215
216
217
218
219
	/* Check if immediate optimization is on and */
	/* if it's an operation with immediate.      */
	if (! env->cg->opt.immops) {
		expr_op = op1;
		imm_op  = NULL;
	}
	else if (is_op_commutative(get_irn_op(env->irn))) {
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
		imm_op  = get_immediate_op(op1, op2);
		expr_op = get_expr_op(op1, op2);
	}
	else {
		imm_op  = get_immediate_op(NULL, op2);
		expr_op = get_expr_op(op1, op2);
	}

	assert((expr_op || imm_op) && "invalid operands");

	if (!expr_op) {
		/* We have two consts here: not yet supported */
		imm_op = NULL;
	}

	if (mode_is_float(mode)) {
		/* floating point operations */
		if (imm_op) {
238
			DB((mod, LEVEL_1, "FP with immediate ..."));
239
			new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_fp, nomem, mode_T);
240
241
242
243
			set_ia32_Immop_attr(new_op, imm_op);
			set_ia32_am_support(new_op, ia32_am_None);
		}
		else {
244
			DB((mod, LEVEL_1, "FP binop ..."));
245
			new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode_T);
246
247
248
249
250
251
252
			set_ia32_am_support(new_op, ia32_am_Source);
		}
	}
	else {
		/* integer operations */
		if (imm_op) {
			/* This is expr + const */
253
			DB((mod, LEVEL_1, "INT with immediate ..."));
254
			new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_gp, nomem, mode_T);
255
256
257
258
259
260
			set_ia32_Immop_attr(new_op, imm_op);

			/* set AM support */
			set_ia32_am_support(new_op, ia32_am_Dest);
		}
		else {
261
			DB((mod, LEVEL_1, "INT binop ..."));
262
			/* This is a normal operation */
263
			new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode_T);
264
265
266
267
268
269

			/* set AM support */
			set_ia32_am_support(new_op, ia32_am_Full);
		}
	}

Christian Würdig's avatar
Christian Würdig committed
270
271
272
273
#ifndef NDEBUG
	set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */

274
275
	set_ia32_res_mode(new_op, mode);

Christian Würdig's avatar
Christian Würdig committed
276
277
278
279
	if (is_op_commutative(get_irn_op(env->irn))) {
		set_ia32_commutative(new_op);
	}

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
	return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}



/**
 * Construct a shift/rotate binary operation, sets AM and immediate if required.
 *
 * @param env   The transformation environment
 * @param op1   The first operand
 * @param op2   The second operand
 * @param func  The node constructor function
 * @return The constructed ia32 node.
 */
static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
	ir_node           *new_op = NULL;
	ir_mode           *mode   = env->mode;
	dbg_info          *dbg    = env->dbg;
	ir_graph          *irg    = env->irg;
	ir_node           *block  = env->block;
	firm_dbg_module_t *mod    = env->mod;
301
	ir_node           *noreg  = ia32_new_NoReg_gp(env->cg);
302
303
304
305
306
307
	ir_node           *nomem  = new_NoMem();
	ir_node           *expr_op, *imm_op;
	tarval            *tv;

	assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");

308
309
310
	/* Check if immediate optimization is on and */
	/* if it's an operation with immediate.      */
	imm_op  = env->cg->opt.immops ? get_immediate_op(NULL, op2) : NULL;
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
	expr_op = get_expr_op(op1, op2);

	assert((expr_op || imm_op) && "invalid operands");

	if (!expr_op) {
		/* We have two consts here: not yet supported */
		imm_op = NULL;
	}

	/* Limit imm_op within range imm8 */
	if (imm_op) {
		tv = get_ia32_Immop_tarval(imm_op);

		if (tv) {
			tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
		}
		else {
			imm_op = NULL;
		}
	}

	/* integer operations */
	if (imm_op) {
		/* This is shift/rot with const */
335
		DB((mod, LEVEL_1, "Shift/Rot with immediate ..."));
336
337
338
339
340
341

		new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
		set_ia32_Immop_attr(new_op, imm_op);
	}
	else {
		/* This is a normal shift/rot */
342
		DB((mod, LEVEL_1, "Shift/Rot binop ..."));
343
344
345
346
347
348
		new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
	}

	/* set AM support */
	set_ia32_am_support(new_op, ia32_am_Dest);

Christian Würdig's avatar
Christian Würdig committed
349
350
351
352
#ifndef NDEBUG
	set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */

353
354
	set_ia32_res_mode(new_op, mode);

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
	return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}


/**
 * Construct a standard unary operation, set AM and immediate if required.
 *
 * @param env   The transformation environment
 * @param op    The operand
 * @param func  The node constructor function
 * @return The constructed ia32 node.
 */
static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) {
	ir_node           *new_op = NULL;
	ir_mode           *mode   = env->mode;
	dbg_info          *dbg    = env->dbg;
371
	firm_dbg_module_t *mod    = env->mod;
372
373
	ir_graph          *irg    = env->irg;
	ir_node           *block  = env->block;
374
	ir_node           *noreg  = ia32_new_NoReg_gp(env->cg);
375
376
377
378
379
	ir_node           *nomem  = new_NoMem();

	new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T);

	if (mode_is_float(mode)) {
380
		DB((mod, LEVEL_1, "FP unop ..."));
381
382
383
384
		/* floating point operations don't support implicit store */
		set_ia32_am_support(new_op, ia32_am_None);
	}
	else {
385
		DB((mod, LEVEL_1, "INT unop ..."));
386
387
388
		set_ia32_am_support(new_op, ia32_am_Dest);
	}

Christian Würdig's avatar
Christian Würdig committed
389
390
391
392
#ifndef NDEBUG
	set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */

393
394
	set_ia32_res_mode(new_op, mode);

395
	return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
396
397
398
399
400
401
402
}



/**
 * Creates an ia32 Add with immediate.
 *
403
404
405
406
 * @param env       The transformation environment
 * @param expr_op   The expression operator
 * @param const_op  The constant
 * @return the created ia32 Add node
407
 */
Christian Würdig's avatar
Christian Würdig committed
408
static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
409
410
411
412
413
414
	ir_node                *new_op     = NULL;
	tarval                 *tv         = get_ia32_Immop_tarval(const_op);
	firm_dbg_module_t      *mod        = env->mod;
	dbg_info               *dbg        = env->dbg;
	ir_graph               *irg        = env->irg;
	ir_node                *block      = env->block;
415
	ir_node                *noreg      = ia32_new_NoReg_gp(env->cg);
416
417
	ir_node                *nomem      = new_NoMem();
	int                     normal_add = 1;
Christian Würdig's avatar
Christian Würdig committed
418
419
	tarval_classification_t class_tv, class_negtv;

420
421
	/* try to optimize to inc/dec  */
	if (env->cg->opt.incdec && tv) {
Christian Würdig's avatar
Christian Würdig committed
422
423
424
425
426
		/* optimize tarvals */
		class_tv    = classify_tarval(tv);
		class_negtv = classify_tarval(tarval_neg(tv));

		if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
Christian Würdig's avatar
Christian Würdig committed
427
			DB((env->mod, LEVEL_2, "Add(1) to Inc ... "));
428
429
			new_op     = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
			normal_add = 0;
Christian Würdig's avatar
Christian Würdig committed
430
431
		}
		else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
Christian Würdig's avatar
Christian Würdig committed
432
			DB((mod, LEVEL_2, "Add(-1) to Dec ... "));
433
434
			new_op     = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
			normal_add = 0;
Christian Würdig's avatar
Christian Würdig committed
435
436
437
		}
	}

438
439
440
441
	if (normal_add) {
		new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
		set_ia32_Immop_attr(new_op, const_op);
	}
Christian Würdig's avatar
Christian Würdig committed
442
443

	return new_op;
444
445
446
447
448
449
450
451
452
453
454
455
}

/**
 * Creates an ia32 Add.
 *
 * @param dbg       firm node dbg
 * @param block     the block the new node should belong to
 * @param op1       first operator
 * @param op2       second operator
 * @param mode      node mode
 * @return the created ia32 Add node
 */
Christian Würdig's avatar
Christian Würdig committed
456
static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
457
458
459
460
461
	ir_node  *new_op = NULL;
	dbg_info *dbg    = env->dbg;
	ir_mode  *mode   = env->mode;
	ir_graph *irg    = env->irg;
	ir_node  *block  = env->block;
462
	ir_node  *noreg  = ia32_new_NoReg_gp(env->cg);
463
464
465
	ir_node  *nomem  = new_NoMem();
	ir_node  *expr_op, *imm_op;

466
467
468
	/* Check if immediate optimization is on and */
	/* if it's an operation with immediate.      */
	imm_op  = env->cg->opt.immops ? get_immediate_op(op1, op2) : NULL;
469
470
471
	expr_op = get_expr_op(op1, op2);

	assert((expr_op || imm_op) && "invalid operands");
Christian Würdig's avatar
Christian Würdig committed
472
473

	if (mode_is_float(mode)) {
474
		return gen_binop(env, op1, op2, new_rd_ia32_fAdd);
Christian Würdig's avatar
Christian Würdig committed
475
	}
476
477
478
479
480
481
482
	else {
		/* integer ADD */
		if (!expr_op) {
			/* No expr_op means, that we have two const - one symconst and */
			/* one tarval or another symconst - because this case is not   */
			/* covered by constant folding                                 */

483
			new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
484
485
486
487
488
489
			add_ia32_am_offs(new_op, get_ia32_cnst(op1));
			add_ia32_am_offs(new_op, get_ia32_cnst(op2));

			/* set AM support */
			set_ia32_am_support(new_op, ia32_am_Source);
			set_ia32_op_type(new_op, ia32_AddrModeS);
490
491
492
493
			set_ia32_am_flavour(new_op, ia32_am_O);

			/* Lea doesn't need a Proj */
			return new_op;
Christian Würdig's avatar
Christian Würdig committed
494
		}
495
496
497
		else if (imm_op) {
			/* This is expr + const */
			new_op = gen_imm_Add(env, expr_op, imm_op);
Christian Würdig's avatar
Christian Würdig committed
498

499
500
501
502
503
504
			/* set AM support */
			set_ia32_am_support(new_op, ia32_am_Dest);
		}
		else {
			/* This is a normal add */
			new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
505

506
507
508
			/* set AM support */
			set_ia32_am_support(new_op, ia32_am_Full);
		}
Christian Würdig's avatar
Christian Würdig committed
509
510
	}

Christian Würdig's avatar
Christian Würdig committed
511
512
513
514
#ifndef NDEBUG
	set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */

515
516
	set_ia32_res_mode(new_op, mode);

517
	return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
Christian Würdig's avatar
Christian Würdig committed
518
519
520
521
}



522
523
524
525
526
527
528
529
530
531
/**
 * Creates an ia32 Mul.
 *
 * @param dbg       firm node dbg
 * @param block     the block the new node should belong to
 * @param op1       first operator
 * @param op2       second operator
 * @param mode      node mode
 * @return the created ia32 Mul node
 */
Christian Würdig's avatar
Christian Würdig committed
532
static ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
533
534
	ir_node *new_op;

Christian Würdig's avatar
Christian Würdig committed
535
	if (mode_is_float(env->mode)) {
536
		new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul);
Christian Würdig's avatar
Christian Würdig committed
537
538
	}
	else {
539
		new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
Christian Würdig's avatar
Christian Würdig committed
540
	}
541

542
543
	return new_op;
}
544
545
546
547
548
549
550
551



/**
 * Creates an ia32 Mulh.
 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
 * this result while Mul returns the lower 32 bit.
 *
552
553
554
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
555
556
 * @return the created ia32 Mulh node
 */
Christian Würdig's avatar
Christian Würdig committed
557
static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
558
559
	ir_node *proj_EAX, *proj_EDX, *mulh;
	ir_node *in[1];
560

561
562
563
564
	assert(mode_is_float(env->mode) && "Mulh with float not supported");
	proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh);
	mulh     = get_Proj_pred(proj_EAX);
	proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX);
565

566
567
	/* to be on the save side */
	set_Proj_proj(proj_EAX, pn_EAX);
568

569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
	if (get_ia32_cnst(mulh)) {
		/* Mulh with const cannot have AM */
		set_ia32_am_support(mulh, ia32_am_None);
	}
	else {
		/* Mulh cannot have AM for destination */
		set_ia32_am_support(mulh, ia32_am_Source);
	}

	in[0] = proj_EAX;

	/* keep EAX */
	be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);

	return proj_EDX;
584
585
}

586
587


588
589
590
/**
 * Creates an ia32 And.
 *
591
592
593
594
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 And node
595
 */
Christian Würdig's avatar
Christian Würdig committed
596
static ir_node *gen_And(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
597
598
599
600
601
602
	if (mode_is_float(env->mode)) {
		return gen_binop(env, op1, op2, new_rd_ia32_fAnd);
	}
	else {
		return gen_binop(env, op1, op2, new_rd_ia32_And);
	}
603
604
605
606
607
608
609
}



/**
 * Creates an ia32 Or.
 *
610
611
612
613
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 Or node
614
 */
Christian Würdig's avatar
Christian Würdig committed
615
static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
616
617
618
619
620
621
	if (mode_is_float(env->mode)) {
		return gen_binop(env, op1, op2, new_rd_ia32_fOr);
	}
	else {
		return gen_binop(env, op1, op2, new_rd_ia32_Or);
	}
622
623
624
625
626
627
628
}



/**
 * Creates an ia32 Eor.
 *
629
630
631
632
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 Eor node
633
 */
Christian Würdig's avatar
Christian Würdig committed
634
static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
635
636
637
638
639
640
	if (mode_is_float(env->mode)) {
		return gen_binop(env, op1, op2, new_rd_ia32_fEor);
	}
	else {
		return gen_binop(env, op1, op2, new_rd_ia32_Eor);
	}
641
642
643
644
645
646
647
}



/**
 * Creates an ia32 Max.
 *
648
649
650
651
 * @param env      The transformation environment
 * @param op1      The first operator
 * @param op2      The second operator
 * @return the created ia32 Max node
652
 */
Christian Würdig's avatar
Christian Würdig committed
653
static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
654
655
656
657
658
659
660
661
	ir_node *new_op;

	if (mode_is_float(env->mode)) {
		new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax);
	}
	else {
		new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
		set_ia32_am_support(new_op, ia32_am_None);
662
663
664
#ifndef NDEBUG
		set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
665
666
667
	}

	return new_op;
668
669
670
671
672
673
674
}



/**
 * Creates an ia32 Min.
 *
675
676
677
678
 * @param env      The transformation environment
 * @param op1      The first operator
 * @param op2      The second operator
 * @return the created ia32 Min node
679
 */
Christian Würdig's avatar
Christian Würdig committed
680
static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
681
682
683
684
685
686
687
688
	ir_node *new_op;

	if (mode_is_float(env->mode)) {
		new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin);
	}
	else {
		new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
		set_ia32_am_support(new_op, ia32_am_None);
Christian Würdig's avatar
Christian Würdig committed
689
690
691
#ifndef NDEBUG
		set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
692
693
694
	}

	return new_op;
695
696
697
698
699
700
701
}



/**
 * Creates an ia32 Sub with immediate.
 *
702
703
704
705
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 Sub node
706
 */
Christian Würdig's avatar
Christian Würdig committed
707
static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
708
709
710
711
712
713
	ir_node                *new_op     = NULL;
	tarval                 *tv         = get_ia32_Immop_tarval(const_op);
	firm_dbg_module_t      *mod        = env->mod;
	dbg_info               *dbg        = env->dbg;
	ir_graph               *irg        = env->irg;
	ir_node                *block      = env->block;
714
	ir_node                *noreg      = ia32_new_NoReg_gp(env->cg);
715
716
	ir_node                *nomem      = new_NoMem();
	int                     normal_sub = 1;
Christian Würdig's avatar
Christian Würdig committed
717
718
	tarval_classification_t class_tv, class_negtv;

719
720
	/* try to optimize to inc/dec  */
	if (env->cg->opt.incdec && tv) {
Christian Würdig's avatar
Christian Würdig committed
721
722
723
724
725
		/* optimize tarvals */
		class_tv    = classify_tarval(tv);
		class_negtv = classify_tarval(tarval_neg(tv));

		if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
Christian Würdig's avatar
Christian Würdig committed
726
			DB((mod, LEVEL_2, "Sub(1) to Dec ... "));
727
728
			new_op     = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
			normal_sub = 0;
Christian Würdig's avatar
Christian Würdig committed
729
730
		}
		else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
Christian Würdig's avatar
Christian Würdig committed
731
			DB((mod, LEVEL_2, "Sub(-1) to Inc ... "));
732
733
			new_op     = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
			normal_sub = 0;
Christian Würdig's avatar
Christian Würdig committed
734
735
736
		}
	}

737
738
739
740
	if (normal_sub) {
		new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
		set_ia32_Immop_attr(new_op, const_op);
	}
Christian Würdig's avatar
Christian Würdig committed
741
742

	return new_op;
743
744
745
746
747
}

/**
 * Creates an ia32 Sub.
 *
748
749
750
751
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 Sub node
752
 */
Christian Würdig's avatar
Christian Würdig committed
753
static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
754
755
756
757
758
	ir_node  *new_op = NULL;
	dbg_info *dbg    = env->dbg;
	ir_mode  *mode   = env->mode;
	ir_graph *irg    = env->irg;
	ir_node  *block  = env->block;
759
	ir_node  *noreg  = ia32_new_NoReg_gp(env->cg);
760
761
762
	ir_node  *nomem  = new_NoMem();
	ir_node  *expr_op, *imm_op;

763
764
765
	/* Check if immediate optimization is on and */
	/* if it's an operation with immediate.      */
	imm_op  = env->cg->opt.immops ? get_immediate_op(NULL, op2) : NULL;
766
767
768
769
770
771
	expr_op = get_expr_op(op1, op2);

	assert((expr_op || imm_op) && "invalid operands");

	if (mode_is_float(mode)) {
		return gen_binop(env, op1, op2, new_rd_ia32_fSub);
Christian Würdig's avatar
Christian Würdig committed
772
	}
773
774
775
776
777
778
779
	else {
		/* integer SUB */
		if (!expr_op) {
			/* No expr_op means, that we have two const - one symconst and */
			/* one tarval or another symconst - because this case is not   */
			/* covered by constant folding                                 */

780
			new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
781
782
783
784
785
786
			add_ia32_am_offs(new_op, get_ia32_cnst(op1));
			sub_ia32_am_offs(new_op, get_ia32_cnst(op2));

			/* set AM support */
			set_ia32_am_support(new_op, ia32_am_Source);
			set_ia32_op_type(new_op, ia32_AddrModeS);
787
788
789
790
			set_ia32_am_flavour(new_op, ia32_am_O);

			/* Lea doesn't need a Proj */
			return new_op;
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
		}
		else if (imm_op) {
			/* This is expr - const */
			new_op = gen_imm_Sub(env, expr_op, imm_op);

			/* set AM support */
			set_ia32_am_support(new_op, ia32_am_Dest);
		}
		else {
			/* This is a normal sub */
			new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);

			/* set AM support */
			set_ia32_am_support(new_op, ia32_am_Full);
		}
	}

Christian Würdig's avatar
Christian Würdig committed
808
809
810
811
#ifndef NDEBUG
	set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */

812
813
	set_ia32_res_mode(new_op, mode);

814
	return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
815
816
817
818
819
}



/**
Christian Würdig's avatar
Christian Würdig committed
820
821
 * Generates an ia32 DivMod with additional infrastructure for the
 * register allocator if needed.
822
 *
Christian Würdig's avatar
Christian Würdig committed
823
824
825
826
827
828
 * @param env      The transformation environment
 * @param dividend -no comment- :)
 * @param divisor  -no comment- :)
 * @param dm_flav  flavour_Div/Mod/DivMod
 * @return The created ia32 DivMod node
 */
829
static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
Christian Würdig's avatar
Christian Würdig committed
830
831
832
833
834
835
836
837
	ir_node  *res, *proj;
	ir_node  *edx_node, *cltd;
	ir_node  *in_keep[1];
	dbg_info *dbg   = env->dbg;
	ir_graph *irg   = env->irg;
	ir_node  *block = env->block;
	ir_mode  *mode  = env->mode;
	ir_node  *irn   = env->irn;
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
	ir_node  *mem;

	switch (dm_flav) {
		case flavour_Div:
			mem = get_Div_mem(irn);
			break;
		case flavour_Mod:
			mem = get_Mod_mem(irn);
			break;
		case flavour_DivMod:
			mem = get_DivMod_mem(irn);
			break;
		default:
			assert(0);
	}
Christian Würdig's avatar
Christian Würdig committed
853
854
855

	if (mode_is_signed(mode)) {
		/* in signed mode, we need to sign extend the dividend */
856
		cltd     = new_rd_ia32_Cdq(dbg, irg, block, dividend, mode_T);
Christian Würdig's avatar
Christian Würdig committed
857
858
859
860
861
		dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX);
		edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX);
	}
	else {
		edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
862
		set_ia32_Const_type(edx_node, ia32_Const);
Christian Würdig's avatar
Christian Würdig committed
863
864
865
		set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
	}

866
	res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884

	set_ia32_flavour(res, dm_flav);
	set_ia32_n_res(res, 2);

	/* Only one proj is used -> We must add a second proj and */
	/* connect this one to a Keep node to eat up the second   */
	/* destroyed register.                                    */
	if (get_irn_n_edges(irn) == 1) {
		proj = get_edge_src_irn(get_irn_out_edge_first(irn));
		assert(is_Proj(proj) && "non-Proj to Div/Mod node");

		if (get_Proj_proj(proj) == pn_DivMod_res_div) {
			in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_mod);
		}
		else {
			in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
		}

885
		be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
Christian Würdig's avatar
Christian Würdig committed
886
887
	}

Christian Würdig's avatar
Christian Würdig committed
888
889
890
891
#ifndef NDEBUG
	set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */

892
893
	set_ia32_res_mode(res, mode_Is);

Christian Würdig's avatar
Christian Würdig committed
894
895
896
897
898
899
	return res;
}


/**
 * Wrapper for generate_DivMod. Sets flavour_Mod.
900
 */
Christian Würdig's avatar
Christian Würdig committed
901
static ir_node *gen_Mod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
Christian Würdig's avatar
Christian Würdig committed
902
	return generate_DivMod(env, op1, op2, flavour_Mod);
903
904
905
906
907
}



/**
Christian Würdig's avatar
Christian Würdig committed
908
 * Wrapper for generate_DivMod. Sets flavour_Div.
909
 */
Christian Würdig's avatar
Christian Würdig committed
910
static ir_node *gen_Div(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
Christian Würdig's avatar
Christian Würdig committed
911
	return generate_DivMod(env, op1, op2, flavour_Div);
912
913
914
915
916
}



/**
Christian Würdig's avatar
Christian Würdig committed
917
 * Wrapper for generate_DivMod. Sets flavour_DivMod.
918
 */
Christian Würdig's avatar
Christian Würdig committed
919
static ir_node *gen_DivMod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
Christian Würdig's avatar
Christian Würdig committed
920
	return generate_DivMod(env, op1, op2, flavour_DivMod);
Christian Würdig's avatar
Christian Würdig committed
921
922
923
924
925
926
927
}



/**
 * Creates an ia32 floating Div.
 *
928
929
930
931
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 fDiv node
Christian Würdig's avatar
Christian Würdig committed
932
 */
Christian Würdig's avatar
Christian Würdig committed
933
static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
Christian Würdig's avatar
Christian Würdig committed
934
935
936
937
938
939
940
	ir_node *noreg = ia32_new_NoReg_gp(env->cg);
	ir_node *nomem = new_rd_NoMem(env->irg);
	ir_node *new_op;

	new_op = new_rd_ia32_fDiv(env->dbg, env->irg, env->block, noreg, noreg, op1, op2, nomem, env->mode);
	set_ia32_am_support(new_op, ia32_am_Source);

Christian Würdig's avatar
Christian Würdig committed
941
942
943
944
#ifndef NDEBUG
	set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
945
	return new_op;
946
947
948
949
950
951
952
}



/**
 * Creates an ia32 Shl.
 *
953
954
955
956
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 Shl node
957
 */
Christian Würdig's avatar
Christian Würdig committed
958
static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
959
	return gen_shift_binop(env, op1, op2, new_rd_ia32_Shl);
960
961
962
963
964
965
966
}



/**
 * Creates an ia32 Shr.
 *
967
968
969
970
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 Shr node
971
 */
Christian Würdig's avatar
Christian Würdig committed
972
static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
973
	return gen_shift_binop(env, op1, op2, new_rd_ia32_Shr);
974
975
976
977
978
979
980
}



/**
 * Creates an ia32 Shrs.
 *
981
982
983
984
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 Shrs node
985
 */
Christian Würdig's avatar
Christian Würdig committed
986
static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
987
	return gen_shift_binop(env, op1, op2, new_rd_ia32_Shrs);
988
989
990
991
992
993
994
}



/**
 * Creates an ia32 RotL.
 *
995
996
997
998
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 RotL node
999
 */
Christian Würdig's avatar
Christian Würdig committed
1000
static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
1001
	return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL);
1002
1003
1004
1005
1006
1007
1008
1009
1010
}



/**
 * Creates an ia32 RotR.
 * NOTE: There is no RotR with immediate because this would always be a RotL
 *       "imm-mode_size_bits" which can be pre-calculated.
 *
1011
1012
1013
1014
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 RotR node
1015
 */
Christian Würdig's avatar
Christian Würdig committed
1016
static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
1017
	return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR);
1018
1019
1020
1021
1022
1023
1024
}



/**
 * Creates an ia32 RotR or RotL (depending on the found pattern).
 *
1025
1026
1027
1028
 * @param env   The transformation environment
 * @param op1   The first operator
 * @param op2   The second operator
 * @return The created ia32 RotL or RotR node
1029
 */
Christian Würdig's avatar
Christian Würdig committed
1030
static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
Christian Würdig's avatar
Christian Würdig committed
1031
	ir_node *rotate = NULL;
1032

Christian Würdig's avatar
Christian Würdig committed
1033
1034
1035
	/* Firm has only Rot (which is a RotL), so we are looking for a right (op2)
		 operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
		 that means we can create a RotR instead of an Add and a RotL */
1036

1037
1038
	if (is_Proj(op2)) {
		ir_node *pred = get_Proj_pred(op2);
1039

1040
1041
1042
1043
		if (is_ia32_Add(pred)) {
			ir_node *pred_pred = get_irn_n(pred, 2);
			tarval  *tv        = get_ia32_Immop_tarval(pred);
			long     bits      = get_mode_size_bits(env->mode);
1044

1045
1046
			if (is_Proj(pred_pred)) {
				pred_pred = get_Proj_pred(pred_pred);
Christian Würdig's avatar
Christian Würdig committed
1047
1048
			}

1049
1050
1051
1052
1053
1054
			if (is_ia32_Minus(pred_pred) &&
				tarval_is_long(tv)       &&
				get_tarval_long(tv) == bits)
			{
				DB((env->mod, LEVEL_1, "RotL into RotR ... "));
				rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
Christian Würdig's avatar
Christian Würdig committed
1055
			}
Christian Würdig's avatar
Christian Würdig committed
1056
1057
1058

		}
	}
1059
1060
1061

	if (!rotate) {
		rotate = gen_RotL(env, op1, op2);
Christian Würdig's avatar
Christian Würdig committed
1062
1063
	}

1064
	return rotate;
1065
1066
1067
1068
1069
1070
1071
}



/**
 * Transforms a Minus node.
 *
1072
1073
1074
 * @param env   The transformation environment
 * @param op    The operator
 * @return The created ia32 Minus node
1075
 */
Christian Würdig's avatar
Christian Würdig committed
1076
static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
1077
	char    *name;
1078
	ir_node *new_op;
1079
1080
1081
	ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg);
	ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg);
	ir_node *nomem    = new_rd_NoMem(env->irg);
1082
	int      size;
1083
1084

	if (mode_is_float(env->mode)) {
1085
		new_op = new_rd_ia32_fEor(env->dbg, env->irg, env->block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T);
1086
1087
1088
1089
1090
1091

		size   = get_mode_size_bits(env->mode);
		name   = gen_fp_known_const(env->mode, size == 32 ? ia32_SSIGN : ia32_DSIGN);

		set_ia32_sc(new_op, name);

Christian Würdig's avatar
Christian Würdig committed
1092
1093
1094
1095
#ifndef NDEBUG
		set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */

1096
1097
		set_ia32_res_mode(new_op, env->mode);

1098
		new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
Christian Würdig's avatar
Christian Würdig committed
1099
1100
	}
	else {
1101
		new_op = gen_unop(env, op, new_rd_ia32_Minus);
Christian Würdig's avatar
Christian Würdig committed
1102
	}
1103
1104

	return new_op;
1105
1106
1107
1108
1109
1110
1111
}



/**
 * Transforms a Not node.
 *
1112
1113
1114
 * @param env   The transformation environment
 * @param op    The operator
 * @return The created ia32 Not node
1115
 */
Christian Würdig's avatar
Christian Würdig committed
1116
static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
	ir_node *new_op;

	if (mode_is_float(env->mode)) {
		assert(0);
	}
	else {
		new_op = gen_unop(env, op, new_rd_ia32_Not);
	}

	return new_op;
1127
1128
1129
1130
1131
1132
1133
}



/**
 * Transforms an Abs node.
 *
1134
1135
1136
 * @param env   The transformation environment
 * @param op    The operator
 * @return The created ia32 Abs node
1137
 */
Christian Würdig's avatar
Christian Würdig committed
1138
1139
static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
	ir_node  *res, *p_eax, *p_edx;
1140
1141
1142
1143
1144
1145
1146
	dbg_info *dbg      = env->dbg;
	ir_mode  *mode     = env->mode;
	ir_graph *irg      = env->irg;
	ir_node  *block    = env->block;
	ir_node  *noreg_gp = ia32_new_NoReg_gp(env->cg);
	ir_node  *noreg_fp = ia32_new_NoReg_fp(env->cg);
	ir_node  *nomem    = new_NoMem();
1147
1148
	int       size;
	char     *name;
Christian Würdig's avatar
Christian Würdig committed
1149

1150
	if (mode_is_float(mode)) {
1151
		res = new_rd_ia32_fAnd(dbg,irg, block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T);
1152
1153
1154

		size   = get_mode_size_bits(mode);
		name   = gen_fp_known_const(mode, size == 32 ? ia32_SABS : ia32_DABS);
1155

1156
1157
		set_ia32_sc(res, name);

Christian Würdig's avatar
Christian Würdig committed
1158
1159
1160
1161
#ifndef NDEBUG
		set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */

1162
1163
		set_ia32_res_mode(res, mode);

1164
1165
1166
1167
		res = new_rd_Proj(dbg, irg, block, res, mode, 0);
	}
	else {
		res   = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T);
Christian Würdig's avatar
Christian Würdig committed
1168
1169
1170
#ifndef NDEBUG
		set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
1171
		set_ia32_res_mode(res, mode);
Christian Würdig's avatar
Christian Würdig committed
1172

1173
1174
		p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
		p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
Christian Würdig's avatar
Christian Würdig committed
1175

1176
		res   = new_rd_ia32_Eor(dbg, irg, block, noreg_gp, noreg_gp, p_eax, p_edx, nomem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
1177
1178
1179
#ifndef NDEBUG
		set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
1180
		set_ia32_res_mode(res, mode);
Christian Würdig's avatar
Christian Würdig committed
1181

1182
		res   = new_rd_Proj(dbg, irg, block, res, mode, 0);
Christian Würdig's avatar
Christian Würdig committed
1183

1184
		res   = new_rd_ia32_Sub(dbg, irg, block, noreg_gp, noreg_gp, res, p_edx, nomem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
1185
1186
1187
#ifndef NDEBUG
		set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
1188
		set_ia32_res_mode(res, mode);
Christian Würdig's avatar
Christian Würdig committed
1189

1190
1191
		res   = new_rd_Proj(dbg, irg, block, res, mode, 0);
	}
1192

Christian Würdig's avatar
Christian Würdig committed
1193
	return res;
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
}



/**
 * Transforms a Load.
 *
 * @param mod     the debug module
 * @param block   the block the new node should belong to
 * @param node    the ir Load node
 * @param mode    node mode
 * @return the created ia32 Load node
 */
Christian Würdig's avatar
Christian Würdig committed
1207
static ir_node *gen_Load(ia32_transform_env_t *env) {
1208
	ir_node *node  = env->irn;
1209
	ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1210
	ir_node *new_op;
Christian Würdig's avatar
Christian Würdig committed
1211
1212

	if (mode_is_float(env->mode)) {
1213
1214
1215
1216
		new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
	}
	else {
		new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
Christian Würdig's avatar
Christian Würdig committed
1217
	}
1218
1219

	set_ia32_am_support(new_op, ia32_am_Source);
Christian Würdig's avatar
Christian Würdig committed
1220
1221
	set_ia32_op_type(new_op, ia32_AddrModeS);
	set_ia32_am_flavour(new_op, ia32_B);
1222
1223
	set_ia32_ls_mode(new_op, get_Load_mode(node));

Christian Würdig's avatar
Christian Würdig committed
1224
1225
1226
1227
#ifndef NDEBUG
	set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */

1228
	return new_op;
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
}



/**
 * Transforms a Store.
 *
 * @param mod     the debug module
 * @param block   the block the new node should belong to
 * @param node    the ir Store node
 * @param mode    node mode
 * @return the created ia32 Store node
 */
Christian Würdig's avatar
Christian Würdig committed
1242
static ir_node *gen_Store(ia32_transform_env_t *env) {
1243
	ir_node *node  = env->irn;
1244
	ir_node *noreg = ia32_new_NoReg_gp(env->cg);
Christian Würdig's avatar
Christian Würdig committed
1245
1246
1247
1248
	ir_node *val   = get_Store_value(node);
	ir_node *ptr   = get_Store_ptr(node);
	ir_node *mem   = get_Store_mem(node);
	ir_node *sval  = val;
1249
	ir_node *new_op;
Christian Würdig's avatar
Christian Würdig committed
1250

Christian Würdig's avatar
Christian Würdig committed
1251
1252
1253
1254
1255
	/* in case of storing a const -> make it an attribute */
	if (is_ia32_Cnst(val)) {
		sval = noreg;
	}

Christian Würdig's avatar
Christian Würdig committed
1256
	if (mode_is_float(env->mode)) {
Christian Würdig's avatar
Christian Würdig committed
1257
		new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
Christian Würdig's avatar
Christian Würdig committed
1258
	}
1259
	else {
Christian Würdig's avatar
Christian Würdig committed
1260
1261
1262
1263
1264
1265
		new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
	}

	/* stored const is an attribute (saves a register) */
	if (is_ia32_Cnst(val)) {
		set_ia32_Immop_attr(new_op, val);