amd64_transform.c 77.6 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   code selection (transform FIRM into amd64 FIRM)
 */
Matthias Braun's avatar
Matthias Braun committed
10
#include "debug.h"
Matthias Braun's avatar
Matthias Braun committed
11
#include "panic.h"
Matthias Braun's avatar
Matthias Braun committed
12
13
14
#include "heights.h"
#include "ircons.h"
#include "irgmod.h"
15
16
#include "irgraph_t.h"
#include "irmode_t.h"
Matthias Braun's avatar
Matthias Braun committed
17
#include "irnode_t.h"
18
#include "iropt_t.h"
19
#include "tv_t.h"
Matthias Braun's avatar
Matthias Braun committed
20
#include "util.h"
21

22
23
24
#include "benode.h"
#include "betranshlp.h"
#include "beutil.h"
25
#include "bearch_amd64_t.h"
26
27
#include "beirg.h"
#include "beabihelper.h"
Matthias Braun's avatar
Matthias Braun committed
28
#include "besched.h"
29

Matthias Braun's avatar
Matthias Braun committed
30
#include "amd64_cconv.h"
31
#include "amd64_common_transform.h"
Matthias Braun's avatar
Matthias Braun committed
32
#include "amd64_new_nodes.h"
33
34
#include "amd64_nodes_attr.h"
#include "amd64_transform.h"
Matthias Braun's avatar
Matthias Braun committed
35
#include "../ia32/x86_address_mode.h"
36
37
38
39
40

#include "gen_amd64_regalloc_if.h"

DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

41
42
43
44
45
46
typedef struct reg_info_t {
	size_t   offset;
	ir_node *irn;
} reg_info_t;

static ir_mode         *mode_gp;
Matthias Braun's avatar
Matthias Braun committed
47
static ir_mode         *mode_flags;
48
49
50
51
52
53
54
55
static amd64_cconv_t   *current_cconv = NULL;
static reg_info_t       start_mem;
static reg_info_t       start_sp;
static reg_info_t       start_fp;
static size_t           start_callee_saves_offset;
static size_t           start_params_offset;
static pmap            *node_to_stack;
static be_stackorder_t *stackorder;
56

Matthias Braun's avatar
Matthias Braun committed
57
static const arch_register_req_t amd64_requirement_gp = {
58
59
60
61
62
63
	.cls             = &amd64_reg_classes[CLASS_amd64_gp],
	.limited         = NULL,
	.type            = arch_register_req_type_normal,
	.other_same      = 0,
	.other_different = 0,
	.width           = 1,
64
65
66
};

static const arch_register_req_t amd64_requirement_flags = {
67
68
69
70
71
72
	.cls             = &amd64_reg_classes[CLASS_amd64_flags],
	.limited         = NULL,
	.type            = arch_register_req_type_normal,
	.other_same      = 0,
	.other_different = 0,
	.width           = 1,
73
74
75
};

static const arch_register_req_t amd64_requirement_xmm = {
76
77
78
79
80
81
	.cls             = &amd64_reg_classes[CLASS_amd64_xmm],
	.limited         = NULL,
	.type            = arch_register_req_type_normal,
	.other_same      = 0,
	.other_different = 0,
	.width           = 1,
Matthias Braun's avatar
Matthias Braun committed
82
83
};

Matthias Braun's avatar
Matthias Braun committed
84
85
86
#define BIT(x)    (1u << x)

static const arch_register_req_t amd64_requirement_gp_same_0 = {
87
88
89
90
91
92
93
	.cls             = &amd64_reg_classes[CLASS_amd64_gp],
	.limited         = NULL,
	.type            = arch_register_req_type_normal
	                   | arch_register_req_type_should_be_same,
	.other_same      = BIT(0),
	.other_different = 0,
	.width           = 1,
Matthias Braun's avatar
Matthias Braun committed
94
95
};

96
static const arch_register_req_t amd64_requirement_xmm_same_0 = {
97
98
99
100
101
102
103
	.cls             = &amd64_reg_classes[CLASS_amd64_xmm],
	.limited         = NULL,
	.type            = arch_register_req_type_normal
	                   | arch_register_req_type_should_be_same,
	.other_same      = BIT(0),
	.other_different = 0,
	.width           = 1,
104
105
};

Matthias Braun's avatar
Matthias Braun committed
106
static const arch_register_req_t amd64_requirement_gp_same_0_not_1 = {
107
108
109
110
111
112
113
114
	.cls             = &amd64_reg_classes[CLASS_amd64_gp],
	.limited         = NULL,
	.type            = arch_register_req_type_normal
	                   | arch_register_req_type_should_be_same
	                   | arch_register_req_type_must_be_different,
	.other_same      = BIT(0),
	.other_different = BIT(1),
	.width           = 1,
Matthias Braun's avatar
Matthias Braun committed
115
116
117
118
};

static const unsigned amd64_limited_gp_rcx [] = { BIT(REG_GP_RCX) };
static const arch_register_req_t amd64_requirement_rcx = {
119
120
121
122
123
124
	.cls             = &amd64_reg_classes[CLASS_amd64_gp],
	.limited         = amd64_limited_gp_rcx,
	.type            = arch_register_req_type_limited,
	.other_same      = 0,
	.other_different = 0,
	.width           = 1,
Matthias Braun's avatar
Matthias Braun committed
125
126
};

127
128
static const unsigned amd64_limited_gp_rax [] = { BIT(REG_GP_RAX) };
static const arch_register_req_t amd64_requirement_rax = {
129
130
131
132
133
134
	.cls             = &amd64_reg_classes[CLASS_amd64_gp],
	.limited         = amd64_limited_gp_rax,
	.type            = arch_register_req_type_limited,
	.other_same      = 0,
	.other_different = 0,
	.width           = 1,
135
136
};

137
138
static const unsigned amd64_limited_gp_rdx [] = { BIT(REG_GP_RDX) };
static const arch_register_req_t amd64_requirement_rdx = {
139
140
141
142
143
144
	.cls             = &amd64_reg_classes[CLASS_amd64_gp],
	.limited         = amd64_limited_gp_rdx,
	.type            = arch_register_req_type_limited,
	.other_same      = 0,
	.other_different = 0,
	.width           = 1,
145
146
};

Matthias Braun's avatar
Matthias Braun committed
147
148
149
150
151
152
static const arch_register_req_t *mem_reqs[] = {
	&arch_no_requirement,
};

static const arch_register_req_t *reg_mem_reqs[] = {
	&amd64_requirement_gp,
Matthias Braun's avatar
Matthias Braun committed
153
154
155
	&arch_no_requirement,
};

156
157
158
159
160
static const arch_register_req_t *xmm_mem_reqs[] = {
	&amd64_requirement_xmm,
	&arch_no_requirement,
};

Matthias Braun's avatar
Matthias Braun committed
161
162
static const arch_register_req_t *reg_reg_mem_reqs[] = {
	&amd64_requirement_gp,
Matthias Braun's avatar
Matthias Braun committed
163
164
165
166
	&amd64_requirement_gp,
	&arch_no_requirement,
};

