sparc_transform.c 79.6 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
18
19
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "irgmod.h"
#include "iredges.h"
#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
34
35
36
37
38
39
#include "bearch_sparc_t.h"

#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_stackorder_t       *stackorder;
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 pmap                  *node_to_stack;
52
static ir_node               *frame_base;
53
static ir_node               *initial_va_list;
Hannes Rapp's avatar
Hannes Rapp committed
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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],
};

72
static inline bool mode_needs_gp_reg(ir_mode *mode)
Hannes Rapp's avatar
Hannes Rapp committed
73
{
74
75
76
77
78
79
	if (mode_is_int(mode) || mode_is_reference(mode)) {
		/* we should only see 32bit code */
		assert(get_mode_size_bits(mode) <= 32);
		return true;
	}
	return false;
Hannes Rapp's avatar
Hannes Rapp committed
80
81
}

82
83
84
/**
 * Create an And that will zero out upper bits.
 *
Michael Beck's avatar
Michael Beck committed
85
86
87
 * @param dbgi      debug info
 * @param block     the basic block
 * @param op        the original node
88
89
90
91
92
93
 * @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) {
94
		return new_bd_sparc_And_imm(dbgi, block, op, NULL, 0xFF);
95
	} else if (src_bits == 16) {
96
		ir_node *lshift = new_bd_sparc_Sll_imm(dbgi, block, op, NULL, 16);
97
		ir_node *rshift = new_bd_sparc_Srl_imm(dbgi, block, lshift, NULL, 16);
98
99
100
101
102
103
104
105
		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
106
107
108
109
110
 *
 * @param dbgi      debug info
 * @param block     the basic block
 * @param op        the original node
 * @param src_bits  number of lower bits that will remain
111
112
113
114
115
 */
static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                                   int src_bits)
{
	int shift_width = 32 - src_bits;
116
117
	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);
118
119
120
	return rshift_node;
}

Michael Beck's avatar
Michael Beck committed
121
122
123
124
125
126
127
128
/**
 * 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
 */
129
130
131
132
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);
133
	assert(bits < 32);
134
135
136
137
138
139
140
141

	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
142
typedef enum {
143
144
145
146
147
	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) */
148
	MATCH_SIGN_EXT_LEFT = 1U << 2, /**< we need to sign-extend the left operand
Christoph Mallon's avatar
Christoph Mallon committed
149
	                                    (for cases when mode < 32bit) */
150
151
	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
152
} match_flags_t;
153
ENUM_BITSET(match_flags_t)
Hannes Rapp's avatar
Hannes Rapp committed
154
155

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
156
typedef ir_node* (*new_binop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode);
157
typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_entity *entity, int32_t immediate);
158
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
159
160

/**
161
 * checks if a node's value can be encoded as a immediate
Hannes Rapp's avatar
Hannes Rapp committed
162
163
164
165
166
167
 */
static bool is_imm_encodeable(const ir_node *node)
{
	if (!is_Const(node))
		return false;

168
	long const value = get_Const_long(node);
169
	return sparc_is_value_imm_encodeable(value);
Hannes Rapp's avatar
Hannes Rapp committed
170
171
}

172
static bool needs_extension(ir_node *op)
173
{
174
	ir_mode *mode = get_irn_mode(op);
175
176
	unsigned gp_bits = get_mode_size_bits(mode_gp);
	if (get_mode_size_bits(mode) >= gp_bits)
177
		return false;
178
	return !be_upper_bits_clean(op, mode);
179
180
}

181
static void sparc_parse_constraint_letter(void const *const env, be_asm_constraint_t* const c, char const l)
182
{
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	(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;

197
198
	case 'g':
		c->all_registers_allowed = true;
199
		c->memory_possible       = true;
200
201
		/* FALLTHROUGH */
	case 'A':
202
	case 'I':
203
204
205
206
207
	case 'J':
	case 'L':
	case 'M':
	case 'O':
	case 'P':
208
	case 'i':
209
	case 'n':
210
211
212
213
		c->cls            = &sparc_reg_classes[CLASS_sparc_gp];
		c->immediate_type = l;
		break;

214
215
216
217
218
	case 'm':
	case 'w':
		c->memory_possible = true;
		break;

219
220
	default:
		panic("unknown asm constraint '%c'", l);
221
	}
222
}
223

