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

6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
10
 * @file
 * @brief       This file implements the mapping of 64Bit intrinsic
 *              functions to code or library calls.
 * @author      Michael Beck
11
 */
12
13
#include "ia32_bearch_t.h"

14
#include "iredges_t.h"
15
#include "irgmod.h"
16
#include "irop_t.h"
17
#include "irnode_t.h"
18
#include "ircons_t.h"
19
#include "irprog_t.h"
20
#include "iroptimize.h"
21
#include "lower_dw.h"
22
#include "array.h"
Matthias Braun's avatar
Matthias Braun committed
23
#include "panic.h"
24
#include "util.h"
25
26
#include "constbits.h"
#include "tv.h"
27

28
#include "ia32_new_nodes.h"
29
#include "gen_ia32_regalloc_if.h"
Matthias Braun's avatar
Matthias Braun committed
30
#include "begnuas.h"
31
#include "x86_x87.h"
32

33
34
35
36
37
38
typedef enum {
	no_carry = 0,
	can_carry,
	must_carry
} carry_result;

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
static ir_tarval *bitinfo_max(bitinfo *info)
{
	ir_tarval *z    = info->z;
	ir_tarval *o    = info->o;
	ir_mode   *mode = get_tarval_mode(z);
	ir_tarval *min  = get_mode_min(mode);

	assert(get_mode_arithmetic(mode) == irma_twos_complement);
	return tarval_and(z, tarval_ornot(o, min));
}

static ir_tarval *bitinfo_min(bitinfo *info)
{
	ir_tarval *z    = info->z;
	ir_tarval *o    = info->o;
	ir_mode   *mode = get_tarval_mode(z);
	ir_tarval *min  = get_mode_min(mode);

	assert(get_mode_arithmetic(mode) == irma_twos_complement);
	return tarval_or(o, tarval_and(z, min));
}

61
static carry_result lower_add_carry(ir_node *left, ir_node *right, ir_mode *mode)
62
{
63
64
	assert(!mode_is_signed(mode));

65
66
	bitinfo *bi_left = get_bitinfo(left);
	if (!bi_left) {
67
		return can_carry;
68
69
70
71
72
73
	}
	bitinfo *bi_right = get_bitinfo(right);
	// If we have bitinfo for one node, we should also have it for
	// the other
	assert(bi_right);

74
75
76
77
78
	ir_tarval    *lmin   = tarval_convert_to(bitinfo_min(bi_left),  mode);
	ir_tarval    *rmin   = tarval_convert_to(bitinfo_min(bi_right), mode);
	ir_tarval    *lmax   = tarval_convert_to(bitinfo_max(bi_left),  mode);
	ir_tarval    *rmax   = tarval_convert_to(bitinfo_max(bi_right), mode);
	carry_result  result = no_carry;
79

Matthias Braun's avatar
Matthias Braun committed
80
81
	int old_wrap_on_overflow = tarval_get_wrap_on_overflow();
	tarval_set_wrap_on_overflow(false);
82

83
84
85
86
87
	if (tarval_add(lmax, rmax) == tarval_bad) {
		result = can_carry;
		if (tarval_add(lmin, rmin) == tarval_bad) {
			result = must_carry;
		}
88
89
	}

Matthias Braun's avatar
Matthias Braun committed
90
	tarval_set_wrap_on_overflow(old_wrap_on_overflow);
91
92
93
94

	return result;
}

95
static carry_result lower_sub_borrow(ir_node *left, ir_node *right, ir_mode *mode)
96
{
97
98
	assert(!mode_is_signed(mode));

99
100
	bitinfo *bi_left = get_bitinfo(left);
	if (!bi_left) {
101
		return can_carry;
102
103
104
105
106
107
	}
	bitinfo *bi_right = get_bitinfo(right);
	// If we have bitinfo for one node, we should also have it for
	// the other
	assert(bi_right);

108
109
110
111
112
	ir_tarval    *lmin   = tarval_convert_to(bitinfo_min(bi_left),  mode);
	ir_tarval    *rmin   = tarval_convert_to(bitinfo_min(bi_right), mode);
	ir_tarval    *lmax   = tarval_convert_to(bitinfo_max(bi_left),  mode);
	ir_tarval    *rmax   = tarval_convert_to(bitinfo_max(bi_right), mode);
	carry_result  result = no_carry;
113

Matthias Braun's avatar
Matthias Braun committed
114
115
	int old_wrap_on_overflow = tarval_get_wrap_on_overflow();
	tarval_set_wrap_on_overflow(false);
116

117
	if (tarval_sub(lmin, rmax) == tarval_bad) {
118
		result = can_carry;
119
		if (tarval_sub(lmax, rmin) == tarval_bad) {
120
121
			result = must_carry;
		}
122
123
	}

Matthias Braun's avatar
Matthias Braun committed
124
	tarval_set_wrap_on_overflow(old_wrap_on_overflow);
125
126
127
128

	return result;
}