167
168
169
170
171
172
static const arch_register_req_t *xmm_reg_mem_reqs[] = {
	&amd64_requirement_xmm,
	&amd64_requirement_gp,
	&arch_no_requirement,
};

Matthias Braun's avatar
Matthias Braun committed
173
174
static const arch_register_req_t *reg_reg_reg_mem_reqs[] = {
	&amd64_requirement_gp,
Matthias Braun's avatar
Matthias Braun committed
175
176
177
178
179
	&amd64_requirement_gp,
	&amd64_requirement_gp,
	&arch_no_requirement,
};

180
181
182
183
184
185
186
static const arch_register_req_t *xmm_reg_reg_mem_reqs[] = {
	&amd64_requirement_xmm,
	&amd64_requirement_gp,
	&amd64_requirement_gp,
	&arch_no_requirement,
};

Tobias Rapp's avatar
Tobias Rapp committed
187
static const arch_register_req_t *reg_flags_reqs[] = {
188
189
190
191
	&amd64_requirement_gp,
	&amd64_requirement_flags,
};

Matthias Braun's avatar
Matthias Braun committed
192
193
static const arch_register_req_t *reg_reg_reqs[] = {
	&amd64_requirement_gp,
194
195
196
	&amd64_requirement_gp,
};

197
198
199
200
201
static const arch_register_req_t *rax_reg_reqs[] = {
	&amd64_requirement_rax,
	&amd64_requirement_gp,
};

202
static const arch_register_req_t *rax_reg_rdx_mem_reqs[] = {
203
204
205
	&amd64_requirement_rax,
	&amd64_requirement_gp,
	&amd64_requirement_rdx,
206
	&arch_no_requirement,
207
208
};

Matthias Braun's avatar
Matthias Braun committed
209
210
211
212
static const arch_register_req_t *reg_reqs[] = {
	&amd64_requirement_gp,
};

213
214
215
216
static const arch_register_req_t *xmm_reqs[] = {
	&amd64_requirement_xmm,
};

Matthias Braun's avatar
Matthias Braun committed
217
218
219
220
221
static const arch_register_req_t *reg_rcx_reqs[] = {
	&amd64_requirement_gp,
	&amd64_requirement_rcx,
};

222
223
224
static const arch_register_req_t *no_reqs[] = {
};

225
226
227
228
229
static const arch_register_req_t *xmm_xmm_reqs[] = {
	&amd64_requirement_xmm,
	&amd64_requirement_xmm,
};

Matthias Braun's avatar
Matthias Braun committed
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
static inline bool mode_needs_gp_reg(ir_mode *mode)
{
	return get_mode_arithmetic(mode) == irma_twos_complement;
}

static bool is_downconv(const ir_node *node)
{
	if (!is_Conv(node))
		return false;

	ir_mode *dest_mode = get_irn_mode(node);
	if (!mode_needs_gp_reg(dest_mode))
		return false;
	ir_mode *src_mode = get_irn_mode(get_Conv_op(node));
	if (!mode_needs_gp_reg(src_mode))
		return false;
	return get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}

static ir_node *skip_downconv(ir_node *node)
{
	while (is_downconv(node)) {
		if (get_irn_n_edges(node) > 1)
			break;
		node = get_Conv_op(node);
	}
	return node;
}

static bool is_sameconv(const ir_node *node)
{
	if (!is_Conv(node))
		return false;
	ir_mode *dest_mode = get_irn_mode(node);
	if (!mode_needs_gp_reg(dest_mode))
		return false;
	ir_mode *src_mode = get_irn_mode(get_Conv_op(node));
	if (!mode_needs_gp_reg(src_mode))
		return false;
	return get_mode_size_bits(dest_mode) == get_mode_size_bits(src_mode);
}

static ir_node *skip_sameconv(ir_node *node)
273
{
Matthias Braun's avatar
Matthias Braun committed
274
275
276
277
278
279
	while (is_sameconv(node)) {
		if (get_irn_n_edges(node) > 1)
			break;
		node = get_Conv_op(node);
	}
	return node;
280
281
}

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
static ir_node *get_reg(ir_graph *const irg, reg_info_t *const reg)
{
	if (!reg->irn) {
		/* this is already the transformed start node */
		ir_node *const start = get_irg_start(irg);
		assert(is_amd64_Start(start));
		arch_register_class_t const *const cls
			= arch_get_irn_register_req_out(start, reg->offset)->cls;
		reg->irn = new_r_Proj(start, cls ? cls->mode : mode_M, reg->offset);
	}
	return reg->irn;
}

static ir_node *get_initial_sp(ir_graph *irg)
{
	return get_reg(irg, &start_sp);
}

static ir_node *get_initial_fp(ir_graph *irg)
{
	return get_reg(irg, &start_fp);
}

static ir_node *get_initial_mem(ir_graph *irg)
{
	return get_reg(irg, &start_mem);
}

static ir_node *get_frame_base(ir_graph *irg)
{
	if (current_cconv->omit_fp) {
		return get_initial_sp(irg);
	} else {
		return get_initial_fp(irg);
	}
}
318

319
320
static ir_node *gen_Const(ir_node *node)
{
321
	ir_node  *block = be_transform_node(get_nodes_block(node));
322
	dbg_info *dbgi  = get_irn_dbg_info(node);
323
	ir_mode  *mode  = get_irn_mode(node);
324
	ir_tarval *tv = get_Const_tarval(node);
325
326
327

	if (!mode_needs_gp_reg(mode)) {
		if (tarval_is_null(tv)) {
328
			return new_bd_amd64_xXorp0(dbgi, block);
329
330
		}

331
		return create_float_const(dbgi, block, tv);
332
333
	}

334
335
	uint64_t val = get_tarval_uint64(tv);
	amd64_insn_mode_t imode = val > UINT32_MAX ? INSN_MODE_64 : INSN_MODE_32;
Matthias Braun's avatar
Matthias Braun committed
336
	return new_bd_amd64_MovImm(dbgi, block, imode, val, NULL);
337
338
}

Matthias Braun's avatar
Matthias Braun committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
typedef enum reference_mode_t {
	REFERENCE_DIRECT,
	REFERENCE_IP_RELATIVE,
	REFERENCE_GOT,
} reference_mode_t;

static reference_mode_t need_relative_addressing(const ir_entity *entity)
{
	if (!be_options.pic)
		return REFERENCE_DIRECT;

	/* simply everything is instruction pointer relative, external functions
	 * use a global offset table */
	return entity_has_definition(entity)
	   && (get_entity_linkage(entity) & IR_LINKAGE_MERGE) == 0
	    ? REFERENCE_IP_RELATIVE : REFERENCE_GOT;
}

