amd64_transform.c 103 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
#include "heights.h"
#include "ircons.h"
14
#include "iredges_t.h"
Matthias Braun's avatar
Matthias Braun committed
15
#include "irgmod.h"
16
17
#include "irgraph_t.h"
#include "irmode_t.h"
Matthias Braun's avatar
Matthias Braun committed
18
#include "irnode_t.h"
19
#include "iropt_t.h"
20
#include "irprog_t.h"
21
#include "tv_t.h"
Matthias Braun's avatar
Matthias Braun committed
22
#include "util.h"
23

24
25
#include "benode.h"
#include "betranshlp.h"
26
#include "beirg.h"
Matthias Braun's avatar
Matthias Braun committed
27
#include "besched.h"
28

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

#include "gen_amd64_regalloc_if.h"

DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

41
42
static x86_cconv_t    *current_cconv = NULL;
static be_stack_env_t  stack_env;
43

44
45
46
/** we don't have a concept of aliasing registers, so enumerate them
 * manually for the asm nodes. */
const x86_clobber_name_t amd64_additional_clobber_names[] = {
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
	{ "al", REG_RAX }, { "ah", REG_RAX }, { "ax", REG_RAX }, { "eax", REG_RAX },
	{ "bl", REG_RBX }, { "bh", REG_RBX }, { "bx", REG_RBX }, { "ebx", REG_RBX },
	{ "cl", REG_RCX }, { "ch", REG_RCX }, { "cx", REG_RCX }, { "ecx", REG_RCX },
	{ "dl", REG_RDX }, { "dh", REG_RDX }, { "dx", REG_RDX }, { "edx", REG_RDX },
	{ "sil",  REG_RSI }, { "si",   REG_RSI }, { "esi",  REG_RSI },
	{ "dil",  REG_RDI }, { "di",   REG_RDI }, { "edi",  REG_RDI },
	{ "bpl",  REG_RBP }, { "bp",   REG_RBP }, { "ebp",  REG_RBP },
	{ "spl",  REG_RSP }, { "sp",   REG_RSP }, { "esp",  REG_RSP },
	{ "r8b",  REG_R8  }, { "r8w",  REG_R8  }, { "r8d",  REG_R8  },
	{ "r9b",  REG_R9  }, { "r9w",  REG_R9  }, { "r9d",  REG_R9  },
	{ "r10b", REG_R10 }, { "r10w", REG_R10 }, { "r10d", REG_R10 },
	{ "r11b", REG_R11 }, { "r11w", REG_R11 }, { "r11d", REG_R11 },
	{ "r12b", REG_R12 }, { "r12w", REG_R12 }, { "r12d", REG_R12 },
	{ "r13b", REG_R13 }, { "r13w", REG_R13 }, { "r13d", REG_R13 },
	{ "r14b", REG_R14 }, { "r14w", REG_R14 }, { "r14d", REG_R14 },
	{ "r15b", REG_R15 }, { "r15w", REG_R15 }, { "r15d", REG_R15 },
63
64
65
66
	{ NULL, ~0u }
};

#define GP &amd64_reg_classes[CLASS_amd64_gp]
67
const x86_asm_constraint_list_t amd64_asm_constraints = {
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	['A'] = { MATCH_REG, GP, 1 << REG_GP_RAX | 1 << REG_GP_RDX },
	['D'] = { MATCH_REG, GP, 1 << REG_GP_RDI },
	['I'] = { MATCH_IMM, GP, 0 },
	['J'] = { MATCH_IMM, GP, 0 },
	['K'] = { MATCH_IMM, GP, 0 },
	['L'] = { MATCH_IMM, GP, 0 },
	['M'] = { MATCH_IMM, GP, 0 },
	['N'] = { MATCH_IMM, GP, 0 },
	['O'] = { MATCH_IMM, GP, 0 },
	['R'] = { MATCH_REG, GP, 1 << REG_GP_RAX | 1 << REG_GP_RBX
		| 1 << REG_GP_RCX | 1 << REG_GP_RDX | 1 << REG_GP_RSI
		| 1 << REG_GP_RDI | 1 << REG_GP_RBP | 1 << REG_GP_RSP },
	['S'] = { MATCH_REG, GP, 1 << REG_GP_RSI },
	['Q'] = { MATCH_REG, GP, 1 << REG_GP_RAX | 1 << REG_GP_RBX
		| 1 << REG_GP_RCX | 1 << REG_GP_RDX },
	['V'] = { MATCH_MEM, GP, 0 },
	['X'] = { MATCH_ANY, GP, 0 },
	['a'] = { MATCH_REG, GP, 1 << REG_GP_RAX },
	['b'] = { MATCH_REG, GP, 1 << REG_GP_RBX },
	['c'] = { MATCH_REG, GP, 1 << REG_GP_RCX },
	['d'] = { MATCH_REG, GP, 1 << REG_GP_RDX },
89
	['e'] = { MATCH_IMM, GP, 0 },
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
	['g'] = { MATCH_ANY, GP, 0 },
	['i'] = { MATCH_IMM, GP, 0 },
	['l'] = { MATCH_REG, GP, 1 << REG_GP_RAX | 1 << REG_GP_RBX
		| 1 << REG_GP_RCX | 1 << REG_GP_RDX | 1 << REG_GP_RSI
		| 1 << REG_GP_RDI | 1 << REG_GP_RBP },
	['m'] = { MATCH_MEM, GP, 0 },
	['n'] = { MATCH_IMM, GP, 0 },
	['o'] = { MATCH_MEM, GP, 0 },
	['p'] = { MATCH_REG, GP, 0 },
	['q'] = { MATCH_REG, GP, 0 },
	['r'] = { MATCH_REG, GP, 0 },
	['x'] = { MATCH_REG, &amd64_reg_classes[CLASS_amd64_xmm], 0 },

	// see comments in ia32_transform.c about unimplemented stuff.
};
#undef GP