129
/**
Matthias Braun's avatar
Matthias Braun committed
130
 * lower 64bit addition: an 32bit add for the lower parts, an add with
131
132
 * carry for the higher parts. If the carry's value is known, fold it
 * into the upper add.
133
 */
Matthias Braun's avatar
Matthias Braun committed
134
static void ia32_lower_add64(ir_node *node, ir_mode *mode)
135
{
136
137
138
139
140
141
142
143
144
145
146
	dbg_info     *dbg        = get_irn_dbg_info(node);
	ir_node      *block      = get_nodes_block(node);
	ir_node      *left       = get_Add_left(node);
	ir_node      *right      = get_Add_right(node);
	ir_node      *left_low   = get_lowered_low(left);
	ir_node      *left_high  = get_lowered_high(left);
	ir_node      *right_low  = get_lowered_low(right);
	ir_node      *right_high = get_lowered_high(right);
	ir_mode      *low_mode   = get_irn_mode(left_low);
	ir_mode      *high_mode  = get_irn_mode(left_high);
	carry_result  cr         = lower_add_carry(left, right, low_mode);
147
148
149

	assert(get_irn_mode(left_low)  == get_irn_mode(right_low));
	assert(get_irn_mode(left_high) == get_irn_mode(right_high));
150

151
	if (cr == no_carry) {
152
		ir_node *add_low  = new_rd_Add(dbg, block, left_low,  right_low, low_mode);
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
		ir_node *add_high = new_rd_Add(dbg, block, left_high, right_high, high_mode);
		ir_set_dw_lowered(node, add_low, add_high);
	} else if (cr == must_carry && (is_Const(left_high) || is_Const(right_high))) {
		// We cannot assume that left_high and right_high form a normalized Add.
		ir_node *constant;
		ir_node *other;

		if (is_Const(left_high)) {
			constant = left_high;
			other    = right_high;
		} else {
			constant = right_high;
			other    = left_high;
		}

		ir_graph *irg            = get_irn_irg(right_high);
		ir_node  *one            = new_rd_Const(dbg, irg, get_mode_one(high_mode));
		ir_node  *const_plus_one = new_rd_Add(dbg, block, constant, one, high_mode);
		ir_node  *add_high       = new_rd_Add(dbg, block, other, const_plus_one, high_mode);
		ir_node  *add_low        = new_rd_Add(dbg, block, left_low, right_low, low_mode);
173
174
175
176
177
178
179
180
181
182
183
184
185
		ir_set_dw_lowered(node, add_low, add_high);
	} else {
		/* l_res = a_l + b_l */
		ir_node  *add_low    = new_bd_ia32_l_Add(dbg, block, left_low, right_low);
		ir_mode  *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
		ir_node  *res_low    = new_r_Proj(add_low, ia32_mode_gp, pn_ia32_l_Add_res);
		ir_node  *flags      = new_r_Proj(add_low, mode_flags, pn_ia32_l_Add_flags);

		/* h_res = a_h + b_h + carry */
		ir_node  *add_high
			= new_bd_ia32_l_Adc(dbg, block, left_high, right_high, flags, mode);
		ir_set_dw_lowered(node, res_low, add_high);
	}
186
187
188
}

/**
189
190
191
 * lower 64bit subtraction: a 32bit sub for the lower parts, a sub
 * with borrow for the higher parts. If the borrow's value is known,
 * fold it into the upper sub.
192
 */
