sparc_emitter.c 40 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   emit assembler for a backend graph
Matthias Braun's avatar
Matthias Braun committed
9
 * @author  Hannes Rapp, Matthias Braun
Hannes Rapp's avatar
Hannes Rapp committed
10
 */
11
#include <inttypes.h>
Hannes Rapp's avatar
Hannes Rapp committed
12

13
#include "beasm.h"
14
#include "beblocksched.h"
15
#include "bediagnostic.h"
16
17
#include "beemithlp.h"
#include "beemitter.h"
18
19
20
21
22
23
#include "begnuas.h"
#include "beirg.h"
#include "benode.h"
#include "bepeephole.h"
#include "besched.h"
#include "bestack.h"
24
#include "beutil.h"
Hannes Rapp's avatar
Hannes Rapp committed
25
#include "debug.h"
26
27
28
29
#include "execfreq_t.h"
#include "gen_sparc_emitter.h"
#include "gen_sparc_regalloc_if.h"
#include "heights.h"
30
#include "iredges_t.h"
Hannes Rapp's avatar
Hannes Rapp committed
31
#include "irgwalk.h"
Matthias Braun's avatar
Matthias Braun committed
32
#include "panic.h"
33
#include "pmap.h"
34
#include "sparc_bearch_t.h"
Hannes Rapp's avatar
Hannes Rapp committed
35
36
#include "sparc_emitter.h"
#include "sparc_new_nodes.h"
37
#include "util.h"
Hannes Rapp's avatar
Hannes Rapp committed
38

Hannes Rapp's avatar
Hannes Rapp committed
39
40
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

41
42
43
static ir_heights_t *heights;
static unsigned     *delay_slot_fillers;
static pmap         *delay_slots;
44

45
46
static bool emitting_delay_slot;

47
static void sparc_emit_immediate(int32_t value, ir_entity *entity)
Hannes Rapp's avatar
Hannes Rapp committed
48
{
49
	if (entity == NULL) {
50
		be_emit_irprintf("%"PRId32, value);
51
	} else {
52
		if (is_tls_entity(entity)) {
53
54
55
56
			be_emit_cstring("%tle_lox10(");
		} else {
			be_emit_cstring("%lo(");
		}
57
		be_gas_emit_entity(entity);
58
		if (value != 0) {
59
			be_emit_irprintf("%+"PRId32, value);
60
61
62
		}
		be_emit_char(')');
	}
63
64
}

65
static void sparc_emit_high_immediate(ir_node const *node)
66
{
67
68
69
70
71
	const sparc_attr_t *attr   = get_sparc_attr_const(node);
	ir_entity          *entity = attr->immediate_value_entity;

	if (entity == NULL) {
		uint32_t value = (uint32_t) attr->immediate_value;
72
		be_emit_irprintf("%%hi(0x%X)", value);
73
	} else {
74
		if (is_tls_entity(entity)) {
75
76
77
78
			be_emit_cstring("%tle_hix22(");
		} else {
			be_emit_cstring("%hi(");
		}
79
80
		be_gas_emit_entity(entity);
		if (attr->immediate_value != 0) {
81
			be_emit_irprintf("%+"PRId32, attr->immediate_value);
82
		}
83
		be_emit_char(')');
84
	}
Hannes Rapp's avatar
Hannes Rapp committed
85
86
}

87
static void sparc_emit_register(const arch_register_t *const reg)
Hannes Rapp's avatar
Hannes Rapp committed
88
89
{
	be_emit_char('%');
90
	be_emit_string(reg->name);
Hannes Rapp's avatar
Hannes Rapp committed
91
92
}

93
94
95
96
97
98
static void sparc_emit_source_register(ir_node const *node, int const pos)
{
	const arch_register_t *reg = arch_get_irn_register_in(node, pos);
	sparc_emit_register(reg);
}

99
static void sparc_emit_dest_register(ir_node const *const node, int const pos)
Hannes Rapp's avatar
Hannes Rapp committed
100
{
Matthias Braun's avatar
Matthias Braun committed
101
	const arch_register_t *reg = arch_get_irn_register_out(node, pos);
102
	sparc_emit_register(reg);
Hannes Rapp's avatar
Hannes Rapp committed
103
104
}

105
106
107
/**
 * emit SP offset
 */
108
static void sparc_emit_offset(const ir_node *node, int offset_node_pos)
Hannes Rapp's avatar
Hannes Rapp committed
109
{
110
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
111

112
113
114
115
116
117
118
	if (attr->is_reg_reg) {
		assert(!attr->is_frame_entity);
		assert(attr->base.immediate_value == 0);
		assert(attr->base.immediate_value_entity == NULL);
		be_emit_char('+');
		sparc_emit_source_register(node, offset_node_pos);
	} else if (attr->is_frame_entity) {
119
120
		int32_t offset = attr->base.immediate_value;
		if (offset != 0) {
121
			assert(sparc_is_value_imm_encodeable(offset));
122
			be_emit_irprintf("%+"PRId32, offset);
123
		}
124
	} else if (attr->base.immediate_value != 0
yb9976's avatar
yb9976 committed
125
	           || attr->base.immediate_value_entity != NULL) {
126
		be_emit_char('+');
127
128
		sparc_emit_immediate(attr->base.immediate_value,
		                     attr->base.immediate_value_entity);
129
	}
Hannes Rapp's avatar
Hannes Rapp committed
130
131
132
}

/**
133
 *  Emit load mode
Hannes Rapp's avatar
Hannes Rapp committed
134
 */