357
static ir_node *gen_Address(ir_node *node)
358
359
360
{
	ir_node   *block  = be_transform_node(get_nodes_block(node));
	dbg_info  *dbgi   = get_irn_dbg_info(node);
361
	ir_entity *entity = get_Address_entity(node);
362

Matthias Braun's avatar
Matthias Braun committed
363
364
	/* do we need RIP-relative addressing because of PIC? */
	reference_mode_t mode = need_relative_addressing(entity);
Matthias Braun's avatar
Matthias Braun committed
365
	if (mode == REFERENCE_DIRECT)
Matthias Braun's avatar
Matthias Braun committed
366
367
368
369
		return new_bd_amd64_MovImm(dbgi, block, INSN_MODE_64, 0, entity);

	amd64_addr_t addr;
	memset(&addr, 0, sizeof(addr));
370
	addr.base_input  = NO_INPUT;
Matthias Braun's avatar
Matthias Braun committed
371
372
	addr.index_input = NO_INPUT;
	addr.mem_input   = NO_INPUT;
Matthias Braun's avatar
Matthias Braun committed
373
374

	if (mode == REFERENCE_IP_RELATIVE) {
Matthias Braun's avatar
Matthias Braun committed
375
		addr.immediate.entity = entity;
376
377
		ir_node *lea = new_bd_amd64_Lea(dbgi, block, 0, NULL, INSN_MODE_64, addr);
		return new_r_Proj(lea, mode_gp, pn_amd64_Lea_res);
Matthias Braun's avatar
Matthias Braun committed
378
379
	} else {
		assert(mode == REFERENCE_GOT);
Matthias Braun's avatar
Matthias Braun committed
380
		addr.immediate.entity = new_got_entry_entity(entity);
381
382
		ir_node *load = new_bd_amd64_Mov(dbgi, block, 0, NULL, INSN_MODE_64,
										 AMD64_OP_ADDR, addr);
Matthias Braun's avatar
Matthias Braun committed
383
		return new_r_Proj(load, mode_gp, pn_amd64_Mov_res);
Matthias Braun's avatar
Matthias Braun committed
384
385
386
	}
}

387
388
ir_node *amd64_new_IncSP(ir_node *block, ir_node *old_sp, int offset,
                         unsigned align)
Tobias Rapp's avatar
Tobias Rapp committed
389
{
390
391
392
393
	ir_node *incsp = be_new_IncSP(&amd64_registers[REG_RSP], block, old_sp,
	                              offset, align);
	arch_add_irn_flags(incsp, arch_irn_flag_modify_flags);
	return incsp;
Tobias Rapp's avatar
Tobias Rapp committed
394
395
}

Matthias Braun's avatar
Matthias Braun committed
396
typedef ir_node *(*construct_binop_func)(dbg_info *dbgi, ir_node *block,
Matthias Braun's avatar
Matthias Braun committed
397
	int arity, ir_node *in[], const amd64_binop_addr_attr_t *attr_init);
Matthias Braun's avatar
Matthias Braun committed
398

399
400
401
402
typedef ir_node *(*construct_rax_binop_func)(dbg_info *dbgi, ir_node *block,
	int arity, ir_node *in[], amd64_insn_mode_t insn_mode,
	amd64_op_mode_t op_mode, amd64_addr_t addr);

Matthias Braun's avatar
Matthias Braun committed
403
404
405
406
407
408
409
410
typedef enum match_flags_t {
	match_am           = 1 << 0,
	match_mode_neutral = 1 << 1,
	match_immediate    = 1 << 2,
	match_commutative  = 1 << 3,
} match_flags_t;

typedef struct amd64_args_t {
Matthias Braun's avatar
Matthias Braun committed
411
412
413
414
	amd64_binop_addr_attr_t     attr;
	ir_node                    *mem_proj;
	ir_node                    *in[4];
	int                         arity;
Matthias Braun's avatar
Matthias Braun committed
415
416
417
	const arch_register_req_t **reqs;
} amd64_args_t;

Matthias Braun's avatar
Matthias Braun committed
418
static bool match_immediate_32(amd64_imm32_t *imm, const ir_node *op,
419
420
                               bool can_match_ip_relative,
                               bool upper32_dont_care)
Matthias Braun's avatar
Matthias Braun committed
421
422
{
	assert(mode_needs_gp_reg(get_irn_mode(op)));
Matthias Braun's avatar
Matthias Braun committed
423
	assert(imm->offset == 0 && imm->entity == NULL);
Matthias Braun's avatar
Matthias Braun committed
424
425
426
427
428
429
430
431
	if (is_Const(op)) {
		ir_tarval *tv = get_Const_tarval(op);
		if (!tarval_is_long(tv))
			return false;
		long    lval = get_tarval_long(tv);
		int32_t val  = (int32_t)lval;
		if ((long)val != lval)
			return false;
432
433
434
435
436
		/** the immediate value is signed extended to 64bit, sometimes
		 * this is not what we want. */
		if (!upper32_dont_care && val < 0
		    && !mode_is_signed(get_tarval_mode(tv)))
		    return false;
Matthias Braun's avatar
Matthias Braun committed
437
438
439
440
441
442
		imm->offset = val;
		return true;
	} else if (can_match_ip_relative && is_Address(op)) {
		/* TODO: check if entity is in lower 4GB address space/relative */
		ir_entity *entity = get_Address_entity(op);
		imm->entity = entity;
Matthias Braun's avatar
Matthias Braun committed
443
444
		return true;
	}
Matthias Braun's avatar
Matthias Braun committed
445
	/* TODO: SymConst, Add(SymConst, Const) ... */
Matthias Braun's avatar
Matthias Braun committed
446
447
448
449
450
	return false;
}

static ir_heights_t *heights;

451
452
453
454
455
456
457
458
459
static bool input_depends_on_load(ir_node *load, ir_node *input)
{
	ir_node *block = get_nodes_block(load);
	/* if the dependency is in another block, then we ignore it for now
	   as we only match address mode loads in the same block. */
	return get_nodes_block(input) == block
	    && heights_reachable_in_block(heights, input, load);
}

Tobias Rapp's avatar
Tobias Rapp committed
460
461
462
463
464
465
466
467
468
static void fix_node_mem_proj(ir_node *node, ir_node *mem_proj)
{
	if (mem_proj == NULL)
		return;

	ir_node *load = get_Proj_pred(mem_proj);
	be_set_transformed_node(load, node);
}