Matthias Braun's avatar
Matthias Braun committed
107
108
#define BIT(x)    (1u << x)

109
arch_register_req_t const amd64_requirement_gp_same_0 = {
110
111
112
	.cls               = &amd64_reg_classes[CLASS_amd64_gp],
	.should_be_same    = BIT(0),
	.width             = 1,
Matthias Braun's avatar
Matthias Braun committed
113
114
};

115
static const arch_register_req_t amd64_requirement_xmm_same_0 = {
116
117
118
	.cls               = &amd64_reg_classes[CLASS_amd64_xmm],
	.should_be_same    = BIT(0),
	.width             = 1,
119
120
};

Matthias Braun's avatar
Matthias Braun committed
121
static const arch_register_req_t amd64_requirement_gp_same_0_not_1 = {
122
123
124
125
	.cls               = &amd64_reg_classes[CLASS_amd64_gp],
	.should_be_same    = BIT(0),
	.must_be_different = BIT(1),
	.width             = 1,
Matthias Braun's avatar
Matthias Braun committed
126
127
};

128
static const arch_register_req_t amd64_requirement_xmm_same_0_not_1 = {
129
130
131
132
	.cls               = &amd64_reg_classes[CLASS_amd64_xmm],
	.should_be_same    = BIT(0),
	.must_be_different = BIT(1),
	.width             = 1,
133
134
};

Matthias Braun's avatar
Matthias Braun committed
135
136
137
138
139
140
static const arch_register_req_t amd64_requirement_x87killed = {
	.cls         = &amd64_reg_classes[CLASS_amd64_x87],
	.width       = 1,
	.kills_value = true,
};

Matthias Braun's avatar
Matthias Braun committed
141
static const arch_register_req_t *mem_reqs[] = {
142
	&arch_memory_requirement,
Matthias Braun's avatar
Matthias Braun committed
143
144
145
};

static const arch_register_req_t *reg_mem_reqs[] = {
146
	&amd64_class_reg_req_gp,
147
	&arch_memory_requirement,
Matthias Braun's avatar
Matthias Braun committed
148
149
};

Tobias Rapp's avatar
Tobias Rapp committed
150
static const arch_register_req_t *rsp_mem_reqs[] = {
151
	&amd64_single_reg_req_gp_rsp,
152
	&arch_memory_requirement,
Tobias Rapp's avatar
Tobias Rapp committed
153
154
};

155
arch_register_req_t const *rsp_reg_mem_reqs[] = {
156
157
	&amd64_single_reg_req_gp_rsp,
	&amd64_class_reg_req_gp,
158
	&arch_memory_requirement,
Tobias Rapp's avatar
Tobias Rapp committed
159
160
};

161
static const arch_register_req_t *xmm_mem_reqs[] = {
162
	&amd64_class_reg_req_xmm,
163
	&arch_memory_requirement,
164
165
};

Matthias Braun's avatar
Matthias Braun committed
166
167
static const arch_register_req_t *x87K_mem_reqs[] = {
	&amd64_requirement_x87killed,
Matthias Braun's avatar
Matthias Braun committed
168
169
170
	&arch_memory_requirement,
};

Matthias Braun's avatar
Matthias Braun committed
171
static const arch_register_req_t *reg_reg_mem_reqs[] = {
172
173
	&amd64_class_reg_req_gp,
	&amd64_class_reg_req_gp,
174
	&arch_memory_requirement,
Matthias Braun's avatar
Matthias Braun committed
175
176
};

177
arch_register_req_t const *xmm_reg_mem_reqs[] = {
178
179
	&amd64_class_reg_req_xmm,
	&amd64_class_reg_req_gp,
180
	&arch_memory_requirement,
181
182
};

Matthias Braun's avatar
Matthias Braun committed
183
184
185
186
187
188
static const arch_register_req_t *x87_reg_mem_reqs[] = {
	&amd64_class_reg_req_x87,
	&amd64_class_reg_req_gp,
	&arch_memory_requirement,
};

Matthias Braun's avatar
Matthias Braun committed
189
190
191
192
193
194
static const arch_register_req_t *x87K_reg_mem_reqs[] = {
	&amd64_requirement_x87killed,
	&amd64_class_reg_req_gp,
	&arch_memory_requirement,
};

Matthias Braun's avatar
Matthias Braun committed
195
static const arch_register_req_t *reg_reg_reg_mem_reqs[] = {
196
197
198
	&amd64_class_reg_req_gp,
	&amd64_class_reg_req_gp,
	&amd64_class_reg_req_gp,
199
	&arch_memory_requirement,
Matthias Braun's avatar
Matthias Braun committed
200
201
};

