sparc_emitter.c 42 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 "bearch_sparc_t.h"
14
#include "beasm.h"
15
#include "beblocksched.h"
16
#include "bediagnostic.h"
17
18
19
20
21
22
#include "begnuas.h"
#include "beirg.h"
#include "benode.h"
#include "bepeephole.h"
#include "besched.h"
#include "bestack.h"
23
#include "beutil.h"
Hannes Rapp's avatar
Hannes Rapp committed
24
#include "debug.h"
25
26
27
28
#include "execfreq_t.h"
#include "gen_sparc_emitter.h"
#include "gen_sparc_regalloc_if.h"
#include "heights.h"
Hannes Rapp's avatar
Hannes Rapp committed
29
#include "irgwalk.h"
Matthias Braun's avatar
Matthias Braun committed
30
#include "panic.h"
31
#include "pmap.h"
Hannes Rapp's avatar
Hannes Rapp committed
32
33
#include "sparc_emitter.h"
#include "sparc_new_nodes.h"
34
#include "util.h"
Hannes Rapp's avatar
Hannes Rapp committed
35

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

38
39
40
static ir_heights_t *heights;
static unsigned     *delay_slot_fillers;
static pmap         *delay_slots;
41

42
43
static bool emitting_delay_slot;

44
45
46
47
48
/**
 * indent before instruction. (Adds additional indentation when emitting
 * delay slots)
 */
static void sparc_emit_indent(void)
49
50
51
52
53
{
	be_emit_char('\t');
	if (emitting_delay_slot)
		be_emit_char(' ');
}
54

55
static void sparc_emit_immediate(int32_t value, ir_entity *entity)
Hannes Rapp's avatar
Hannes Rapp committed
56
{
57
	if (entity == NULL) {
58
		be_emit_irprintf("%"PRId32, value);
59
	} else {
60
		if (is_tls_entity(entity)) {
61
62
63
64
			be_emit_cstring("%tle_lox10(");
		} else {
			be_emit_cstring("%lo(");
		}
65
		be_gas_emit_entity(entity);
66
		if (value != 0) {
67
			be_emit_irprintf("%+"PRId32, value);
68
69
70
		}
		be_emit_char(')');
	}
71
72
}

73
static void sparc_emit_high_immediate(ir_node const *node)
74
{
75
76
77
78
79
	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;
80
		be_emit_irprintf("%%hi(0x%X)", value);
81
	} else {
82
		if (is_tls_entity(entity)) {
83
84
85
86
			be_emit_cstring("%tle_hix22(");
		} else {
			be_emit_cstring("%hi(");
		}
87
88
		be_gas_emit_entity(entity);
		if (attr->immediate_value != 0) {
89
			be_emit_irprintf("%+"PRId32, attr->immediate_value);
90
		}
91
		be_emit_char(')');
92
	}
Hannes Rapp's avatar
Hannes Rapp committed
93
94
}

95
static void sparc_emit_register(const arch_register_t *const reg)
Hannes Rapp's avatar
Hannes Rapp committed
96
97
{
	be_emit_char('%');
98
	be_emit_string(reg->name);
Hannes Rapp's avatar
Hannes Rapp committed
99
100
}

101
102
103
104
105
106
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);
}

107
static void sparc_emit_dest_register(ir_node const *const node, int const pos)
Hannes Rapp's avatar
Hannes Rapp committed
108
{
Matthias Braun's avatar
Matthias Braun committed
109
	const arch_register_t *reg = arch_get_irn_register_out(node, pos);
110
	sparc_emit_register(reg);
Hannes Rapp's avatar
Hannes Rapp committed
111
112
}

113
114
115
/**
 * emit SP offset
 */
