sparc_emitter.c 30.5 KB
Newer Older
Hannes Rapp's avatar
Hannes Rapp committed
1
/*
2
 * Copyright (C) 1995-2010 University of Karlsruhe.  All right reserved.
Hannes Rapp's avatar
Hannes Rapp committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

/**
 * @file
 * @brief   emit assembler for a backend graph
Matthias Braun's avatar
Matthias Braun committed
23
 * @author  Hannes Rapp, Matthias Braun
Michael Beck's avatar
Michael Beck committed
24
 * @version $Id$
Hannes Rapp's avatar
Hannes Rapp committed
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 */
#include "config.h"

#include <limits.h>

#include "xmalloc.h"
#include "tv.h"
#include "iredges.h"
#include "debug.h"
#include "irgwalk.h"
#include "irprintf.h"
#include "irop_t.h"
#include "irargs_t.h"
#include "irprog.h"
#include "irargs_t.h"
#include "error.h"
#include "raw_bitset.h"
#include "dbginfo.h"
43
#include "heights.h"
Hannes Rapp's avatar
Hannes Rapp committed
44
45
46
47
48
49
50

#include "../besched.h"
#include "../beblocksched.h"
#include "../beirg.h"
#include "../begnuas.h"
#include "../be_dbgout.h"
#include "../benode.h"
51
#include "../bestack.h"
Hannes Rapp's avatar
Hannes Rapp committed
52
53
54
55
56

#include "sparc_emitter.h"
#include "gen_sparc_emitter.h"
#include "sparc_nodes_attr.h"
#include "sparc_new_nodes.h"
Hannes Rapp's avatar
Hannes Rapp committed
57
58
#include "gen_sparc_regalloc_if.h"

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

61
62
63
64
65
66
static ir_heights_t  *heights;
static const ir_node *delay_slot_filler; /**< this node has been choosen to fill
                                              the next delay slot */

static void sparc_emit_node(const ir_node *node);

Hannes Rapp's avatar
Hannes Rapp committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/**
 * Returns the register at in position pos.
 */
static const arch_register_t *get_in_reg(const ir_node *node, int pos)
{
	ir_node                *op;
	const arch_register_t  *reg = NULL;

	assert(get_irn_arity(node) > pos && "Invalid IN position");

	/* The out register of the operator at position pos is the
	   in register we need. */
	op = get_irn_n(node, pos);

	reg = arch_get_irn_register(op);

	assert(reg && "no in register found");
	return reg;
}

/**
 * Returns the register at out position pos.
 */
static const arch_register_t *get_out_reg(const ir_node *node, int pos)
{
	ir_node                *proj;
	const arch_register_t  *reg = NULL;

	/* 1st case: irn is not of mode_T, so it has only                 */
	/*           one OUT register -> good                             */
	/* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
	/*           Proj with the corresponding projnum for the register */

	if (get_irn_mode(node) != mode_T) {
		reg = arch_get_irn_register(node);
	} else if (is_sparc_irn(node)) {
		reg = arch_irn_get_register(node, pos);
	} else {
		const ir_edge_t *edge;

		foreach_out_edge(node, edge) {
			proj = get_edge_src_irn(edge);
			assert(is_Proj(proj) && "non-Proj from mode_T node");
			if (get_Proj_proj(proj) == pos) {
				reg = arch_get_irn_register(proj);
				break;
			}
		}
	}

	assert(reg && "no out register found");
	return reg;
}

void sparc_emit_immediate(const ir_node *node)
{
123
124
125
126
127
	const sparc_attr_t *attr   = get_sparc_attr_const(node);
	ir_entity          *entity = attr->immediate_value_entity;

	if (entity == NULL) {
		int32_t value = attr->immediate_value;
128
		assert(sparc_is_value_imm_encodeable(value));
129
130
131
132
133
134
135
136
137
		be_emit_irprintf("%d", value);
	} else {
		be_emit_cstring("%lo(");
		be_gas_emit_entity(entity);
		if (attr->immediate_value != 0) {
			be_emit_irprintf("%+d", attr->immediate_value);
		}
		be_emit_char(')');
	}
138
139
140
141
}

void sparc_emit_high_immediate(const ir_node *node)
{
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	const sparc_attr_t *attr   = get_sparc_attr_const(node);
	ir_entity          *entity = attr->immediate_value_entity;

	be_emit_cstring("%hi(");
	if (entity == NULL) {
		uint32_t value = (uint32_t) attr->immediate_value;
		be_emit_irprintf("0x%X", value);
	} else {
		be_gas_emit_entity(entity);
		if (attr->immediate_value != 0) {
			be_emit_irprintf("%+d", attr->immediate_value);
		}
	}
	be_emit_char(')');
Hannes Rapp's avatar
Hannes Rapp committed
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
}

void sparc_emit_source_register(const ir_node *node, int pos)
{
	const arch_register_t *reg = get_in_reg(node, pos);
	be_emit_char('%');
	be_emit_string(arch_register_get_name(reg));
}

void sparc_emit_dest_register(const ir_node *node, int pos)
{
	const arch_register_t *reg = get_out_reg(node, pos);
	be_emit_char('%');
	be_emit_string(arch_register_get_name(reg));
}

/**
 * Emits either a imm or register depending on arity of node
 * @param node
 * @param register no (-1 if no register)
 */