224
225
226
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);
227
228
229
230
231
232
233
234
235
236
237
238
239
240
}

static const arch_register_t *find_register(const char *name)
{
	for (size_t i = 0; i < N_SPARC_REGISTERS; ++i) {
		const arch_register_t *const reg = &sparc_registers[i];
		if (strcmp(reg->name, name) == 0)
			return reg;
	}
	return NULL;
}

void sparc_init_asm_constraints(void)
{
241
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER,  "0123456789efr");
242
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE, "AIJLMOPin");
243
244
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_SUPPORTS_ANY,       "g");
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP,     "mw");
245
246
247
248
249
250
251
252
253
	/* Note there are many more flags in gcc which we can't properly support
	 * at the moment. see gcc/config/sparc/constraints.md */
}

int sparc_is_valid_clobber(const char *clobber)
{
	return strcmp(clobber, "memory") == 0 || strcmp(clobber, "cc") == 0;
}

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
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;
	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");
}

272
273
274
275
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
276
277
	unsigned   reloc_kind;
	if (!be_match_immediate(node, &offset, &entity, &reloc_kind))
278
279
		return false;

280
	if (entity && imm_type != 'g' && imm_type != 'i')
281
282
283
284
285
		return false;

	long value;
	if (offset) {
		value = get_tarval_long(offset);
286
		if (!sparc_check_immediate_constraint(value, imm_type))
287
288
289
290
291
292
293
294
295
296
297
			return false;
	} else {
		value = 0;
	}

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

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
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]);
		if (strcmp(clobber, "memory") == 0)
			continue;
		if (strcmp(clobber, "cc") == 0) {
			continue;
		}

		const arch_register_t *reg = find_register(clobber);
		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
	}

322
323
324
325
	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);
326

327
328
329
330
	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);
331
332

	/* construct output constraints */
333
	arch_register_req_t const **out_reqs = NEW_ARR_F(arch_register_req_t const*, 0);
334
335
336
337
338

	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;
339
		be_asm_constraint_t      parsed_constraint;
340
341
342
		parse_asm_constraints(&parsed_constraint, constraint->constraint, true);

		assert(parsed_constraint.immediate_type == 0);
343
344
		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);
345
346
347
348
349
350
351
352
353

		/* 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 */
354
355
	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);
356
357
358
359
360
	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;

361
		be_asm_constraint_t parsed_constraint;
362
363
364
365
366
367
		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;
368
369
		if (imm_type != '\0' && sparc_match_immediate(operand, pred, imm_type))
			continue;
370

371
372
		ir_node             *const new_pred = be_transform_node(pred);
		operand_kind_t             kind     = ASM_OPERAND_INPUT_VALUE;
373
		arch_register_req_t const *req      = be_make_register_req(obst, &parsed_constraint, n_out_constraints, out_reqs, i);
374
375
376
377
		if (req == arch_no_register_req) {
			kind = ASM_OPERAND_MEMORY;
			req  = arch_get_irn_register_req(new_pred)->cls->class_req;
		}
378

379
		operand->kind = kind;
380
381
382
		operand->pos  = ARR_LEN(in);
		ARR_APP1(ir_node*, in, new_pred);
		ARR_APP1(arch_register_req_t const*, in_reqs, req);
383
384
385
386
387
388
389
390
	}

	/* parse clobbers */
	for (size_t c = 0; c < get_ASM_n_clobbers(node); ++c) {
		const char *const clobber = get_id_str(clobbers[c]);
		if (strcmp(clobber, "memory") == 0)
			continue;
		if (strcmp(clobber, "cc") == 0) {
391
392
			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);
393
394
395
396
397
			continue;
		}

		const arch_register_t *reg = find_register(clobber);
		assert(reg != NULL); /* otherwise we had a panic earlier */
398
		ARR_APP1(arch_register_req_t const*, out_reqs, reg->single_req);
399
400
	}

401
	return be_make_asm(node, in, in_reqs, out_reqs, operands);