116
static void sparc_emit_offset(const ir_node *node, int offset_node_pos)
Hannes Rapp's avatar
Hannes Rapp committed
117
{
118
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
119

120
121
122
123
124
125
126
	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) {
127
128
		int32_t offset = attr->base.immediate_value;
		if (offset != 0) {
129
			assert(sparc_is_value_imm_encodeable(offset));
130
			be_emit_irprintf("%+"PRId32, offset);
131
		}
132
133
	} else if (attr->base.immediate_value != 0
			|| attr->base.immediate_value_entity != NULL) {
134
		be_emit_char('+');
135
136
		sparc_emit_immediate(attr->base.immediate_value,
		                     attr->base.immediate_value_entity);
137
	}
Hannes Rapp's avatar
Hannes Rapp committed
138
139
140
}

/**
141
 *  Emit load mode
Hannes Rapp's avatar
Hannes Rapp committed
142
 */
143
static void sparc_emit_load_mode(ir_node const *const node)
Hannes Rapp's avatar
Hannes Rapp committed
144
145
{
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
146
147
148
149
	ir_mode *mode      = attr->load_store_mode;
	int      bits      = get_mode_size_bits(mode);
	bool     is_signed = mode_is_signed(mode);

150
151
152
153
154
155
156
	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);
157
	}
Hannes Rapp's avatar
Hannes Rapp committed
158
159
160
161
162
}

/**
 * Emit store mode char
 */
163
static void sparc_emit_store_mode(ir_node const *const node)
Hannes Rapp's avatar
Hannes Rapp committed
164
165
{
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
166
167
168
	ir_mode *mode      = attr->load_store_mode;
	int      bits      = get_mode_size_bits(mode);

169
170
171
172
173
174
175
	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);
176
	}
Hannes Rapp's avatar
Hannes Rapp committed
177
178
}

179
static void emit_fp_suffix(const ir_mode *mode)
Hannes Rapp's avatar
Hannes Rapp committed
180
{
181
	assert(mode_is_float(mode));
182
183
184
185
186
	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");
187
	}
Hannes Rapp's avatar
Hannes Rapp committed
188
189
}

190
191
192
193
194
static void set_jump_target(ir_node *jump, ir_node *target)
{
	set_irn_link(jump, target);
}

195
196
static ir_node *get_jump_target(const ir_node *jump)
{
197
	return (ir_node*)get_irn_link(jump);
198
199
}

Hannes Rapp's avatar
Hannes Rapp committed
200
201
202
203
204
/**
 * Returns the target label for a control flow node.
 */
static void sparc_emit_cfop_target(const ir_node *node)
{
205
	ir_node *block = get_jump_target(node);
206
	be_gas_emit_block_name(block);
Hannes Rapp's avatar
Hannes Rapp committed
207
208
}

209
210
211
212
213
214
215
216
217
/**
 * 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;
}

218
219
static int get_sparc_Call_dest_addr_pos(const ir_node *node)
{
220
	assert(is_sparc_reg_call(node));
221
222
223
224
225
226
	return get_irn_arity(node)-1;
}

static bool ba_is_fallthrough(const ir_node *node)
{
	ir_node *block      = get_nodes_block(node);
227
	ir_node *next_block = (ir_node*)get_irn_link(block);
228
	return get_jump_target(node) == next_block;
229
230
231
232
233
234
}

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
235
236
		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);
237
238
239
240

		if (src_reg == dest_reg)
			return true;
	}
241
242
	if (be_is_IncSP(node) && be_get_IncSP_offset(node) == 0)
		return true;
243
244
245
246
	/* Ba is not emitted if it is a simple fallthrough */
	if (is_sparc_Ba(node) && ba_is_fallthrough(node))
		return true;

247
	return be_is_Keep(node) || is_sparc_Start(node) || is_Phi(node);
248
249
250
251
}

static bool has_delay_slot(const ir_node *node)
{
252
253
254
	if (is_sparc_Ba(node)) {
		return !ba_is_fallthrough(node);
	}
255

256
	return arch_get_irn_flags(node) & sparc_arch_irn_flag_has_delay_slot;
257
258
259
260
261
262
263
264
265
266
267
268
269
}