202
static const arch_register_req_t *xmm_reg_reg_mem_reqs[] = {
203
204
205
	&amd64_class_reg_req_xmm,
	&amd64_class_reg_req_gp,
	&amd64_class_reg_req_gp,
206
	&arch_memory_requirement,
207
208
};

Matthias Braun's avatar
Matthias Braun committed
209
210
static const arch_register_req_t *x87K_reg_reg_mem_reqs[] = {
	&amd64_requirement_x87killed,
Matthias Braun's avatar
Matthias Braun committed
211
212
213
214
215
	&amd64_class_reg_req_gp,
	&amd64_class_reg_req_gp,
	&arch_memory_requirement,
};

Tobias Rapp's avatar
Tobias Rapp committed
216
static const arch_register_req_t *reg_flags_reqs[] = {
217
218
	&amd64_class_reg_req_gp,
	&amd64_class_reg_req_flags,
219
220
};

221
arch_register_req_t const *amd64_reg_reg_reqs[] = {
222
223
	&amd64_class_reg_req_gp,
	&amd64_class_reg_req_gp,
224
225
};

226
static const arch_register_req_t *reg_rax_reqs[] = {
227
	&amd64_class_reg_req_gp,
228
	&amd64_single_reg_req_gp_rax,
229
230
};

231
static const arch_register_req_t *reg_rax_rdx_mem_reqs[] = {
232
	&amd64_class_reg_req_gp,
233
	&amd64_single_reg_req_gp_rax,
234
	&amd64_single_reg_req_gp_rdx,
235
	&arch_memory_requirement,
236
237
};

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
static const arch_register_req_t *rax_reg_mem_reqs[] = {
	&amd64_single_reg_req_gp_rax,
	&amd64_class_reg_req_gp,
	&arch_memory_requirement,
};

static const arch_register_req_t *reg_rax_reg_mem_reqs[] = {
	&amd64_class_reg_req_gp,
	&amd64_single_reg_req_gp_rax,
	&amd64_class_reg_req_gp,
	&arch_memory_requirement,
};

static const arch_register_req_t *reg_reg_rax_reg_mem_reqs[] = {
	&amd64_class_reg_req_gp,
	&amd64_class_reg_req_gp,
	&amd64_single_reg_req_gp_rax,
	&amd64_class_reg_req_gp,
	&arch_memory_requirement,
};

259
arch_register_req_t const *reg_reqs[] = {
260
	&amd64_class_reg_req_gp,
Matthias Braun's avatar
Matthias Braun committed
261
262
};

263
arch_register_req_t const *amd64_xmm_reqs[] = {
264
	&amd64_class_reg_req_xmm,
265
266
};

Matthias Braun's avatar
Matthias Braun committed
267
static const arch_register_req_t *reg_rcx_reqs[] = {
268
269
	&amd64_class_reg_req_gp,
	&amd64_single_reg_req_gp_rcx,
Matthias Braun's avatar
Matthias Braun committed
270
271
};

272
arch_register_req_t const *amd64_xmm_xmm_reqs[] = {
273
274
	&amd64_class_reg_req_xmm,
	&amd64_class_reg_req_xmm,
275
276
};

277
arch_register_req_t const **const gp_am_reqs[] = {
278
279
280
281
282
283
284
285
286
287
288
289
290
	mem_reqs,
	reg_mem_reqs,
	reg_reg_mem_reqs,
	reg_reg_reg_mem_reqs,
};

static arch_register_req_t const **const xmm_am_reqs[] = {
	mem_reqs,
	xmm_mem_reqs,
	xmm_reg_mem_reqs,
	xmm_reg_reg_mem_reqs,
};

Matthias Braun's avatar
Matthias Braun committed
291
static arch_register_req_t const **const x87K_am_reqs[] = {
Matthias Braun's avatar
Matthias Braun committed
292
	mem_reqs,
Matthias Braun's avatar
Matthias Braun committed
293
294
295
	x87K_mem_reqs,
	x87K_reg_mem_reqs,
	x87K_reg_reg_mem_reqs,
Matthias Braun's avatar
Matthias Braun committed
296
297
};

Matthias Braun's avatar
Matthias Braun committed
298
299
static inline bool mode_needs_gp_reg(ir_mode *mode)
{
300
301
	return get_mode_arithmetic(mode) == irma_twos_complement
	    && mode != amd64_mode_xmm; /* mode_xmm is 128bit int at the moment */
Matthias Braun's avatar
Matthias Braun committed
302
303
}

304
305
static ir_node *get_initial_sp(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
306
	return be_get_Start_proj(irg, &amd64_registers[REG_RSP]);
307
308
309
310
}

static ir_node *get_initial_fp(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
311
	return be_get_Start_proj(irg, &amd64_registers[REG_RBP]);
312
313
314
315
316
317
318
319
320
321
}

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);
	}
}
322

323
ir_entity *create_float_const_entity(ir_tarval *const tv)
324
{
325
	/* TODO: share code with ia32 backend */
326
	ir_entity *entity = pmap_get(ir_entity, amd64_constants, tv);
327
328
329
330
	if (entity != NULL)
		return entity;

	ir_mode *mode = get_tarval_mode(tv);
331
	ir_type *type = get_type_for_mode(mode);
332
333
	ir_type *glob = get_glob_type();

334
	entity = new_global_entity(glob, id_unique("C"), type,
335
336
	                           ir_visibility_private,
	                           IR_LINKAGE_CONSTANT | IR_LINKAGE_NO_IDENTITY);
337
338
339
340

	ir_initializer_t *initializer = create_initializer_tarval(tv);
	set_entity_initializer(entity, initializer);

341
	pmap_insert(amd64_constants, tv, entity);
342
343
344
	return entity;
}