402
403
}

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
/* 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
438
439
440
/**
 * helper function for binop operations
 *
Michael Beck's avatar
Michael Beck committed
441
442
 * @param new_reg  register generation function ptr
 * @param new_imm  immediate generation function ptr
Hannes Rapp's avatar
Hannes Rapp committed
443
 */
Matthias Braun's avatar
Matthias Braun committed
444
445
446
447
448
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
449
{
450
	dbg_info *dbgi  = get_irn_dbg_info(node);
451
	ir_node  *block = be_transform_nodes_block(node);
452
453

	if (flags & MATCH_MODE_NEUTRAL) {
454
455
		op1 = be_skip_downconv(op1, false);
		op2 = be_skip_downconv(op2, false);
456
	}
Matthias Braun's avatar
Matthias Braun committed
457
	ir_mode *mode2 = get_irn_mode(op2);
458
459
	/* we should not see 64bit code */
	assert(get_mode_size_bits(get_irn_mode(op1)) <= 32);
460
	assert(get_mode_size_bits(mode2) <= 32);
Hannes Rapp's avatar
Hannes Rapp committed
461
462

	if (is_imm_encodeable(op2)) {
463
464
		int32_t  const immediate = get_Const_long(op2);
		ir_node *const new_op1   = gen_helper_binop_left(op1, dbgi, block, flags);
465
		return new_imm(dbgi, block, new_op1, NULL, immediate);
Hannes Rapp's avatar
Hannes Rapp committed
466
	}
Matthias Braun's avatar
Matthias Braun committed
467
	ir_node *new_op2 = be_transform_node(op2);
468
	if (! (flags & MATCH_MODE_NEUTRAL) && needs_extension(op2)) {
469
470
		new_op2 = gen_extension(dbgi, block, new_op2, mode2);
	}
Hannes Rapp's avatar
Hannes Rapp committed
471
472

	if ((flags & MATCH_COMMUTATIVE) && is_imm_encodeable(op1)) {
473
		int32_t const immediate = get_Const_long(op1);
474
		return new_imm(dbgi, block, new_op2, NULL, immediate);
Hannes Rapp's avatar
Hannes Rapp committed
475
476
	}

477
	ir_node *new_op1 = gen_helper_binop_left(op1, dbgi, block, flags);
Hannes Rapp's avatar
Hannes Rapp committed
478
479
480
	return new_reg(dbgi, block, new_op1, new_op2);
}

Matthias Braun's avatar
Matthias Braun committed
481
482
483
484
485
486
487
488
489
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
490
491
492
/**
 * helper function for FP binop operations
 */
493
static ir_node *gen_helper_binfpop(ir_node *node, ir_mode *mode,
494
495
496
                                   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
497
{
498
	ir_node  *block   = be_transform_nodes_block(node);
Hannes Rapp's avatar
Hannes Rapp committed
499
	ir_node  *op1     = get_binop_left(node);
500
	ir_node  *new_op1 = be_transform_node(op1);
Hannes Rapp's avatar
Hannes Rapp committed
501
	ir_node  *op2     = get_binop_right(node);
502
	ir_node  *new_op2 = be_transform_node(op2);
Hannes Rapp's avatar
Hannes Rapp committed
503
	dbg_info *dbgi    = get_irn_dbg_info(node);
504
505
506
507
508
509
510
511
512
513
514
515
516
	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
517
518
}

519
520
521
522
523
524
525
526
527
528
529
530
531
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);
532
	ir_node  *block     = be_transform_nodes_block(node);
533
534
535
536
537
538
539
540
541
	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)) {
542
543
		int32_t  const immediate = get_Const_long(op2);
		ir_node *const new_op1   = be_transform_node(op1);
544
545
		return new_binopx_imm(dbgi, block, new_op1, new_flags, NULL, immediate);
	}
Matthias Braun's avatar
Matthias Braun committed
546
	ir_node *new_op2 = be_transform_node(op2);
547
	if ((match_flags & MATCH_COMMUTATIVE) && is_imm_encodeable(op1)) {
548
		int32_t const immediate = get_Const_long(op1);
549
550
		return new_binopx_imm(dbgi, block, new_op2, new_flags, NULL, immediate);
	}
Matthias Braun's avatar
Matthias Braun committed
551
	ir_node *new_op1 = be_transform_node(op1);