/** 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;

270
	if (is_sparc_Call(node))
Matthias Braun's avatar
Matthias Braun committed
271
		return arch_get_irn_flags(node) & sparc_arch_irn_flag_aggregate_return;
272

273
274
	return is_sparc_SMulh(node) || is_sparc_UMulh(node)
		|| is_sparc_SDiv(node) || is_sparc_UDiv(node)
Manuel Mohr's avatar
Manuel Mohr committed
275
		|| be_is_MemPerm(node) || be_is_Perm(node)
276
		|| is_sparc_SubSP(node) || is_sparc_ASM(node);
277
278
}

279
static bool uses_reg(const ir_node *node, unsigned reg_index, unsigned width)
280
281
{
	int arity = get_irn_arity(node);
Matthias Braun's avatar
Matthias Braun committed
282
	for (int i = 0; i < arity; ++i) {
283
284
285
286
287
288
		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)
289
290
291
292
293
			return true;
	}
	return false;
}

294
static bool writes_reg(const ir_node *node, unsigned reg_index, unsigned width)
295
{
296
	be_foreach_out(node, o) {
Matthias Braun's avatar
Matthias Braun committed
297
		const arch_register_t *out_reg = arch_get_irn_register_out(node, o);
298
299
300
301
302
		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)
303
304
305
306
307
			return true;
	}
	return false;
}

308
309
310
311
312
313
314
315
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;
316
317
	if (is_sparc_Save(node))
		return false;
318
319
320
321
	return true;
}

static bool can_move_down_into_delayslot(const ir_node *node, const ir_node *to)
322
{
323
324
325
	if (!is_legal_delay_slot_filler(node))
		return false;

326
	if (!be_can_move_down(heights, node, to, sparc_get_frame_entity))
327
328
329
330
		return false;

	if (is_sparc_Call(to)) {
		ir_node *check;
331
		/** all inputs are used after the delay slot so, we're fine */
332
333
334
335
336
337
		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;
338

339
340
341
		/* 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. */
342
		if (uses_reg(node, REG_O7, 1))
343
344
345
346
347
			return false;
		return true;
	} else if (is_sparc_Return(to)) {
		/* return uses the value of %o7, all other values are not
		 * immediately used */
348
		if (writes_reg(node, REG_O7, 1))
349
350
351
352
			return false;
		return true;
	} else {
		/* the node must not use our computed values */
353
		foreach_irn_in(to, i, in) {
354
355
356
357
			if (skip_Proj(in) == node)
				return false;
		}
		return true;
358
359
360
	}
}