469
static ir_node *source_am_possible(ir_node *block, ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
470
471
{
	if (!is_Proj(node))
472
		return NULL;
Matthias Braun's avatar
Matthias Braun committed
473
474
	ir_node *load = get_Proj_pred(node);
	if (!is_Load(load))
475
		return NULL;
476
	assert(get_Proj_num(node) == pn_Load_res);
Matthias Braun's avatar
Matthias Braun committed
477
	if (get_nodes_block(load) != block)
478
		return NULL;
Matthias Braun's avatar
Matthias Braun committed
479
480
	/* make sure we are the only user */
	if (get_irn_n_edges(node) != 1)
481
		return NULL;
Matthias Braun's avatar
Matthias Braun committed
482
483
484
	/* ia32 backend claims this can happen, use an assert for now and see
	 * if we hit it :) */
	assert(!be_is_transformed(node));
485
	return load;
Matthias Braun's avatar
Matthias Braun committed
486
487
488
489
490
491
492
493
494
495
}

static bool needs_extension(ir_node *op)
{
	ir_mode *mode = get_irn_mode(op);
	if (get_mode_size_bits(mode) >= 32)
		return false;
	return !be_upper_bits_clean(op, mode);
}

Tobias Rapp's avatar
Tobias Rapp committed
496
static ir_node *create_sext(ir_node *block, ir_node *const node, ir_mode *mode)
497
498
499
{
	amd64_insn_mode_t insn_mode = get_insn_mode_from_mode(mode);
	dbg_info *const   dbgi      = get_irn_dbg_info(node);
Tobias Rapp's avatar
Tobias Rapp committed
500
501
	ir_node  *const   new_node  = be_transform_node(node);
	ir_node  *const   new_block = be_transform_node(block);
502
503
504
505
506
507

	amd64_shift_attr_t attr;
	memset(&attr, 0, sizeof(attr));
	attr.base.op_mode = AMD64_OP_SHIFT_IMM;
	attr.insn_mode    = insn_mode;
	attr.immediate    = get_mode_size_bits(mode) - 1;
Tobias Rapp's avatar
Tobias Rapp committed
508
509
510
	ir_node *in[1]    = { new_node };
	ir_node *sext     = new_bd_amd64_Sar(dbgi, new_block, ARRAY_SIZE(in),
	                                     in, &attr);
511
512
513
514
515
516
517

	arch_set_irn_register_reqs_in(sext, reg_reqs);
	arch_set_irn_register_req_out(sext, 0, &amd64_requirement_gp_same_0);

	return sext;
}

Tobias Rapp's avatar
Tobias Rapp committed
518
static ir_node *create_zext(ir_node *block, ir_node *const node)
519
{
Tobias Rapp's avatar
Tobias Rapp committed
520
521
522
	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const new_block = be_transform_node(block);
	ir_node  *const zero      = new_bd_amd64_Xor0(dbgi, new_block);
523
524
525
526
527

	arch_set_irn_register_reqs_in(zero, reg_reqs);
	return zero;
}

Tobias Rapp's avatar
Tobias Rapp committed
528
529
static bool use_address_matching(ir_mode *mode, match_flags_t flags,
                                 ir_node *block,
530
531
532
                                 ir_node *op1, ir_node *op2,
                                 ir_node **out_load, ir_node **out_op)
{
533
534
	if (! (flags & match_am))
		return false;
535

Tobias Rapp's avatar
Tobias Rapp committed
536
537
538
539
	unsigned mode_bits = get_mode_size_bits(mode);
	if (mode_bits == 8 || mode_bits == 16)
		return false;

540
541
542
	ir_node *load2 = source_am_possible(block, op2);
	if (load2 != NULL && !input_depends_on_load(load2, op1)) {
		(*out_load) = load2;
543
544
		(*out_op)   = op1;
		return true;
545
546
547
548
549
550
551
552
553
	}

	if (flags & match_commutative) {
		ir_node *load1 = source_am_possible(block, op1);
		if (load1 != NULL && !input_depends_on_load(load1, op2)) {
			(*out_load) = load1;
			(*out_op)   = op2;
			return true;
		}
554
555
556
557
	}
	return false;
}

558
559
static void perform_address_matching(ir_node *ptr, int *arity,
                                     ir_node **in, amd64_addr_t *addr)
560
561
562
{
	x86_address_t maddr;
	memset(&maddr, 0, sizeof(maddr));
563
	x86_create_address_mode(&maddr, ptr, x86_create_am_normal);
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

	if (maddr.base != NULL) {
		int base_input   = (*arity)++;
		addr->base_input = base_input;
		in[base_input]   = be_transform_node(maddr.base);
	} else {
		addr->base_input = NO_INPUT;
	}
	if (maddr.index != NULL) {
		int index_input = (*arity)++;
		addr->index_input = index_input;
		in[index_input]  = be_transform_node(maddr.index);
	} else {
		addr->index_input = NO_INPUT;
	}
579
580
581
582
583
584
585
586
587
588
	if (maddr.frame_entity != NULL) {
		assert(maddr.entity == NULL);
		addr->immediate.entity = maddr.frame_entity;
		/* not supported yet */
		assert(!is_parameter_entity(maddr.frame_entity)
		       || get_entity_parameter_number(maddr.frame_entity)
		          != IR_VA_START_PARAMETER_NUMBER);
	} else {
		addr->immediate.entity = maddr.entity;
	}
589
590
591
592
	addr->immediate.offset = maddr.offset;
	addr->log_scale        = maddr.scale;
}

Matthias Braun's avatar
Matthias Braun committed
593
594
595
static void match_binop(amd64_args_t *args, ir_node *block,
                        ir_mode *mode, ir_node *op1, ir_node *op2,
                        match_flags_t flags)
Matthias Braun's avatar
Matthias Braun committed
596
597
598
{
	memset(args, 0, sizeof(*args));

599
	bool use_am;
600
	bool use_xmm       = mode_is_float(mode);
Matthias Braun's avatar
Matthias Braun committed
601
	bool use_immediate = flags & match_immediate;
602
	bool mode_neutral  = flags & match_mode_neutral;
Matthias Braun's avatar
Matthias Braun committed
603

Matthias Braun's avatar
Matthias Braun committed
604
	args->attr.base.insn_mode = get_insn_mode_from_mode(mode);
Matthias Braun's avatar
Matthias Braun committed
605
606

	/* TODO: legalize phase */
607
	if (mode_neutral) {
Matthias Braun's avatar
Matthias Braun committed
608
609
610
611
612
613
614
615
616
		op1 = skip_downconv(op1);
		op2 = skip_downconv(op2);
	} else {
		/* TODO: extend inputs? */
		(void)needs_extension;
	}

	ir_node *load;
	ir_node *op;
617

Tobias Rapp's avatar
Tobias Rapp committed
618
	use_am = use_address_matching(mode, flags, block, op1, op2, &load, &op);
619

620
621
	if (use_immediate
	    && match_immediate_32(&args->attr.u.immediate, op2, false, mode_neutral)) {
622
		assert(!use_xmm && "Can't (yet) match binop with xmm immediate");
Matthias Braun's avatar
Matthias Braun committed
623
		/* fine, we found an immediate */
Matthias Braun's avatar
Matthias Braun committed
624
625
626
		args->attr.base.base.op_mode = AMD64_OP_REG_IMM;
		args->in[args->arity++]      = be_transform_node(op1);
		args->reqs                   = reg_reqs;
627
	} else if (use_am) {
Matthias Braun's avatar
Matthias Braun committed
628
629
630
631
		ir_node *new_op        = be_transform_node(op);
		int      reg_input     = args->arity++;
		args->attr.u.reg_input = reg_input;
		args->in[reg_input]    = new_op;
632
		amd64_addr_t *addr     = &args->attr.base.addr;
Matthias Braun's avatar
Matthias Braun committed
633

634
635
636
		ir_node *ptr = get_Load_ptr(load);
		perform_address_matching(ptr, &(args->arity), args->in, addr);

637
		args->reqs = use_xmm ? xmm_mem_reqs : reg_mem_reqs;
638
		if (addr->base_input != NO_INPUT && addr->index_input != NO_INPUT) {
639
			args->reqs = use_xmm ? xmm_reg_reg_mem_reqs
640
			             : reg_reg_reg_mem_reqs;
641
		} else if (addr->base_input != NO_INPUT || addr->index_input != NO_INPUT) {
642
			args->reqs = use_xmm ? xmm_reg_mem_reqs
643
			             : reg_reg_mem_reqs;
644
645
646
647
648
		}
		ir_node *new_mem    = be_transform_node(get_Load_mem(load));
		int mem_input       = args->arity++;
		args->in[mem_input] = new_mem;
		addr->mem_input     = mem_input;
649

650
		args->mem_proj      = be_get_Proj_for_pn(load, pn_Load_M);
651
		args->attr.base.base.op_mode = AMD64_OP_ADDR_REG;
Matthias Braun's avatar
Matthias Braun committed
652
653
654
655
	} else {
		/* simply transform the arguments */
		args->in[args->arity++] = be_transform_node(op1);
		args->in[args->arity++] = be_transform_node(op2);
Matthias Braun's avatar
Matthias Braun committed
656
		args->attr.base.base.op_mode = AMD64_OP_REG_REG;
657

658
		args->reqs = use_xmm ? xmm_xmm_reqs : reg_reg_reqs;
Matthias Braun's avatar
Matthias Braun committed
659
660
661
662
663
664
665
666
667
	}
}

static ir_node *gen_binop_am(ir_node *node, ir_node *op1, ir_node *op2,
                             construct_binop_func func, match_flags_t flags)
{
	ir_node *block = get_nodes_block(node);
	ir_mode *mode  = get_irn_mode(node);
	amd64_args_t args;
Matthias Braun's avatar
Matthias Braun committed
668
	match_binop(&args, block, mode, op1, op2, flags);
Matthias Braun's avatar
Matthias Braun committed
669
670
671
672

	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const new_block = be_transform_node(block);

Matthias Braun's avatar
Matthias Braun committed
673
	ir_node *new_node = func(dbgi, new_block, args.arity, args.in, &args.attr);
Matthias Braun's avatar
Matthias Braun committed
674
	arch_set_irn_register_reqs_in(new_node, args.reqs);
675

Tobias Rapp's avatar
Tobias Rapp committed
676
	fix_node_mem_proj(new_node, args.mem_proj);
Matthias Braun's avatar
Matthias Braun committed
677

678
679
680
	if (mode_is_float(mode)) {
		arch_set_irn_register_req_out(new_node, 0,
		                              &amd64_requirement_xmm_same_0);
Tobias Rapp's avatar
Tobias Rapp committed
681
		return new_r_Proj(new_node, mode_D, pn_amd64_xSubs_res);
682
683
684
685
686
	} else {
		arch_set_irn_register_req_out(new_node, 0,
		                              &amd64_requirement_gp_same_0);
		return new_r_Proj(new_node, mode_gp, pn_amd64_Sub_res);
	}
Matthias Braun's avatar
Matthias Braun committed
687
688
}

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
static ir_node *gen_binop_rax(ir_node *node, ir_node *op1, ir_node *op2,
                              construct_rax_binop_func make_node,
                              match_flags_t flags)
{
	bool use_am;
	bool mode_neutral  = flags & match_mode_neutral;
	assert(! (flags & match_immediate));

	ir_mode *mode = get_irn_mode(op1);
	amd64_insn_mode_t insn_mode = get_insn_mode_from_mode(mode);

	/* TODO: legalize phase */
	if (mode_neutral) {
		op1 = skip_downconv(op1);
		op2 = skip_downconv(op2);
	} else {
		/* TODO: extend inputs? */
		(void)needs_extension;
	}

	ir_node *load;
	ir_node *op;
	ir_node *block = get_nodes_block(node);
	ir_node *in[4];
	int      arity = 0;
	const arch_register_req_t **reqs;
	amd64_op_mode_t op_mode;
	amd64_addr_t    addr;
	memset(&addr, 0, sizeof(addr));

Tobias Rapp's avatar
Tobias Rapp committed
719
	use_am = use_address_matching(mode, flags, block, op1, op2, &load, &op);
720

721
	ir_node *mem_proj = NULL;
722
723
724
725
726
	if (use_am) {
		ir_node *new_op    = be_transform_node(op);
		int      reg_input = arity++;
		in[reg_input]      = new_op;

727
728
729
730
731
732
		ir_node *ptr = get_Load_ptr(load);
		perform_address_matching(ptr, &arity, in, &addr);

		reqs = reg_mem_reqs;
		if (addr.base_input != NO_INPUT && addr.index_input != NO_INPUT) {
			reqs = reg_reg_reg_mem_reqs;
733
		} else if (addr.base_input != NO_INPUT || addr.index_input != NO_INPUT) {
734
735
736
737
738
739
740
			reqs = reg_reg_mem_reqs;
		}

		ir_node *new_mem = be_transform_node(get_Load_mem(load));
		int mem_input    = arity++;
		in[mem_input]    = new_mem;
		addr.mem_input   = mem_input;
741
742
743
744
745

		mem_proj                = be_get_Proj_for_pn(load, pn_Load_M);
		op_mode                 = AMD64_OP_RAX_ADDR;
	} else {
		/* simply transform the arguments */
746
747
748
749
		in[arity++] = be_transform_node(op1);
		in[arity++] = be_transform_node(op2);
		reqs        = rax_reg_reqs;
		op_mode     = AMD64_OP_RAX_REG;
750
751
	}

752
	assert((size_t)arity <= ARRAY_SIZE(in));
753
754
755
756
757
	dbg_info *dbgi      = get_irn_dbg_info(node);
	ir_node  *new_block = be_transform_node(block);
	ir_node  *new_node  = make_node(dbgi, new_block, arity, in, insn_mode,
	                                op_mode, addr);
	arch_set_irn_register_reqs_in(new_node, reqs);
758
759
760
	if (mem_proj != NULL) {
		be_set_transformed_node(load, new_node);
	}
761
762
763
	return new_node;
}

Matthias Braun's avatar
Matthias Braun committed
764
typedef ir_node *(*construct_shift_func)(dbg_info *dbgi, ir_node *block,
Matthias Braun's avatar
Matthias Braun committed
765
	int arity, ir_node *in[], const amd64_shift_attr_t *attr_init);
Matthias Braun's avatar
Matthias Braun committed
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780

static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
                                construct_shift_func func, match_flags_t flags)
{
	ir_mode *mode = get_irn_mode(node);
	assert(!mode_is_float(mode));

	if (get_mode_modulo_shift(mode) != 32 && get_mode_size_bits(mode) != 64)
		panic("insupported modulo shift used");

	ir_node *in[3];
	int      arity = 0;
	if (flags & match_mode_neutral) {
		op1 = skip_downconv(op1);
		in[arity++] = be_transform_node(op1);
Matthias Braun's avatar
Matthias Braun committed
781
		mode = get_mode_size_bits(mode) > 32 ? mode_gp : mode_Iu;
Matthias Braun's avatar
Matthias Braun committed
782
783
	} else {
		op1 = skip_sameconv(op1);
784
785
786

		/* Use 8/16bit operations instead of doing zext/upconv */
		in[arity++] = be_transform_node(op1);
Matthias Braun's avatar
Matthias Braun committed
787
788
789
790
791
792
	}

	/* we can skip any convs for the shift count, as it only uses the lowest
	 * 5/6 bits anyway */
	while (is_Conv(op2) && get_irn_n_edges(op2) == 1) {
		ir_node *const op = get_Conv_op(op2);
793
		if (get_mode_arithmetic(get_irn_mode(op)) != irma_twos_complement)
Matthias Braun's avatar
Matthias Braun committed
794
795
796
797
			break;
		op2 = op;
	}

Matthias Braun's avatar
Matthias Braun committed
798
799
	amd64_shift_attr_t attr;
	memset(&attr, 0, sizeof(attr));
Matthias Braun's avatar
Matthias Braun committed
800
801
802
	const arch_register_req_t **reqs;
	const arch_register_req_t  *out_req0;
	if (is_Const(op2)) {
Matthias Braun's avatar
Matthias Braun committed
803
804
805
806
		attr.base.op_mode = AMD64_OP_SHIFT_IMM;
		reqs              = reg_reqs;
		out_req0          = &amd64_requirement_gp_same_0;
		attr.immediate    = get_tarval_long(get_Const_tarval(op2));
Matthias Braun's avatar
Matthias Braun committed
807
	} else {
Matthias Braun's avatar
Matthias Braun committed
808
809
810
811
		attr.base.op_mode = AMD64_OP_SHIFT_REG;
		in[arity++]       = be_transform_node(op2);
		reqs              = reg_rcx_reqs;
		out_req0          = &amd64_requirement_gp_same_0_not_1;
Matthias Braun's avatar
Matthias Braun committed
812
	}
Matthias Braun's avatar
Matthias Braun committed
813
	attr.insn_mode = get_insn_mode_from_mode(mode);
Matthias Braun's avatar
Matthias Braun committed
814

Matthias Braun's avatar
Matthias Braun committed
815
816
817
818
	ir_node  *const block     = get_nodes_block(node);
	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const new_block = be_transform_node(block);
	ir_node  *const new_node  = func(dbgi, new_block, arity, in, &attr);
Matthias Braun's avatar
Matthias Braun committed
819
820
821
	arch_set_irn_register_reqs_in(new_node, reqs);
	arch_set_irn_register_req_out(new_node, 0, out_req0);
	return new_node;
822
823
}