135
static void sparc_emit_load_mode(ir_node const *const node)
Hannes Rapp's avatar
Hannes Rapp committed
136
137
{
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
138
139
140
141
	ir_mode *mode      = attr->load_store_mode;
	int      bits      = get_mode_size_bits(mode);
	bool     is_signed = mode_is_signed(mode);

142
143
144
145
146
147
148
	switch (bits) {
	case   8: be_emit_string(is_signed ? "sb" : "ub"); break;
	case  16: be_emit_string(is_signed ? "sh" : "uh"); break;
	case  32: break;
	case  64: be_emit_char('d'); break;
	case 128: be_emit_char('q'); break;
	default:  panic("invalid load/store mode %+F", mode);
149
	}
Hannes Rapp's avatar
Hannes Rapp committed
150
151
152
153
154
}

/**
 * Emit store mode char
 */
155
static void sparc_emit_store_mode(ir_node const *const node)
Hannes Rapp's avatar
Hannes Rapp committed
156
157
{
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
158
159
160
	ir_mode *mode      = attr->load_store_mode;
	int      bits      = get_mode_size_bits(mode);

161
162
163
164
165
166
167
	switch (bits) {
	case   8: be_emit_char('b'); break;
	case  16: be_emit_char('h'); break;
	case  32: break;
	case  64: be_emit_char('d'); break;
	case 128: be_emit_char('q'); break;
	default:  panic("invalid load/store mode %+F", mode);
168
	}
Hannes Rapp's avatar
Hannes Rapp committed
169
170
}

171
static void emit_fp_suffix(const ir_mode *mode)
Hannes Rapp's avatar
Hannes Rapp committed
172
{
173
	assert(mode_is_float(mode));
174
175
176
177
178
	switch (get_mode_size_bits(mode)) {
	case  32: be_emit_char('s'); break;
	case  64: be_emit_char('d'); break;
	case 128: be_emit_char('q'); break;
	default:  panic("invalid FP mode");
179
	}
Hannes Rapp's avatar
Hannes Rapp committed
180
181
}

Hannes Rapp's avatar
Hannes Rapp committed
182
183
184
185
186
/**
 * Returns the target label for a control flow node.
 */
static void sparc_emit_cfop_target(const ir_node *node)
{
187
	ir_node *block = be_emit_get_cfop_target(node);
188
	be_gas_emit_block_name(block);
Hannes Rapp's avatar
Hannes Rapp committed
189
190
}

191
192
193
194
195
196
197
198
199
/**
 * returns true if a sparc_call calls a register and not an immediate
 */
static bool is_sparc_reg_call(const ir_node *node)
{
	const sparc_attr_t *attr = get_sparc_attr_const(node);
	return attr->immediate_value_entity == NULL;
}

200
201
static int get_sparc_Call_dest_addr_pos(const ir_node *node)
{
202
	assert(is_sparc_reg_call(node));
203
204
205
206
207
	return get_irn_arity(node)-1;
}

static bool ba_is_fallthrough(const ir_node *node)
{
208
209
210
	ir_node *const block  = get_nodes_block(node);
	ir_node *const target = be_emit_get_cfop_target(node);
	return be_emit_get_prev_block(target) == block;
211
212
213
214
215
216
}

static bool is_no_instruction(const ir_node *node)
{
	/* copies are nops if src_reg == dest_reg */
	if (be_is_Copy(node) || be_is_CopyKeep(node)) {
Matthias Braun's avatar
Matthias Braun committed
217
218
		const arch_register_t *src_reg  = arch_get_irn_register_in(node, 0);
		const arch_register_t *dest_reg = arch_get_irn_register_out(node, 0);
219
220
221
222

		if (src_reg == dest_reg)
			return true;
	}
223
224
	if (be_is_IncSP(node) && be_get_IncSP_offset(node) == 0)
		return true;
225
226
227
228
	/* Ba is not emitted if it is a simple fallthrough */
	if (is_sparc_Ba(node) && ba_is_fallthrough(node))
		return true;

Christoph Mallon's avatar
Christoph Mallon committed
229
	return be_is_Keep(node) || be_is_Start(node) || is_Phi(node);
230
231
232
233
}

static bool has_delay_slot(const ir_node *node)
{
234
235
236
	if (is_sparc_Ba(node)) {
		return !ba_is_fallthrough(node);
	}
237

238
	return arch_get_irn_flags(node) & sparc_arch_irn_flag_has_delay_slot;
239
240
241
242
243
244
245
246
247
248
249
250
251
}

/** returns true if the emitter for this sparc node can produce more than one
 * actual sparc instruction.
 * Usually it is a bad sign if we have to add instructions here. We should
 * rather try to get them lowered down. So we can actually put them into
 * delay slots and make them more accessible to the scheduler.
 */
static bool emits_multiple_instructions(const ir_node *node)
{
	if (has_delay_slot(node))
		return true;

252
	if (is_sparc_Call(node))
Matthias Braun's avatar
Matthias Braun committed
253
		return arch_get_irn_flags(node) & sparc_arch_irn_flag_aggregate_return;
254

255
256
	return is_sparc_SMulh(node) || is_sparc_UMulh(node)
		|| is_sparc_SDiv(node) || is_sparc_UDiv(node)
Manuel Mohr's avatar
Manuel Mohr committed
257
		|| be_is_MemPerm(node) || be_is_Perm(node)
258
		|| is_sparc_SubSP(node) || be_is_Asm(node);
259
260
}