361
362
363
364
365
366
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' */
367
	foreach_irn_in(node, i, in) {
368
369
370
371
372
373
374
		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 */
375
	if (is_sparc_Restore(node) || is_sparc_RestoreZero(node)) {
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
		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 */
396
		be_foreach_out(to, o) {
397
398
399
400
401
402
403
404
405
406
			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
407
		for (int i = 0, arity = get_irn_arity(to); i < arity; ++i) {
408
			assert((unsigned)n_sparc_SDiv_dividend_high == (unsigned)n_sparc_UDiv_dividend_high);
409
410
411
412
413
414
415
416
417
			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
418
	}
419
420
421
422
423
424
425
426
	return true;
}

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

427
428
	assert((unsigned)pn_sparc_Bicc_false == (unsigned)pn_sparc_fbfcc_false);
	assert((unsigned)pn_sparc_Bicc_true  == (unsigned)pn_sparc_fbfcc_true);
429
430
	foreach_out_edge(node, edge) {
		ir_node *proj = get_edge_src_irn(edge);
431
432
		unsigned pn   = get_Proj_num(proj);
		if (pn == pn_sparc_Bicc_true) {
433
434
			proj_true = proj;
		} else {
435
			assert(pn == pn_sparc_Bicc_false);
436
437
438
439
440
441
442
443
444
445
446
447
448
			proj_false = proj;
		}
	}
	assert(proj_true != NULL && proj_false != NULL);

	/* for now, the code works for scheduled and non-schedules blocks */
	const ir_node *block = get_nodes_block(node);

	/* we have a block schedule */
	const ir_node *next_block = (ir_node*)get_irn_link(block);

	if (get_jump_target(proj_true) == next_block) {
		/* exchange both proj destinations so the second one can be omitted */
449
450
		set_Proj_num(proj_true,  pn_sparc_Bicc_false);
		set_Proj_num(proj_false, pn_sparc_Bicc_true);
451
452
453
454
455
456

		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
457
/**
458
 * search for an instruction that can fill the delay slot of @p node
Hannes Rapp's avatar
Hannes Rapp committed
459
 */
460
static ir_node *pick_delay_slot_for(ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
461
{
462
	static const unsigned PICK_DELAY_SLOT_MAX_DISTANCE = 10;
463
464
	assert(has_delay_slot(node));

465
466
467
	if (is_sparc_Bicc(node) || is_sparc_fbfcc(node)) {
		optimize_fallthrough(node);
	}
468

469
	unsigned tries = 0;
470
	sched_foreach_reverse_before(node, schedpoint) {
471
472
		if (has_delay_slot(schedpoint))
			break;
473
474
		if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE)
			break;
475

476
		if (!can_move_down_into_delayslot(schedpoint, node))
477
478
			continue;

479
480
481
482
483
484
		/* found something */
		return schedpoint;
	}

	/* search after the current position */
	tries = 0;
485
	sched_foreach_after(node, schedpoint) {
486
487
		if (has_delay_slot(schedpoint))
			break;
488
489
		if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE)
			break;
490
		if (!is_legal_delay_slot_filler(schedpoint))
491
			continue;
492
		if (!can_move_up_into_delayslot(schedpoint, node))
493
494
495
496
497
498
			continue;

		/* found something */
		return schedpoint;
	}

499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
	/* 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;
			/* can't move pinned nodes accross blocks */
			if (get_irn_pinned(schedpoint) == op_pin_state_pinned)
				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)) {
				/* it's fine to move the insn accross blocks */
				return schedpoint;
			} else if (is_sparc_Bicc(node) || is_sparc_fbfcc(node)) {
				ir_node *proj = get_Block_cfgpred(succ, 0);
531
				unsigned nr   = get_Proj_num(proj);
532
533
534
535
536
537
538
539
540
541
542
				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;
				}
			}
		}
	}

543
	return NULL;
Hannes Rapp's avatar
Hannes Rapp committed
544
545
}