void sparc_emit_reg_or_imm(const ir_node *node, int pos)
{
179
	if (arch_irn_get_flags(node) & ((arch_irn_flags_t)sparc_arch_irn_flag_immediate_form)) {
Hannes Rapp's avatar
Hannes Rapp committed
180
181
		// we have a imm input
		sparc_emit_immediate(node);
182
183
184
	} else {
		// we have reg input
		sparc_emit_source_register(node, pos);
Hannes Rapp's avatar
Hannes Rapp committed
185
186
187
	}
}

188
189
190
/**
 * emit SP offset
 */
191
void sparc_emit_offset(const ir_node *node, int offset_node_pos)
Hannes Rapp's avatar
Hannes Rapp committed
192
{
193
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
194

195
196
197
198
199
200
201
	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) {
202
203
		int32_t offset = attr->base.immediate_value;
		if (offset != 0) {
204
			assert(sparc_is_value_imm_encodeable(offset));
205
206
			be_emit_irprintf("%+ld", offset);
		}
207
208
	} else if (attr->base.immediate_value != 0
			|| attr->base.immediate_value_entity != NULL) {
209
210
		be_emit_char('+');
		sparc_emit_immediate(node);
211
	}
Hannes Rapp's avatar
Hannes Rapp committed
212
213
}

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
void sparc_emit_float_load_store_mode(const ir_node *node)
{
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
	ir_mode *mode = attr->load_store_mode;
	int      bits = get_mode_size_bits(mode);

	assert(mode_is_float(mode));

	switch (bits) {
	case 32:  return;
	case 64:  be_emit_char('d'); return;
	case 128: be_emit_char('q'); return;
	}
	panic("invalid flaot load/store mode %+F", mode);
}
229

Hannes Rapp's avatar
Hannes Rapp committed
230
231
232
233
234
235
/**
 *  Emit load mode char
 */
void sparc_emit_load_mode(const ir_node *node)
{
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
236
237
238
239
240
241
242
243
244
	ir_mode *mode      = attr->load_store_mode;
	int      bits      = get_mode_size_bits(mode);
	bool     is_signed = mode_is_signed(mode);

	if (bits == 16) {
		be_emit_string(is_signed ? "sh" : "uh");
	} else if (bits == 8) {
		be_emit_string(is_signed ? "sb" : "ub");
	} else if (bits == 64) {
245
		be_emit_char('d');
246
247
248
	} else {
		assert(bits == 32);
	}
Hannes Rapp's avatar
Hannes Rapp committed
249
250
251
252
253
254
255
256
}

/**
 * Emit store mode char
 */
void sparc_emit_store_mode(const ir_node *node)
{
	const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
257
258
259
260
261
262
263
264
	ir_mode *mode      = attr->load_store_mode;
	int      bits      = get_mode_size_bits(mode);

	if (bits == 16) {
		be_emit_string("h");
	} else if (bits == 8) {
		be_emit_string("b");
	} else if (bits == 64) {
265
		be_emit_char('d');
266
267
268
	} else {
		assert(bits == 32);
	}
Hannes Rapp's avatar
Hannes Rapp committed
269
270
}

Hannes Rapp's avatar
Hannes Rapp committed
271
272
273
274
275
/**
 * emit integer signed/unsigned prefix char
 */
void sparc_emit_mode_sign_prefix(const ir_node *node)
{
276
277
278
	ir_mode *mode      = get_irn_mode(node);
	bool     is_signed = mode_is_signed(mode);
	be_emit_string(is_signed ? "s" : "u");
Hannes Rapp's avatar
Hannes Rapp committed
279
280
}

281
static void emit_fp_suffix(const ir_mode *mode)
Hannes Rapp's avatar
Hannes Rapp committed
282
{
283
	unsigned bits = get_mode_size_bits(mode);
284
	assert(mode_is_float(mode));
Hannes Rapp's avatar
Hannes Rapp committed
285

286
	if (bits == 32) {
287
		be_emit_char('s');
288
	} else if (bits == 64) {
289
290
291
		be_emit_char('d');
	} else if (bits == 128) {
		be_emit_char('q');
292
	} else {
293
		panic("invalid FP mode");
294
	}
Hannes Rapp's avatar
Hannes Rapp committed
295
296
}

297
void sparc_emit_fp_conv_source(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
298
{
299
300
301
	const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(node);
	emit_fp_suffix(attr->src_mode);
}
Hannes Rapp's avatar
Hannes Rapp committed
302

303
304
305
306
void sparc_emit_fp_conv_destination(const ir_node *node)
{
	const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(node);
	emit_fp_suffix(attr->dest_mode);
Hannes Rapp's avatar
Hannes Rapp committed
307
308
309
310
311
312
313
}

/**
 * emits the FP mode suffix char
 */
void sparc_emit_fp_mode_suffix(const ir_node *node)
{
314
315
	const sparc_fp_attr_t *attr = get_sparc_fp_attr_const(node);
	emit_fp_suffix(attr->fp_mode);
Hannes Rapp's avatar
Hannes Rapp committed
316
317
}

318
319
static ir_node *get_jump_target(const ir_node *jump)
{
320
	return (ir_node*)get_irn_link(jump);
321
322
}

Hannes Rapp's avatar
Hannes Rapp committed
323
324
325
326
327
/**
 * Returns the target label for a control flow node.
 */
static void sparc_emit_cfop_target(const ir_node *node)
{
328
	ir_node *block = get_jump_target(node);
329
	be_gas_emit_block_name(block);
Hannes Rapp's avatar
Hannes Rapp committed
330
331
}

332
333
334
335
336
337
338
339
static int get_sparc_Call_dest_addr_pos(const ir_node *node)
{
	return get_irn_arity(node)-1;
}

static bool ba_is_fallthrough(const ir_node *node)
{
	ir_node *block      = get_nodes_block(node);
340
	ir_node *next_block = (ir_node*)get_irn_link(block);
341
342
343
344
345
346
347
348
349
350
351
352
353
	return get_irn_link(node) == next_block;
}

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)) {
		const arch_register_t *src_reg  = get_in_reg(node, 0);
		const arch_register_t *dest_reg = get_out_reg(node, 0);

		if (src_reg == dest_reg)
			return true;
	}