Matthias Braun's avatar
Matthias Braun committed
193
static void ia32_lower_sub64(ir_node *node, ir_mode *mode)
194
{
195
196
197
198
199
200
201
202
203
204
205
	dbg_info     *dbg        = get_irn_dbg_info(node);
	ir_node      *block      = get_nodes_block(node);
	ir_node      *left       = get_Sub_left(node);
	ir_node      *right      = get_Sub_right(node);
	ir_node      *left_low   = get_lowered_low(left);
	ir_node      *left_high  = get_lowered_high(left);
	ir_node      *right_low  = get_lowered_low(right);
	ir_node      *right_high = get_lowered_high(right);
	ir_mode      *low_mode   = get_irn_mode(left_low);
	ir_mode      *high_mode  = get_irn_mode(left_high);
	carry_result  cr         = lower_sub_borrow(left, right, low_mode);
206
207
208
209

	assert(get_irn_mode(left_low)  == get_irn_mode(right_low));
	assert(get_irn_mode(left_high) == get_irn_mode(right_high));

210
	if (cr == no_carry) {
211
		ir_node *sub_low  = new_rd_Sub(dbg, block, left_low,  right_low, low_mode);
212
213
214
215
216
217
218
219
220
221
222
223
224
225
		ir_node *sub_high = new_rd_Sub(dbg, block, left_high, right_high, high_mode);
		ir_set_dw_lowered(node, sub_low, sub_high);
	} else if (cr == must_carry && (is_Const(left_high) || is_Const(right_high))) {
		ir_node  *sub_high;
		ir_graph *irg        = get_irn_irg(right_high);
		ir_node  *one        = new_rd_Const(dbg, irg, get_mode_one(high_mode));

		if (is_Const(right_high)) {
			ir_node *new_const = new_rd_Add(dbg, block, right_high, one, high_mode);
			sub_high = new_rd_Sub(dbg, block, left_high, new_const, high_mode);
		} else if (is_Const(left_high)) {
			ir_node *new_const = new_rd_Sub(dbg, block, left_high, one, high_mode);
			sub_high = new_rd_Sub(dbg, block, new_const, right_high, high_mode);
		} else {
226
			panic("logic error");
227
228
229
		}

		ir_node  *sub_low  = new_rd_Sub(dbg, block, left_low, right_low, low_mode);
230
231
232
233
234
235
236
		ir_set_dw_lowered(node, sub_low, sub_high);
	} else {
		/* l_res = a_l - b_l */
		ir_node  *sub_low    = new_bd_ia32_l_Sub(dbg, block, left_low, right_low);
		ir_mode  *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
		ir_node  *res_low    = new_r_Proj(sub_low, ia32_mode_gp, pn_ia32_l_Sub_res);
		ir_node  *flags      = new_r_Proj(sub_low, mode_flags, pn_ia32_l_Sub_flags);
237

238
239
240
241
242
		/* h_res = a_h - b_h - carry */
		ir_node  *sub_high
			= new_bd_ia32_l_Sbb(dbg, block, left_high, right_high, flags, mode);
		ir_set_dw_lowered(node, res_low, sub_high);
	}
243
244
}

245
/**
Matthias Braun's avatar
Matthias Braun committed
246
 * Checks whether node high is a sign extension of low.
247
 */
Matthias Braun's avatar
Matthias Braun committed
248
static bool is_sign_extend(ir_node *low, ir_node *high)
249
250
{
	if (is_Shrs(high)) {
Matthias Braun's avatar
Matthias Braun committed
251
252
		ir_node *high_r = get_Shrs_right(high);
		if (!is_Const(high_r)) return false;
253

Matthias Braun's avatar
Matthias Braun committed
254
255
256
		ir_tarval *shift_count = get_Const_tarval(high_r);
		if (!tarval_is_long(shift_count))       return false;
		if (get_tarval_long(shift_count) != 31) return false;
257

Matthias Braun's avatar
Matthias Braun committed
258
		ir_node *high_l = get_Shrs_left(high);
259

Matthias Braun's avatar
Matthias Braun committed
260
261
		if (is_Conv(low)    && get_Conv_op(low)    == high_l) return true;
		if (is_Conv(high_l) && get_Conv_op(high_l) == low)    return true;
262
	} else if (is_Const(low) && is_Const(high)) {
Matthias Braun's avatar
Matthias Braun committed
263
264
		ir_tarval *tl = get_Const_tarval(low);
		ir_tarval *th = get_Const_tarval(high);
265
266
267
268
269
270
271
272
273

		if (tarval_is_long(th) && tarval_is_long(tl)) {
			long l = get_tarval_long(tl);
			long h = get_tarval_long(th);

			return (h == 0  && l >= 0) || (h == -1 && l <  0);
		}
	}

Matthias Braun's avatar
Matthias Braun committed
274
	return false;
275
276
}

