amd64_new_nodes.c 9.2 KB
Newer Older
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
4
5
6
7
8
9
10
11
12
 */

/**
 * @file
 * @brief   This file implements the creation of the achitecture specific firm
 *          opcodes and the coresponding node constructors for the amd64
 *          assembler irg.
 */
#include <stdlib.h>
Matthias Braun's avatar
Matthias Braun committed
13
#include <inttypes.h>
14

15
#include "error.h"
16
17
18
19
20
21
22
23
24
25
#include "irprog_t.h"
#include "irgraph_t.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "ircons_t.h"
#include "iropt_t.h"
#include "irop.h"
#include "irprintf.h"
#include "xmalloc.h"

26
#include "bearch.h"
27
28
29
30
31

#include "amd64_nodes_attr.h"
#include "amd64_new_nodes.h"
#include "gen_amd64_regalloc_if.h"

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
static const char *get_op_mode_string(amd64_op_mode_t mode)
{
	switch (mode) {
	case AMD64_OP_NONE:       return "none";
	case AMD64_OP_ADDR:       return "addr";
	case AMD64_OP_REG:        return "reg";
	case AMD64_OP_REG_REG:    return "reg+reg";
	case AMD64_OP_REG_IMM:    return "reg+imm";
	case AMD64_OP_IMM32:      return "imm32";
	case AMD64_OP_IMM64:      return "imm64";
	case AMD64_OP_ADDR_REG:   return "addr+reg";
	case AMD64_OP_ADDR_IMM:   return "addr+imm";
	case AMD64_OP_UNOP_REG:   return "unop_reg";
	case AMD64_OP_SHIFT_REG:  return "shift_reg";
	case AMD64_OP_SHIFT_IMM:  return "shift_imm";
	case AMD64_OP_CALL_ADDR:  return "call_addr";
	case AMD64_OP_CALL_IMM32: return "call_imm32";
	case AMD64_OP_RAX_REG:    return "rax_reg";
	case AMD64_OP_RAX_ADDR:   return "rax_addr";
	}
	panic("invalid op_mode");
}

static const char *get_insn_mode_string(amd64_insn_mode_t mode)
{
	switch (mode) {
	case INSN_MODE_8:  return "8";
	case INSN_MODE_16: return "16";
	case INSN_MODE_32: return "32";
	case INSN_MODE_64: return "64";
	}
	panic("invalid insn_mode");
}

66
67
68
/**
 * Dumper interface for dumping amd64 nodes in vcg.
 * @param F        the output file
69
 * @param n        the node to dump
70
71
 * @param reason   indicates which kind of information should be dumped
 */
72
static void amd64_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
73
74
75
76
77
78
79
{
	switch (reason) {
	case dump_node_opcode_txt:
		fprintf(F, "%s", get_irn_opname(n));
		break;

	case dump_node_mode_txt:
80
		fprintf(F, "[%s]", get_mode_name(get_irn_mode(n)));
81
82
83
84
85
86
87
		break;

	case dump_node_nodeattr_txt:
		break;

	case dump_node_info_txt:
		arch_dump_reqs_and_registers(F, n);
Matthias Braun's avatar
Matthias Braun committed
88
		const amd64_attr_t *attr = get_amd64_attr_const(n);
89
		fprintf(F, "mode = %s\n", get_op_mode_string(attr->op_mode));
90
91
		switch (attr->op_mode) {
		case AMD64_OP_UNOP_REG: {
92
			const amd64_unop_attr_t *unop_attr = get_amd64_unop_attr_const(n);
93
94
			fprintf(F, "size = %s\n", get_insn_mode_string(unop_attr->insn_mode));
			break;
Matthias Braun's avatar
Matthias Braun committed
95
		}
96
97
98
99
100
101
102
103

		case AMD64_OP_ADDR_REG: {
			const amd64_binop_addr_attr_t *binop_attr = get_amd64_binop_addr_attr_const(n);
			fprintf(F, "reg input: %d\n", binop_attr->u.reg_input);
		} /* FALLTHROUGH */
		case AMD64_OP_ADDR: {
			const amd64_addr_attr_t *addr_attr = get_amd64_addr_attr_const(n);
			fprintf(F, "size = %s\n", get_insn_mode_string(addr_attr->insn_mode));
Matthias Braun's avatar
Matthias Braun committed
104
105
			fprintf(F, "base input: %d\n", addr_attr->addr.base_input);
			fprintf(F, "index input: %d\n", addr_attr->addr.index_input);
106
107
108
			ir_fprintf(F, "am imm: %+F%+" PRId32 "\n", addr_attr->addr.immediate.entity, addr_attr->addr.immediate.offset);
			break;
		}
Matthias Braun's avatar
Matthias Braun committed
109
		}
110
111
112
113
		break;
	}
}

