sparc_transform.c 77.9 KB
Newer Older
Hannes Rapp's avatar
Hannes Rapp committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Hannes Rapp's avatar
Hannes Rapp committed
4
5
6
7
8
 */

/**
 * @file
 * @brief   code selection (transform FIRM into SPARC FIRM)
Matthias Braun's avatar
Matthias Braun committed
9
 * @author  Hannes Rapp, Matthias Braun
Hannes Rapp's avatar
Hannes Rapp committed
10
 */
11
#include <stdint.h>
12
#include <stdbool.h>
13

Hannes Rapp's avatar
Hannes Rapp committed
14
15
16
17
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "irgmod.h"
18
#include "iredges_t.h"
Hannes Rapp's avatar
Hannes Rapp committed
19
#include "ircons.h"
20
#include "iroptimize.h"
Hannes Rapp's avatar
Hannes Rapp committed
21
22
23
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"
Matthias Braun's avatar
Matthias Braun committed
24
#include "panic.h"
Matthias Braun's avatar
Matthias Braun committed
25
#include "util.h"
Hannes Rapp's avatar
Hannes Rapp committed
26

27
#include "beasm.h"
28
29
30
31
#include "benode.h"
#include "beirg.h"
#include "beutil.h"
#include "betranshlp.h"
Hannes Rapp's avatar
Hannes Rapp committed
32

33
#include "sparc_bearch_t.h"
Hannes Rapp's avatar
Hannes Rapp committed
34
35
36
37
38
39
#include "sparc_nodes_attr.h"
#include "sparc_transform.h"
#include "sparc_new_nodes.h"
#include "gen_sparc_new_nodes.h"

#include "gen_sparc_regalloc_if.h"
40
#include "sparc_cconv.h"
Hannes Rapp's avatar
Hannes Rapp committed
41
42
43

DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

44
static const arch_register_t *sp_reg = &sparc_registers[REG_SP];
45
static calling_convention_t  *current_cconv = NULL;
46
static be_stack_env_t         stack_env;
47
48
static ir_mode               *mode_gp;
static ir_mode               *mode_fp;
49
50
static ir_mode               *mode_fp2;
//static ir_mode               *mode_fp4;
51
static ir_node               *frame_base;
52
static ir_node               *initial_va_list;
Hannes Rapp's avatar
Hannes Rapp committed
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
static const arch_register_t *const omit_fp_callee_saves[] = {
	&sparc_registers[REG_L0],
	&sparc_registers[REG_L1],
	&sparc_registers[REG_L2],
	&sparc_registers[REG_L3],
	&sparc_registers[REG_L4],
	&sparc_registers[REG_L5],
	&sparc_registers[REG_L6],
	&sparc_registers[REG_L7],
	&sparc_registers[REG_I0],
	&sparc_registers[REG_I1],
	&sparc_registers[REG_I2],
	&sparc_registers[REG_I3],
	&sparc_registers[REG_I4],
	&sparc_registers[REG_I5],
};

71
72
73
/**
 * Create an And that will zero out upper bits.
 *
Michael Beck's avatar
Michael Beck committed
74
75
76
 * @param dbgi      debug info
 * @param block     the basic block
 * @param op        the original node
77
78
79
80
81
82
 * @param src_bits  number of lower bits that will remain
 */
static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                                   int src_bits)
{
	if (src_bits == 8) {
83
		return new_bd_sparc_And_imm(dbgi, block, op, NULL, 0xFF);
84
	} else if (src_bits == 16) {
85
		ir_node *lshift = new_bd_sparc_Sll_imm(dbgi, block, op, NULL, 16);
86
		ir_node *rshift = new_bd_sparc_Srl_imm(dbgi, block, lshift, NULL, 16);
87
88
89
90
91
92
93
94
		return rshift;
	} else {
		panic("zero extension only supported for 8 and 16 bits");
	}
}

/**
 * Generate code for a sign extension.
Michael Beck's avatar
Michael Beck committed
95
96
97
98
99
 *
 * @param dbgi      debug info
 * @param block     the basic block
 * @param op        the original node
 * @param src_bits  number of lower bits that will remain
100
101
102
103
104
 */
static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                                   int src_bits)
{
	int shift_width = 32 - src_bits;
105
106
	ir_node *lshift_node = new_bd_sparc_Sll_imm(dbgi, block, op, NULL, shift_width);
	ir_node *rshift_node = new_bd_sparc_Sra_imm(dbgi, block, lshift_node, NULL, shift_width);
107
108
109
	return rshift_node;
}

Michael Beck's avatar
Michael Beck committed
110
111
112
113
114
115
116
117
/**
 * Extend a value to 32 bit signed/unsigned depending on its mode.
 *
 * @param dbgi      debug info
 * @param block     the basic block
 * @param op        the original node
 * @param orig_mode the original mode of op
 */
118
119
120
121
static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                              ir_mode *orig_mode)
{
	int bits = get_mode_size_bits(orig_mode);
122
	assert(bits < 32);
123
124
125
126
127
128
129
130

	if (mode_is_signed(orig_mode)) {
		return gen_sign_extension(dbgi, block, op, bits);
	} else {
		return gen_zero_extension(dbgi, block, op, bits);
	}
}