277
/**
Matthias Braun's avatar
Matthias Braun committed
278
 * lower 64bit Mul operation.
279
 */
Matthias Braun's avatar
Matthias Braun committed
280
static void ia32_lower_mul64(ir_node *node, ir_mode *mode)
281
{
Matthias Braun's avatar
Matthias Braun committed
282
283
284
285
286
287
288
289
	dbg_info *dbg        = get_irn_dbg_info(node);
	ir_node  *block      = get_nodes_block(node);
	ir_node  *left       = get_Mul_left(node);
	ir_node  *right      = get_Mul_right(node);
	ir_node  *left_low   = get_lowered_low(left);
	ir_node  *left_high  = get_lowered_high(left);
	ir_node  *right_low  = get_lowered_low(right);
	ir_node  *right_high = get_lowered_high(right);
290
291

	/*
Matthias Braun's avatar
Matthias Braun committed
292
		EDX:EAX = left_low * right_low
293
294
		l_res   = EAX

Matthias Braun's avatar
Matthias Braun committed
295
		t1 = right_low * left_high
296
		t2 = t1 + EDX
Matthias Braun's avatar
Matthias Braun committed
297
		t3 = left_low * right_high
298
299
		h_res = t2 + t3
	*/
Michael Beck's avatar
Michael Beck committed
300

301
	/* handle the often used case of 32x32=64 mul */
Matthias Braun's avatar
Matthias Braun committed
302
303
304
305
306
307
	ir_node *h_res;
	ir_node *l_res;
	if (is_sign_extend(left_low, left_high)
	    && is_sign_extend(right_low, right_high)) {
		ir_node *mul = new_bd_ia32_l_IMul(dbg, block, left_low, right_low);
		h_res = new_rd_Proj(dbg, mul, mode, pn_ia32_l_IMul_res_high);
308
		l_res = new_rd_Proj(dbg, mul, ia32_mode_gp, pn_ia32_l_IMul_res_low);
309
310
	} else {
		/* note that zero extension is handled hare efficiently */
Matthias Braun's avatar
Matthias Braun committed
311
312
		ir_node *mul  = new_bd_ia32_l_Mul(dbg, block, left_low, right_low);
		ir_node *pEDX = new_rd_Proj(dbg, mul, mode, pn_ia32_l_Mul_res_high);
313
		l_res = new_rd_Proj(dbg, mul, ia32_mode_gp, pn_ia32_l_Mul_res_low);
Matthias Braun's avatar
Matthias Braun committed
314
315

		ir_node *right_lowc = new_rd_Conv(dbg, block, right_low, mode);
316
		ir_node *mul1 = new_rd_Mul(dbg, block, left_high, right_lowc);
Matthias Braun's avatar
Matthias Braun committed
317
318
		ir_node *add        = new_rd_Add(dbg, block, mul1, pEDX, mode);
		ir_node *left_lowc  = new_rd_Conv(dbg, block, left_low, mode);
319
		ir_node *mul2 = new_rd_Mul(dbg, block, left_lowc, right_high);
Matthias Braun's avatar
Matthias Braun committed
320
		h_res = new_rd_Add(dbg, block, add, mul2, mode);
321
	}
Matthias Braun's avatar
Matthias Braun committed
322
	ir_set_dw_lowered(node, l_res, h_res);
323
324
}

325
/**
Matthias Braun's avatar
Matthias Braun committed
326
 * lower 64bit minus operation
327
 */
Matthias Braun's avatar
Matthias Braun committed
328
static void ia32_lower_minus64(ir_node *node, ir_mode *mode)
329
{
Matthias Braun's avatar
Matthias Braun committed
330
331
332
333
334
335
	dbg_info *dbg     = get_irn_dbg_info(node);
	ir_node  *block   = get_nodes_block(node);
	ir_node  *op      = get_Minus_op(node);
	ir_node  *op_low  = get_lowered_low(op);
	ir_node  *op_high = get_lowered_high(op);
	ir_node  *minus   = new_bd_ia32_l_Minus64(dbg, block, op_low, op_high);
336
	ir_node  *l_res   = new_r_Proj(minus, ia32_mode_gp, pn_ia32_Minus64_res_low);
Matthias Braun's avatar
Matthias Braun committed
337
338
	ir_node  *h_res   = new_r_Proj(minus, mode, pn_ia32_Minus64_res_high);
	ir_set_dw_lowered(node, l_res, h_res);
339
340
341
}