Matthias Braun's avatar
Matthias Braun committed
114
115
static void init_be_info(ir_node *node, arch_irn_flags_t flags,
                         const arch_register_req_t **in_reqs, int n_res)
116
{
117
118
119
120
121
122
123
	arch_set_irn_flags(node, flags);
	arch_set_irn_register_reqs_in(node, in_reqs);

	ir_graph       *irg  = get_irn_irg(node);
	struct obstack *obst = get_irg_obstack(irg);
	backend_info_t *info = be_get_info(node);
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_res);
124
125
}

Matthias Braun's avatar
Matthias Braun committed
126
127
128
static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
                                  const arch_register_req_t **in_reqs,
                                  int n_res, amd64_op_mode_t op_mode)
129
{
Matthias Braun's avatar
Matthias Braun committed
130
131
132
133
	init_be_info(node, flags, in_reqs, n_res);
	amd64_attr_t *attr = get_amd64_attr(node);
	attr->op_mode = op_mode;
}
134

Matthias Braun's avatar
Matthias Braun committed
135
136
137
138
static void init_amd64_switch_attributes(ir_node *node,
                                         const ir_switch_table *table,
                                         ir_entity *table_entity)
{
139
140
141
142
	amd64_switch_jmp_attr_t *attr = get_amd64_switch_jmp_attr(node);
	attr->table        = table;
	attr->table_entity = table_entity;

Matthias Braun's avatar
Matthias Braun committed
143
	for (unsigned o = 0, n_outs = arch_get_irn_n_outs(node); o < n_outs; o++) {
144
145
146
147
		arch_set_irn_register_req_out(node, o, arch_no_register_req);
	}
}

148
static void init_amd64_cc_attributes(ir_node *node, x86_condition_code_t cc)
149
{
150
	amd64_cc_attr_t *attr = get_amd64_cc_attr(node);
151
	attr->cc = cc;
152
153
}

Matthias Braun's avatar
Matthias Braun committed
154
155
156
static void init_amd64_movimm_attributes(ir_node *node,
                                         amd64_insn_mode_t insn_mode,
                                         ir_entity *entity, int64_t offset)
157
{
158
	amd64_movimm_attr_t *attr = get_amd64_movimm_attr(node);
Matthias Braun's avatar
Matthias Braun committed
159
160
161
	attr->insn_mode        = insn_mode;
	attr->immediate.entity = entity;
	attr->immediate.offset = offset;
162
163
}

Matthias Braun's avatar
Matthias Braun committed
164
165
static int cmp_imm32(const amd64_imm32_t *const imm0,
                     const amd64_imm32_t *const imm1)
Matthias Braun's avatar
Matthias Braun committed
166
{
Matthias Braun's avatar
Matthias Braun committed
167
168
169
170
171
172
173
174
175
176
177
178
179
	return imm0->offset != imm1->offset || imm0->entity != imm1->entity;
}

static int cmp_imm64(const amd64_imm64_t *const imm0,
                     const amd64_imm64_t *const imm1)
{
	return imm0->offset != imm1->offset || imm0->entity != imm1->entity;
}

static int cmp_addr(const amd64_addr_t *const am0,
                    const amd64_addr_t *const am1)
{
	return cmp_imm32(&am0->immediate, &am1->immediate)
Matthias Braun's avatar
Matthias Braun committed
180
181
182
183
184
185
	    || am0->base_input != am1->base_input
	    || am0->index_input != am1->index_input
	    || am0->log_scale != am1->log_scale
	    || am0->segment != am1->segment;
}

Michael Beck's avatar
Michael Beck committed
186
static int cmp_amd64_attr(const ir_node *a, const ir_node *b)
187
188
189
{
	const amd64_attr_t *attr_a = get_amd64_attr_const(a);
	const amd64_attr_t *attr_b = get_amd64_attr_const(b);
Matthias Braun's avatar
Matthias Braun committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
	return attr_a->op_mode != attr_b->op_mode;
}