Hannes Rapp's avatar
Hannes Rapp committed
131
typedef enum {
132
133
134
135
136
	MATCH_NONE          = 0,
	MATCH_COMMUTATIVE   = 1U << 0, /**< commutative operation. */
	MATCH_MODE_NEUTRAL  = 1U << 1, /**< the higher bits of the inputs don't
	                                    influence the significant lower bit at
	                                    all (for cases where mode < 32bit) */
137
	MATCH_SIGN_EXT_LEFT = 1U << 2, /**< we need to sign-extend the left operand
Christoph Mallon's avatar
Christoph Mallon committed
138
	                                    (for cases when mode < 32bit) */
139
140
	MATCH_ZERO_EXT_LEFT = 1U << 3, /**< we need to zero-extend the left operand
                                            (for cases when mode < 32bit) */
Hannes Rapp's avatar
Hannes Rapp committed
141
} match_flags_t;
142
ENUM_BITSET(match_flags_t)
Hannes Rapp's avatar
Hannes Rapp committed
143
144

typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
Hannes Rapp's avatar
Hannes Rapp committed
145
typedef ir_node* (*new_binop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode);
146
typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_entity *entity, int32_t immediate);
147
typedef ir_node* (*new_unop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_mode *mode);
Hannes Rapp's avatar
Hannes Rapp committed
148
149

/**
150
 * checks if a node's value can be encoded as a immediate
Hannes Rapp's avatar
Hannes Rapp committed
151
152
153
154
155
156
 */
static bool is_imm_encodeable(const ir_node *node)
{
	if (!is_Const(node))
		return false;

157
	long const value = get_Const_long(node);
158
	return sparc_is_value_imm_encodeable(value);
Hannes Rapp's avatar
Hannes Rapp committed
159
160
}

161
static bool needs_extension(ir_node *op)
162
{
163
	ir_mode *mode = get_irn_mode(op);
164
165
	unsigned gp_bits = get_mode_size_bits(mode_gp);
	if (get_mode_size_bits(mode) >= gp_bits)
166
		return false;
167
	return !be_upper_bits_clean(op, mode);
168
169
}

170
static void sparc_parse_constraint_letter(void const *const env, be_asm_constraint_t* const c, char const l)
171
{
172
173
174
175
176
177
178
179
180
181
182
183
184
185
	(void)env;

	switch (l) {
	case 'r':
		c->cls                   = &sparc_reg_classes[CLASS_sparc_gp];
		c->all_registers_allowed = true;
		break;

	case 'e':
	case 'f':
		c->cls                   = &sparc_reg_classes[CLASS_sparc_fp];
		c->all_registers_allowed = true;
		break;

186
187
	case 'g':
		c->all_registers_allowed = true;
188
		c->memory_possible       = true;
189
190
		/* FALLTHROUGH */
	case 'A':
191
	case 'I':
192
	case 'J':
193
	case 'K':
194
195
196
197
	case 'L':
	case 'M':
	case 'O':
	case 'P':
198
	case 'i':
199
	case 'n':
200
201
202
203
		c->cls            = &sparc_reg_classes[CLASS_sparc_gp];
		c->immediate_type = l;
		break;

204
205
206
207
208
	case 'm':
	case 'w':
		c->memory_possible = true;
		break;

209
210
	default:
		panic("unknown asm constraint '%c'", l);
211
	}
212
}
213

214
215
216
static void parse_asm_constraints(be_asm_constraint_t *const constraint, ident *const constraint_text, bool const is_output)
{
	be_parse_asm_constraints_internal(constraint, constraint_text, is_output, &sparc_parse_constraint_letter, NULL);
217
218
219
220
}

void sparc_init_asm_constraints(void)
{
221
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER,  "0123456789efr");
222
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE, "AIJKLMOPin");
223
224
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_SUPPORTS_ANY,       "g");
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP,     "mw");
225
226
227
228
	/* Note there are many more flags in gcc which we can't properly support
	 * at the moment. see gcc/config/sparc/constraints.md */
}

229
230
231
232
233
234
static bool sparc_check_immediate_constraint(long const val, char const imm_type)
{
	switch (imm_type) {
	case 'A': return   -16 <= val && val <   16;
	case 'I': return sparc_is_value_imm_encodeable(val);
	case 'J': return val ==    0;
235
	case 'K': return (val & 0x03FF) == 0;
236
237
238
239
240
241
242
243
244
245
246
247
	case 'L': return -1024 <= val && val < 1024;
	case 'M': return  -512 <= val && val <  512;
	case 'O': return val == 4096;
	case 'P': return val ==   -1;

	case 'g':
	case 'i':
	case 'n': return true;
	}
	panic("invalid immediate constraint found");
}

248
249
250
251
static bool sparc_match_immediate(sparc_asm_operand_t *const operand, ir_node *const node, char const imm_type)
{
	ir_tarval *offset;
	ir_entity *entity;
Matthias Braun's avatar
Matthias Braun committed
252
253
	unsigned   reloc_kind;
	if (!be_match_immediate(node, &offset, &entity, &reloc_kind))
254
255
		return false;

256
	if (entity && imm_type != 'g' && imm_type != 'i')
257
258
259
260
261
		return false;

	long value;
	if (offset) {
		value = get_tarval_long(offset);
262
		if (!sparc_check_immediate_constraint(value, imm_type))
263
264
265
266
267
268
269
270
271
272
273
			return false;
	} else {
		value = 0;
	}

	operand->kind                   = ASM_OPERAND_IMMEDIATE;
	operand->immediate_value        = value;
	operand->immediate_value_entity = entity;
	return true;
}