345
void init_lconst_addr(x86_addr_t *addr, ir_entity *entity)
346
{
347
	assert(entity_has_definition(entity));
348
	assert(get_entity_linkage(entity) & IR_LINKAGE_CONSTANT);
349
	assert(get_entity_visibility(entity) == ir_visibility_private);
350
351
	x86_immediate_kind_t kind = be_options.pic_style != BE_PIC_NONE
	                          ? X86_IMM_PCREL : X86_IMM_ADDR;
352
	*addr = (x86_addr_t) {
353
354
355
356
357
358
		.immediate = {
			.entity = entity,
			.kind   = kind,
		},
		.variant = kind == X86_IMM_PCREL ? X86_ADDR_RIP : X86_ADDR_JUST_IMM,
	};
359
360
}

361
static ir_node *create_float_const(dbg_info *dbgi, ir_node *block,
Matthias Braun's avatar
Matthias Braun committed
362
                                   ir_tarval *tv)
363
364
365
{
	ir_graph  *irg     = get_irn_irg(block);
	ir_mode   *tv_mode = get_tarval_mode(tv);
366
	ir_entity *entity  = create_float_const_entity(tv);
367
368
369
	ir_node   *nomem   = get_irg_no_mem(irg);

	ir_node *in[] = { nomem };
370
	x86_addr_t addr;
371
	init_lconst_addr(&addr, entity);
372

373
	ir_node *load;
374
	unsigned pn_res;
375
376
	x86_insn_size_t size = x86_size_from_mode(tv_mode);
	if (size == X86_SIZE_128) {
377
		load = new_bd_amd64_movdqa(dbgi, block, ARRAY_SIZE(in), in, mem_reqs, AMD64_OP_ADDR, addr);
378
		pn_res = pn_amd64_movdqa_res;
379
	} else {
380
		load = new_bd_amd64_movs_xmm(dbgi, block, ARRAY_SIZE(in), in, mem_reqs, size, AMD64_OP_ADDR, addr);
381
		pn_res = pn_amd64_movs_xmm_res;
382
	}
Matthias Braun's avatar
Matthias Braun committed
383
	set_irn_pinned(load, false);
384
	arch_add_irn_flags(load, arch_irn_flag_rematerializable);
385

386
	return be_new_Proj(load, pn_res);
387
388
389
390
391
}

ir_tarval *create_sign_tv(ir_mode *mode)
{
	unsigned size = get_mode_size_bits(mode);
Matthias Braun's avatar
Matthias Braun committed
392
393
394
395
	assert(size == 32 || size == 64 || size == 128);
	ir_mode *intmode = size == 128 ? amd64_mode_xmm
	                 : size == 64  ? mode_Lu
	                               : mode_Iu;
396
397
398
	ir_tarval *one  = get_mode_one(intmode);
	ir_tarval *sign = tarval_shl_unsigned(one, size-1);
	return tarval_bitcast(sign, mode);
399
400
}

401
static ir_node *gen_x87_Const(dbg_info *const dbgi, ir_node *const block, ir_tarval *tv)
Matthias Braun's avatar
Matthias Braun committed
402
403
404
{
	/* TODO: avoid code duplication with ia32 backend */
	if (tarval_is_null(tv)) {
405
		return new_bd_amd64_fldz(dbgi, block);
Matthias Braun's avatar
Matthias Braun committed
406
	} else if (tarval_is_one(tv)) {
407
		return new_bd_amd64_fld1(dbgi, block);
Matthias Braun's avatar
Matthias Braun committed
408
	} else {
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
		ir_mode *mode = get_tarval_mode(tv);
		/* try to reduce the mode to produce smaller sized entities */
		ir_mode *const modes[] = { mode_F, mode_D, NULL };
		for (ir_mode *const *i = modes; *i != NULL; ++i) {
			ir_mode *const to = *i;
			if (tarval_ieee754_can_conv_lossless(tv, to)) {
				tv   = tarval_convert_to(tv, to);
				mode = to;
				break;
			}
		}
		ir_entity *entity = create_float_const_entity(tv);
		ir_graph  *irg    = get_irn_irg(block);
		ir_node   *nomem  = get_irg_no_mem(irg);
		ir_node   *in[1]  = { nomem };
424
		x86_addr_t addr;
425
		init_lconst_addr(&addr, entity);
426
		x86_insn_size_t size = x86_size_from_mode(mode);
427
		ir_node *load = new_bd_amd64_fld(dbgi, block, ARRAY_SIZE(in), in,
428
		                                 mem_reqs, size, AMD64_OP_ADDR, addr);
429
430
		set_irn_pinned(load, false);
		return be_new_Proj(load, pn_amd64_fld_res);
Matthias Braun's avatar
Matthias Braun committed
431
432
433
	}
}

434
435
436
437
438
439
440
441
442
443
static ir_node *make_const(dbg_info *const dbgi, ir_node *const block, uint64_t const val)
{
	x86_insn_size_t const imode = val > UINT32_MAX ? X86_SIZE_64 : X86_SIZE_32;
	amd64_imm64_t const imm = {
		.kind   = X86_IMM_VALUE,
		.offset = val,
	};
	return new_bd_amd64_mov_imm(dbgi, block, imode, &imm);
}