static int cmp_amd64_addr_attr(const ir_node *a, const ir_node *b)
{
	const amd64_addr_attr_t *attr_a = get_amd64_addr_attr_const(a);
	const amd64_addr_attr_t *attr_b = get_amd64_addr_attr_const(b);
	return cmp_amd64_attr(a, b)
	    || cmp_addr(&attr_a->addr, &attr_b->addr)
	    || attr_a->insn_mode != attr_b->insn_mode
	    || attr_a->needs_frame_ent != attr_b->needs_frame_ent;
}

static int cmp_amd64_unop_attr(const ir_node *a, const ir_node *b)
{
	const amd64_unop_attr_t *attr_a = get_amd64_unop_attr_const(a);
	const amd64_unop_attr_t *attr_b = get_amd64_unop_attr_const(b);
	return cmp_amd64_attr(a, b)
	    || attr_a->insn_mode != attr_b->insn_mode;
}

static int cmp_amd64_binop_addr_attr(const ir_node *a,
                                     const ir_node *b)
{
	const amd64_binop_addr_attr_t *attr_a = get_amd64_binop_addr_attr_const(a);
	const amd64_binop_addr_attr_t *attr_b = get_amd64_binop_addr_attr_const(b);
	if (cmp_amd64_addr_attr(a, b))
		return 1;
	amd64_op_mode_t op_mode = attr_a->base.base.op_mode;
	if (op_mode == AMD64_OP_REG_IMM || op_mode == AMD64_OP_ADDR_IMM) {
		return cmp_imm32(&attr_a->u.immediate, &attr_b->u.immediate);
	} else {
		return attr_a->u.reg_input != attr_b->u.reg_input;
	}
224
225
226
227
228
229
230
}

static int cmp_amd64_movimm_attr(const ir_node *const a,
                                 const ir_node *const b)
{
	const amd64_movimm_attr_t *const attr_a = get_amd64_movimm_attr_const(a);
	const amd64_movimm_attr_t *const attr_b = get_amd64_movimm_attr_const(b);
Matthias Braun's avatar
Matthias Braun committed
231
232
233
234
235
236
237
238
239
240
241
242
243
	return cmp_amd64_attr(a, b)
	    || cmp_imm64(&attr_a->immediate, &attr_b->immediate)
	    || attr_a->insn_mode != attr_b->insn_mode;
}

static int cmp_amd64_shift_attr(const ir_node *const a,
                                const ir_node *const b)
{
	const amd64_shift_attr_t *const attr_a = get_amd64_shift_attr_const(a);
	const amd64_shift_attr_t *const attr_b = get_amd64_shift_attr_const(b);
	return cmp_amd64_attr(a, b)
	    || attr_a->immediate != attr_b->immediate
	    || attr_a->insn_mode != attr_b->insn_mode;
244
245
246
247
248
249
250
251
252
}

static int cmp_amd64_cc_attr(const ir_node *const a,
                             const ir_node *const b)
{
	if (cmp_amd64_attr(a, b))
		return true;
	const amd64_cc_attr_t *const attr_a = get_amd64_cc_attr_const(a);
	const amd64_cc_attr_t *const attr_b = get_amd64_cc_attr_const(b);
253
	return attr_a->cc != attr_b->cc;
254
255
256
257
258
259
260
261
262
263
264
265
}

static int cmp_amd64_switch_jmp_attr(const ir_node *const a,
                                    const ir_node *const b)
{
	if (cmp_amd64_attr(a, b))
		return true;
	const amd64_switch_jmp_attr_t *const attr_a
		= get_amd64_switch_jmp_attr_const(a);
	const amd64_switch_jmp_attr_t *const attr_b
		= get_amd64_switch_jmp_attr_const(b);
	return attr_a->table != attr_b->table;
266
267
}

268
static void amd64_copy_attr(ir_graph *irg, const ir_node *old_node,
269
                            ir_node *new_node)
270
271
272
273
274
275
276
277
278
279
280
{
	struct obstack   *obst       = get_irg_obstack(irg);
	const amd64_attr_t *attr_old = get_amd64_attr_const(old_node);
	amd64_attr_t     *attr_new   = get_amd64_attr(new_node);
	backend_info_t   *old_info   = be_get_info(old_node);
	backend_info_t   *new_info   = be_get_info(new_node);

	/* copy the attributes */
	memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));

	/* copy out flags */
281
	new_info->flags = old_info->flags;
282
283
	new_info->out_infos =
		DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
284
	new_info->in_reqs = old_info->in_reqs;
285
286
}

287
288
/* Include the generated constructor functions */
#include "gen_amd64_new_nodes.c.inl"