261
static bool uses_reg(const ir_node *node, unsigned reg_index, unsigned width)
262
263
{
	int arity = get_irn_arity(node);
Matthias Braun's avatar
Matthias Braun committed
264
	for (int i = 0; i < arity; ++i) {
265
266
267
268
269
270
		const arch_register_t     *in_reg = arch_get_irn_register_in(node, i);
		const arch_register_req_t *in_req = arch_get_irn_register_req_in(node, i);
		if (in_reg == NULL)
			continue;
		if (reg_index < (unsigned)in_reg->global_index + in_req->width
			&& reg_index + width > in_reg->global_index)
271
272
273
274
275
			return true;
	}
	return false;
}

276
static bool writes_reg(const ir_node *node, unsigned reg_index, unsigned width)
277
{
278
	be_foreach_out(node, o) {
Matthias Braun's avatar
Matthias Braun committed
279
		const arch_register_t *out_reg = arch_get_irn_register_out(node, o);
280
281
282
283
284
		if (out_reg == NULL)
			continue;
		const arch_register_req_t *out_req = arch_get_irn_register_req_out(node, o);
		if (reg_index < (unsigned)out_reg->global_index + out_req->width
			&& reg_index + width > out_reg->global_index)
285
286
287
288
289
			return true;
	}
	return false;
}

290
291
292
293
294
295
296
297
static bool is_legal_delay_slot_filler(const ir_node *node)
{
	if (is_no_instruction(node))
		return false;
	if (emits_multiple_instructions(node))
		return false;
	if (rbitset_is_set(delay_slot_fillers, get_irn_idx(node)))
		return false;
298
299
	if (is_sparc_Save(node))
		return false;
300
301
302
303
	return true;
}

static bool can_move_down_into_delayslot(const ir_node *node, const ir_node *to)
304
{
305
306
307
	if (!is_legal_delay_slot_filler(node))
		return false;

308
	if (!be_can_move_down(heights, node, to, sparc_get_frame_entity))
309
310
311
312
		return false;

	if (is_sparc_Call(to)) {
		ir_node *check;
313
		/** all inputs are used after the delay slot so, we're fine */
314
315
316
317
318
319
		if (!is_sparc_reg_call(to))
			return true;

		check = get_irn_n(to, get_sparc_Call_dest_addr_pos(to));
		if (skip_Proj(check) == node)
			return false;
320

321
322
323
		/* the Call also destroys the value of %o7, but since this is
		 * currently marked as ignore register in the backend, it
		 * should never be used by the instruction in the delay slot. */
324
		if (uses_reg(node, REG_O7, 1))
325
326
327
328
329
			return false;
		return true;
	} else if (is_sparc_Return(to)) {
		/* return uses the value of %o7, all other values are not
		 * immediately used */
330
		if (writes_reg(node, REG_O7, 1))
331
332
333
334
			return false;
		return true;
	} else {
		/* the node must not use our computed values */
335
		foreach_irn_in(to, i, in) {
336
337
338
339
			if (skip_Proj(in) == node)
				return false;
		}
		return true;
340
341
342
	}
}

343
344
345
346
347
348
static bool can_move_up_into_delayslot(const ir_node *node, const ir_node *to)
{
	if (!be_can_move_up(heights, node, to))
		return false;

	/* node must not use any results of 'to' */
349
	foreach_irn_in(node, i, in) {
350
351
352
353
354
355
356
		ir_node *skipped = skip_Proj(in);
		if (skipped == to)
			return false;
	}

	/* register window cycling effects at Restore aren't correctly represented
	 * in the graph yet so we need this exception here */
357
	if (is_sparc_Restore(node) || is_sparc_RestoreZero(node)) {
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
		return false;
	} else if (is_sparc_Call(to)) {
		/* node must not overwrite any of the inputs of the call,
		 * (except for the dest_addr) */
		int dest_addr_pos = is_sparc_reg_call(to)
			? get_sparc_Call_dest_addr_pos(to) : -1;

		int call_arity = get_irn_arity(to);
		for (int i = 0; i < call_arity; ++i) {
			if (i == dest_addr_pos)
				continue;
			const arch_register_t *reg = arch_get_irn_register_in(to, i);
			if (reg == NULL)
				continue;
			const arch_register_req_t *req = arch_get_irn_register_req_in(to, i);
			if (writes_reg(node, reg->global_index, req->width))
				return false;
		}

		/* node must not write to one of the call outputs */
378
		be_foreach_out(to, o) {
379
380
381
382
383
384
385
386
387
388
			const arch_register_t *reg = arch_get_irn_register_out(to, o);
			if (reg == NULL)
				continue;
			const arch_register_req_t *req = arch_get_irn_register_req_out(to, o);
			if (writes_reg(node, reg->global_index, req->width))
				return false;
		}
	} else if (is_sparc_SDiv(to) || is_sparc_UDiv(to)) {
		/* node will be inserted between wr and div so it must not overwrite
		 * anything except the wr input */
Matthias Braun's avatar
Matthias Braun committed
389
		for (int i = 0, arity = get_irn_arity(to); i < arity; ++i) {
390
			assert((unsigned)n_sparc_SDiv_dividend_high == (unsigned)n_sparc_UDiv_dividend_high);
391
392
393
394
395
396
397
398
399
			if (i == n_sparc_SDiv_dividend_high)
				continue;
			const arch_register_t *reg = arch_get_irn_register_in(to, i);
			if (reg == NULL)
				continue;
			const arch_register_req_t *req = arch_get_irn_register_req_in(to, i);
			if (writes_reg(node, reg->global_index, req->width))
				return false;
		}
yb9976's avatar
yb9976 committed
400
	}
401
402
403
404
405
406
407
408
	return true;
}