274
275
276
277
278
279
280
static ir_node *gen_ASM(ir_node *node)
{
	ident   **clobbers     = get_ASM_clobbers(node);
	//unsigned  clobber_bits[BITSET_SIZE_ELEMS(N_SPARC_REGISTERS)];

	for (size_t c = 0; c < get_ASM_n_clobbers(node); ++c) {
		const char *const clobber = get_id_str(clobbers[c]);
Christoph Mallon's avatar
Christoph Mallon committed
281
		if (streq(clobber, "cc"))
282
283
			continue;

Christoph Mallon's avatar
Christoph Mallon committed
284
		arch_register_t const *const reg = arch_find_register(clobber);
285
286
287
288
289
290
291
292
293
294
		if (reg == NULL)
			panic("invalid clobber in sparc asm");

#if 0
		rbitset_set(clobber_bits, reg->global_index);
#else
		panic("clobbers not correctly supported yet");
#endif
	}

295
296
297
298
	unsigned             const n_operands = be_count_asm_operands(node);
	ir_graph            *const irg        = get_irn_irg(node);
	struct obstack      *const obst       = get_irg_obstack(irg);
	sparc_asm_operand_t *const operands   = NEW_ARR_DZ(sparc_asm_operand_t, obst, n_operands);
299

300
301
302
303
	int                      n_inputs          = get_ASM_n_inputs(node);
	size_t                   n_out_constraints = get_ASM_n_output_constraints(node);
	ir_asm_constraint const *in_constraints    = get_ASM_input_constraints(node);
	ir_asm_constraint const *out_constraints   = get_ASM_output_constraints(node);
304
305

	/* construct output constraints */
306
	arch_register_req_t const **out_reqs = NEW_ARR_F(arch_register_req_t const*, 0);
307
308
309
310
311

	size_t out_idx;
	for (out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
		const ir_asm_constraint *constraint = &out_constraints[out_idx];
		unsigned                 pos        = constraint->pos;
312
		be_asm_constraint_t      parsed_constraint;
313
314
315
		parse_asm_constraints(&parsed_constraint, constraint->constraint, true);

		assert(parsed_constraint.immediate_type == 0);
316
317
		arch_register_req_t const *const req = be_make_register_req(obst, &parsed_constraint, n_out_constraints, out_reqs, out_idx);
		ARR_APP1(arch_register_req_t const*, out_reqs, req);
318
319
320
321
322
323
324
325
326

		/* TODO: adjust register_req for clobbers */

		sparc_asm_operand_t *const operand = &operands[pos];
		operand->kind = ASM_OPERAND_OUTPUT_VALUE;
		operand->pos  = out_idx;
	}

	/* inputs + input constraints */
327
328
	ir_node                   **in      = NEW_ARR_F(ir_node*, 0);
	arch_register_req_t const **in_reqs = NEW_ARR_F(arch_register_req_t const*, 0);
329
330
331
332
333
	for (int i = 0; i < n_inputs; ++i) {
		ir_node                 *pred         = get_ASM_input(node, i);
		const ir_asm_constraint *constraint   = &in_constraints[i];
		unsigned                 pos          = constraint->pos;

334
		be_asm_constraint_t parsed_constraint;
335
336
337
338
339
340
		parse_asm_constraints(&parsed_constraint, constraint->constraint, false);

		sparc_asm_operand_t *const operand = &operands[pos];

		/* try to use an immediate value */
		char imm_type = parsed_constraint.immediate_type;
341
342
		if (imm_type != '\0' && sparc_match_immediate(operand, pred, imm_type))
			continue;
343

344
345
		ir_node             *const new_pred = be_transform_node(pred);
		operand_kind_t             kind     = ASM_OPERAND_INPUT_VALUE;
346
		arch_register_req_t const *req      = be_make_register_req(obst, &parsed_constraint, n_out_constraints, out_reqs, i);
347
348
349
350
		if (req == arch_no_register_req) {
			kind = ASM_OPERAND_MEMORY;
			req  = arch_get_irn_register_req(new_pred)->cls->class_req;
		}
351

352
		operand->kind = kind;
353
354
355
		operand->pos  = ARR_LEN(in);
		ARR_APP1(ir_node*, in, new_pred);
		ARR_APP1(arch_register_req_t const*, in_reqs, req);
356
357
358
359
360
	}

	/* parse clobbers */
	for (size_t c = 0; c < get_ASM_n_clobbers(node); ++c) {
		const char *const clobber = get_id_str(clobbers[c]);
Christoph Mallon's avatar
Christoph Mallon committed
361
		if (streq(clobber, "cc")) {
362
363
			ARR_APP1(arch_register_req_t const*, out_reqs, sparc_registers[REG_PSR].single_req);
			ARR_APP1(arch_register_req_t const*, out_reqs, sparc_registers[REG_FSR].single_req);
364
365
366
			continue;
		}

367
		arch_register_t const *const reg = arch_find_register(clobber);
368
		assert(reg != NULL); /* otherwise we had a panic earlier */
369
		ARR_APP1(arch_register_req_t const*, out_reqs, reg->single_req);
370
371
	}

372
	return be_make_asm(node, in, in_reqs, out_reqs, operands);
373
374
}

375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
/* Transforms the left operand of a binary operation.
 *
 * Performs sign/zero extension if necessary.
 */
static ir_node *gen_helper_binop_left(ir_node *left, dbg_info *dbgi,
                                      ir_node *block, match_flags_t flags)
{
	ir_mode *mode     = get_irn_mode(left);
	ir_node *new_left = be_transform_node(left);

	if (flags & MATCH_MODE_NEUTRAL)
		return new_left;

	int bits    = get_mode_size_bits(mode);
	int gp_bits = get_mode_size_bits(mode_gp);

	if (bits >= gp_bits)
		return new_left;

	if (flags & MATCH_SIGN_EXT_LEFT) {
		if (!mode_is_signed(mode) || needs_extension(left)) {
			return gen_sign_extension(dbgi, block, new_left, bits);
		}
	} else if (flags & MATCH_ZERO_EXT_LEFT) {
		if (mode_is_signed(mode) || needs_extension(left)) {
			return gen_zero_extension(dbgi, block, new_left, bits);
		}
	} else if (needs_extension(left)) {
		return gen_extension(dbgi, block, new_left, mode);
	}

	return new_left;
}