824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
static ir_node *create_Lea_as_Add(ir_node *node, ir_node *op1, ir_node *op2)
{
	dbg_info *const dbgi = get_irn_dbg_info(node);
	ir_node  *block      = get_nodes_block(node);
	ir_node  *new_block  = be_transform_node(block);
	ir_mode *mode        = get_irn_mode(node);

	amd64_insn_mode_t insn_mode;
	if (get_mode_size_bits(mode) <= 32)
		insn_mode = INSN_MODE_32;
	else
		insn_mode = INSN_MODE_64;

	const arch_register_req_t **reqs;
	amd64_addr_t addr;
	memset(&addr, 0, sizeof(addr));

	ir_node *in[2];
	int arity = 0;

	if (match_immediate_32(&addr.immediate, op2, false, true)) {
		in[arity++]      = be_transform_node(op1);
		reqs             = reg_reqs;
		addr.index_input = NO_INPUT;
	} else {
		in[arity++]      = be_transform_node(op1);
		in[arity++]      = be_transform_node(op2);
		addr.index_input = 0;
		addr.base_input  = 1;
		reqs             = reg_reg_reqs;
	}

	ir_node *res = new_bd_amd64_Lea(dbgi, new_block, arity, in, insn_mode, addr);
	arch_set_irn_register_reqs_in(res, reqs);
858
	return new_r_Proj(res, mode_gp, pn_amd64_Lea_res);
859
860
}