static void optimize_fallthrough(ir_node *node)
{
	ir_node *proj_true  = NULL;
	ir_node *proj_false = NULL;

409
410
	assert((unsigned)pn_sparc_Bicc_false == (unsigned)pn_sparc_fbfcc_false);
	assert((unsigned)pn_sparc_Bicc_true  == (unsigned)pn_sparc_fbfcc_true);
411
412
	foreach_out_edge(node, edge) {
		ir_node *proj = get_edge_src_irn(edge);
413
414
		unsigned pn   = get_Proj_num(proj);
		if (pn == pn_sparc_Bicc_true) {
415
416
			proj_true = proj;
		} else {
417
			assert(pn == pn_sparc_Bicc_false);
418
419
420
421
422
			proj_false = proj;
		}
	}
	assert(proj_true != NULL && proj_false != NULL);

423
424
	ir_node const *const block       = get_nodes_block(node);
	ir_node const *const true_target = be_emit_get_cfop_target(proj_true);
425

426
	if (be_emit_get_prev_block(true_target) == block) {
427
		/* exchange both proj destinations so the second one can be omitted */
428
429
		set_Proj_num(proj_true,  pn_sparc_Bicc_false);
		set_Proj_num(proj_false, pn_sparc_Bicc_true);
430
431
432
433
434
435

		sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr(node);
		attr->relation = get_negated_relation(attr->relation);
	}
}

Hannes Rapp's avatar
Hannes Rapp committed
436
/**
437
 * search for an instruction that can fill the delay slot of @p node
Hannes Rapp's avatar
Hannes Rapp committed
438
 */
439
static ir_node *pick_delay_slot_for(ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
440
{
441
	static const unsigned PICK_DELAY_SLOT_MAX_DISTANCE = 10;
442
443
	assert(has_delay_slot(node));

444
445
446
	if (is_sparc_Bicc(node) || is_sparc_fbfcc(node)) {
		optimize_fallthrough(node);
	}
447

448
	unsigned tries = 0;
449
	sched_foreach_reverse_before(node, schedpoint) {
450
451
		if (has_delay_slot(schedpoint))
			break;
452
453
		if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE)
			break;
454

455
		if (!can_move_down_into_delayslot(schedpoint, node))
456
457
			continue;

458
459
460
461
462
463
		/* found something */
		return schedpoint;
	}

	/* search after the current position */
	tries = 0;
464
	sched_foreach_after(node, schedpoint) {
465
466
		if (has_delay_slot(schedpoint))
			break;
467
468
		if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE)
			break;
469
		if (!is_legal_delay_slot_filler(schedpoint))
470
			continue;
471
		if (!can_move_up_into_delayslot(schedpoint, node))
472
473
474
475
476
477
			continue;

		/* found something */
		return schedpoint;
	}

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
	/* look in successor blocks */
	ir_node *block = get_nodes_block(node);
	/* TODO: sort succs by execution frequency */
	foreach_block_succ(block, edge) {
		ir_node *succ = get_edge_src_irn(edge);
		/* we can't easily move up stuff from blocks with multiple predecessors
		 * since the instruction is lacking for the other preds then.
		 * (We also don't have to do any phi translation) */
		if (get_Block_n_cfgpreds(succ) > 1)
			continue;

		tries = 0;
		sched_foreach(succ, schedpoint) {
			if (has_delay_slot(schedpoint))
				break;
493
			/* can't move pinned nodes across blocks */
Matthias Braun's avatar
Matthias Braun committed
494
			if (get_irn_pinned(schedpoint))
495
496
497
498
499
500
501
502
503
504
505
				continue;
			/* restore doesn't model register window switching correctly,
			 * so it appears like we could move it, which is not true */
			if (is_sparc_Restore(schedpoint)
			    || is_sparc_RestoreZero(schedpoint))
				continue;
			if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE)
				break;
			if (!is_legal_delay_slot_filler(schedpoint))
				continue;
			if (can_move_up_into_delayslot(schedpoint, node)) {
506
				/* it's fine to move the insn across blocks */
507
508
509
				return schedpoint;
			} else if (is_sparc_Bicc(node) || is_sparc_fbfcc(node)) {
				ir_node *proj = get_Block_cfgpred(succ, 0);
510
				unsigned nr   = get_Proj_num(proj);
511
512
513
514
515
516
517
518
519
520
521
				if ((nr == pn_sparc_Bicc_true || nr == pn_sparc_fbfcc_true)
					&& be_can_move_up(heights, schedpoint, succ)) {
					/* we can use it with the annul flag */
					sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr(node);
					attr->annul_delay_slot = true;
					return schedpoint;
				}
			}
		}
	}

522
	return NULL;
Hannes Rapp's avatar
Hannes Rapp committed
523
524
}