Hannes Rapp's avatar
Hannes Rapp committed
409
410
411
/**
 * helper function for binop operations
 *
Michael Beck's avatar
Michael Beck committed
412
413
 * @param new_reg  register generation function ptr
 * @param new_imm  immediate generation function ptr
Hannes Rapp's avatar
Hannes Rapp committed
414
 */
Matthias Braun's avatar
Matthias Braun committed
415
416
417
418
419
static ir_node *gen_helper_binop_args(ir_node *node,
                                      ir_node *op1, ir_node *op2,
                                      match_flags_t flags,
                                      new_binop_reg_func new_reg,
                                      new_binop_imm_func new_imm)
Hannes Rapp's avatar
Hannes Rapp committed
420
{
421
	dbg_info *dbgi  = get_irn_dbg_info(node);
422
	ir_node  *block = be_transform_nodes_block(node);
423
424

	if (flags & MATCH_MODE_NEUTRAL) {
425
426
		op1 = be_skip_downconv(op1, false);
		op2 = be_skip_downconv(op2, false);
427
	}
Matthias Braun's avatar
Matthias Braun committed
428
	ir_mode *mode2 = get_irn_mode(op2);
429
430
	/* we should not see 64bit code */
	assert(get_mode_size_bits(get_irn_mode(op1)) <= 32);
431
	assert(get_mode_size_bits(mode2) <= 32);
Hannes Rapp's avatar
Hannes Rapp committed
432
433

	if (is_imm_encodeable(op2)) {
434
435
		int32_t  const immediate = get_Const_long(op2);
		ir_node *const new_op1   = gen_helper_binop_left(op1, dbgi, block, flags);
436
		return new_imm(dbgi, block, new_op1, NULL, immediate);
Hannes Rapp's avatar
Hannes Rapp committed
437
	}
Matthias Braun's avatar
Matthias Braun committed
438
	ir_node *new_op2 = be_transform_node(op2);
439
	if (! (flags & MATCH_MODE_NEUTRAL) && needs_extension(op2)) {
440
441
		new_op2 = gen_extension(dbgi, block, new_op2, mode2);
	}
Hannes Rapp's avatar
Hannes Rapp committed
442
443

	if ((flags & MATCH_COMMUTATIVE) && is_imm_encodeable(op1)) {
444
		int32_t const immediate = get_Const_long(op1);
445
		return new_imm(dbgi, block, new_op2, NULL, immediate);
Hannes Rapp's avatar
Hannes Rapp committed
446
447
	}

448
	ir_node *new_op1 = gen_helper_binop_left(op1, dbgi, block, flags);
Hannes Rapp's avatar
Hannes Rapp committed
449
450
451
	return new_reg(dbgi, block, new_op1, new_op2);
}

Matthias Braun's avatar
Matthias Braun committed
452
453
454
455
456
457
458
459
460
static ir_node *gen_helper_binop(ir_node *node, match_flags_t flags,
                                 new_binop_reg_func new_reg,
                                 new_binop_imm_func new_imm)
{
	ir_node *op1 = get_binop_left(node);
	ir_node *op2 = get_binop_right(node);
	return gen_helper_binop_args(node, op1, op2, flags, new_reg, new_imm);
}

Hannes Rapp's avatar
Hannes Rapp committed
461
462
463
/**
 * helper function for FP binop operations
 */
464
static ir_node *gen_helper_binfpop(ir_node *node, ir_mode *mode,
465
466
467
                                   new_binop_fp_func new_func_single,
                                   new_binop_fp_func new_func_double,
                                   new_binop_fp_func new_func_quad)
Hannes Rapp's avatar
Hannes Rapp committed
468
{
469
	ir_node  *block   = be_transform_nodes_block(node);
Hannes Rapp's avatar
Hannes Rapp committed
470
	ir_node  *op1     = get_binop_left(node);
471
	ir_node  *new_op1 = be_transform_node(op1);
Hannes Rapp's avatar
Hannes Rapp committed
472
	ir_node  *op2     = get_binop_right(node);
473
	ir_node  *new_op2 = be_transform_node(op2);
Hannes Rapp's avatar
Hannes Rapp committed
474
	dbg_info *dbgi    = get_irn_dbg_info(node);
475
476
477
478
479
480
481
482
483
484
485
486
487
	unsigned  bits    = get_mode_size_bits(mode);

	switch (bits) {
	case 32:
		return new_func_single(dbgi, block, new_op1, new_op2, mode);
	case 64:
		return new_func_double(dbgi, block, new_op1, new_op2, mode);
	case 128:
		return new_func_quad(dbgi, block, new_op1, new_op2, mode);
	default:
		break;
	}
	panic("unsupported mode %+F for float op", mode);
Hannes Rapp's avatar
Hannes Rapp committed
488
489
}

490
491
492
493
494
495
496
497
498
499
500
501
502
typedef ir_node* (*new_binopx_imm_func)(dbg_info *dbgi, ir_node *block,
                                        ir_node *op1, ir_node *flags,
                                        ir_entity *imm_entity, int32_t imm);

typedef ir_node* (*new_binopx_reg_func)(dbg_info *dbgi, ir_node *block,
                                        ir_node *op1, ir_node *op2,
                                        ir_node *flags);