546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
void sparc_emitf(ir_node const *const node, char const *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	sparc_emit_indent();
	for (;;) {
		char const *start = fmt;

		while (*fmt != '%' && *fmt != '\0')
			++fmt;
		be_emit_string_len(start, fmt - start);
		if (*fmt == '\0')
			break;
		++fmt;

		bool plus = false;
		if (*fmt == '+') {
			plus = true;
			++fmt;
		}

		switch (*fmt++) {
		case '%':
			be_emit_char('%');
			break;

572
573
574
575
576
577
578
579
580
		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;
		}

581
		case 'D':
582
			if (!is_digit(*fmt))
583
584
585
586
587
588
589
590
				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) {
591
				be_emit_irprintf(plus ? "%+"PRId32 : "%"PRId32, attr->immediate_value);
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
			}
			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;

612
613
614
		case 'L': {
			ir_node *n = va_arg(ap, ir_node*);
			sparc_emit_cfop_target(n);
615
			break;
616
		}
617
618
619

		case 'M':
			switch (*fmt++) {
620
621
622
623
624
625
626
627
628
629
630
			case 'O': {
				if (!is_digit(*fmt))
					goto unknown;
				unsigned const pos = *fmt++ - '0';
				be_emit_char('[');
				sparc_emit_source_register(node, pos);
				sparc_emit_offset(node, pos + 1);
				be_emit_char(']');
				break;
			}

631
632
633
634
635
636
637
638
639
			case 'L': sparc_emit_load_mode(node);  break;
			case 'S': sparc_emit_store_mode(node); break;
			default:  goto unknown;
			}
			break;

		case 'R': {
			arch_register_t const *const reg = va_arg(ap, const arch_register_t*);
			be_emit_char('%');
640
			be_emit_string(reg->name);
641
642
643
644
645
646
647
648
649
			break;
		}

		case 'S': {
			bool imm = false;
			if (*fmt == 'I') {
				imm = true;
				++fmt;
			}
650
			if (!is_digit(*fmt))
651
652
653
				goto unknown;
			unsigned const pos = *fmt++ - '0';
			if (imm && arch_get_irn_flags(node) & (arch_irn_flags_t)sparc_arch_irn_flag_immediate_form) {
654
655
656
				const sparc_attr_t *const attr = get_sparc_attr_const(node);
				sparc_emit_immediate(attr->immediate_value,
				                     attr->immediate_value_entity);
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
			} 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;
		}

681
682
683
684
685
686
		case 'X': {
			unsigned const num = va_arg(ap, unsigned);
			be_emit_irprintf("%X", num);
			break;
		}

687
688
689
690
691
692
693
694
695
		default:
unknown:
			panic("unknown format conversion in sparc_emitf()");
		}
	}
	be_emit_finish_line_gas(node);
	va_end(ap);
}

Hannes Rapp's avatar
Hannes Rapp committed
696
697
698
699
700
/**
 * Emits code for stack space management
 */
static void emit_be_IncSP(const ir_node *irn)
{
701
	int offset = be_get_IncSP_offset(irn);
Hannes Rapp's avatar
Hannes Rapp committed
702

703
	if (offset == 0)
704
		return;
Hannes Rapp's avatar
Hannes Rapp committed
705

706
	/* SPARC stack grows downwards */
707
708
	char const *const insn = offset > 0 ? offset = -offset, "add" : "sub";
	sparc_emitf(irn, "%s %S0, %d, %D0", insn, offset);
709
}
710

711
static void emit_sparc_asm_operand(ir_node const *const node, char const modifier, unsigned const pos)
712
{
713
	bool address_only = false;
714
	bool zero_as_g0   = false;
715
716
717
718
719
720
721
722
723
	switch (modifier) {
	case '\0':
		break;

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

724
725
726
727
	case 'r':
		zero_as_g0 = true;
		break;

728
	default:
729
730
		be_errorf(node, "asm contains unknown modifier '%c'", modifier);
		return;
731
732
	}

733
734
735
	sparc_asm_attr_t    const *const attr = get_sparc_asm_attr_const(node);
	sparc_asm_operand_t const *const op   = &attr->operands[pos];
	switch (op->kind) {
736
	case ASM_OPERAND_IMMEDIATE:
737
738
739
740
		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);
741
742
		return;

743
	case ASM_OPERAND_INPUT_VALUE:
744
745
746
		sparc_emit_register(arch_get_irn_register_in(node, op->pos));
		return;

747
	case ASM_OPERAND_OUTPUT_VALUE:
748
749
		sparc_emit_register(arch_get_irn_register_out(node, op->pos));
		return;
750
751

	case ASM_OPERAND_MEMORY:
752
753
		if (!address_only)
			be_emit_char('[');
754
		sparc_emit_register(arch_get_irn_register_in(node, op->pos));
755
756
		if (!address_only)
			be_emit_char(']');
757
		return;
758
	}
759
	panic("invalid asm operand kind");
760
761
}

762
763
static void emit_sparc_ASM(const ir_node *node)
{
764
765
	sparc_asm_attr_t const *const attr = get_sparc_asm_attr_const(node);
	be_emit_asm(node, attr->text, ARR_LEN(attr->operands), emit_sparc_asm_operand);
766
767
}