525
526
void sparc_emitf(ir_node const *const node, char const *fmt, ...)
{
527
	BE_EMITF(node, fmt, ap, emitting_delay_slot) {
528
529
530
531
532
533
534
		bool plus = false;
		if (*fmt == '+') {
			plus = true;
			++fmt;
		}

		switch (*fmt++) {
535
536
537
538
539
540
541
542
543
		case 'A': {
			const sparc_jmp_cond_attr_t *attr
				= get_sparc_jmp_cond_attr_const(node);
			if (attr->annul_delay_slot) {
				be_emit_cstring(",a");
			}
			break;
		}

544
		case 'D':
545
			if (!is_digit(*fmt))
546
547
548
549
550
551
552
553
				goto unknown;
			sparc_emit_dest_register(node, *fmt++ - '0');
			break;

		case 'E': {
			sparc_attr_t const *const attr = get_sparc_attr_const(node);
			be_gas_emit_entity(attr->immediate_value_entity);
			if (attr->immediate_value != 0) {
554
				be_emit_irprintf(plus ? "%+"PRId32 : "%"PRId32, attr->immediate_value);
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
			}
			break;
		}

		case 'F': {
			ir_mode *mode;
			switch (*fmt++) {
			case 'D': mode = get_sparc_fp_conv_attr_const(node)->dest_mode; break;
			case 'M': mode = get_sparc_fp_attr_const(node)->fp_mode;        break;
			case 'S': mode = get_sparc_fp_conv_attr_const(node)->src_mode;  break;
			default:  goto unknown;
			}
			emit_fp_suffix(mode);
			break;
		}

		case 'H':
			sparc_emit_high_immediate(node);
			break;

575
576
577
		case 'L': {
			ir_node *n = va_arg(ap, ir_node*);
			sparc_emit_cfop_target(n);
578
			break;
579
		}
580
581
582
583
584
585
586
587
588

		case 'M':
			switch (*fmt++) {
			case 'L': sparc_emit_load_mode(node);  break;
			case 'S': sparc_emit_store_mode(node); break;
			default:  goto unknown;
			}
			break;

589
590
591
592
		case 'O':
			if (!is_digit(*fmt))
				goto unknown;
			unsigned const pos = *fmt++ - '0';
593
594
			if (!plus)
				be_emit_char('[');
595
596
			sparc_emit_source_register(node, pos);
			sparc_emit_offset(node, pos + 1);
597
598
			if (!plus)
				be_emit_char(']');
599
600
			break;

601
602
603
		case 'R': {
			arch_register_t const *const reg = va_arg(ap, const arch_register_t*);
			be_emit_char('%');
604
			be_emit_string(reg->name);
605
606
607
608
609
610
611
612
613
			break;
		}

		case 'S': {
			bool imm = false;
			if (*fmt == 'I') {
				imm = true;
				++fmt;
			}
614
			if (!is_digit(*fmt))
615
616
617
				goto unknown;
			unsigned const pos = *fmt++ - '0';
			if (imm && arch_get_irn_flags(node) & (arch_irn_flags_t)sparc_arch_irn_flag_immediate_form) {
618
619
620
				const sparc_attr_t *const attr = get_sparc_attr_const(node);
				sparc_emit_immediate(attr->immediate_value,
				                     attr->immediate_value_entity);
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
			} else {
				sparc_emit_source_register(node, pos);
			}
			break;
		}

		case 'd': {
			int const num = va_arg(ap, int);
			be_emit_irprintf(plus ? "%+d" : "%d", num);
			break;
		}

		case 's': {
			char const *const str = va_arg(ap, char const*);
			be_emit_string(str);
			break;
		}

		case 'u': {
			unsigned const num = va_arg(ap, unsigned);
			be_emit_irprintf(plus ? "%+u" : "%u", num);
			break;
		}

645
646
647
648
649
650
		case 'X': {
			unsigned const num = va_arg(ap, unsigned);
			be_emit_irprintf("%X", num);
			break;
		}

651
652
653
654
655
656
657
		default:
unknown:
			panic("unknown format conversion in sparc_emitf()");
		}
	}
}

Hannes Rapp's avatar
Hannes Rapp committed
658
659
660
661
662
/**
 * Emits code for stack space management
 */
static void emit_be_IncSP(const ir_node *irn)
{
663
	int offset = be_get_IncSP_offset(irn);
Hannes Rapp's avatar
Hannes Rapp committed
664

665
	if (offset == 0)
666
		return;
Hannes Rapp's avatar
Hannes Rapp committed
667

668
	/* SPARC stack grows downwards */
669
670
	char const *const insn = offset > 0 ? offset = -offset, "add" : "sub";
	sparc_emitf(irn, "%s %S0, %d, %D0", insn, offset);
671
}
672

673
static void emit_sparc_asm_operand(ir_node const *const node, char const modifier, unsigned const pos)
674
{
675
	bool address_only = false;
676
	bool zero_as_g0   = false;
677
678
679
680
681
682
683
684
685
	switch (modifier) {
	case '\0':
		break;

	case 'f':
	case 'm':
		address_only = true;
		break;

686
687
688
689
	case 'r':
		zero_as_g0 = true;
		break;

690
	default:
691
692
		be_errorf(node, "asm contains unknown modifier '%c'", modifier);
		return;
693
694
	}

695
696
	be_asm_attr_t       const *const attr = get_be_asm_attr_const(node);
	sparc_asm_operand_t const *const op   = &((sparc_asm_operand_t const*)attr->operands)[pos];
697
	switch (op->kind) {
698
	case ASM_OPERAND_IMMEDIATE:
699
700
701
702
		if (zero_as_g0 && op->immediate_value == 0 && !op->immediate_value_entity)
			sparc_emit_register(&sparc_registers[REG_G0]);
		else
			sparc_emit_immediate(op->immediate_value, op->immediate_value_entity);
703
704
		return;

705
	case ASM_OPERAND_INPUT_VALUE:
706
707
708
		sparc_emit_register(arch_get_irn_register_in(node, op->pos));
		return;

709
	case ASM_OPERAND_OUTPUT_VALUE:
710
711
		sparc_emit_register(arch_get_irn_register_out(node, op->pos));
		return;
712
713

	case ASM_OPERAND_MEMORY:
714
715
		if (!address_only)
			be_emit_char('[');
716
		sparc_emit_register(arch_get_irn_register_in(node, op->pos));
717
718
		if (!address_only)
			be_emit_char(']');
719
		return;
720
	}
721
	panic("invalid asm operand kind");
722
723
}