static ir_node *gen_helper_binopx(ir_node *node, match_flags_t match_flags,
                                  new_binopx_reg_func new_binopx_reg,
                                  new_binopx_imm_func new_binopx_imm)
{
	dbg_info *dbgi      = get_irn_dbg_info(node);
503
	ir_node  *block     = be_transform_nodes_block(node);
504
505
506
507
508
509
510
511
512
	ir_node  *op1       = get_irn_n(node, 0);
	ir_node  *op2       = get_irn_n(node, 1);
	ir_node  *flags     = get_irn_n(node, 2);
	ir_node  *new_flags = be_transform_node(flags);

	/* only support for mode-neutral implemented so far */
	assert(match_flags & MATCH_MODE_NEUTRAL);

	if (is_imm_encodeable(op2)) {
513
514
		int32_t  const immediate = get_Const_long(op2);
		ir_node *const new_op1   = be_transform_node(op1);
515
516
		return new_binopx_imm(dbgi, block, new_op1, new_flags, NULL, immediate);
	}
Matthias Braun's avatar
Matthias Braun committed
517
	ir_node *new_op2 = be_transform_node(op2);
518
	if ((match_flags & MATCH_COMMUTATIVE) && is_imm_encodeable(op1)) {
519
		int32_t const immediate = get_Const_long(op1);
520
521
		return new_binopx_imm(dbgi, block, new_op2, new_flags, NULL, immediate);
	}
Matthias Braun's avatar
Matthias Braun committed
522
	ir_node *new_op1 = be_transform_node(op1);
523
524
525
526
	return new_binopx_reg(dbgi, block, new_op1, new_op2, new_flags);

}

527
528
static ir_node *get_g0(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
529
	return be_get_Start_proj(irg, &sparc_registers[REG_G0]);
530
531
}

532
533
static ir_node *get_g7(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
534
	return be_get_Start_proj(irg, &sparc_registers[REG_G7]);
535
536
537
538
539
540
541
542
543
544
545
546
547
}

static ir_node *make_tls_offset(dbg_info *dbgi, ir_node *block,
                                ir_entity *entity, int32_t offset)
{
	ir_node  *hi  = new_bd_sparc_SetHi(dbgi, block, entity, offset);
	ir_node  *low = new_bd_sparc_Xor_imm(dbgi, block, hi, entity, offset);
	return low;
}

static ir_node *make_address(dbg_info *dbgi, ir_node *block, ir_entity *entity,
                             int32_t offset)
{
548
	if (is_tls_entity(entity)) {
549
550
551
552
553
554
555
556
557
558
559
560
		ir_graph *irg     = get_irn_irg(block);
		ir_node  *g7      = get_g7(irg);
		ir_node  *offsetn = make_tls_offset(dbgi, block, entity, offset);
		ir_node  *add     = new_bd_sparc_Add_reg(dbgi, block, g7, offsetn);
		return add;
	} else {
		ir_node *hi  = new_bd_sparc_SetHi(dbgi, block, entity, offset);
		ir_node *low = new_bd_sparc_Or_imm(dbgi, block, hi, entity, offset);
		return low;
	}
}

561
typedef struct address_t {
562
563
	ir_node   *ptr;
	ir_node   *ptr2;
564
565
566
567
	ir_entity *entity;
	int32_t    offset;
} address_t;

568
569
570
571
/**
 * Match a load/store address
 */
static void match_address(ir_node *ptr, address_t *address, bool use_ptr2)
572
573
574
575
576
577
578
579
{
	ir_node   *base   = ptr;
	int32_t    offset = 0;

	if (is_Add(base)) {
		ir_node *add_right = get_Add_right(base);
		if (is_Const(add_right)) {
			base    = get_Add_left(base);
580
			offset += get_Const_long(add_right);
581
582
583
584
585
		}
	}
	/* Note that we don't match sub(x, Const) or chains of adds/subs
	 * because this should all be normalized by now */

586
	/* we only use the entity if we're the only user otherwise we probably
587
588
	 * won't save anything but produce multiple sethi+or combinations with
	 * just different offsets */
Matthias Braun's avatar
Matthias Braun committed
589
590
	ir_node   *ptr2   = NULL;
	ir_entity *entity = NULL;
591
592
	if (is_Address(base) && get_irn_n_edges(base) == 1) {
		ir_entity *sc_entity = get_Address_entity(base);
593
		dbg_info  *dbgi      = get_irn_dbg_info(ptr);
594
		ir_node   *new_block = be_transform_nodes_block(ptr);
595

596
		if (is_tls_entity(sc_entity)) {
597
598
599
600
601
602
603
604
605
606
607
608
			if (!use_ptr2) {
				goto only_offset;
			} else {
				ptr2   = make_tls_offset(dbgi, new_block, sc_entity, offset);
				offset = 0;
				base   = get_g7(get_irn_irg(base));
			}
		} else {
			entity = sc_entity;
			base   = new_bd_sparc_SetHi(dbgi, new_block, entity, offset);
		}
	} else if (use_ptr2 && is_Add(base) && offset == 0) {
609
610
		ptr2 = be_transform_node(get_Add_right(base));
		base = be_transform_node(get_Add_left(base));
611
	} else {
612
only_offset:
613
		if (sparc_is_value_imm_encodeable(offset)) {
614
615
616
617
618
619
620
			base = be_transform_node(base);
		} else {
			base   = be_transform_node(ptr);
			offset = 0;
		}
	}

621
622
	address->ptr    = base;
	address->ptr2   = ptr2;
623
624
625
626
	address->entity = entity;
	address->offset = offset;
}

Hannes Rapp's avatar
Hannes Rapp committed
627
628
629
630
631
632
633
634
/**
 * Creates an sparc Add.
 *
 * @param node   FIRM node
 * @return the created sparc Add node
 */