Matthias Braun's avatar
Matthias Braun committed
444
static ir_node *gen_Const(ir_node *const node)
445
{
446
	ir_node  *block = be_transform_nodes_block(node);
447
	dbg_info *dbgi  = get_irn_dbg_info(node);
448
	ir_mode  *mode  = get_irn_mode(node);
449
	ir_tarval *tv = get_Const_tarval(node);
450
451

	if (!mode_needs_gp_reg(mode)) {
Matthias Braun's avatar
Matthias Braun committed
452
		if (mode == x86_mode_E) {
453
			return gen_x87_Const(dbgi, block, tv);
Matthias Braun's avatar
Matthias Braun committed
454
		} else if (tarval_is_null(tv)) {
455
			return new_bd_amd64_xorp_0(dbgi, block, X86_SIZE_64);
456
		}
457
		return create_float_const(dbgi, block, tv);
458
459
	}

460
461
	uint64_t const val = get_tarval_uint64(tv);
	return make_const(dbgi, block, val);
462
463
}

Matthias Braun's avatar
Matthias Braun committed
464
static ir_node *gen_Address(ir_node *const node)
465
{
466
	ir_node   *block  = be_transform_nodes_block(node);
467
	dbg_info  *dbgi   = get_irn_dbg_info(node);
468
	ir_entity *entity = get_Address_entity(node);
469

470
471
472
473
	amd64_imm64_t const imm = {
		.kind   = X86_IMM_ADDR,
		.entity = entity,
	};
474
	return new_bd_amd64_mov_imm(dbgi, block, X86_SIZE_64, &imm);
475
}
Matthias Braun's avatar
Matthias Braun committed
476

477
static ir_node *create_picaddr_lea(dbg_info *const dbgi, ir_node *const block,
478
479
480
                                   x86_immediate_kind_t const kind,
                                   ir_entity *const entity)
{
481
	x86_addr_t addr = {
482
483
484
485
		.immediate = (x86_imm32_t) {
			.kind   = kind,
			.entity = entity,
		},
486
		.variant = X86_ADDR_RIP,
487
	};
488
	return new_bd_amd64_lea(dbgi, block, 0, NULL, NULL, X86_SIZE_64, addr);
489
490
}

Matthias Braun's avatar
Matthias Braun committed
491
static ir_node *gen_be_Relocation(ir_node *const node)
492
{
493
	dbg_info            *const dbgi   = get_irn_dbg_info(node);
494
495
496
497
	ir_node             *const block  = be_transform_nodes_block(node);
	ir_entity           *const entity = be_get_Relocation_entity(node);
	x86_immediate_kind_t const kind
		= (x86_immediate_kind_t)be_get_Relocation_kind(node);
Matthias Braun's avatar
Matthias Braun committed
498

499
500
501
	switch (kind) {
	case X86_IMM_ADDR: {
		amd64_imm64_t const imm = {
Matthias Braun's avatar
Matthias Braun committed
502
503
504
			.kind   = X86_IMM_ADDR,
			.entity = entity,
		};
505
		return new_bd_amd64_mov_imm(dbgi, block, X86_SIZE_64, &imm);
506
507
	}
	case X86_IMM_PCREL:
508
	case X86_IMM_GOTPCREL: /* can GOTPCREL happen here? */
509
		return create_picaddr_lea(dbgi, block, kind, entity);
510
511
512
513
	default:
		break;
	}
	panic("Unexpected relocation kind");
Matthias Braun's avatar
Matthias Braun committed
514
515
}

516
ir_node *amd64_new_IncSP(ir_node *block, ir_node *old_sp, int offset,
517
                         bool no_align)
Tobias Rapp's avatar
Tobias Rapp committed
518
{
519
	ir_node *incsp = be_new_IncSP(&amd64_registers[REG_RSP], block, old_sp,
520
	                              offset, no_align);
521
522
	arch_add_irn_flags(incsp, arch_irn_flag_modify_flags);
	return incsp;
Tobias Rapp's avatar
Tobias Rapp committed
523
524
}

525
typedef ir_node *(*construct_binop_func)(dbg_info *dbgi, ir_node *block, int arity, ir_node *const *in, arch_register_req_t const **in_reqs, amd64_binop_addr_attr_t const *attr_init);
Matthias Braun's avatar
Matthias Braun committed
526

527
typedef ir_node *(*construct_rax_binop_func)(dbg_info *dbgi, ir_node *block, int arity, ir_node *const *in, arch_register_req_t const **in_reqs, x86_insn_size_t size, amd64_op_mode_t op_mode, x86_addr_t addr);
528

Matthias Braun's avatar
Matthias Braun committed
529
530
531
532
533
534
535
536
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
537
538
539
540
	amd64_binop_addr_attr_t     attr;
	ir_node                    *mem_proj;
	ir_node                    *in[4];
	int                         arity;
Matthias Braun's avatar
Matthias Braun committed
541
542
543
	const arch_register_req_t **reqs;
} amd64_args_t;