724
725
static void emit_sparc_ASM(const ir_node *node)
{
726
	be_emit_asm(node, emit_sparc_asm_operand);
727
728
}

Manuel Mohr's avatar
Manuel Mohr committed
729
730
731
732
733
/**
 * Emits code for stack space management.
 */
static void emit_sparc_SubSP(const ir_node *irn)
{
734
735
	sparc_emitf(irn, "sub %S0, %SI1, %D0");
	sparc_emitf(irn, "add %S0, %u, %D1", SPARC_MIN_STACKSIZE);
Hannes Rapp's avatar
Hannes Rapp committed
736
}
737

738
static void fill_delay_slot(const ir_node *node)
739
{
740
	emitting_delay_slot = true;
741
742
743
744
	const ir_node *filler = pmap_get(ir_node, delay_slots, node);
	if (filler != NULL) {
		assert(!is_no_instruction(filler));
		assert(!emits_multiple_instructions(filler));
745
		be_emit_node(filler);
746
	} else {
747
		sparc_emitf(NULL, "nop");
748
	}
749
	emitting_delay_slot = false;
750
751
}

752
static void emit_sparc_Div(const ir_node *node, char const *const insn)
753
{
754
	sparc_emitf(node, "wr %S1, 0, %%y");
755

Matthias Braun's avatar
Matthias Braun committed
756
757
758
759
	/* TODO: we should specify number of delayslots in an architecture
	 * specification */
	unsigned wry_delay_count = 3;
	for (unsigned i = 0; i < wry_delay_count; ++i) {
760
761
762
763
764
765
766
		if (i == 0) {
			fill_delay_slot(node);
		} else {
			emitting_delay_slot = true;
			sparc_emitf(NULL, "nop");
			emitting_delay_slot = false;
		}
767
768
	}

769
	sparc_emitf(node, "%s %S2, %SI3, %D0", insn);
770
771
772
773
}

static void emit_sparc_SDiv(const ir_node *node)
{
774
	emit_sparc_Div(node, "sdiv");
775
776
777
778
}

static void emit_sparc_UDiv(const ir_node *node)
{
779
	emit_sparc_Div(node, "udiv");
780
781
}