552
553
554
555
	return new_binopx_reg(dbgi, block, new_op1, new_op2, new_flags);

}

556
557
static ir_node *get_g0(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
558
	return be_get_Start_proj(irg, &sparc_registers[REG_G0]);
559
560
}

561
562
static ir_node *get_g7(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
563
	return be_get_Start_proj(irg, &sparc_registers[REG_G7]);
564
565
566
567
568
569
570
571
572
573
574
575
576
}

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)
{
577
	if (is_tls_entity(entity)) {
578
579
580
581
582
583
584
585
586
587
588
589
		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;
	}
}

590
typedef struct address_t {
591
592
	ir_node   *ptr;
	ir_node   *ptr2;
593
594
595
596
	ir_entity *entity;
	int32_t    offset;
} address_t;

597
598
599
600
/**
 * Match a load/store address
 */
static void match_address(ir_node *ptr, address_t *address, bool use_ptr2)
601
602
603
604
605
606
607
608
{
	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);
609
			offset += get_Const_long(add_right);
610
611
612
613
614
		}
	}
	/* Note that we don't match sub(x, Const) or chains of adds/subs
	 * because this should all be normalized by now */

615
	/* we only use the entity if we're the only user otherwise we probably
616
617
	 * won't save anything but produce multiple sethi+or combinations with
	 * just different offsets */
Matthias Braun's avatar
Matthias Braun committed
618
619
	ir_node   *ptr2   = NULL;
	ir_entity *entity = NULL;
620
621
	if (is_Address(base) && get_irn_n_edges(base) == 1) {
		ir_entity *sc_entity = get_Address_entity(base);
622
		dbg_info  *dbgi      = get_irn_dbg_info(ptr);
623
		ir_node   *new_block = be_transform_nodes_block(ptr);
624

625
		if (is_tls_entity(sc_entity)) {
626
627
628
629
630
631
632
633
634
635
636
637
			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) {
638
639
		ptr2 = be_transform_node(get_Add_right(base));
		base = be_transform_node(get_Add_left(base));
640
	} else {
641
only_offset:
642
		if (sparc_is_value_imm_encodeable(offset)) {
643
644
645
646
647
648
649
			base = be_transform_node(base);
		} else {
			base   = be_transform_node(ptr);
			offset = 0;
		}
	}

650
651
	address->ptr    = base;
	address->ptr2   = ptr2;
652
653
654
655
	address->entity = entity;
	address->offset = offset;
}

Hannes Rapp's avatar
Hannes Rapp committed
656
657
658
659
660
661
662
663
/**
 * Creates an sparc Add.
 *
 * @param node   FIRM node
 * @return the created sparc Add node
 */
static ir_node *gen_Add(ir_node *node)
{
664
	ir_mode *mode = get_irn_mode(node);
665
	if (mode_is_float(mode)) {
666
667
		return gen_helper_binfpop(node, mode, new_bd_sparc_fadd_s,
		                          new_bd_sparc_fadd_d, new_bd_sparc_fadd_q);
668
	}
Hannes Rapp's avatar
Hannes Rapp committed
669

670
	/* special case: + 0x1000 can be represented as - 0x1000 */
Matthias Braun's avatar
Matthias Braun committed
671
	ir_node *right = get_Add_right(node);
672
	if (is_Const(right)) {
Matthias Braun's avatar
Matthias Braun committed
673
		ir_node   *left = get_Add_left(node);
674
675
		/* is this simple address arithmetic? then we can let the linker do
		 * the calculation. */
676
		if (is_Address(left) && get_irn_n_edges(left) == 1) {
677
			dbg_info *dbgi  = get_irn_dbg_info(node);
678
			ir_node  *block = be_transform_nodes_block(node);
679

680
			/* the value of use_ptr2 shouldn't matter here */
Matthias Braun's avatar
Matthias Braun committed
681
			address_t address;
682
683
684
			match_address(node, &address, false);
			assert(is_sparc_SetHi(address.ptr));
			return new_bd_sparc_Or_imm(dbgi, block, address.ptr,
685
686
687
			                           address.entity, address.offset);
		}

688
		uint32_t const val = get_Const_long(right);
689
690
		if (val == 0x1000) {
			dbg_info *dbgi   = get_irn_dbg_info(node);
691
			ir_node  *block  = be_transform_nodes_block(node);
692
693
			ir_node  *op     = get_Add_left(node);
			ir_node  *new_op = be_transform_node(op);
694
			return new_bd_sparc_Sub_imm(dbgi, block, new_op, NULL, -0x1000);
695
696
697
		}
	}

698
699
	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
700
701
}