544
static bool match_immediate_32(x86_imm32_t *const imm, ir_node const *const op, bool const must_match_ip_relative)
Matthias Braun's avatar
Matthias Braun committed
545
546
{
	assert(mode_needs_gp_reg(get_irn_mode(op)));
Matthias Braun's avatar
Matthias Braun committed
547
548
	assert(imm->offset == 0 && imm->entity == NULL
	       && imm->kind == X86_IMM_VALUE);
549
550
551

	ir_tarval *tv;
	ir_entity *entity;
Matthias Braun's avatar
Matthias Braun committed
552
553
	unsigned   reloc_kind;
	if (!be_match_immediate(op, &tv, &entity, &reloc_kind))
554
555
556
557
		return false;

	int32_t val;
	if (tv) {
558
		if (get_tarval_magnitude(tv) > 32)
559
			return false;
560
		val = get_tarval_uint64(tv);
561
562
563
564
	} else {
		val = 0;
	}

565
566
567
	if ((entity != NULL) != must_match_ip_relative)
		return false;

Matthias Braun's avatar
Matthias Braun committed
568
	x86_immediate_kind_t kind = (x86_immediate_kind_t)reloc_kind;
Matthias Braun's avatar
Matthias Braun committed
569
	if (entity != NULL) {
570
571
		if (kind == X86_IMM_VALUE || kind == X86_IMM_ADDR) {
			kind = X86_IMM_PCREL;
572
		} else if (kind != X86_IMM_PCREL && kind != X86_IMM_PLT)
Matthias Braun's avatar
Matthias Braun committed
573
			return false;
Matthias Braun's avatar
Matthias Braun committed
574
	}
575
576

	imm->entity = entity;
Matthias Braun's avatar
Matthias Braun committed
577
578
	imm->offset = val;
	imm->kind   = kind;
579
	return true;
Matthias Braun's avatar
Matthias Braun committed
580
581
582
583
}

static ir_heights_t *heights;

584
585
586
587
588
589
590
591
592
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
593
594
595
596
597
598
599
600
601
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);
}

602
static ir_node *source_am_possible(ir_node *block, ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
603
604
{
	if (!is_Proj(node))
605
		return NULL;
Matthias Braun's avatar
Matthias Braun committed
606
607
	ir_node *load = get_Proj_pred(node);
	if (!is_Load(load))
608
		return NULL;
609
	assert(get_Proj_num(node) == pn_Load_res);
Matthias Braun's avatar
Matthias Braun committed
610
	if (get_nodes_block(load) != block)
611
		return NULL;
Matthias Braun's avatar
Matthias Braun committed
612
613
	/* make sure we are the only user */
	if (get_irn_n_edges(node) != 1)
614
		return NULL;
615
616
617
618
619
620
	/* From ia32_transform.c:751:
	 * in some edge cases with address mode we might reach the load normally
	 * and through some AM sequence, if it is already materialized then we
	 * can't create an AM node from it */
	if (be_is_transformed(node))
		return NULL;
621
	return load;
Matthias Braun's avatar
Matthias Braun committed
622
623
624
625
626
627
628
629
630
631
}

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
632
633
static bool use_address_matching(ir_mode *mode, match_flags_t flags,
                                 ir_node *block,
634
635
636
                                 ir_node *op1, ir_node *op2,
                                 ir_node **out_load, ir_node **out_op)
{
637
638
	if (! (flags & match_am))
		return false;
639

Tobias Rapp's avatar
Tobias Rapp committed
640
641
642
643
	unsigned mode_bits = get_mode_size_bits(mode);
	if (mode_bits == 8 || mode_bits == 16)
		return false;

644
645
646
	ir_node *load2 = source_am_possible(block, op2);
	if (load2 != NULL && !input_depends_on_load(load2, op1)) {
		(*out_load) = load2;
647
648
		(*out_op)   = op1;
		return true;
649
650
651
652
653
654
655
656
657
	}

	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;
		}
658
659
660
661
	}
	return false;
}

662
static void perform_address_matching_flags(ir_node *const ptr, int *const arity, ir_node **const in, x86_addr_t *const addr, x86_create_am_flags_t const flags)
663
664
665
{
	x86_address_t maddr;
	memset(&maddr, 0, sizeof(maddr));
666
	x86_create_address_mode(&maddr, ptr, flags);
667

668
669
	x86_addr_variant_t variant = maddr.variant;
	assert(variant != X86_ADDR_INVALID);
670
	if (x86_addr_variant_has_base(variant)) {
671
672
673
674
		int base_input   = (*arity)++;
		addr->base_input = base_input;
		in[base_input]   = be_transform_node(maddr.base);
	} else {
675
		assert(maddr.base == NULL);
676
	}
677
	if (x86_addr_variant_has_index(variant)) {
678
		int index_input   = (*arity)++;
679
		addr->index_input = index_input;
680
		in[index_input]   = be_transform_node(maddr.index);
681
	} else {
682
		assert(maddr.index == NULL);
683
	}
684
	ir_entity *entity = maddr.imm.entity;
685
	if (entity != NULL && is_parameter_entity(entity) &&
686
		get_entity_parameter_number(entity) == IR_VA_START_PARAMETER_NUMBER)
Christoph Mallon's avatar
Christoph Mallon committed
687
		panic("request for invalid parameter (va_start parameter)");
688

689
	addr->segment   = X86_SEGMENT_DEFAULT;
Matthias Braun's avatar
Matthias Braun committed
690
691
	addr->immediate = maddr.imm;
	addr->log_scale = maddr.scale;
692
	addr->variant   = variant;
693
694
}