354
355
	if (be_is_IncSP(node) && be_get_IncSP_offset(node) == 0)
		return true;
356
357
358
359
	/* Ba is not emitted if it is a simple fallthrough */
	if (is_sparc_Ba(node) && ba_is_fallthrough(node))
		return true;

360
	return be_is_Keep(node) || be_is_Start(node) || is_Phi(node);
361
362
363
364
365
366
367
368
369
}

static bool has_delay_slot(const ir_node *node)
{
	if (is_sparc_Ba(node) && ba_is_fallthrough(node))
		return false;

	return is_sparc_Bicc(node) || is_sparc_fbfcc(node) || is_sparc_Ba(node)
		|| is_sparc_SwitchJmp(node) || is_sparc_Call(node)
370
371
		|| is_sparc_SDiv(node) || is_sparc_UDiv(node)
		|| be_is_Return(node);
372
373
374
375
376
377
378
379
380
381
382
383
384
385
}

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

	return is_sparc_Mulh(node) || is_sparc_SDiv(node) || is_sparc_UDiv(node)
386
		|| be_is_MemPerm(node) || be_is_Perm(node);
387
388
}

Hannes Rapp's avatar
Hannes Rapp committed
389
/**
390
 * search for an instruction that can fill the delay slot of @p node
Hannes Rapp's avatar
Hannes Rapp committed
391
 */
392
static const ir_node *pick_delay_slot_for(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
393
{
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
	const ir_node *check      = node;
	const ir_node *schedpoint = node;
	unsigned       tries      = 0;
	/* currently we don't track which registers are still alive, so we can't
	 * pick any other instructions other than the one directly preceding */
	static const unsigned PICK_DELAY_SLOT_MAX_DISTANCE = 1;

	assert(has_delay_slot(node));

	if (is_sparc_Call(node)) {
		const sparc_attr_t *attr   = get_sparc_attr_const(node);
		ir_entity          *entity = attr->immediate_value_entity;
		if (entity != NULL) {
			check = NULL; /* pick any instruction, dependencies on Call
			                 don't matter */
		} else {
			/* we only need to check the value for the call destination */
			check = get_irn_n(node, get_sparc_Call_dest_addr_pos(node));
		}

		/* 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. */
417
418
419
420
421
422
423
424
425
	} else if (be_is_Return(node)) {
		/* we only have to check the jump destination value */
		int arity = get_irn_arity(node);
		int i;

		check = NULL;
		for (i = 0; i < arity; ++i) {
			ir_node               *in  = get_irn_n(node, i);
			const arch_register_t *reg = arch_get_irn_register(in);
Matthias Braun's avatar
Matthias Braun committed
426
			if (reg == &sparc_registers[REG_O7]) {
427
428
429
430
				check = skip_Proj(in);
				break;
			}
		}
431
432
433
434
435
436
437
438
439
440
441
442
443
444
	} else {
		check = node;
	}

	while (sched_has_prev(schedpoint)) {
		schedpoint = sched_prev(schedpoint);

		if (has_delay_slot(schedpoint))
			break;

		/* skip things which don't really result in instructions */
		if (is_no_instruction(schedpoint))
			continue;

445
446
447
		if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE)
			break;

448
449
450
451
452
453
454
455
456
457
458
459
460
461
		if (emits_multiple_instructions(schedpoint))
			continue;

		/* allowed for delayslot: any instruction which is not necessary to
		 * compute an input to the branch. */
		if (check != NULL
				&& heights_reachable_in_block(heights, check, schedpoint))
			continue;

		/* found something */
		return schedpoint;
	}

	return NULL;
Hannes Rapp's avatar
Hannes Rapp committed
462
463
464
465
466
467
468
}

/**
 * Emits code for stack space management
 */
static void emit_be_IncSP(const ir_node *irn)
{
469
	int offset = be_get_IncSP_offset(irn);
Hannes Rapp's avatar
Hannes Rapp committed
470

471
	if (offset == 0)
472
		return;
Hannes Rapp's avatar
Hannes Rapp committed
473

474
	/* SPARC stack grows downwards */
475
	if (offset < 0) {
476
		be_emit_cstring("\tsub ");
477
		offset = -offset;
Hannes Rapp's avatar
Hannes Rapp committed
478
	} else {
479
		be_emit_cstring("\tadd ");
Hannes Rapp's avatar
Hannes Rapp committed
480
481
	}

482
	sparc_emit_source_register(irn, 0);
483
	be_emit_irprintf(", %d", -offset);
484
485
486
487
	be_emit_cstring(", ");
	sparc_emit_dest_register(irn, 0);
	be_emit_finish_line_gas(irn);
}
488

Hannes Rapp's avatar
Hannes Rapp committed
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
/**
 * emits code for mulh
 */
