amd64_new_nodes.c 9.13 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

Matthias Braun's avatar
Matthias Braun committed
15
#include "panic.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
#include "bedump.h"
28
29
30

#include "amd64_nodes_attr.h"
#include "amd64_new_nodes.h"
31
#include "bearch_amd64_t.h"
32
33
#include "gen_amd64_regalloc_if.h"

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

static const char *get_insn_mode_string(amd64_insn_mode_t mode)
{
	switch (mode) {
60
61
62
63
64
	case INSN_MODE_8:   return "8";
	case INSN_MODE_16:  return "16";
	case INSN_MODE_32:  return "32";
	case INSN_MODE_64:  return "64";
	case INSN_MODE_128: return "128";
65
	case INSN_MODE_INVALID: break;
66
67
68
69
	}
	panic("invalid insn_mode");
}

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

	case dump_node_mode_txt:
84
		fprintf(F, "[%s]", get_mode_name(get_irn_mode(n)));
85
86
87
88
89
90
		break;

	case dump_node_nodeattr_txt:
		break;

	case dump_node_info_txt:
91
		be_dump_reqs_and_registers(F, n);
Matthias Braun's avatar
Matthias Braun committed
92
		const amd64_attr_t *attr = get_amd64_attr_const(n);
93
		fprintf(F, "mode = %s\n", get_op_mode_string(attr->op_mode));
94
95
		amd64_op_mode_t op_mode = attr->op_mode;
		if (op_mode == AMD64_OP_ADDR_REG) {
96
97
			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);
98
99
100
101
102
		} else if (op_mode == AMD64_OP_IMM64) {
			const amd64_imm64_t *const imm
				= &get_amd64_movimm_attr_const(n)->immediate;
			ir_fprintf(F, "imm64 entity: %+F\n", imm->entity);
			fprintf(F, "imm64 offset: 0x%" PRIX64 "\n", (uint64_t)imm->offset);
103
104
		}
		if (amd64_has_addr_attr(n)) {
105
106
			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
107
108
			fprintf(F, "base input: %d\n", addr_attr->addr.base_input);
			fprintf(F, "index input: %d\n", addr_attr->addr.index_input);
109
110
111
			ir_fprintf(F, "am imm: %+F%+" PRId32 "\n", addr_attr->addr.immediate.entity, addr_attr->addr.immediate.offset);
			break;
		}
112
113
114
	}
}

Matthias Braun's avatar
Matthias Braun committed
115
116
static void init_be_info(ir_node *node, arch_irn_flags_t flags,
                         const arch_register_req_t **in_reqs, int n_res)
117
{
118
119
120
121
122
123
124
	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);
125
126
}

Matthias Braun's avatar
Matthias Braun committed
127
128
129
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)
130
{
Matthias Braun's avatar
Matthias Braun committed
131
132
133
134
	init_be_info(node, flags, in_reqs, n_res);
	amd64_attr_t *attr = get_amd64_attr(node);
	attr->op_mode = op_mode;
}
135

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

Christoph Mallon's avatar
Christoph Mallon committed
144
	be_foreach_out(node, o) {
145
146
147
148
		arch_set_irn_register_req_out(node, o, arch_no_register_req);
	}
}

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

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

165
166
static bool imm32s_equal(const amd64_imm32_t *const imm0,
                         const amd64_imm32_t *const imm1)
Matthias Braun's avatar
Matthias Braun committed
167
{
168
	return imm0->offset == imm1->offset && imm0->entity == imm1->entity;
Matthias Braun's avatar
Matthias Braun committed
169
170
}

171
172
static bool imm64s_equal(const amd64_imm64_t *const imm0,
                         const amd64_imm64_t *const imm1)
Matthias Braun's avatar
Matthias Braun committed
173
{
174
	return imm0->offset == imm1->offset && imm0->entity == imm1->entity;
Matthias Braun's avatar
Matthias Braun committed
175
176
}