static ir_node *gen_Add(ir_node *node)
{
635
	ir_mode *mode = get_irn_mode(node);
636
	if (mode_is_float(mode)) {
637
638
		return gen_helper_binfpop(node, mode, new_bd_sparc_fadd_s,
		                          new_bd_sparc_fadd_d, new_bd_sparc_fadd_q);
639
	}
Hannes Rapp's avatar
Hannes Rapp committed
640

641
	/* special case: + 0x1000 can be represented as - 0x1000 */
Matthias Braun's avatar
Matthias Braun committed
642
	ir_node *right = get_Add_right(node);
643
	if (is_Const(right)) {
Matthias Braun's avatar
Matthias Braun committed
644
		ir_node   *left = get_Add_left(node);
645
646
		/* is this simple address arithmetic? then we can let the linker do
		 * the calculation. */
647
		if (is_Address(left) && get_irn_n_edges(left) == 1) {
648
			dbg_info *dbgi  = get_irn_dbg_info(node);
649
			ir_node  *block = be_transform_nodes_block(node);
650

651
			/* the value of use_ptr2 shouldn't matter here */
Matthias Braun's avatar
Matthias Braun committed
652
			address_t address;
653
654
655
			match_address(node, &address, false);
			assert(is_sparc_SetHi(address.ptr));
			return new_bd_sparc_Or_imm(dbgi, block, address.ptr,
656
657
658
			                           address.entity, address.offset);
		}

659
		uint32_t const val = get_Const_long(right);
660
661
		if (val == 0x1000) {
			dbg_info *dbgi   = get_irn_dbg_info(node);
662
			ir_node  *block  = be_transform_nodes_block(node);
663
664
			ir_node  *op     = get_Add_left(node);
			ir_node  *new_op = be_transform_node(op);
665
			return new_bd_sparc_Sub_imm(dbgi, block, new_op, NULL, -0x1000);
666
667
668
		}
	}

669
670
	return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_MODE_NEUTRAL,
	                        new_bd_sparc_Add_reg, new_bd_sparc_Add_imm);
Hannes Rapp's avatar
Hannes Rapp committed
671
672
}

673
674
static ir_node *gen_AddCC_t(ir_node *node)
{
yb9976's avatar
yb9976 committed
675
676
677
	ir_node *left     = get_irn_n(node, n_sparc_AddCC_t_left);
	ir_node *right    = get_irn_n(node, n_sparc_AddCC_t_right);
	ir_node *new_node = gen_helper_binop_args(node, left, right,
678
679
	                             MATCH_COMMUTATIVE | MATCH_MODE_NEUTRAL,
	                             new_bd_sparc_AddCC_reg, new_bd_sparc_AddCC_imm);
680
	arch_set_irn_register_out(new_node, pn_sparc_AddCC_flags, &sparc_registers[REG_PSR]);
yb9976's avatar
yb9976 committed
681
682

	return new_node;
683
684
685
686
}

static ir_node *gen_Proj_AddCC_t(ir_node *node)
{
687
	unsigned pn       = get_Proj_num(node);
688
689
690
691
692
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);

	switch (pn) {
	case pn_sparc_AddCC_t_res:
693
		return be_new_Proj(new_pred, pn_sparc_AddCC_res);
694
	case pn_sparc_AddCC_t_flags:
695
		return be_new_Proj(new_pred, pn_sparc_AddCC_flags);
696
	default:
697
		panic("invalid proj found");
698
699
700
701
702
703
704
705
706
	}
}

static ir_node *gen_AddX_t(ir_node *node)
{
	return gen_helper_binopx(node, MATCH_COMMUTATIVE | MATCH_MODE_NEUTRAL,
	                         new_bd_sparc_AddX_reg, new_bd_sparc_AddX_imm);
}

Hannes Rapp's avatar
Hannes Rapp committed
707
708
709
710
711
712
713
714
/**
 * Creates an sparc Sub.
 *
 * @param node       FIRM node
 * @return the created sparc Sub node
 */
static ir_node *gen_Sub(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
715
	ir_mode *mode = get_irn_mode(node);
716
	if (mode_is_float(mode)) {
717
718
		return gen_helper_binfpop(node, mode, new_bd_sparc_fsub_s,
		                          new_bd_sparc_fsub_d, new_bd_sparc_fsub_q);
719
	}
Hannes Rapp's avatar
Hannes Rapp committed
720

Matthias Braun's avatar
Matthias Braun committed
721
722
	return gen_helper_binop(node, MATCH_MODE_NEUTRAL,
	                        new_bd_sparc_Sub_reg, new_bd_sparc_Sub_imm);
Hannes Rapp's avatar
Hannes Rapp committed
723
724
}

725
726
static ir_node *gen_SubCC_t(ir_node *node)
{
yb9976's avatar
yb9976 committed
727
728
729
	ir_node *left     = get_irn_n(node, n_sparc_SubCC_t_left);
	ir_node *right    = get_irn_n(node, n_sparc_SubCC_t_right);
	ir_node *new_node = gen_helper_binop_args(node, left, right, MATCH_MODE_NEUTRAL,
730
	                             new_bd_sparc_SubCC_reg, new_bd_sparc_SubCC_imm);
731
	arch_set_irn_register_out(new_node, pn_sparc_SubCC_flags, &sparc_registers[REG_PSR]);
yb9976's avatar
yb9976 committed
732
733

	return new_node;
734
735
736
737
}

static ir_node *gen_Proj_SubCC_t(ir_node *node)
{
738
	unsigned pn       = get_Proj_num(node);
739
740
741
742
743
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);

	switch (pn) {
	case pn_sparc_SubCC_t_res:
744
		return be_new_Proj(new_pred, pn_sparc_SubCC_res);
745
	case pn_sparc_SubCC_t_flags:
746
		return be_new_Proj(new_pred, pn_sparc_SubCC_flags);
747
	default:
748
		panic("invalid proj found");
749
750
751
752
753
754
755
756
757
	}
}