Matthias Braun's avatar
Matthias Braun committed
861
862
static ir_node *gen_Add(ir_node *const node)
{
863
864
865
	match_flags_t flags = match_immediate | match_am | match_mode_neutral
	                      | match_commutative;

Matthias Braun's avatar
Matthias Braun committed
866
867
	ir_node *op1 = get_Add_left(node);
	ir_node *op2 = get_Add_right(node);
868
869
870
871
872

	ir_mode *mode  = get_irn_mode(node);
	ir_node *block = get_nodes_block(node);
	ir_node *load, *op;

873
	if (mode_is_float(mode)) {
874
		return gen_binop_am(node, op1, op2, new_bd_amd64_xAdds,
875
876
877
		                    match_commutative | match_am);
	}

878
879
880
881
882
883
884
885
	bool use_am = use_address_matching(mode, flags, block, op1, op2, &load, &op);

	ir_node *res;
	if (use_am)
		res = gen_binop_am(node, op1, op2, new_bd_amd64_Add, flags);
	else
		res = create_Lea_as_Add(node, op1, op2);

Matthias Braun's avatar
Matthias Braun committed
886
887
888
	x86_mark_non_am(node);
	return res;
}
889

Matthias Braun's avatar
Matthias Braun committed
890
static ir_node *gen_Sub(ir_node *const node)
891
{
Matthias Braun's avatar
Matthias Braun committed
892
893
	ir_node  *const op1     = get_Sub_left(node);
	ir_node  *const op2     = get_Sub_right(node);
894
	ir_mode  *const mode    = get_irn_mode(node);
895
896

	if (mode_is_float(mode)) {
897
		return gen_binop_am(node, op1, op2, new_bd_amd64_xSubs, match_am);
898
899
900
901
902
903
	} else {
		/* do not match AM yet until we have a sub->neg+add rule
		 * in amd64_finish */
		return gen_binop_am(node, op1, op2, new_bd_amd64_Sub,
		                    /* match_am | */ match_immediate);
	}
Matthias Braun's avatar
Matthias Braun committed
904
905
906
907
908
909
910
911
912
}

static ir_node *gen_And(ir_node *const node)
{
	ir_node *op1 = get_And_left(node);
	ir_node *op2 = get_And_right(node);
	return gen_binop_am(node, op1, op2, new_bd_amd64_And,
	                    match_immediate | match_am | match_mode_neutral
	                    | match_commutative);
913
914
}

Matthias Braun's avatar
Matthias Braun committed
915
916
917
918
919
920
921
922
923
924
925
926
927
static ir_node *gen_Eor(ir_node *const node)
{
	ir_node *op1 = get_Eor_left(node);
	ir_node *op2 = get_Eor_right(node);
	return gen_binop_am(node, op1, op2, new_bd_amd64_Xor,
	                    match_immediate | match_am | match_mode_neutral
	                    | match_commutative);
}

static ir_node *gen_Or(ir_node *const node)
{
	ir_node *op1 = get_Or_left(node);
	ir_node *op2 = get_Or_right(node);
928
	return gen_binop_am(node, op1, op2, new_bd_amd64_Or,
Matthias Braun's avatar
Matthias Braun committed
929
930
931
932
933
934
	                    match_immediate | match_am | match_mode_neutral
	                    | match_commutative);
}