177
178
static bool amd64_addrs_equal(const amd64_addr_t *const am0,
                              const amd64_addr_t *const am1)
Matthias Braun's avatar
Matthias Braun committed
179
{
180
181
182
183
184
	return imm32s_equal(&am0->immediate, &am1->immediate)
	    && am0->base_input == am1->base_input
	    && am0->index_input == am1->index_input
	    && am0->log_scale == am1->log_scale
	    && am0->segment == am1->segment;
Matthias Braun's avatar
Matthias Braun committed
185
186
}

187
static int amd64_attrs_equal(const ir_node *a, const ir_node *b)
188
189
190
{
	const amd64_attr_t *attr_a = get_amd64_attr_const(a);
	const amd64_attr_t *attr_b = get_amd64_attr_const(b);
191
	return attr_a->op_mode == attr_b->op_mode;
Matthias Braun's avatar
Matthias Braun committed
192
193
}

194
static int amd64_addr_attrs_equal(const ir_node *a, const ir_node *b)
Matthias Braun's avatar
Matthias Braun committed
195
196
197
{
	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);
198
199
200
201
	return amd64_attrs_equal(a, b)
	    && amd64_addrs_equal(&attr_a->addr, &attr_b->addr)
	    && attr_a->insn_mode == attr_b->insn_mode
	    && attr_a->needs_frame_ent == attr_b->needs_frame_ent;
Matthias Braun's avatar
Matthias Braun committed
202
203
}

204
205
static int amd64_binop_addr_attrs_equal(const ir_node *a,
                                        const ir_node *b)
Matthias Braun's avatar
Matthias Braun committed
206
207
208
{
	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);
209
210
	if (!amd64_addr_attrs_equal(a, b))
		return false;
Matthias Braun's avatar
Matthias Braun committed
211
212
	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) {
213
		return imm32s_equal(&attr_a->u.immediate, &attr_b->u.immediate);
Matthias Braun's avatar
Matthias Braun committed
214
	} else {
215
		return attr_a->u.reg_input == attr_b->u.reg_input;
Matthias Braun's avatar
Matthias Braun committed
216
	}
217
218
}

219
220
static int amd64_movimm_attrs_equal(const ir_node *const a,
                                    const ir_node *const b)
221
222
223
{
	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);
224
225
226
	return amd64_attrs_equal(a, b)
	    && imm64s_equal(&attr_a->immediate, &attr_b->immediate)
	    && attr_a->insn_mode == attr_b->insn_mode;
Matthias Braun's avatar
Matthias Braun committed
227
228
}

229
230
static int amd64_shift_attrs_equal(const ir_node *const a,
                                   const ir_node *const b)
Matthias Braun's avatar
Matthias Braun committed
231
232
233
{
	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);
234
235
236
	return amd64_attrs_equal(a, b)
	    && attr_a->immediate == attr_b->immediate
	    && attr_a->insn_mode == attr_b->insn_mode;
237
238
}

239
240
static int amd64_cc_attrs_equal(const ir_node *const a,
                                const ir_node *const b)
241
242
243
{
	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);
244
	return amd64_attrs_equal(a, b) && attr_a->cc == attr_b->cc;
245
246
}

247
248
static int amd64_switch_jmp_attrs_equal(const ir_node *const a,
                                        const ir_node *const b)
249
250
251
252
253
{
	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);
254
	return amd64_attrs_equal(a, b) && attr_a->table == attr_b->table;
255
256
}

257
static void amd64_copy_attr(ir_graph *irg, const ir_node *old_node,
258
                            ir_node *new_node)
259
260
261
262
263
264
265
266
267
268
269
{
	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 */
270
	new_info->flags = old_info->flags;
271
272
	new_info->out_infos =
		DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
273
	new_info->in_reqs = old_info->in_reqs;
274
275
}

276
277
/* Include the generated constructor functions */
#include "gen_amd64_new_nodes.c.inl"