/**
Matthias Braun's avatar
Matthias Braun committed
342
 * lower 64bit conversions
343
 */
Matthias Braun's avatar
Matthias Braun committed
344
static void ia32_lower_conv64(ir_node *node, ir_mode *mode)
345
{
Matthias Braun's avatar
Matthias Braun committed
346
347
348
349
	dbg_info  *dbg       = get_irn_dbg_info(node);
	ir_node   *op        = get_Conv_op(node);
	ir_mode   *mode_from = get_irn_mode(op);
	ir_mode   *mode_to   = get_irn_mode(node);
350

Matthias Braun's avatar
Matthias Braun committed
351
352
	if (mode_is_float(mode_from) && get_mode_size_bits(mode_to) == 64
	    && get_mode_arithmetic(mode_to) == irma_twos_complement) {
353
		/* We have a Conv float -> long long here */
Matthias Braun's avatar
Matthias Braun committed
354
355
356
357
		ir_node *float_to_ll;
		ir_node *l_res;
		ir_node *h_res;
		if (mode_is_signed(mode)) {
358
			/* convert from float to signed 64bit */
Matthias Braun's avatar
Matthias Braun committed
359
360
			ir_node *block = get_nodes_block(node);
			float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, op);
361
			l_res = new_r_Proj(float_to_ll, ia32_mode_gp,
362
			                   pn_ia32_l_FloattoLL_res_low);
Matthias Braun's avatar
Matthias Braun committed
363
			h_res = new_r_Proj(float_to_ll, mode,
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
364
			                   pn_ia32_l_FloattoLL_res_high);
365
		} else {
Christoph Mallon's avatar
Christoph Mallon committed
366
			/* Convert from float to unsigned 64bit. */
Matthias Braun's avatar
Matthias Braun committed
367
368
			ir_graph  *irg = get_irn_irg(node);
			ir_tarval *flt_tv
369
				= new_tarval_from_str("9223372036854775808", 19, x86_mode_E);
Matthias Braun's avatar
Matthias Braun committed
370
371
372
373
			ir_node   *flt_corr  = new_r_Const(irg, flt_tv);

			ir_node *lower_blk = part_block_dw(node);
			ir_node *upper_blk = get_nodes_block(node);
374
			set_dw_control_flow_changed();
Matthias Braun's avatar
Matthias Braun committed
375

376
			ir_node *opc  = new_rd_Conv(dbg, upper_blk, op, x86_mode_E);
Matthias Braun's avatar
Matthias Braun committed
377
378
379
380
381
382
383
384
			ir_node *cmp  = new_rd_Cmp(dbg, upper_blk, opc, flt_corr,
			                           ir_relation_less);
			ir_node *cond = new_rd_Cond(dbg, upper_blk, cmp);
			ir_node *in[] = {
				new_r_Proj(cond, mode_X, pn_Cond_true),
				new_r_Proj(cond, mode_X, pn_Cond_false)
			};
			ir_node *blk   = new_r_Block(irg, 1, &in[1]);
385
			in[1] = new_r_Jmp(blk);
386
387
388
389

			set_irn_in(lower_blk, 2, in);

			/* create to Phis */
Matthias Braun's avatar
Matthias Braun committed
390
			ir_node *phi_in[] = {
391
				new_r_Const_null(irg, mode),
Matthias Braun's avatar
Matthias Braun committed
392
393
394
395
396
397
398
				new_r_Const_long(irg, mode, 0x80000000)
			};
			ir_node *int_phi
				= new_r_Phi(lower_blk, ARRAY_SIZE(phi_in), phi_in, mode);

			ir_node *fphi_in[] = {
				opc,
399
				new_rd_Sub(dbg, upper_blk, opc, flt_corr, x86_mode_E)
Matthias Braun's avatar
Matthias Braun committed
400
401
402
			};
			ir_node *flt_phi
				= new_r_Phi(lower_blk, ARRAY_SIZE(fphi_in), fphi_in,
403
				            x86_mode_E);
404

405
			/* fix Phi links for next part_block() */
406
407
408
409
			if (is_Phi(int_phi))
				add_Block_phi(lower_blk, int_phi);
			if (is_Phi(flt_phi))
				add_Block_phi(lower_blk, flt_phi);
410
411

			float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi);
412
			l_res = new_r_Proj(float_to_ll, ia32_mode_gp,
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
413
			                   pn_ia32_l_FloattoLL_res_low);
Matthias Braun's avatar
Matthias Braun committed
414
			h_res = new_r_Proj(float_to_ll, mode,
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
415
			                   pn_ia32_l_FloattoLL_res_high);
Matthias Braun's avatar
Matthias Braun committed
416
			h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, mode);