702
703
static ir_node *gen_AddCC_t(ir_node *node)
{
yb9976's avatar
yb9976 committed
704
705
706
	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,
707
708
	                             MATCH_COMMUTATIVE | MATCH_MODE_NEUTRAL,
	                             new_bd_sparc_AddCC_reg, new_bd_sparc_AddCC_imm);
709
	arch_set_irn_register_out(new_node, pn_sparc_AddCC_flags, &sparc_registers[REG_PSR]);
yb9976's avatar
yb9976 committed
710
711

	return new_node;
712
713
714
715
}

static ir_node *gen_Proj_AddCC_t(ir_node *node)
{
716
	unsigned pn       = get_Proj_num(node);
717
718
719
720
721
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);

	switch (pn) {
	case pn_sparc_AddCC_t_res:
722
		return be_new_Proj(new_pred, pn_sparc_AddCC_res);
723
	case pn_sparc_AddCC_t_flags:
724
		return be_new_Proj(new_pred, pn_sparc_AddCC_flags);
725
	default:
726
		panic("invalid proj found");
727
728
729
730
731
732
733
734
735
	}
}

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
736
737
738
739
740
741
742
743
/**
 * 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
744
	ir_mode *mode = get_irn_mode(node);
745
	if (mode_is_float(mode)) {
746
747
		return gen_helper_binfpop(node, mode, new_bd_sparc_fsub_s,
		                          new_bd_sparc_fsub_d, new_bd_sparc_fsub_q);
748
	}
Hannes Rapp's avatar
Hannes Rapp committed
749

Matthias Braun's avatar
Matthias Braun committed
750
751
	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
752
753
}

754
755
static ir_node *gen_SubCC_t(ir_node *node)
{
yb9976's avatar
yb9976 committed
756
757
758
	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,
759
	                             new_bd_sparc_SubCC_reg, new_bd_sparc_SubCC_imm);
760
	arch_set_irn_register_out(new_node, pn_sparc_SubCC_flags, &sparc_registers[REG_PSR]);
yb9976's avatar
yb9976 committed
761
762

	return new_node;
763
764
765
766
}

static ir_node *gen_Proj_SubCC_t(ir_node *node)
{
767
	unsigned pn       = get_Proj_num(node);
768
769
770
771
772
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);

	switch (pn) {
	case pn_sparc_SubCC_t_res:
773
		return be_new_Proj(new_pred, pn_sparc_SubCC_res);
774
	case pn_sparc_SubCC_t_flags:
775
		return be_new_Proj(new_pred, pn_sparc_SubCC_flags);
776
	default:
777
		panic("invalid proj found");
778
779
780
781
782
783
784
785
786
	}
}

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

787
788
789
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)
790
791
792
793
794
{
	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,
795
		                          offset, is_frame_entity);
796
797
	} else if (bits == 64) {
		return new_bd_sparc_Ldf_d(dbgi, block, ptr, mem, mode, entity,
798
		                          offset, is_frame_entity);
799
800
801
	} else {
		assert(bits == 128);
		return new_bd_sparc_Ldf_q(dbgi, block, ptr, mem, mode, entity,
802
		                          offset, is_frame_entity);
803
804
805
	}
}

806
807
808
809
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)
810
811
812
813
{
	unsigned bits = get_mode_size_bits(mode);
	assert(mode_is_float(mode));
	if (bits == 32) {
814
		return new_bd_sparc_Stf_s(dbgi, block, value, ptr, mem, mode, entity,
815
		                          offset, is_frame_entity);
816
	} else if (bits == 64) {
817
		return new_bd_sparc_Stf_d(dbgi, block, value, ptr, mem, mode, entity,
818
		                          offset, is_frame_entity);
819
820
	} else {
		assert(bits == 128);
821
		return new_bd_sparc_Stf_q(dbgi, block, value, ptr, mem, mode, entity,
822
		                          offset, is_frame_entity);
823
824
825
	}
}

Hannes Rapp's avatar
Hannes Rapp committed
826
827
828
829
830
831
832
833
/**
 * Transforms a Load.
 *
 * @param node    the ir Load node
 * @return the created sparc Load node
 */