static ir_node *gen_SubX_t(ir_node *node)
{
	return gen_helper_binopx(node, MATCH_MODE_NEUTRAL,
	                         new_bd_sparc_SubX_reg, new_bd_sparc_SubX_imm);
}

758
759
760
ir_node *create_ldf(dbg_info *dbgi, ir_node *block, ir_node *ptr,
                    ir_node *mem, ir_mode *mode, ir_entity *entity,
                    long offset, bool is_frame_entity)
761
762
763
764
765
{
	unsigned bits = get_mode_size_bits(mode);
	assert(mode_is_float(mode));
	if (bits == 32) {
		return new_bd_sparc_Ldf_s(dbgi, block, ptr, mem, mode, entity,
766
		                          offset, is_frame_entity);
767
768
	} else if (bits == 64) {
		return new_bd_sparc_Ldf_d(dbgi, block, ptr, mem, mode, entity,
769
		                          offset, is_frame_entity);
770
771
772
	} else {
		assert(bits == 128);
		return new_bd_sparc_Ldf_q(dbgi, block, ptr, mem, mode, entity,
773
		                          offset, is_frame_entity);
774
775
776
	}
}

777
778
779
780
ir_node *create_stf(dbg_info *dbgi, ir_node *block, ir_node *value,
                    ir_node *ptr, ir_node *mem, ir_mode *mode,
                    ir_entity *entity, long offset,
                    bool is_frame_entity)
781
782
783
784
{
	unsigned bits = get_mode_size_bits(mode);
	assert(mode_is_float(mode));
	if (bits == 32) {
785
		return new_bd_sparc_Stf_s(dbgi, block, value, ptr, mem, mode, entity,
786
		                          offset, is_frame_entity);
787
	} else if (bits == 64) {
788
		return new_bd_sparc_Stf_d(dbgi, block, value, ptr, mem, mode, entity,
789
		                          offset, is_frame_entity);
790
791
	} else {
		assert(bits == 128);
792
		return new_bd_sparc_Stf_q(dbgi, block, value, ptr, mem, mode, entity,
793
		                          offset, is_frame_entity);
794
795
796
	}
}

Hannes Rapp's avatar
Hannes Rapp committed
797
798
799
800
801
802
803
804
/**
 * Transforms a Load.
 *
 * @param node    the ir Load node
 * @return the created sparc Load node
 */
static ir_node *gen_Load(ir_node *node)
{
805
	dbg_info *dbgi     = get_irn_dbg_info(node);
Hannes Rapp's avatar
Hannes Rapp committed
806
	ir_mode  *mode     = get_Load_mode(node);
807
	ir_node  *block    = be_transform_nodes_block(node);
Hannes Rapp's avatar
Hannes Rapp committed
808
809
810
	ir_node  *ptr      = get_Load_ptr(node);
	ir_node  *mem      = get_Load_mem(node);
	ir_node  *new_mem  = be_transform_node(mem);
811

812
	if (get_Load_unaligned(node) == align_non_aligned) {
813
		panic("transformation of unaligned Loads not implemented yet");
814
815
	}

Matthias Braun's avatar
Matthias Braun committed
816
	ir_node  *new_load;
817
	if (mode_is_float(mode)) {
Matthias Braun's avatar
Matthias Braun committed
818
		address_t address;
819
820
		match_address(ptr, &address, false);
		new_load = create_ldf(dbgi, block, address.ptr, new_mem, mode,
821
		                      address.entity, address.offset, false);
822
	} else {
Matthias Braun's avatar
Matthias Braun committed
823
		address_t address;
824
825
826
827
828
829
830
831
832
833
		match_address(ptr, &address, true);
		if (address.ptr2 != NULL) {
			assert(address.entity == NULL && address.offset == 0);
			new_load = new_bd_sparc_Ld_reg(dbgi, block, address.ptr,
			                               address.ptr2, new_mem, mode);
		} else {
			new_load = new_bd_sparc_Ld_imm(dbgi, block, address.ptr, new_mem,
			                               mode, address.entity, address.offset,
			                               false);
		}
834
	}
Hannes Rapp's avatar
Hannes Rapp committed
835
836
	set_irn_pinned(new_load, get_irn_pinned(node));

Hannes Rapp's avatar
Hannes Rapp committed
837
838
839
840
841
842
843
844
845
846
847
	return new_load;
}

/**
 * Transforms a Store.
 *
 * @param node    the ir Store node
 * @return the created sparc Store node
 */
static ir_node *gen_Store(ir_node *node)
{
848
	ir_node  *block    = be_transform_nodes_block(node);
Hannes Rapp's avatar
Hannes Rapp committed
849
850
851
852
853
854
	ir_node  *ptr      = get_Store_ptr(node);
	ir_node  *mem      = get_Store_mem(node);
	ir_node  *new_mem  = be_transform_node(mem);
	ir_node  *val      = get_Store_value(node);
	ir_mode  *mode     = get_irn_mode(val);
	dbg_info *dbgi     = get_irn_dbg_info(node);
855

856
	if (get_Store_unaligned(node) == align_non_aligned) {
857
		panic("transformation of unaligned Stores not implemented yet");
858
859
	}

Matthias Braun's avatar
Matthias Braun committed
860
	ir_node  *new_store;
861
	if (mode_is_float(mode)) {
862
		ir_node *new_val = be_transform_node(val);
863
		/* TODO: variants with reg+reg address mode */
Matthias Braun's avatar
Matthias Braun committed
864
		address_t address;
865
866
		match_address(ptr, &address, false);
		new_store = create_stf(dbgi, block, new_val, address.ptr, new_mem,
867
		                       mode, address.entity, address.offset, false);
868
	} else {
869
		val = be_skip_downconv(val, false);
Matthias Braun's avatar
Matthias Braun committed
870
		ir_node *new_val = be_transform_node(val);
871

872
		assert(get_mode_size_bits(mode) <= 32);
Matthias Braun's avatar
Matthias Braun committed
873
		address_t address;
874
875
876
877
878
879
880
881
882
883
		match_address(ptr, &address, true);
		if (address.ptr2 != NULL) {
			assert(address.entity == NULL && address.offset == 0);
			new_store = new_bd_sparc_St_reg(dbgi, block, new_val, address.ptr,
			                                address.ptr2, new_mem, mode);
		} else {
			new_store = new_bd_sparc_St_imm(dbgi, block, new_val, address.ptr,
			                                new_mem, mode, address.entity,
			                                address.offset, false);
		}
884
885
	}
	set_irn_pinned(new_store, get_irn_pinned(node));
Hannes Rapp's avatar
Hannes Rapp committed
886
887
888
889

	return new_store;
}