417
418

			/* move the call and its Proj's to the lower block */
Matthias Braun's avatar
Matthias Braun committed
419
420
			set_nodes_block(node, lower_blk);
			for (ir_node *proj = (ir_node*)get_irn_link(node); proj != NULL;
421
			     proj = (ir_node*)get_irn_link(proj)) {
422
				set_nodes_block(proj, lower_blk);
423
			}
424
		}
Matthias Braun's avatar
Matthias Braun committed
425
426
427
428
		ir_set_dw_lowered(node, l_res, h_res);
	} else if (get_mode_size_bits(mode_from) == 64
	           && get_mode_arithmetic(mode_from) == irma_twos_complement
	           && mode_is_float(mode_to)) {
429
		/* We have a Conv long long -> float here */
Matthias Braun's avatar
Matthias Braun committed
430
431
432
433
434
		ir_node *op_low  = get_lowered_low(op);
		ir_node *op_high = get_lowered_high(op);
		ir_node *block   = get_nodes_block(node);
		ir_node *ll_to_float
			= new_bd_ia32_l_LLtoFloat(dbg, block, op_high, op_low, mode_to);
435

Matthias Braun's avatar
Matthias Braun committed
436
		exchange(node, ll_to_float);
437
	} else {
Matthias Braun's avatar
Matthias Braun committed
438
		ir_default_lower_dw_Conv(node, mode);
439
440
441
	}
}

Matthias Braun's avatar
Matthias Braun committed
442
443
444
static ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
                                            const ir_mode *imode,
                                            const ir_mode *omode, void *context)
445
{
Matthias Braun's avatar
Matthias Braun committed
446
447
448
449
450
451
452
453
454
455
	(void)omode;
	(void)context;

	const char *name;
	if (op == op_Div) {
		name = mode_is_signed(imode) ? "__divdi3" : "__udivdi3";
	} else if (op == op_Mod) {
		name = mode_is_signed(imode) ? "__moddi3" : "__umoddi3";
	} else {
		panic("ia32: Unexpected lowering of 64bit op %s", get_op_name(op));
456
	}
Matthias Braun's avatar
Matthias Braun committed
457
458
	return create_compilerlib_entity(new_id_from_str(name), method);
}
459

Matthias Braun's avatar
Matthias Braun committed
460
461
462
void ia32_lower64(void)
{
	/* perform doubleword lowering */
463
464
	ir_mode *word_unsigned = ia32_reg_classes[CLASS_ia32_gp].mode;
	ir_mode *word_signed   = find_signed_mode(word_unsigned);
Matthias Braun's avatar
Matthias Braun committed
465
466
	lwrdw_param_t lower_dw_params = {
		ia32_create_intrinsic_fkt,
Matthias Braun's avatar
Matthias Braun committed
467
		NULL,
468
469
		word_unsigned,
		word_signed,
Matthias Braun's avatar
Matthias Braun committed
470
471
		64,    /* doubleword size */
		be_is_big_endian(),
Matthias Braun's avatar
Matthias Braun committed
472
473
474
475
476
477
478
479
480
	};

	ir_prepare_dw_lowering(&lower_dw_params);
	ir_register_dw_lower_function(op_Add,   ia32_lower_add64);
	ir_register_dw_lower_function(op_Sub,   ia32_lower_sub64);
	ir_register_dw_lower_function(op_Mul,   ia32_lower_mul64);
	ir_register_dw_lower_function(op_Minus, ia32_lower_minus64);
	ir_register_dw_lower_function(op_Conv,  ia32_lower_conv64);
	ir_lower_dw_ops();
481
}