static void emit_sparc_Mulh(const ir_node *irn)
{
	be_emit_cstring("\t");
	sparc_emit_mode_sign_prefix(irn);
	be_emit_cstring("mul ");

	sparc_emit_source_register(irn, 0);
	be_emit_cstring(", ");
	sparc_emit_reg_or_imm(irn, 1);
	be_emit_cstring(", ");
	sparc_emit_dest_register(irn, 0);
	be_emit_finish_line_gas(irn);

	// our result is in the y register now
	// we just copy it to the assigned target reg
507
	be_emit_cstring("\tmov %y, ");
Hannes Rapp's avatar
Hannes Rapp committed
508
509
510
	sparc_emit_dest_register(irn, 0);
	be_emit_finish_line_gas(irn);
}
511

512
513
static void fill_delay_slot(void)
{
514
515
516
517
518
519
520
	if (delay_slot_filler != NULL) {
		sparc_emit_node(delay_slot_filler);
		delay_slot_filler = NULL;
	} else {
		be_emit_cstring("\tnop\n");
		be_emit_write_line();
	}
521
522
}

523
524
525
526
527
528
529
530
531
532
533
534
static void emit_sparc_Div(const ir_node *node, bool is_signed)
{
	/* can we get the delay count of the wr instruction somewhere? */
	unsigned wry_delay_count = 3;
	unsigned i;

	be_emit_cstring("\twr ");
	sparc_emit_source_register(node, 0);
	be_emit_cstring(", 0, %y");
	be_emit_finish_line_gas(node);

	for (i = 0; i < wry_delay_count; ++i) {
535
		fill_delay_slot();
536
537
538
539
540
	}

	be_emit_irprintf("\t%s ", is_signed ? "sdiv" : "udiv");
	sparc_emit_source_register(node, 1);
	be_emit_cstring(", ");
541
	sparc_emit_reg_or_imm(node, 2);
542
543
544
545
546
547
548
	be_emit_cstring(", ");
	sparc_emit_dest_register(node, 0);
	be_emit_finish_line_gas(node);
}

static void emit_sparc_SDiv(const ir_node *node)
{
549
	emit_sparc_Div(node, true);
550
551
552
553
554
555
556
}

static void emit_sparc_UDiv(const ir_node *node)
{
	emit_sparc_Div(node, false);
}

Hannes Rapp's avatar
Hannes Rapp committed
557
558
559
/**
 * Emits code for Call node
 */