static ir_node *gen_Load(ir_node *node)
{
834
	dbg_info *dbgi     = get_irn_dbg_info(node);
Hannes Rapp's avatar
Hannes Rapp committed
835
	ir_mode  *mode     = get_Load_mode(node);
836
	ir_node  *block    = be_transform_nodes_block(node);
Hannes Rapp's avatar
Hannes Rapp committed
837
838
839
	ir_node  *ptr      = get_Load_ptr(node);
	ir_node  *mem      = get_Load_mem(node);
	ir_node  *new_mem  = be_transform_node(mem);
840

841
	if (get_Load_unaligned(node) == align_non_aligned) {
842
		panic("transformation of unaligned Loads not implemented yet");
843
844
	}

Matthias Braun's avatar
Matthias Braun committed
845
	ir_node  *new_load;
846
	if (mode_is_float(mode)) {
Matthias Braun's avatar
Matthias Braun committed
847
		address_t address;
848
849
		match_address(ptr, &address, false);
		new_load = create_ldf(dbgi, block, address.ptr, new_mem, mode,
850
		                      address.entity, address.offset, false);
851
	} else {
Matthias Braun's avatar
Matthias Braun committed
852
		address_t address;
853
854
855
856
857
858
859
860
861
862
		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);
		}
863
	}
Hannes Rapp's avatar
Hannes Rapp committed
864
865
	set_irn_pinned(new_load, get_irn_pinned(node));

Hannes Rapp's avatar
Hannes Rapp committed
866
867
868
869
870
871
872
873
874
875
876
	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)
{
877
	ir_node  *block    = be_transform_nodes_block(node);
Hannes Rapp's avatar
Hannes Rapp committed
878
879
880
881
882
883
	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);
884

885
	if (get_Store_unaligned(node) == align_non_aligned) {
886
		panic("transformation of unaligned Stores not implemented yet");
887
888
	}

Matthias Braun's avatar
Matthias Braun committed
889
	ir_node  *new_store;
890
	if (mode_is_float(mode)) {
891
		ir_node *new_val = be_transform_node(val);
892
		/* TODO: variants with reg+reg address mode */
Matthias Braun's avatar
Matthias Braun committed
893
		address_t address;
894
895
		match_address(ptr, &address, false);
		new_store = create_stf(dbgi, block, new_val, address.ptr, new_mem,
896
		                       mode, address.entity, address.offset, false);
897
	} else {
898
		val = be_skip_downconv(val, false);
Matthias Braun's avatar
Matthias Braun committed
899
		ir_node *new_val = be_transform_node(val);
900

901
		assert(get_mode_size_bits(mode) <= 32);
Matthias Braun's avatar
Matthias Braun committed
902
		address_t address;
903
904
905
906
907
908
909
910
911
912
		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);
		}
913
914
	}
	set_irn_pinned(new_store, get_irn_pinned(node));
Hannes Rapp's avatar
Hannes Rapp committed
915
916
917
918

	return new_store;
}

919
920
/**
 * Creates an sparc Mul.
921
 * returns the lower 32bits of the 64bit multiply result
922
923
924
 *
 * @return the created sparc Mul node
 */
925
926
927
static ir_node *gen_Mul(ir_node *node)
{
	ir_mode *mode = get_irn_mode(node);
Hannes Rapp's avatar
Hannes Rapp committed
928
	if (mode_is_float(mode)) {
929
930
		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
931
	}
932

933
	return gen_helper_binop(node, MATCH_COMMUTATIVE | MATCH_MODE_NEUTRAL,
934
	                        new_bd_sparc_Mul_reg, new_bd_sparc_Mul_imm);
935
936
937
938
939
940
941
942
}

/**
 * Creates an sparc Mulh.
 * Mulh returns the upper 32bits of a mul instruction
 *
 * @return the created sparc Mulh node
 */