695
696
697
698
699
static void perform_address_matching(ir_node *const ptr, int *const arity, ir_node **const in, x86_addr_t *const addr)
{
	perform_address_matching_flags(ptr, arity, in, addr, x86_create_am_normal);
}

Matthias Braun's avatar
Matthias Braun committed
700
701
702
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
703
704
705
{
	memset(args, 0, sizeof(*args));

706
	bool use_xmm       = mode_is_float(mode);
Matthias Braun's avatar
Matthias Braun committed
707
	bool use_immediate = flags & match_immediate;
708
	bool mode_neutral  = flags & match_mode_neutral;
Matthias Braun's avatar
Matthias Braun committed
709

710
	amd64_binop_addr_attr_t *const attr = &args->attr;
711
	attr->base.base.size = x86_size_from_mode(mode);
Matthias Braun's avatar
Matthias Braun committed
712
713

	/* TODO: legalize phase */
714
	if (mode_neutral) {
715
716
		op1 = be_skip_downconv(op1, true);
		op2 = be_skip_downconv(op2, true);
Matthias Braun's avatar
Matthias Braun committed
717
718
719
720
721
722
723
	} else {
		/* TODO: extend inputs? */
		(void)needs_extension;
	}

	ir_node *load;
	ir_node *op;
Matthias Braun's avatar
Matthias Braun committed
724
725
	bool     use_am
		= use_address_matching(mode, flags, block, op1, op2, &load, &op);
726

727
	x86_addr_t *addr = &attr->base.addr;
728
	if (use_immediate && match_immediate_32(&attr->u.immediate, op2, false)) {
729
		assert(!use_xmm && "Can't (yet) match binop with xmm immediate");
Matthias Braun's avatar
Matthias Braun committed
730
		/* fine, we found an immediate */
731
732
733
734
735
736
		int const reg_input = args->arity++;
		args->in[reg_input]     = be_transform_node(op1);
		addr->variant           = X86_ADDR_REG;
		addr->base_input        = reg_input;
		attr->base.base.op_mode = AMD64_OP_REG_IMM;
		args->reqs              = reg_reqs;
737
	} else if (use_am) {
738
739
740
		int const reg_input = args->arity++;
		attr->u.reg_input   = reg_input;
		args->in[reg_input] = be_transform_node(op);
Matthias Braun's avatar
Matthias Braun committed
741

742
743
744
		ir_node *ptr = get_Load_ptr(load);
		perform_address_matching(ptr, &(args->arity), args->in, addr);

745
746
		args->reqs = (use_xmm ? xmm_am_reqs : gp_am_reqs)[args->arity];

747
748
749
750
		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;
751

752
		args->mem_proj      = get_Proj_for_pn(load, pn_Load_M);
753
		attr->base.base.op_mode = AMD64_OP_REG_ADDR;
Matthias Braun's avatar
Matthias Braun committed
754
755
	} else {
		/* simply transform the arguments */
756
757
758
759
760
761
762
763
		int const reg_input0 = args->arity++;
		int const reg_input1 = args->arity++;
		args->in[reg_input0]    = be_transform_node(op1);
		args->in[reg_input1]    = be_transform_node(op2);
		addr->variant           = X86_ADDR_REG;
		addr->base_input        = reg_input0;
		attr->u.reg_input       = reg_input1;
		attr->base.base.op_mode = AMD64_OP_REG_REG;
764

765
		args->reqs = use_xmm ? amd64_xmm_xmm_reqs : amd64_reg_reg_reqs;
Matthias Braun's avatar
Matthias Braun committed
766
767
768
769
	}
}

static ir_node *gen_binop_am(ir_node *node, ir_node *op1, ir_node *op2,
770
771
                             construct_binop_func func, unsigned pn_res,
                             match_flags_t flags)
Matthias Braun's avatar
Matthias Braun committed
772
773
774
775
{
	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
776
	match_binop(&args, block, mode, op1, op2, flags);
Matthias Braun's avatar
Matthias Braun committed
777
778
779

	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const new_block = be_transform_node(block);
780
	ir_node  *const new_node  = func(dbgi, new_block, args.arity, args.in, args.reqs, &args.attr);
781

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

784
785
786
787
788
789
790
	if (mode_is_float(mode)) {
		arch_set_irn_register_req_out(new_node, 0,
		                              &amd64_requirement_xmm_same_0);
	} else {
		arch_set_irn_register_req_out(new_node, 0,
		                              &amd64_requirement_gp_same_0);
	}
791
	return be_new_Proj(new_node, pn_res);
Matthias Braun's avatar
Matthias Braun committed
792
793
}