890
891
/**
 * Creates an sparc Mul.
892
 * returns the lower 32bits of the 64bit multiply result
893
894
895
 *
 * @return the created sparc Mul node
 */
896
897
898
static ir_node *gen_Mul(ir_node *node)
{
	ir_mode *mode = get_irn_mode(node);
Hannes Rapp's avatar
Hannes Rapp committed
899
	if (mode_is_float(mode)) {
900
901
		return gen_helper_binfpop(node, mode, new_bd_sparc_fmul_s,
		                          new_bd_sparc_fmul_d, new_bd_sparc_fmul_q);
Hannes Rapp's avatar
Hannes Rapp committed
902
	}
903

904
	return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_MODE_NEUTRAL,
905
	                        new_bd_sparc_Mul_reg, new_bd_sparc_Mul_imm);
906
907
908
909
910
911
912
913
}

/**
 * Creates an sparc Mulh.
 * Mulh returns the upper 32bits of a mul instruction
 *
 * @return the created sparc Mulh node
 */
914
915
static ir_node *gen_Mulh(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
916
	ir_mode *mode = get_irn_mode(node);
917
918
919
	if (mode_is_float(mode))
		panic("FP not supported yet");

920
	if (mode_is_signed(mode)) {
921
		return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_SMulh_reg, new_bd_sparc_SMulh_imm);
922
	} else {
923
		return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_UMulh_reg, new_bd_sparc_UMulh_imm);
924
	}
925
}
Hannes Rapp's avatar
Hannes Rapp committed
926

927
928
static ir_node *gen_sign_extension_value(ir_node *node)
{
929
	ir_node *new_block = be_transform_nodes_block(node);
930
931
932
933
934
935
936
	ir_node *new_node  = be_transform_node(node);
	/* TODO: we could do some shortcuts for some value types probably.
	 * (For constants or other cases where we know the sign bit in
	 *  advance) */
	return new_bd_sparc_Sra_imm(NULL, new_block, new_node, NULL, 31);
}

937
938
939
940
941
/**
 * Creates an sparc Div.
 *
 * @return the created sparc Div node
 */
942
943
static ir_node *gen_Div(ir_node *node)
{
944
	dbg_info *dbgi      = get_irn_dbg_info(node);
945
	ir_node  *new_block = be_transform_nodes_block(node);
946
947
948
949
	ir_mode  *mode      = get_Div_resmode(node);
	ir_node  *left      = get_Div_left(node);
	ir_node  *left_low  = be_transform_node(left);
	ir_node  *right     = get_Div_right(node);
950

951
952
	if (mode_is_float(mode)) {
		return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv_s,
yb9976's avatar
yb9976 committed
953
		                          new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q);
954
955
	}

956
957
	ir_node *mem     = get_Div_mem(node);
	ir_node *new_mem = be_transform_node(mem);
Matthias Braun's avatar
Matthias Braun committed
958
	ir_node *res;
959
	if (mode_is_signed(mode)) {
960
961
962
		ir_node *left_high = gen_sign_extension_value(left);

		if (is_imm_encodeable(right)) {
963
			int32_t const immediate = get_Const_long(right);
964
			res = new_bd_sparc_SDiv_imm(dbgi, new_block, new_mem, left_high, left_low,
965
966
967
			                            NULL, immediate);
		} else {
			ir_node *new_right = be_transform_node(right);
968
			res = new_bd_sparc_SDiv_reg(dbgi, new_block, new_mem, left_high, left_low,
969
970
			                            new_right);
		}
971
	} else {
972
973
		ir_graph *irg       = get_irn_irg(node);
		ir_node  *left_high = get_g0(irg);
974
		if (is_imm_encodeable(right)) {
975
			int32_t const immediate = get_Const_long(right);
976
			res = new_bd_sparc_UDiv_imm(dbgi, new_block, new_mem, left_high, left_low,
977
978
979
			                            NULL, immediate);
		} else {
			ir_node *new_right = be_transform_node(right);
980
			res = new_bd_sparc_UDiv_reg(dbgi, new_block, new_mem, left_high, left_low,
981
982
			                            new_right);
		}
983
	}
984

985
	return res;
986
987
}

988
989
990
/**
 * Transforms a Not node.
 *
Michael Beck's avatar
Michael Beck committed
991
 * @return the created sparc Not node
992
993
994
 */
static ir_node *gen_Not(ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
995
	ir_node  *op     = get_Not_op(node);
996
997
	ir_graph *irg    = get_irn_irg(node);
	ir_node  *zero   = get_g0(irg);
998
	dbg_info *dbgi   = get_irn_dbg_info(node);
999
	ir_node  *block  = be_transform_nodes_block(node);
1000
	ir_node  *new_op = be_transform_node(op);
For faster browsing, not all history is shown. View entire blame