782
static void emit_sparc_Call(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
783
{
784
785
	if (is_sparc_reg_call(node)) {
		int dest_addr = get_sparc_Call_dest_addr_pos(node);
786
		sparc_emitf(node, "call %R", arch_get_irn_register_in(node, dest_addr));
787
	} else {
788
		sparc_emitf(node, "call %E, 0");
Hannes Rapp's avatar
Hannes Rapp committed
789
	}
790

791
	fill_delay_slot(node);
792

Matthias Braun's avatar
Matthias Braun committed
793
	if (arch_get_irn_flags(node) & sparc_arch_irn_flag_aggregate_return) {
794
		sparc_emitf(NULL, "unimp 8");
795
	}
Hannes Rapp's avatar
Hannes Rapp committed
796
797
}

798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
static void emit_sparc_Cas(const ir_node *node)
{
	/* except for some patched gaisler binutils nobody understands cas
	 * in v8/leon mode, so we encode the cas in binary form */
#if 0
	sparc_emitf(node, "cas [%S0], %S1, %S2");
#else
	const arch_register_t *reg_new
		= arch_get_irn_register_in(node, n_sparc_Cas_new);
	const arch_register_t *reg_ptr
		= arch_get_irn_register_in(node, n_sparc_Cas_ptr);
	const arch_register_t *reg_old
		= arch_get_irn_register_in(node, n_sparc_Cas_old);
	uint32_t encoding = 3u<<30 | (reg_new->encoding<<25) | (0x3C << 19)
	       | (reg_ptr->encoding<<14) | (0x80<<5) | (reg_old->encoding);
	sparc_emitf(node, ".long 0x%X  /* cas [%S0], %S1, %S2", encoding);
#endif
}

817
818
static void emit_be_Perm(const ir_node *irn)
{
819
820
	arch_register_req_t const *const req = arch_get_irn_register_req_out(irn, 0);
	if (req->cls == &sparc_reg_classes[CLASS_sparc_fp]) {
821
822
823
		arch_register_t const *r0 = arch_get_irn_register_out(irn, 0);
		arch_register_t const *r1 = arch_get_irn_register_out(irn, 1);
		for (unsigned i = 0, width = req->width; i < width; ++r0, ++r1, ++i) {
Matthias Braun's avatar
Matthias Braun committed
824
825
826
827
			sparc_emitf(irn, "fmovs %R, %%f31", r0);
			sparc_emitf(irn, "fmovs %R, %R", r1, r0);
			sparc_emitf(irn, "fmovs %%f31, %R", r1);
		}
828
	} else if (req->cls == &sparc_reg_classes[CLASS_sparc_gp]) {
829
830
831
		sparc_emitf(irn, "xor %D1, %D0, %D0");
		sparc_emitf(irn, "xor %D1, %D0, %D1");
		sparc_emitf(irn, "xor %D1, %D0, %D0");
832
833
	} else {
		panic("unexpected register class");
Matthias Braun's avatar
Matthias Braun committed
834
	}
835
836
}

837
static unsigned get_aligned_sp_change(const unsigned num_regs)
838
{
839
	const unsigned bytes = num_regs * SPARC_REGISTER_SIZE;
840
	return round_up2(bytes, SPARC_STACK_ALIGNMENT);
841
842
}

843
844
845
/* Spill register l0 or both l0 and l1, depending on n_spilled and n_to_spill.*/
static void memperm_emit_spill_registers(const ir_node *node, int n_spilled,
                                         int n_to_spill)
Hannes Rapp's avatar
Hannes Rapp committed
846
{
847
	assert(n_spilled < n_to_spill);
848

849
850
851
852
853
854
	if (n_spilled == 0) {
		/* We always reserve stack space for two registers because during copy
		 * processing we don't know yet if we also need to handle a cycle which
		 * needs two registers.  More complicated code in emit_MemPerm would
		 * prevent wasting SPARC_REGISTER_SIZE bytes of stack space but
		 * it is not worth the worse readability of emit_MemPerm. */
Hannes Rapp's avatar
Hannes Rapp committed
855

856
		const unsigned sp_change = get_aligned_sp_change(2);
857
858
		sparc_emitf(node, "sub %%sp, %u, %%sp", sp_change);
		sparc_emitf(node, "st %%l0, [%%sp%+d]", SPARC_MIN_STACKSIZE);
859
	}
Hannes Rapp's avatar
Hannes Rapp committed
860

861
	if (n_to_spill == 2) {
862
		sparc_emitf(node, "st %%l1, [%%sp%+d]", SPARC_MIN_STACKSIZE + SPARC_REGISTER_SIZE);
863
864
	}
}
865

866
867
868
869
/* Restore register l0 or both l0 and l1, depending on n_spilled. */
static void memperm_emit_restore_registers(const ir_node *node, int n_spilled)
{
	if (n_spilled == 2) {
870
		sparc_emitf(node, "ld [%%sp%+d], %%l1", SPARC_MIN_STACKSIZE + SPARC_REGISTER_SIZE);
871
	}
Hannes Rapp's avatar
Hannes Rapp committed
872

873
	sparc_emitf(node, "ld [%%sp%+d], %%l0", SPARC_MIN_STACKSIZE);
874
	const unsigned sp_change = get_aligned_sp_change(2);
875
	sparc_emitf(node, "add %%sp, %u, %%sp", sp_change);
876
877
878
}

static void memperm_emit_copy(const ir_node *node, ir_entity *in_ent,
Matthias Braun's avatar
Matthias Braun committed
879
                              ir_entity *out_ent, int ent_offset)
880
{
881
882
	ir_graph   *irg     = get_irn_irg(node);
	const char *reg     = sparc_get_irg_data(irg)->omit_fp ? "sp" : "fp";
Matthias Braun's avatar
Matthias Braun committed
883
884
	const int   off_in  = get_entity_offset(in_ent) + ent_offset;
	const int   off_out = get_entity_offset(out_ent) + ent_offset;
885

886
887
	sparc_emitf(node, "ld [%%%s%+d], %%l0", reg, off_in);
	sparc_emitf(node, "st %%l0, [%%%s%+d]", reg, off_out);
888
889
890
}

static void memperm_emit_swap(const ir_node *node, ir_entity *ent1,
Matthias Braun's avatar
Matthias Braun committed
891
                              ir_entity *ent2, int ent_offset)
892
{
893
894
	ir_graph   *irg  = get_irn_irg(node);
	const char *reg  = sparc_get_irg_data(irg)->omit_fp ? "sp" : "fp";
Matthias Braun's avatar
Matthias Braun committed
895
896
	const int   off1 = get_entity_offset(ent1) + ent_offset;
	const int   off2 = get_entity_offset(ent2) + ent_offset;
897
898
899
900
901

	sparc_emitf(node, "ld [%%%s%+d], %%l0", reg, off1);
	sparc_emitf(node, "ld [%%%s%+d], %%l1", reg, off2);
	sparc_emitf(node, "st %%l0, [%%%s%+d]", reg, off2);
	sparc_emitf(node, "st %%l1, [%%%s%+d]", reg, off1);
902
903
904
905
}

static int get_index(ir_entity **ents, int n, ir_entity *ent)
{
Matthias Braun's avatar
Matthias Braun committed
906
	for (int i = 0; i < n; ++i) {
907
908
		if (ents[i] == ent)
			return i;
Matthias Braun's avatar
Matthias Braun committed
909
	}
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935

	return -1;
}

/*
 * Emit code for a MemPerm node.
 *
 * Analyze MemPerm for copy chains and cyclic swaps and resolve them using
 * loads and stores.
 * This function is conceptually very similar to permute_values in
 * beprefalloc.c.
 */
static void emit_be_MemPerm(const ir_node *node)
{
	int         memperm_arity = be_get_MemPerm_entity_arity(node);
	/* Upper limit for the number of participating entities is twice the
	 * arity, e.g., for a simple copying MemPerm node with one input/output. */
	int         max_size      = 2 * memperm_arity;
	ir_entity **entities      = ALLOCANZ(ir_entity *, max_size);
	/* sourceof contains the input entity for each entity.  If an entity is
	 * never used as an output, its entry in sourceof is a fix point. */
	int        *sourceof      = ALLOCANZ(int,         max_size);
	/* n_users counts how many output entities use this entity as their input.*/
	int        *n_users       = ALLOCANZ(int,         max_size);
	/* n_spilled records the number of spilled registers, either 1 or 2. */
	int         n_spilled     = 0;
Matthias Braun's avatar
Matthias Braun committed
936
937
938
939
	ir_graph   *irg           = get_irn_irg(node);
	bool        omit_fp       = sparc_get_irg_data(irg)->omit_fp;

	int ent_offset = be_get_MemPerm_offset(node);
940

Matthias Braun's avatar
Matthias Braun committed
941
	for (int i = 0; i < max_size; ++i) {
942
		sourceof[i] = i;
Hannes Rapp's avatar
Hannes Rapp committed
943
944
	}

Matthias Braun's avatar
Matthias Braun committed
945
946
	int n = 0;
	for (int i = 0; i < memperm_arity; ++i) {
947
948
		ir_entity *out  = be_get_MemPerm_out_entity(node, i);
		ir_entity *in   = be_get_MemPerm_in_entity(node, i);
949

950
951
952
953
954
		/* Insert into entities to be able to operate on unique indices. */
		if (get_index(entities, n, out) == -1)
			entities[n++] = out;
		if (get_index(entities, n, in) == -1)
			entities[n++] = in;
Hannes Rapp's avatar
Hannes Rapp committed
955

Matthias Braun's avatar
Matthias Braun committed
956
957
		int oidx = get_index(entities, n, out);
		int iidx = get_index(entities, n, in);
958

959
960
		sourceof[oidx] = iidx;
		++n_users[iidx];
Hannes Rapp's avatar
Hannes Rapp committed
961
	}
962

963
	/* First do all the copies. */
Matthias Braun's avatar
Matthias Braun committed
964
	for (int oidx = 0; oidx < n; /* empty */) {
965
966
967
968
969
970
971
972
973
974
975
976
977
978
		int iidx = sourceof[oidx];

		/* Nothing to do for fix points.
		 * Also, if entities[oidx] is used as an input by another copy, we
		 * can't overwrite entities[oidx] yet.*/
		if (iidx == oidx || n_users[oidx] > 0) {
			++oidx;
			continue;
		}

		/* We found the end of a 'chain', so do the copy. */
		if (n_spilled == 0) {
			memperm_emit_spill_registers(node, n_spilled, /*n_to_spill=*/1);
			n_spilled = 1;
Matthias Braun's avatar
Matthias Braun committed
979
980
			if (omit_fp)
				ent_offset += 8;
981
		}
Matthias Braun's avatar
Matthias Braun committed
982
		memperm_emit_copy(node, entities[iidx], entities[oidx], ent_offset);
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997

		/* Mark as done. */
		sourceof[oidx] = oidx;

		assert(n_users[iidx] > 0);
		--n_users[iidx];

		if (iidx < oidx && n_users[iidx] == 0) {
			oidx = iidx;
		} else {
			++oidx;
		}
	}

	/* The rest are cycles. */
Matthias Braun's avatar
Matthias Braun committed
998
	for (int oidx = 0; oidx < n; /* empty */) {
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
		int iidx = sourceof[oidx];

		if (iidx == oidx) {
			++oidx;
			continue;
		}

		assert(n_users[iidx] == 1);

		if (n_spilled < 2) {
			memperm_emit_spill_registers(node, n_spilled, /*n_to_spill=*/2);
			n_spilled = 2;
		}
Matthias Braun's avatar
Matthias Braun committed
1012
		memperm_emit_swap(node, entities[iidx], entities[oidx], ent_offset);
1013

Matthias Braun's avatar
Matthias Braun committed
1014
		int tidx = sourceof[iidx];
1015
		sourceof[iidx] = iidx; /* Mark as done. */
1016
1017
1018
1019
1020
1021
1022
1023

		/* The source of oidx is now the old source of iidx, because we swapped
		 * the two entities. */
		sourceof[oidx] = tidx;
	}

#ifdef DEBUG_libfirm
	/* Only fix points should remain. */
Matthias Braun's avatar
Matthias Braun committed
1024
	for (int i = 0; i < max_size; ++i) {
1025
1026
1027
1028
1029
1030
		assert(sourceof[i] == i);
	}
#endif

	assert(n_spilled > 0 && "Useless MemPerm node");
	memperm_emit_restore_registers(node, n_spilled);
Hannes Rapp's avatar
Hannes Rapp committed
1031
1032
}

1033
static void emit_sparc_Return(const ir_node *node)
1034
{
1035
1036
1037
1038
	ir_graph  *irg    = get_irn_irg(node);
	ir_entity *entity = get_irg_entity(irg);
	ir_type   *type   = get_entity_type(entity);

1039
1040
1041
1042
	const char *destreg = "%o7";

	/* hack: we don't explicitely model register changes because of the
	 * restore node. So we have to do it manually here */
1043
1044
1045
	const ir_node *delay_slot = pmap_get(ir_node, delay_slots, node);
	if (delay_slot != NULL &&
	    (is_sparc_Restore(delay_slot) || is_sparc_RestoreZero(delay_slot))) {
1046
1047
		destreg = "%i7";
	}
1048
1049
	char const *const offset = get_method_calling_convention(type) & cc_compound_ret ? "12" : "8";
	sparc_emitf(node, "jmp %s+%s", destreg, offset);
1050
	fill_delay_slot(node);
1051
1052
}

1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
static const arch_register_t *map_i_to_o_reg(const arch_register_t *reg)
{
	unsigned idx = reg->global_index;
	if (idx < REG_I0 || idx > REG_I7)
		return reg;
	idx += REG_O0 - REG_I0;
	assert(REG_O0 <= idx && idx <= REG_O7);
	return &sparc_registers[idx];
}

static void emit_sparc_Restore(const ir_node *node)
{
	const arch_register_t *destreg
		= arch_get_irn_register_out(node, pn_sparc_Restore_res);
1067
	sparc_emitf(node, "restore %S2, %SI3, %R", map_i_to_o_reg(destreg));