794
static ir_node *gen_binop_rax(ir_node *node, ir_node *op0, ir_node *op1,
795
796
797
                              construct_rax_binop_func make_node,
                              match_flags_t flags)
{
Matthias Braun's avatar
Matthias Braun committed
798
	bool mode_neutral = flags & match_mode_neutral;
799
800
	assert(! (flags & match_immediate));

801
802
	ir_mode        *mode = get_irn_mode(op0);
	x86_insn_size_t size = x86_size_from_mode(mode);
803
804
805

	/* TODO: legalize phase */
	if (mode_neutral) {
806
		op0 = be_skip_downconv(op0, true);
807
		op1 = be_skip_downconv(op1, true);
808
809
810
811
812
	} else {
		/* TODO: extend inputs? */
		(void)needs_extension;
	}

Matthias Braun's avatar
Matthias Braun committed
813
	ir_node *block = get_nodes_block(node);
814
815
	ir_node *load;
	ir_node *op;
Matthias Braun's avatar
Matthias Braun committed
816
	bool     use_am
817
		= use_address_matching(mode, flags, block, op0, op1, &load, &op);
Matthias Braun's avatar
Matthias Braun committed
818

819
820
821
	ir_node *in[4];
	int      arity = 0;
	amd64_op_mode_t op_mode;
822
	x86_addr_t addr;
823
824
	memset(&addr, 0, sizeof(addr));

Matthias Braun's avatar
Matthias Braun committed
825
	const arch_register_req_t **reqs;
826
	ir_node *mem_proj = NULL;
827
828
829
830
831
	if (use_am) {
		ir_node *new_op    = be_transform_node(op);
		int      reg_input = arity++;
		in[reg_input]      = new_op;

832
833
834
		ir_node *ptr = get_Load_ptr(load);
		perform_address_matching(ptr, &arity, in, &addr);

835
		reqs = gp_am_reqs[arity];
836
837
838
839
840

		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;
841

842
		mem_proj                = get_Proj_for_pn(load, pn_Load_M);
843
		op_mode                 = AMD64_OP_ADDR;
844
845
	} else {
		/* simply transform the arguments */
846
847
848
849
850
851
852
853
		int const input0 = arity++;
		int const input1 = arity++;
		in[input0]      = be_transform_node(op0);
		in[input1]      = be_transform_node(op1);
		reqs            = reg_rax_reqs;
		op_mode         = AMD64_OP_REG;
		addr.variant    = X86_ADDR_REG;
		addr.base_input = input0;
854
855
	}

856
	assert((size_t)arity <= ARRAY_SIZE(in));
857
858
	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const new_block = be_transform_node(block);
859
	ir_node  *const new_node  = make_node(dbgi, new_block, arity, in, reqs, size, op_mode, addr);
860
861
862
	if (mem_proj != NULL) {
		be_set_transformed_node(load, new_node);
	}
863
864
865
	return new_node;
}

866
867
868
869
870
871
872
873
static ir_node *gen_binop_xmm(ir_node *node, ir_node *op0, ir_node *op1,
                              construct_binop_func make_node,
                              match_flags_t flags)
{
	ir_node *block = get_nodes_block(node);
	ir_mode *mode  = get_irn_mode(op0);
	amd64_args_t args;
	memset(&args, 0, sizeof(args));
874
	amd64_binop_addr_attr_t *const attr = &args.attr;
875
	attr->base.base.size = X86_SIZE_64;
876
877
878
879
880
881

	ir_node *load;
	ir_node *op;
	bool use_am = use_address_matching(mode, flags, block, op0, op1, &load,
	                                   &op);

882
	x86_addr_t *addr = &attr->base.addr;
883
884
	if (use_am) {
		int reg_input = args.arity++;
885
886
		attr->u.reg_input  = reg_input;
		args.in[reg_input] = be_transform_node(op);
887
888
889
890

		ir_node      *ptr  = get_Load_ptr(load);
		perform_address_matching(ptr, &args.arity, args.in, addr);

891
		args.reqs = xmm_am_reqs[args.arity];
892
893
894
895
896
897
898

		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;

		args.mem_proj      = get_Proj_for_pn(load, pn_Load_M);
899
		attr->base.base.op_mode = AMD64_OP_REG_ADDR;
900
	} else {
901
902
903
904
905
906
907
908
909
		int const input0 = args.arity++;
		int const input1 = args.arity++;
		args.in[input0]         = be_transform_node(op0);
		args.in[input1]         = be_transform_node(op1);
		addr->base_input        = input0;
		addr->variant           = X86_ADDR_REG;
		attr->u.reg_input       = input1;
		attr->base.base.op_mode = AMD64_OP_REG_REG;
		args.reqs               = amd64_xmm_xmm_reqs;
910
911
912
913
	}

	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const new_block = be_transform_node(block);
914
	ir_node  *const new_node  = make_node(dbgi, new_block, args.arity, args.in, args.reqs, &args.attr);
915
916
917

	fix_node_mem_proj(new_node, args.mem_proj);

yb9976's avatar
yb9976 committed
918
	arch_set_irn_register_req_out(new_node, 0, &amd64_requirement_xmm_same_0);
919
	return be_new_Proj(new_node, pn_amd64_subs_res);
920
921
}

922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
typedef ir_node *(*construct_x87_binop_func)(
		dbg_info *dbgi, ir_node *block, ir_node *op0, ir_node *op1);

static ir_node *gen_binop_x87(ir_node *const node, ir_node *const op0,
                              ir_node *const op1, construct_x87_binop_func cons)
{
	dbg_info *const dbgi      = get_irn_dbg_info(node);
	ir_node  *const new_block = be_transform_node(get_nodes_block(node));
	ir_node  *const new_op0   = be_transform_node(op0);
	ir_node  *const new_op1   = be_transform_node(op1);
	ir_node  *const res       = cons(dbgi, new_block, new_op0, new_op1);
	/* TODO: address modes */
	return res;
}

937
typedef ir_node *(*construct_shift_func)(