static ir_node *gen_Mul(ir_node *const node)
{
935
936
937
938
939
940
941
	ir_node *op1  = get_Mul_left(node);
	ir_node *op2  = get_Mul_right(node);
	ir_mode *mode = get_irn_mode(node);

	if (get_mode_size_bits(mode) < 16) {
		/* imulb only supports rax - reg form */
		ir_node *new_node =
Tobias Rapp's avatar
Tobias Rapp committed
942
943
944
		            gen_binop_rax(node, op1, op2, new_bd_amd64_IMul1Op,
		                          match_mode_neutral
		                          | match_commutative);
945
		return new_r_Proj(new_node, mode_gp, pn_amd64_IMul1Op_res_low);
Tobias Rapp's avatar
Tobias Rapp committed
946
947
948
	} else if (mode_is_float(mode)) {
		return gen_binop_am(node, op1, op2, new_bd_amd64_xMuls,
		                    match_commutative | match_am);
949
950
	} else {
		return gen_binop_am(node, op1, op2, new_bd_amd64_IMul,
Tobias Rapp's avatar
Tobias Rapp committed
951
952
		                    match_immediate | match_am
		                    | match_mode_neutral | match_commutative);
953
	}
Matthias Braun's avatar
Matthias Braun committed
954
955
}

956
957
static ir_node *gen_Mulh(ir_node *const node)
{
958
959
960
961
962
	ir_node *op1  = get_Mulh_left(node);
	ir_node *op2  = get_Mulh_right(node);
	ir_mode *mode = get_irn_mode(op1);
	ir_node *new_node;

963
	if (mode_is_signed(mode)) {
964
965
966
		new_node = gen_binop_rax(node, op1, op2, new_bd_amd64_IMul1Op,
                        /* match_am TODO */
                        match_mode_neutral | match_commutative);
Tobias Rapp's avatar
Tobias Rapp committed
967
		return new_r_Proj(new_node, mode_gp, pn_amd64_IMul1Op_res_high);
968
969
	} else {
		new_node = gen_binop_rax(node, op1, op2, new_bd_amd64_Mul,
970
971
                         /* match_am TODO */
                         match_mode_neutral | match_commutative);
972
973
		return new_r_Proj(new_node, mode_gp, pn_amd64_Mul_res_high);
	}
974
975
}

Matthias Braun's avatar
Matthias Braun committed
976
977
978
979
980
static ir_node *gen_Shl(ir_node *const node)
{
	ir_node *op1 = get_Shl_left(node);
	ir_node *op2 = get_Shl_right(node);
	return gen_shift_binop(node, op1, op2, new_bd_amd64_Shl,
Matthias Braun's avatar
Matthias Braun committed
981
	                       match_immediate | match_mode_neutral);
Matthias Braun's avatar
Matthias Braun committed
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
}

static ir_node *gen_Shr(ir_node *const node)
{
	ir_node *op1 = get_Shr_left(node);
	ir_node *op2 = get_Shr_right(node);
	return gen_shift_binop(node, op1, op2, new_bd_amd64_Shr,
	                       match_immediate);
}

static ir_node *gen_Shrs(ir_node *const node)
{
	ir_node *op1 = get_Shrs_left(node);
	ir_node *op2 = get_Shrs_right(node);
	return gen_shift_binop(node, op1, op2, new_bd_amd64_Sar,
	                       match_immediate);
}
Robin Redeker's avatar
Robin Redeker committed
999

Matthias Braun's avatar
Matthias Braun committed
1000
static ir_node *create_div(ir_node *const node, ir_mode *const mode,
1001
1002
                           ir_node *const op1, ir_node *const op2,
                           ir_node *const mem)
Matthias Braun's avatar
Matthias Braun committed
1003
{
Tobias Rapp's avatar
Tobias Rapp committed
1004
1005
1006
	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const block     = get_nodes_block(node);
	ir_node  *const new_block = be_transform_node(block);
Matthias Braun's avatar
Matthias Braun committed
1007
1008
	amd64_insn_mode_t insn_mode
		= get_mode_size_bits(mode) > 32 ? INSN_MODE_64 : INSN_MODE_32;
1009

1010
1011
1012
1013
1014
	ir_node *new_op1 = be_transform_node(op1);
	ir_node *new_op2 = be_transform_node(op2);
	ir_node *new_mem = be_transform_node(mem);
	ir_node *upper_value;
	ir_node *(*constructor)(dbg_info*,ir_node*,int,ir_node**,amd64_insn_mode_t);
Matthias Braun's avatar
Matthias Braun committed
1015
	if (mode_is_signed(mode)) {
1016
1017
		upper_value = create_sext(block, op1, mode);
		constructor = new_bd_amd64_IDiv;
Matthias Braun's avatar
Matthias Braun committed
1018
	} else {
1019
1020
		upper_value = create_zext(block, node);
		constructor = new_bd_amd64_Div;
Matthias Braun's avatar
Matthias Braun committed
1021
	}
1022

1023
1024
1025
	ir_node *in[] = { new_op1, new_op2, upper_value, new_mem };
	ir_node *res = constructor(dbgi, new_block, ARRAY_SIZE(in), in, insn_mode);
	arch_set_irn_register_reqs_in(res, rax_reg_rdx_mem_reqs);
Matthias Braun's avatar
Matthias Braun committed
1026
1027
1028
	return res;
}

Tobias Rapp's avatar
Tobias Rapp committed
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
static ir_node *create_sse_div(ir_node *const node, ir_mode *const mode,
                               ir_node *const op1, ir_node *const op2)
{
	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const block     = get_nodes_block(node);
	ir_node  *const new_block = be_transform_node(block);

	amd64_args_t args;
	match_binop(&args, block, mode, op1, op2, match_am);

	ir_node *const new_node = new_bd_amd64_xDivs(dbgi, new_block, args.arity,
	                                             args.in, &args.attr);
	arch_set_irn_register_reqs_in(new_node, args.reqs);

Tobias Rapp's avatar
Tobias Rapp committed
1043
	fix_node_mem_proj(new_node, args.mem_proj);
Tobias Rapp's avatar
Tobias Rapp committed
1044
1045
1046
1047
1048
1049

	arch_set_irn_register_req_out(new_node, 0,
	                              &amd64_requirement_xmm_same_0);
	return new_node;
}

Matthias Braun's avatar
Matthias Braun committed
1050
1051
1052
static ir_node *gen_Div(ir_node *const node)
{
	ir_mode *const mode = get_Div_resmode(node);
1053
1054
1055
	ir_node *const op1  = get_Div_left(node);
	ir_node *const op2  = get_Div_right(node);
	ir_node *const mem  = get_Div_mem(node);
Tobias Rapp's avatar
Tobias Rapp committed
1056
1057
1058
1059

	if (mode_is_float(mode))
		return create_sse_div(node, mode, op1, op2);
	else
1060
		return create_div(node, mode, op1, op2, mem);
Matthias Braun's avatar
Matthias Braun committed
1061
1062
1063
1064
1065
1066
}

static ir_node *gen_Proj_Div(ir_node *const node)
{
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);
1067
	unsigned pn       = get_Proj_num(node);