Manuel Mohr's avatar
Manuel Mohr committed
768
769
770
771
772
/**
 * Emits code for stack space management.
 */
static void emit_sparc_SubSP(const ir_node *irn)
{
773
774
	sparc_emitf(irn, "sub %S0, %SI1, %D0");
	sparc_emitf(irn, "add %S0, %u, %D1", SPARC_MIN_STACKSIZE);
Hannes Rapp's avatar
Hannes Rapp committed
775
}
776

777
static void fill_delay_slot(const ir_node *node)
778
{
779
	emitting_delay_slot = true;
780
781
782
783
	const ir_node *filler = pmap_get(ir_node, delay_slots, node);
	if (filler != NULL) {
		assert(!is_no_instruction(filler));
		assert(!emits_multiple_instructions(filler));
784
		be_emit_node(filler);
785
	} else {
786
		sparc_emitf(NULL, "nop");
787
	}
788
	emitting_delay_slot = false;
789
790
}

791
static void emit_sparc_Div(const ir_node *node, char const *const insn)
792
{
793
	sparc_emitf(node, "wr %S1, 0, %%y");
794

Matthias Braun's avatar
Matthias Braun committed
795
796
797
798
	/* 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) {
799
800
801
802
803
804
805
		if (i == 0) {
			fill_delay_slot(node);
		} else {
			emitting_delay_slot = true;
			sparc_emitf(NULL, "nop");
			emitting_delay_slot = false;
		}
806
807
	}

808
	sparc_emitf(node, "%s %S2, %SI3, %D0", insn);
809
810
811
812
}

static void emit_sparc_SDiv(const ir_node *node)
{
813
	emit_sparc_Div(node, "sdiv");
814
815
816
817
}

static void emit_sparc_UDiv(const ir_node *node)
{
818
	emit_sparc_Div(node, "udiv");
819
820
}

821
static void emit_sparc_Call(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
822
{
823
824
	if (is_sparc_reg_call(node)) {
		int dest_addr = get_sparc_Call_dest_addr_pos(node);
825
		sparc_emitf(node, "call %R", arch_get_irn_register_in(node, dest_addr));
826
	} else {
827
		sparc_emitf(node, "call %E, 0");
Hannes Rapp's avatar
Hannes Rapp committed
828
	}
829

830
	fill_delay_slot(node);
831

Matthias Braun's avatar
Matthias Braun committed
832
	if (arch_get_irn_flags(node) & sparc_arch_irn_flag_aggregate_return) {
833
		sparc_emitf(NULL, "unimp 8");
834
	}
Hannes Rapp's avatar
Hannes Rapp committed
835
836
}

837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
static void emit_sparc_Cas(const ir_node *node)
{
	/* custom emiter is just here to check for should_be_same constraint
	 * which isn't guaranteed to be fulfilled in current firm backend */
	if (arch_get_irn_register_out(node, pn_sparc_Cas_res) !=
	    arch_get_irn_register_in(node, n_sparc_Cas_new)) {
	    panic("sparc: should_be_same in Cas not fulfilled");
	}
	/* 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
}

862
863
static void emit_be_Perm(const ir_node *irn)
{
Matthias Braun's avatar
Matthias Braun committed
864
865
	ir_mode *mode = get_irn_mode(get_irn_n(irn, 0));
	if (mode_is_float(mode)) {
866
867
		arch_register_t const *const reg0 = arch_get_irn_register_out(irn, 0);
		arch_register_t const *const reg1 = arch_get_irn_register_out(irn, 1);
Matthias Braun's avatar
Matthias Braun committed
868
869
		unsigned reg_idx0 = reg0->global_index;
		unsigned reg_idx1 = reg1->global_index;
870
		unsigned width    = arch_get_irn_register_req_out(irn, 0)->width;
Matthias Braun's avatar
Matthias Braun committed
871
872
873
874
875
876
877
878
		for (unsigned i = 0; i < width; ++i) {
			const arch_register_t *r0 = &sparc_registers[reg_idx0+i];
			const arch_register_t *r1 = &sparc_registers[reg_idx1+i];
			sparc_emitf(irn, "fmovs %R, %%f31", r0);
			sparc_emitf(irn, "fmovs %R, %R", r1, r0);
			sparc_emitf(irn, "fmovs %%f31, %R", r1);
		}
	} else {
879
880
881
		sparc_emitf(irn, "xor %D1, %D0, %D0");
		sparc_emitf(irn, "xor %D1, %D0, %D1");
		sparc_emitf(irn, "xor %D1, %D0, %D0");
Matthias Braun's avatar
Matthias Braun committed
882
	}
883
884
}

885
static unsigned get_aligned_sp_change(const unsigned num_regs)
886
{
887
	const unsigned bytes = num_regs * SPARC_REGISTER_SIZE;
888
	return round_up2(bytes, SPARC_STACK_ALIGNMENT);
889
890
}

891
892
893
/* 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
894
{
895
	assert(n_spilled < n_to_spill);
896

897
898
899
900
901
902
	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
903

904
		const unsigned sp_change = get_aligned_sp_change(2);
905
906
		sparc_emitf(node, "sub %%sp, %u, %%sp", sp_change);
		sparc_emitf(node, "st %%l0, [%%sp%+d]", SPARC_MIN_STACKSIZE);
907
	}
Hannes Rapp's avatar
Hannes Rapp committed
908

909
	if (n_to_spill == 2) {
910
		sparc_emitf(node, "st %%l1, [%%sp%+d]", SPARC_MIN_STACKSIZE + SPARC_REGISTER_SIZE);
911
912
	}
}
913

914
915
916
917
/* 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) {
918
		sparc_emitf(node, "ld [%%sp%+d], %%l1", SPARC_MIN_STACKSIZE + SPARC_REGISTER_SIZE);
919
	}
Hannes Rapp's avatar
Hannes Rapp committed
920

921
	sparc_emitf(node, "ld [%%sp%+d], %%l0", SPARC_MIN_STACKSIZE);
922
	const unsigned sp_change = get_aligned_sp_change(2);
923
	sparc_emitf(node, "add %%sp, %u, %%sp", sp_change);
924
925
}

926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
static int get_real_entity_offset(const ir_node *node, ir_entity *ent)
{
	ir_graph          *irg     = get_irn_irg(node);
	be_stack_layout_t *layout  = be_get_irg_stack_layout(irg);
	const int          off_ent = be_get_stack_entity_offset(layout, ent, 0);

	if (layout->sp_relative) {
		ir_entity *ent_ref   = be_get_MemPerm_in_entity(node, 0);
		const int  off_ref   = be_get_stack_entity_offset(layout, ent_ref, 0);
		const int  delta_ent = off_ent - off_ref;
		const int  offset    = be_get_MemPerm_offset(node);
		const int  sp_change = (int)get_aligned_sp_change(2);
		return offset + delta_ent + sp_change;
	} else {
		return off_ent;
	}
}

944
945
946
947
948
static void memperm_emit_copy(const ir_node *node, ir_entity *in_ent,
                              ir_entity *out_ent)
{
	ir_graph          *irg     = get_irn_irg(node);
	be_stack_layout_t *layout  = be_get_irg_stack_layout(irg);
949
950
951
	const char        *reg     = layout->sp_relative ? "sp" : "fp";
	const int          off_in  = get_real_entity_offset(node, in_ent);
	const int          off_out = get_real_entity_offset(node, out_ent);
952

953
954
	sparc_emitf(node, "ld [%%%s%+d], %%l0", reg, off_in);
	sparc_emitf(node, "st %%l0, [%%%s%+d]", reg, off_out);
955
956
957
958
959
}

static void memperm_emit_swap(const ir_node *node, ir_entity *ent1,
                              ir_entity *ent2)
{
960
961
962
963
964
965
966
967
968
969
	ir_graph          *irg    = get_irn_irg(node);
	be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
	const char        *reg    = layout->sp_relative ? "sp" : "fp";
	const int          off1   = get_real_entity_offset(node, ent1);
	const int          off2   = get_real_entity_offset(node, ent2);

	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);
970
971
972
973
}

static int get_index(ir_entity **ents, int n, ir_entity *ent)
{
Matthias Braun's avatar
Matthias Braun committed
974
	for (int i = 0; i < n; ++i) {
975
976
		if (ents[i] == ent)
			return i;
Matthias Braun's avatar
Matthias Braun committed
977
	}
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004

	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
1005
	for (int i = 0; i < max_size; ++i) {
1006
		sourceof[i] = i;
Hannes Rapp's avatar
Hannes Rapp committed
1007
1008
	}

Matthias Braun's avatar
Matthias Braun committed
1009
1010
	int n = 0;
	for (int i = 0; i < memperm_arity; ++i) {
1011
1012
		ir_entity *out  = be_get_MemPerm_out_entity(node, i);
		ir_entity *in   = be_get_MemPerm_in_entity(node, i);
1013

1014
1015
1016
1017
1018
		/* 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
1019

Matthias Braun's avatar
Matthias Braun committed
1020
1021
		int oidx = get_index(entities, n, out);
		int iidx = get_index(entities, n, in);
1022

1023
1024
		sourceof[oidx] = iidx;
		++n_users[iidx];
Hannes Rapp's avatar
Hannes Rapp committed
1025
	}
1026

1027
	/* First do all the copies. */
Matthias Braun's avatar
Matthias Braun committed
1028
	for (int oidx = 0; oidx < n; /* empty */) {
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
		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;
		}
		memperm_emit_copy(node, entities[iidx], entities[oidx]);

		/* 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
1060
	for (int oidx = 0; oidx < n; /* empty */) {
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
		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;
		}
		memperm_emit_swap(node, entities[iidx], entities[oidx]);