943
944
static ir_node *gen_Mulh(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
945
	ir_mode *mode = get_irn_mode(node);
946
947
948
	if (mode_is_float(mode))
		panic("FP not supported yet");

949
	if (mode_is_signed(mode)) {
950
		return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_SMulh_reg, new_bd_sparc_SMulh_imm);
951
	} else {
952
		return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_UMulh_reg, new_bd_sparc_UMulh_imm);
953
	}
954
}
Hannes Rapp's avatar
Hannes Rapp committed
955

956
957
static ir_node *gen_sign_extension_value(ir_node *node)
{
958
	ir_node *new_block = be_transform_nodes_block(node);
959
960
961
962
963
964
965
	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);
}

966
967
968
969
970
/**
 * Creates an sparc Div.
 *
 * @return the created sparc Div node
 */
971
972
static ir_node *gen_Div(ir_node *node)
{
973
	dbg_info *dbgi      = get_irn_dbg_info(node);
974
	ir_node  *new_block = be_transform_nodes_block(node);
975
976
977
978
	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);
979

980
981
	if (mode_is_float(mode)) {
		return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv_s,
yb9976's avatar
yb9976 committed
982
		                          new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q);
983
984
	}

985
986
	ir_node *mem     = get_Div_mem(node);
	ir_node *new_mem = be_transform_node(mem);
Matthias Braun's avatar
Matthias Braun committed
987
	ir_node *res;
988
	if (mode_is_signed(mode)) {
989
990
991
		ir_node *left_high = gen_sign_extension_value(left);

		if (is_imm_encodeable(right)) {
992
			int32_t const immediate = get_Const_long(right);
993
			res = new_bd_sparc_SDiv_imm(dbgi, new_block, new_mem, left_high, left_low,
994
995
996
			                            NULL, immediate);
		} else {
			ir_node *new_right = be_transform_node(right);
997
			res = new_bd_sparc_SDiv_reg(dbgi, new_block, new_mem, left_high, left_low,
998
999
			                            new_right);
		}
1000
	} else {
1001
1002
		ir_graph *irg       = get_irn_irg(node);
		ir_node  *left_high = get_g0(irg);
1003
		if (is_imm_encodeable(right)) {
1004
			int32_t const immediate = get_Const_long(right);
1005
			res = new_bd_sparc_UDiv_imm(dbgi, new_block, new_mem, left_high, left_low,
1006
1007
1008
			                            NULL, immediate);
		} else {
			ir_node *new_right = be_transform_node(right);
1009
			res = new_bd_sparc_UDiv_reg(dbgi, new_block, new_mem, left_high, left_low,
1010
1011
			                            new_right);
		}
1012
	}
1013

1014
	return res;
1015
1016
}

1017
1018
1019
/**
 * Transforms a Not node.
 *
Michael Beck's avatar
Michael Beck committed
1020
 * @return the created sparc Not node
1021
1022
1023
 */
static ir_node *gen_Not(ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
1024
	ir_node  *op     = get_Not_op(node);
1025
1026
	ir_graph *irg    = get_irn_irg(node);
	ir_node  *zero   = get_g0(irg);
1027
	dbg_info *dbgi   = get_irn_dbg_info(node);
1028
	ir_node  *block  = be_transform_nodes_block(node);
1029
	ir_node  *new_op = be_transform_node(op);
1030

1031
	/* Note: Not(Eor()) is normalize in firm localopts already so
Matthias Braun's avatar
Matthias Braun committed
1032
1033
1034
	 * we don't match it for xnor here */

	/* Not can be represented with xnor 0, n */
1035
	return new_bd_sparc_XNor_reg(dbgi, block, zero, new_op);
1036
1037
}

1038
1039
1040
1041
static ir_node *gen_helper_bitop(ir_node *node,
                                 new_binop_reg_func new_reg,
                                 new_binop_imm_func new_imm,
                                 new_binop_reg_func new_not_reg,
1042
1043
                                 new_binop_imm_func new_not_imm,
                                 match_flags_t flags)
1044
{
1045
1046
1047
	ir_node *op1 = get_binop_left(node);
	ir_node *op2 = get_binop_right(node);
	if (is_Not(op1)) {