Matthias Braun's avatar
Matthias Braun committed
1068

1069
1070
1071
1072
	assert((unsigned)pn_amd64_Div_M == (unsigned)pn_amd64_IDiv_M);
	assert((unsigned)pn_amd64_Div_res_div == (unsigned)pn_amd64_IDiv_res_div);
	assert((unsigned)pn_amd64_xDivs_M == (unsigned)pn_amd64_IDiv_M);
	assert((unsigned)pn_amd64_xDivs_res_div == (unsigned)pn_amd64_IDiv_res_div);
Tobias Rapp's avatar
Tobias Rapp committed
1073
1074
1075
1076
1077
1078
1079

	ir_mode *mode;
	if (mode_is_float(get_Div_resmode(pred)))
		mode = mode_D;
	else
		mode = mode_gp;

yb9976's avatar
yb9976 committed
1080
	switch ((pn_Div)pn) {
Matthias Braun's avatar
Matthias Braun committed
1081
1082
1083
	case pn_Div_M:
		return new_r_Proj(new_pred, mode_M, pn_amd64_Div_M);
	case pn_Div_res:
Tobias Rapp's avatar
Tobias Rapp committed
1084
		return new_r_Proj(new_pred, mode, pn_amd64_Div_res_div);
Matthias Braun's avatar
Matthias Braun committed
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
	case pn_Div_X_except:
	case pn_Div_X_regular:
		panic("amd64 exception NIY");
	}
	panic("invalid Div Proj");
}

static ir_node *gen_Mod(ir_node *const node)
{
	ir_mode *const mode = get_Mod_resmode(node);
	ir_node *const op1  = get_Mod_left(node);
	ir_node *const op2  = get_Mod_right(node);
1097
	ir_node *const mem  = get_Mod_mem(node);
Matthias Braun's avatar
Matthias Braun committed
1098
	assert(mode_needs_gp_reg(mode));
1099
	return create_div(node, mode, op1, op2, mem);
Matthias Braun's avatar
Matthias Braun committed
1100
1101
1102
1103
1104
1105
}

static ir_node *gen_Proj_Mod(ir_node *const node)
{
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);
1106
	unsigned pn       = get_Proj_num(node);
Matthias Braun's avatar
Matthias Braun committed
1107

1108
1109
	assert((unsigned)pn_amd64_Div_M == (unsigned)pn_amd64_IDiv_M);
	assert((unsigned)pn_amd64_Div_res_mod == (unsigned)pn_amd64_IDiv_res_mod);
yb9976's avatar
yb9976 committed
1110
	switch ((pn_Mod)pn) {
Matthias Braun's avatar
Matthias Braun committed
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
	case pn_Mod_M:
		return new_r_Proj(new_pred, mode_M, pn_amd64_Div_M);
	case pn_Mod_res:
		return new_r_Proj(new_pred, mode_gp, pn_amd64_Div_res_mod);
	case pn_Mod_X_except:
	case pn_Mod_X_regular:
		panic("amd64 exception NIY");
	}
	panic("invalid Mod Proj");
}

Matthias Braun's avatar
Matthias Braun committed
1122
1123
1124
typedef ir_node* (*unop_constructor)(dbg_info*,ir_node*block,ir_node*op,amd64_insn_mode_t insn_mode);

static ir_node *gen_unop(ir_node *const node, int op_pos, unop_constructor gen)
1125
{
1126
1127
	dbg_info *const dbgi   = get_irn_dbg_info(node);
	ir_node  *const block  = be_transform_node(get_nodes_block(node));
1128
	ir_node  *const op     = get_irn_n(node, op_pos);
1129
	ir_node  *const new_op = be_transform_node(op);
Matthias Braun's avatar
Matthias Braun committed
1130
	ir_mode  *const mode   = get_irn_mode(node);
1131

Matthias Braun's avatar
Matthias Braun committed
1132
1133
1134
	amd64_insn_mode_t insn_mode
		= get_mode_size_bits(mode) > 32 ? INSN_MODE_64 : INSN_MODE_32;
	return gen(dbgi, block, new_op, insn_mode);
1135
1136
}

1137
1138
1139
1140
/** Create a floating point negation by switching the sign bit using a Xor.
  */
static ir_node *gen_float_neg(ir_node *const node)
{
1141
1142
1143
1144
1145
1146
1147
1148
1149
	dbg_info  *const dbgi = get_irn_dbg_info(node);
	ir_node   *block      = get_nodes_block(node);
	ir_node   *new_block  = be_transform_node(block);
	ir_node   *op         = get_irn_n(node, n_Minus_op);
	ir_node   *new_op     = be_transform_node(op);
	ir_mode   *mode       = get_irn_mode(node);
	ir_tarval *tv         = create_sign_tv(mode);
	ir_node   *load       = create_float_const(dbgi, new_block, tv);
	ir_node   *in[]       = { new_op, load };
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159

	amd64_binop_addr_attr_t attr;
	memset(&attr, 0, sizeof(attr));
	attr.base.base.op_mode = AMD64_OP_REG_REG;

	ir_node *xor = new_bd_amd64_xXorp(dbgi, new_block, ARRAY_SIZE(in),
	                                  in, &attr);
	arch_set_irn_register_reqs_in(xor, xmm_xmm_reqs);
	arch_set_irn_register_req_out(xor, 0, &amd64_requirement_xmm_same_0);

1160
	return new_r_Proj(xor, mode, pn_amd64_xXorp_res);
1161
1162
}

1163
1164
static ir_node *gen_Minus(ir_node *const node)
{
1165
1166
1167
1168
1169
1170
1171
	ir_mode *mode = get_irn_mode(node);

	if (mode_is_float(mode)) {
		return gen_float_neg(node);
	} else {
		return gen_unop(node, n_Minus_op, &new_bd_amd64_Neg);
	}
1172
}
Matthias Braun's avatar
Matthias Braun committed
1173
static ir_node *gen_Not(ir_node *const node)
1174
1175
1176
{
	return gen_unop(node, n_Not_op, &new_bd_amd64_Not);
}
1177

1178
static ir_node *gen_Member(ir_node *const node)
1179
{
1180
1181
1182
	ir_node   *block     = get_nodes_block(node);
	ir_node   *new_block = be_transform_node(block);
	dbg_info  *dbgi      = get_irn_dbg_info(node);
1183
	ir_node   *ptr       = get_Member_ptr(node);
1184
1185
	ir_graph  *irg       = get_irn_irg(node);
	ir_node   *base      = get_frame_base(irg);
1186
	ir_entity *entity    = get_Member_entity(node);
1187
1188
	if (!is_Proj(ptr) || !is_Start(get_Proj_pred(ptr)))
		panic("Sel not lowered");
1189
1190
1191
	if (is_parameter_entity(entity) &&
	    get_entity_parameter_number(entity) == IR_VA_START_PARAMETER_NUMBER)
	    panic("va_start NIY");
Matthias Braun's avatar
Matthias Braun committed
1192
1193
1194
1195
	amd64_addr_t addr;
	memset(&addr, 0, sizeof(addr));
	addr.base_input  = 0;
	addr.index_input = NO_INPUT;