Matthias Braun's avatar
Matthias Braun committed
1076
		int tidx = sourceof[iidx];
1077
		sourceof[iidx] = iidx; /* Mark as done. */
1078
1079
1080
1081
1082
1083
1084
1085

		/* 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
1086
	for (int i = 0; i < max_size; ++i) {
1087
1088
1089
1090
1091
1092
		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
1093
1094
}

1095
static void emit_sparc_Return(const ir_node *node)
1096
{
1097
1098
1099
1100
	ir_graph  *irg    = get_irn_irg(node);
	ir_entity *entity = get_irg_entity(irg);
	ir_type   *type   = get_entity_type(entity);

1101
1102
1103
1104
	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 */
1105
1106
1107
	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))) {
1108
1109
		destreg = "%i7";
	}
1110
1111
	char const *const offset = get_method_calling_convention(type) & cc_compound_ret ? "12" : "8";
	sparc_emitf(node, "jmp %s+%s", destreg, offset);
1112
	fill_delay_slot(node);
1113
1114
}

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
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);
1129
	sparc_emitf(node, "restore %S2, %SI3, %R", map_i_to_o_reg(destreg));
1130
1131
}

1132
static void emit_sparc_FrameAddr(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
1133
{
1134
1135
	const sparc_attr_t *attr   = get_sparc_attr_const(node);
	int32_t             offset = attr->immediate_value;
1136

1137
1138
	char const *const insn = offset > 0 ? offset = -offset, "sub" : "add";
	assert(sparc_is_value_imm_encodeable(offset));
1139
	sparc_emitf(node, "%s %S0, %d, %D0", insn, (int)offset);
Hannes Rapp's avatar
Hannes Rapp committed
<