560
static void emit_sparc_Call(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
561
{
562
563
	const sparc_attr_t *attr   = get_sparc_attr_const(node);
	ir_entity          *entity = attr->immediate_value_entity;
Hannes Rapp's avatar
Hannes Rapp committed
564

565
	be_emit_cstring("\tcall ");
Hannes Rapp's avatar
Hannes Rapp committed
566
	if (entity != NULL) {
567
	    be_gas_emit_entity(entity);
568
569
570
	    if (attr->immediate_value != 0) {
			be_emit_irprintf("%+d", attr->immediate_value);
		}
571
		be_emit_cstring(", 0");
Hannes Rapp's avatar
Hannes Rapp committed
572
	} else {
573
574
		int dest_addr = get_sparc_Call_dest_addr_pos(node);
		sparc_emit_source_register(node, dest_addr);
Hannes Rapp's avatar
Hannes Rapp committed
575
	}
576
577
	be_emit_finish_line_gas(node);

578
	fill_delay_slot();
Hannes Rapp's avatar
Hannes Rapp committed
579
580
}

581
/**
Hannes Rapp's avatar
Hannes Rapp committed
582
 * Emit code for Perm node
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
 */
static void emit_be_Perm(const ir_node *irn)
{
	be_emit_cstring("\txor ");
	sparc_emit_source_register(irn, 1);
	be_emit_cstring(", ");
	sparc_emit_source_register(irn, 0);
	be_emit_cstring(", ");
	sparc_emit_source_register(irn, 0);
	be_emit_finish_line_gas(NULL);

	be_emit_cstring("\txor ");
	sparc_emit_source_register(irn, 1);
	be_emit_cstring(", ");
	sparc_emit_source_register(irn, 0);
	be_emit_cstring(", ");
	sparc_emit_source_register(irn, 1);
	be_emit_finish_line_gas(NULL);

	be_emit_cstring("\txor ");
	sparc_emit_source_register(irn, 1);
	be_emit_cstring(", ");
	sparc_emit_source_register(irn, 0);
	be_emit_cstring(", ");
	sparc_emit_source_register(irn, 0);
	be_emit_finish_line_gas(irn);
}

Hannes Rapp's avatar
Hannes Rapp committed
611
612
613
614
615
static void emit_be_MemPerm(const ir_node *node)
{
	int i;
	int memperm_arity;
	int sp_change = 0;
616
617
618
619
620
	ir_graph          *irg    = get_irn_irg(node);
	be_stack_layout_t *layout = be_get_irg_stack_layout(irg);

	/* this implementation only works with frame pointers currently */
	assert(layout->sp_relative == false);
Hannes Rapp's avatar
Hannes Rapp committed
621
622
623
624
625
626
627
628
629

	/* TODO: this implementation is slower than necessary.
	   The longterm goal is however to avoid the memperm node completely */

	memperm_arity = be_get_MemPerm_entity_arity(node);
	// we use our local registers - so this is limited to 8 inputs !
	if (memperm_arity > 8)
		panic("memperm with more than 8 inputs not supported yet");

630
631
632
	be_emit_irprintf("\tsub %%sp, %d, %%sp", memperm_arity*4);
	be_emit_finish_line_gas(node);

Hannes Rapp's avatar
Hannes Rapp committed
633
634
	for (i = 0; i < memperm_arity; ++i) {
		ir_entity *entity = be_get_MemPerm_in_entity(node, i);
635
		int        offset = be_get_stack_entity_offset(layout, entity, 0);
Hannes Rapp's avatar
Hannes Rapp committed
636
637

		/* spill register */
638
		be_emit_irprintf("\tst %%l%d, [%%sp%+d]", i, sp_change + SPARC_MIN_STACKSIZE);
Hannes Rapp's avatar
Hannes Rapp committed
639
640
641
		be_emit_finish_line_gas(node);

		/* load from entity */
642
		be_emit_irprintf("\tld [%%fp%+d], %%l%d", offset, i);
Hannes Rapp's avatar
Hannes Rapp committed
643
		be_emit_finish_line_gas(node);
644
		sp_change += 4;
Hannes Rapp's avatar
Hannes Rapp committed
645
646
647
648
	}

	for (i = memperm_arity-1; i >= 0; --i) {
		ir_entity *entity = be_get_MemPerm_out_entity(node, i);
649
650
651
		int        offset = be_get_stack_entity_offset(layout, entity, 0);

		sp_change -= 4;
Hannes Rapp's avatar
Hannes Rapp committed
652
653

		/* store to new entity */
654
		be_emit_irprintf("\tst %%l%d, [%%fp%+d]", i, offset);
Hannes Rapp's avatar
Hannes Rapp committed
655
656
		be_emit_finish_line_gas(node);
		/* restore register */
657
		be_emit_irprintf("\tld [%%sp%+d], %%l%d", sp_change + SPARC_MIN_STACKSIZE, i);
Hannes Rapp's avatar
Hannes Rapp committed
658
659
		be_emit_finish_line_gas(node);
	}
660
661
662
663

	be_emit_irprintf("\tadd %%sp, %d, %%sp", memperm_arity*4);
	be_emit_finish_line_gas(node);

Hannes Rapp's avatar
Hannes Rapp committed
664
665
666
	assert(sp_change == 0);
}

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
static void emit_be_Return(const ir_node *node)
{
	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 */
	if (delay_slot_filler != NULL &&
			(is_sparc_Restore(delay_slot_filler)
			 || is_sparc_RestoreZero(delay_slot_filler))) {
		destreg = "%i7";
	}
	be_emit_cstring("\tjmp ");
	be_emit_string(destreg);
	be_emit_cstring("+8");
	be_emit_finish_line_gas(node);
	fill_delay_slot();
}

685
static void emit_sparc_FrameAddr(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
686
{
687
688
	const sparc_attr_t *attr   = get_sparc_attr_const(node);
	int32_t             offset = attr->immediate_value;
689

690
	if (offset < 0) {
691
		be_emit_cstring("\tadd ");
692
		sparc_emit_source_register(node, 0);
693
		be_emit_cstring(", ");
694
695
		assert(sparc_is_value_imm_encodeable(offset));
		be_emit_irprintf("%ld", offset);
696
697
	} else {
		be_emit_cstring("\tsub ");
698
		sparc_emit_source_register(node, 0);
699
		be_emit_cstring(", ");
700
701
		assert(sparc_is_value_imm_encodeable(-offset));
		be_emit_irprintf("%ld", -offset);
702
703
	}

Hannes Rapp's avatar
Hannes Rapp committed
704
	be_emit_cstring(", ");
705
706
	sparc_emit_dest_register(node, 0);
	be_emit_finish_line_gas(node);
Hannes Rapp's avatar
Hannes Rapp committed
707
708
}

709
710
711
712
713
714
715
716
717
718
719
720
static const char *get_icc_unsigned(ir_relation relation)
{
	switch (relation & (ir_relation_less_equal_greater)) {
	case ir_relation_false:              return "bn";
	case ir_relation_equal:              return "be";
	case ir_relation_less:               return "blu";
	case ir_relation_less_equal:         return "bleu";
	case ir_relation_greater:            return "bgu";
	case ir_relation_greater_equal:      return "bgeu";
	case ir_relation_less_greater:       return "bne";
	case ir_relation_less_equal_greater: return "ba";
	default: panic("Cmp has unsupported relation");
721
722
723
	}
}

724
static const char *get_icc_signed(ir_relation relation)
725
{
726
727
728
729
730
731
732
733
734
735
	switch (relation & (ir_relation_less_equal_greater)) {
	case ir_relation_false:              return "bn";
	case ir_relation_equal:              return "be";
	case ir_relation_less:               return "bl";
	case ir_relation_less_equal:         return "ble";
	case ir_relation_greater:            return "bg";
	case ir_relation_greater_equal:      return "bge";
	case ir_relation_less_greater:       return "bne";
	case ir_relation_less_equal_greater: return "ba";
	default: panic("Cmp has unsupported relation");
736
737
738
	}
}

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
static const char *get_fcc(ir_relation relation)
{
	switch (relation) {
	case ir_relation_false:                   return "fbn";
	case ir_relation_equal:                   return "fbe";
	case ir_relation_less:                    return "fbl";
	case ir_relation_less_equal:              return "fble";
	case ir_relation_greater:                 return "fbg";
	case ir_relation_greater_equal:           return "fbge";
	case ir_relation_less_greater:            return "fblg";
	case ir_relation_less_equal_greater:      return "fbo";
	case ir_relation_unordered:               return "fbu";
	case ir_relation_unordered_equal:         return "fbue";
	case ir_relation_unordered_less:          return "fbul";
	case ir_relation_unordered_less_equal:    return "fbule";
	case ir_relation_unordered_greater:       return "fbug";
	case ir_relation_unordered_greater_equal: return "fbuge";
	case ir_relation_unordered_less_greater:  return "fbne";
	case ir_relation_true:                    return "fba";
758
	}
759
	panic("invalid relation");
760
761
}

762
typedef const char* (*get_cc_func)(ir_relation relation);
Hannes Rapp's avatar
Hannes Rapp committed
763

764
static void emit_sparc_branch(const ir_node *node, get_cc_func get_cc)
Hannes Rapp's avatar
Hannes Rapp committed
765
{
766
	const sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr_const(node);
767
	ir_relation      relation    = attr->relation;
768
769
	const ir_node   *proj_true   = NULL;
	const ir_node   *proj_false  = NULL;
770
	const ir_edge_t *edge;
771
772
773
774
	const ir_node   *block;
	const ir_node   *next_block;

	foreach_out_edge(node, edge) {
775
776
777
778
779
780
781
782
783
784
		ir_node *proj = get_edge_src_irn(edge);
		long nr = get_Proj_proj(proj);
		if (nr == pn_Cond_true) {
			proj_true = proj;
		} else {
			proj_false = proj;
		}
	}

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

	/* we have a block schedule */
788
	next_block = (ir_node*)get_irn_link(block);
789
790
791
792
793
794
795

	if (get_irn_link(proj_true) == next_block) {
		/* exchange both proj's so the second one can be omitted */
		const ir_node *t = proj_true;

		proj_true  = proj_false;
		proj_false = t;
796
		relation   = get_negated_relation(relation);
797
798
799
	}

	/* emit the true proj */
800
	be_emit_cstring("\t");
801
	be_emit_string(get_cc(relation));
802
	be_emit_char(' ');
803
804
805
	sparc_emit_cfop_target(proj_true);
	be_emit_finish_line_gas(proj_true);

806
	fill_delay_slot();
807
808

	if (get_irn_link(proj_false) == next_block) {
809
		be_emit_cstring("\t/* fallthrough to ");
810
811
812
813
814
815
816
		sparc_emit_cfop_target(proj_false);
		be_emit_cstring(" */");
		be_emit_finish_line_gas(proj_false);
	} else {
		be_emit_cstring("\tba ");
		sparc_emit_cfop_target(proj_false);
		be_emit_finish_line_gas(proj_false);
817
		fill_delay_slot();
818
	}
Hannes Rapp's avatar
Hannes Rapp committed
819
820
}

821
822
823
824
825
826
827
828
829
830
831
832
static void emit_sparc_Bicc(const ir_node *node)
{
	const sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr_const(node);
	bool             is_unsigned = attr->is_unsigned;
	emit_sparc_branch(node, is_unsigned ? get_icc_unsigned : get_icc_signed);
}

static void emit_sparc_fbfcc(const ir_node *node)
{
	emit_sparc_branch(node, get_fcc);
}

833
static void emit_sparc_Ba(const ir_node *node)
834
{
835
836
837
838
839
	if (ba_is_fallthrough(node)) {
		be_emit_cstring("\t/* fallthrough to ");
		sparc_emit_cfop_target(node);
		be_emit_cstring(" */");
	} else {
840
841
		be_emit_cstring("\tba ");
		sparc_emit_cfop_target(node);
842
		be_emit_finish_line_gas(node);
843
		fill_delay_slot();
844
845
846
847
	}
	be_emit_finish_line_gas(node);
}

848
849
850
851
852
853
854
static void emit_jump_table(const ir_node *node)
{
	const sparc_switch_jmp_attr_t *attr = get_sparc_switch_jmp_attr_const(node);
	long             switch_max    = LONG_MIN;
	long             default_pn    = attr->default_proj_num;
	ir_entity       *entity        = attr->jump_table;
	ir_node         *default_block = NULL;
855
	unsigned long    length;
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
	const ir_edge_t *edge;
	unsigned         i;
	ir_node        **table;

	/* go over all proj's and collect them */
	foreach_out_edge(node, edge) {
		ir_node *proj = get_edge_src_irn(edge);
		long     pn   = get_Proj_proj(proj);

		/* check for default proj */
		if (pn == default_pn) {
			assert(default_block == NULL); /* more than 1 default_pn? */
			default_block = get_jump_target(proj);
		} else {
			switch_max = pn > switch_max ? pn : switch_max;
		}
	}
873
874
875
876
877
878
879
880
881
	assert(switch_max > LONG_MIN);

	length = (unsigned long) switch_max + 1;
	/* the 16000 isn't a real limit of the architecture. But should protect us
	 * from seamingly endless compiler runs */
	if (length > 16000) {
		/* switch lowerer should have broken this monster to pieces... */
		panic("too large switch encountered");
	}
882
883
884
885
886
887
888
889

	table = XMALLOCNZ(ir_node*, length);
	foreach_out_edge(node, edge) {
		ir_node *proj = get_edge_src_irn(edge);
		long     pn   = get_Proj_proj(proj);
		if (pn == default_pn)
			continue;

890
		table[pn] = get_jump_target(proj);
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
	}

	/* emit table */
	be_gas_emit_switch_section(GAS_SECTION_RODATA);
	be_emit_cstring("\t.align 4\n");
	be_gas_emit_entity(entity);
	be_emit_cstring(":\n");
	for (i = 0; i < length; ++i) {
		ir_node *block = table[i];
		if (block == NULL)
			block = default_block;
		be_emit_cstring("\t.long ");
		be_gas_emit_block_name(block);
		be_emit_char('\n');
		be_emit_write_line();
	}
	be_gas_emit_switch_section(GAS_SECTION_TEXT);

	xfree(table);
}

static void emit_sparc_SwitchJmp(const ir_node *node)
{
	be_emit_cstring("\tjmp ");
	sparc_emit_source_register(node, 0);
	be_emit_finish_line_gas(node);
	fill_delay_slot();

	emit_jump_table(node);
}

922
923
924
static void emit_fmov(const ir_node *node, const arch_register_t *src_reg,
                      const arch_register_t *dst_reg)
{
Matthias Braun's avatar
Matthias Braun committed
925
	be_emit_cstring("\tfmovs %");
926
	be_emit_string(arch_register_get_name(src_reg));
Matthias Braun's avatar
Matthias Braun committed
927
	be_emit_cstring(", %");
928
929
930
931
932
933
	be_emit_string(arch_register_get_name(dst_reg));
	be_emit_finish_line_gas(node);
}

static const arch_register_t *get_next_fp_reg(const arch_register_t *reg)
{
934
	unsigned index = reg->global_index;
935
	assert(reg == &sparc_registers[index]);
936
	index++;
937
938
	assert(index - REG_F0 < N_sparc_fp_REGS);
	return &sparc_registers[index];
939
940
941
}

static void emit_be_Copy(const ir_node *node)
942
{
943
944
945
	ir_mode               *mode    = get_irn_mode(node);
	const arch_register_t *src_reg = get_in_reg(node, 0);
	const arch_register_t *dst_reg = get_out_reg(node, 0);
946

947
	if (src_reg == dst_reg)
948
949
950
		return;

	if (mode_is_float(mode)) {
951
952
953
954
955
956
957
958
959
		unsigned bits = get_mode_size_bits(mode);
		int      n    = bits > 32 ? bits > 64 ? 3 : 1 : 0;
		int      i;
		emit_fmov(node, src_reg, dst_reg);
		for (i = 0; i < n; ++i) {
			src_reg = get_next_fp_reg(src_reg);
			dst_reg = get_next_fp_reg(dst_reg);
			emit_fmov(node, src_reg, dst_reg);
		}
960
961
	} else if (mode_is_data(mode)) {
		be_emit_cstring("\tmov ");
962
		sparc_emit_source_register(node, 0);
963
		be_emit_cstring(", ");
964
965
		sparc_emit_dest_register(node, 0);
		be_emit_finish_line_gas(node);
966
	} else {
967
		panic("emit_be_Copy: invalid mode");
968
969
970
	}
}

Hannes Rapp's avatar
Hannes Rapp committed
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
static void emit_nothing(const ir_node *irn)
{
	(void) irn;
}

typedef void (*emit_func) (const ir_node *);

static inline void set_emitter(ir_op *op, emit_func sparc_emit_node)
{
	op->ops.generic = (op_func)sparc_emit_node;
}

/**
 * Enters the emitter functions for handled nodes into the generic
 * pointer of an opcode.
 */
static void sparc_register_emitters(void)
{
	/* first clear the generic function pointer for all ops */
	clear_irp_opcodes_generic_func();
	/* register all emitter functions defined in spec */
	sparc_register_spec_emitters();

	/* custom emitter */
995
996
997
998
999
1000
	set_emitter(op_be_Copy,         emit_be_Copy);
	set_emitter(op_be_CopyKeep,     emit_be_Copy);
	set_emitter(op_be_IncSP,        emit_be_IncSP);
	set_emitter(op_be_MemPerm,      emit_be_MemPerm);
	set_emitter(op_be_Perm,         emit_be_Perm);
	set_emitter(op_be_Return,       emit_be_Return);
1001
	set_emitter(op_sparc_Ba,        emit_sparc_Ba);
1002
	set_emitter(op_sparc_Bicc,      emit_sparc_Bicc);
1003
	set_emitter(op_sparc_Call,      emit_sparc_Call);
1004
	set_emitter(op_sparc_fbfcc,     emit_sparc_fbfcc);
1005
1006
	set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
	set_emitter(op_sparc_Mulh,      emit_sparc_Mulh);
1007
	set_emitter(op_sparc_SDiv,      emit_sparc_SDiv);
1008
	set_emitter(op_sparc_SwitchJmp, emit_sparc_SwitchJmp);
1009
	set_emitter(op_sparc_UDiv,      emit_sparc_UDiv);
1010
1011
1012
1013
1014

	/* no need to emit anything for the following nodes */
	set_emitter(op_be_Keep,    emit_nothing);
	set_emitter(op_be_Start,   emit_nothing);
	set_emitter(op_Phi,        emit_nothing);
Hannes Rapp's avatar
Hannes Rapp committed
1015
1016
1017
1018
1019
}

/**
 * Emits code for a node.
 */
1020
static void sparc_emit_node(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
1021
{
1022
	ir_op *op = get_irn_op(node);
Hannes Rapp's avatar
Hannes Rapp committed
1023
1024
1025
1026
1027
1028

	if (op->ops.generic) {
		emit_func func = (emit_func) op->ops.generic;
		be_dbg_set_dbg_info(get_irn_dbg_info(node));
		(*func) (node);
	} else {
1029
		panic("No emit handler for node %+F (graph %+F)\n", node,
1030
		      current_ir_graph);
Hannes Rapp's avatar
Hannes Rapp committed
1031
1032
1033
	}
}

1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
static ir_node *find_next_delay_slot(ir_node *from)
{
	ir_node *schedpoint = from;
	while (!has_delay_slot(schedpoint)) {
		if (!sched_has_next(schedpoint))
			return NULL;
		schedpoint = sched_next(schedpoint);
	}
	return schedpoint;
}

Hannes Rapp's avatar
Hannes Rapp committed
1045
1046
1047
1048
/**
 * Walks over the nodes in a block connected by scheduling edges
 * and emits code for each node.
 */
1049
static void sparc_emit_block(ir_node *block)
1050
{
Hannes Rapp's avatar
Hannes Rapp committed
1051
	ir_node *node;
1052
	ir_node *next_delay_slot;
Hannes Rapp's avatar
Hannes Rapp committed
1053

1054
	assert(is_Block(block));
1055
1056
1057

	be_gas_emit_block_name(block);
	be_emit_cstring(":\n");
Hannes Rapp's avatar
Hannes Rapp committed
1058
	be_emit_write_line();
1059

1060
1061
1062
1063
	next_delay_slot = find_next_delay_slot(sched_first(block));
	if (next_delay_slot != NULL)
		delay_slot_filler = pick_delay_slot_for(next_delay_slot);

Hannes Rapp's avatar
Hannes Rapp committed
1064
	sched_foreach(block, node) {
1065
1066
1067
1068
		if (node == delay_slot_filler) {
			continue;
		}

Hannes Rapp's avatar
Hannes Rapp committed
1069
		sparc_emit_node(node);
1070
1071
1072
1073
1074
1075
1076

		if (node == next_delay_slot) {
			assert(delay_slot_filler == NULL);
			next_delay_slot = find_next_delay_slot(sched_next(node));
			if (next_delay_slot != NULL)
				delay_slot_filler = pick_delay_slot_for(next_delay_slot);
		}
Hannes Rapp's avatar
Hannes Rapp committed
1077
1078
1079
1080
1081
1082
	}
}

/**
 * Emits code for function start.
 */
1083
static void sparc_emit_func_prolog(ir_graph *irg)
1084
{
Hannes Rapp's avatar
Hannes Rapp committed
1085
	ir_entity *ent = get_irg_entity(irg);
1086
	be_gas_emit_function_prolog(ent, 4);
Hannes Rapp's avatar
Hannes Rapp committed
1087
1088
1089
1090
1091
1092
	be_emit_write_line();
}

/**
 * Emits code for function end
 */
1093
static void sparc_emit_func_epilog(ir_graph *irg)
1094
{
Hannes Rapp's avatar
Hannes Rapp committed
1095
1096
	ir_entity *ent = get_irg_entity(irg);
	const char *irg_name = get_entity_ld_name(ent);
1097
	be_emit_write_line();
Hannes Rapp's avatar
Hannes Rapp committed
1098
1099
1100
1101
1102
1103
1104
	be_emit_irprintf("\t.size  %s, .-%s\n", irg_name, irg_name);
	be_emit_cstring("# -- End ");
	be_emit_string(irg_name);
	be_emit_cstring("\n");
	be_emit_write_line();
}

1105
static void sparc_gen_labels(ir_node *block, void *env)
1106
{
Hannes Rapp's avatar
Hannes Rapp committed
1107
1108
1109
1110
1111
1112
	ir_node *pred;
	int n = get_Block_n_cfgpreds(block);
	(void) env;

	for (n--; n >= 0; n--) {
		pred = get_Block_cfgpred(block, n);
1113
		set_irn_link(pred, block); // link the pred of a block (which is a jmp)
Hannes Rapp's avatar
Hannes Rapp committed
1114
1115
1116
	}
}

1117
void sparc_emit_routine(ir_graph *irg)
Hannes Rapp's avatar
Hannes Rapp committed
1118
{
1119
1120
	ir_entity  *entity = get_irg_entity(irg);
	ir_node   **block_schedule;
Michael Beck's avatar
Michael Beck committed
1121
1122
	size_t      i;
	size_t      n;
Hannes Rapp's avatar
Hannes Rapp committed
1123

1124
	be_gas_elf_type_char      = '#';
1125
	be_gas_object_file_format = OBJECT_FILE_FORMAT_ELF_SPARC;
1126

1127
1128
	heights = heights_new(irg);

Hannes Rapp's avatar
Hannes Rapp committed
1129
1130
	/* register all emitter functions */
	sparc_register_emitters();
1131
	be_dbg_method_begin(entity);
1132
1133

	/* create the block schedule. For now, we don't need it earlier. */
1134
	block_schedule = be_create_block_schedule(irg);
1135

Hannes Rapp's avatar
Hannes Rapp committed
1136
1137
1138
	sparc_emit_func_prolog(irg);
	irg_block_walk_graph(irg, sparc_gen_labels, NULL, NULL);

1139
1140
1141
1142
1143
1144
1145
	/* inject block scheduling links & emit code of each block */
	n = ARR_LEN(block_schedule);
	for (i = 0; i < n; ++i) {
		ir_node *block      = block_schedule[i];
		ir_node *next_block = i+1 < n ? block_schedule[i+1] : NULL;
		set_irn_link(block, next_block);
	}
1146

1147
1148
1149
1150
1151
	for (i = 0; i < n; ++i) {
		ir_node *block = block_schedule[i];
		if (block == get_irg_end_block(irg))
			continue;
		sparc_emit_block(block);
1152
1153
	}

1154
	/* emit function epilog */
1155
	sparc_emit_func_epilog(irg);
1156
1157

	heights_free(heights);
Hannes Rapp's avatar
Hannes Rapp committed
1158
1159
1160
1161
1162
1163
}

void sparc_init_emitter(void)
{
	FIRM_DBG_REGISTER(dbg, "firm.be.sparc.emit");
}