4a71cd70009a423d907a66e288d70214a3c1376b
[libfirm] / ir / be / amd64 / amd64_spec.pl
1 # Creation: 2006/02/13
2 # $Id: amd64_spec.pl 26673 2009-10-01 16:43:13Z matze $
3
4 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
5
6 $arch = "amd64";
7
8 # The node description is done as a perl hash initializer with the
9 # following structure:
10 #
11 # %nodes = (
12 #
13 # <op-name> => {
14 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",                 # optional
15 #   irn_flags => "R|N|I"                                # optional
16 #   arity     => "0|1|2|3 ... |variable|dynamic|any",   # optional
17 #   state     => "floats|pinned|mem_pinned|exc_pinned", # optional
18 #   args      => [
19 #                    { type => "type 1", name => "name 1" },
20 #                    { type => "type 2", name => "name 2" },
21 #                    ...
22 #                  ],
23 #   comment   => "any comment for constructor",  # optional
24 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
25 #   cmp_attr  => "c source code for comparing node attributes", # optional
26 #   outs      => { "out1", "out2" },# optional, creates pn_op_out1, ... consts
27 #   ins       => { "in1", "in2" },  # optional, creates n_op_in1, ... consts
28 #   mode      => "mode_Iu",         # optional, predefines the mode
29 #   emit      => "emit code with templates",   # optional for virtual nodes
30 #   attr      => "additional attribute arguments for constructor", # optional
31 #   init_attr => "emit attribute initialization template",         # optional
32 #   rd_constructor => "c source code which constructs an ir_node", # optional
33 #   hash_func => "name of the hash function for this operation",   # optional, get the default hash function else
34 #   latency   => "latency of this operation (can be float)"        # optional
35 #   attr_type => "name of the attribute struct",                   # optional
36 # },
37 #
38 # ... # (all nodes you need to describe)
39 #
40 # ); # close the %nodes initializer
41
42 # op_flags: flags for the operation, OPTIONAL (default is "N")
43 # the op_flags correspond to the firm irop_flags:
44 #   N   irop_flag_none
45 #   L   irop_flag_labeled
46 #   C   irop_flag_commutative
47 #   X   irop_flag_cfopcode
48 #   I   irop_flag_ip_cfopcode
49 #   F   irop_flag_fragile
50 #   Y   irop_flag_forking
51 #   H   irop_flag_highlevel
52 #   c   irop_flag_constlike
53 #   K   irop_flag_keep
54 #
55 # irn_flags: special node flags, OPTIONAL (default is 0)
56 # following irn_flags are supported:
57 #   R   rematerializeable
58 #   N   not spillable
59 #   I   ignore for register allocation
60 #
61 # state: state of the operation, OPTIONAL (default is "floats")
62 #
63 # arity: arity of the operation, MUST NOT BE OMITTED
64 #
65 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
66 #        are always the first 3 arguments and are always autmatically
67 #        created)
68 #        If this key is missing the following arguments will be created:
69 #        for i = 1 .. arity: ir_node *op_i
70 #        ir_mode *mode
71 #
72 # outs:  if a node defines more than one output, the names of the projections
73 #        nodes having outs having automatically the mode mode_T
74 #
75 # comment: OPTIONAL comment for the node constructor
76 #
77 # rd_constructor: for every operation there will be a
78 #      new_rd_<arch>_<op-name> function with the arguments from above
79 #      which creates the ir_node corresponding to the defined operation
80 #      you can either put the complete source code of this function here
81 #
82 #      This key is OPTIONAL. If omitted, the following constructor will
83 #      be created:
84 #      if (!op_<arch>_<op-name>) assert(0);
85 #      for i = 1 to arity
86 #         set in[i] = op_i
87 #      done
88 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
89 #      return res
90 #
91 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
92
93 # register types:
94 #   0 - no special type
95 #   1 - caller save (register must be saved by the caller of a function)
96 #   2 - callee save (register must be saved by the called function)
97 #   4 - ignore (do not assign this register)
98 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
99 %reg_classes = (
100         gp => [
101                 { name => "rax", type => 1 },
102                 { name => "rcx", type => 1 },
103                 { name => "rdx", type => 1 },
104                 { name => "rsi", type => 1 },
105                 { name => "rdi", type => 1 },
106                 { name => "rbx", type => 2 },
107                 { name => "rbp", type => 2 },
108                 { name => "rsp", type => 4 }, # stackpointer?
109                 { name => "r8",  type => 1 },
110                 { name => "r9",  type => 1 },
111                 { name => "r10", type => 1 },
112                 { name => "r11", type => 1 },
113                 { name => "r12", type => 2 },
114                 { name => "r13", type => 2 },
115                 { name => "r14", type => 2 },
116                 { name => "r15", type => 2 },
117 #               { name => "gp_NOREG", type => 4 }, # we need a dummy register for NoReg nodes
118                 { mode => "mode_Lu" }
119         ],
120 #       fp => [
121 #               { name => "xmm0", type => 1 },
122 #               { name => "xmm1", type => 1 },
123 #               { name => "xmm2", type => 1 },
124 #               { name => "xmm3", type => 1 },
125 #               { name => "xmm4", type => 1 },
126 #               { name => "xmm5", type => 1 },
127 #               { name => "xmm6", type => 1 },
128 #               { name => "xmm7", type => 1 },
129 #               { name => "xmm8", type => 1 },
130 #               { name => "xmm9", type => 1 },
131 #               { name => "xmm10", type => 1 },
132 #               { name => "xmm11", type => 1 },
133 #               { name => "xmm12", type => 1 },
134 #               { name => "xmm13", type => 1 },
135 #               { name => "xmm14", type => 1 },
136 #               { name => "xmm15", type => 1 },
137 #               { mode => "mode_D" }
138 #       ]
139         flags => [
140                 { name => "eflags", type => 0 },
141                 { mode => "mode_Iu", flags => "manual_ra" }
142         ],
143 );
144
145 $mode_gp        = "mode_Lu";
146 $mode_flags     = "mode_Iu";
147
148 sub amd64_custom_init_attr {
149         my $constr = shift;
150         my $node   = shift;
151         my $name   = shift;
152         my $res    = "";
153
154         if(defined($node->{modified_flags})) {
155                 $res .= "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n";
156         }
157         return $res;
158 }
159 $custom_init_attr_func = \&amd64_custom_init_attr;
160
161 $default_copy_attr = "amd64_copy_attr";
162
163 %emit_templates = (
164         S1 => "${arch}_emit_source_register(node, 0);",
165         S2 => "${arch}_emit_source_register(node, 1);",
166         S3 => "${arch}_emit_source_register(node, 2);",
167         S4 => "${arch}_emit_source_register(node, 3);",
168         S5 => "${arch}_emit_source_register(node, 4);",
169         S6 => "${arch}_emit_source_register(node, 5);",
170         D1 => "${arch}_emit_dest_register(node, 0);",
171         D2 => "${arch}_emit_dest_register(node, 1);",
172         D3 => "${arch}_emit_dest_register(node, 2);",
173         D4 => "${arch}_emit_dest_register(node, 3);",
174         D5 => "${arch}_emit_dest_register(node, 4);",
175         D6 => "${arch}_emit_dest_register(node, 5);",
176         C  => "${arch}_emit_immediate(node);",
177         O  => "${arch}_emit_fp_offset(node);",
178 );
179
180 %init_attr = (
181         amd64_attr_t           =>
182                  "\tinit_amd64_attributes(res, flags, in_reqs, exec_units, n_res);",
183         amd64_SymConst_attr_t =>
184                 "\tinit_amd64_attributes(res, flags, in_reqs, exec_units, n_res);"
185                 . "\tinit_amd64_SymConst_attributes(res, entity);",
186         amd64_condcode_attr_t =>
187                 "\tinit_amd64_attributes(res, flags, in_reqs, exec_units, n_res);"
188                 . "\tinit_amd64_condcode_attributes(res, pnc);",
189 );
190
191 %compare_attr = (
192         amd64_attr_t           => "cmp_amd64_attr",
193         amd64_SymConst_attr_t  => "cmp_amd64_attr_SymConst",
194         amd64_condcode_attr_t  => "cmp_amd64_attr_condcode",
195 );
196
197 %nodes = (
198 Push => {
199         state     => "exc_pinned",
200         reg_req   => { in => [ "gp", "gp", "none", "gp", "rsp" ], out => [ "rsp:I|S", "none" ] },
201         ins       => [ "base", "index", "mem", "val", "stack" ],
202         emit      => '. push %S1',
203         outs      => [ "stack", "M" ],
204         am        => "source,unary",
205         latency   => 2,
206 #       units     => [ "GP" ],
207 },
208 Add => {
209         op_flags   => "C",
210         irn_flags  => "R",
211         state      => "exc_pinned",
212         reg_req    => { in => [ "gp", "gp" ],
213                         out => [ "gp" ] },
214         in         => [ "left", "right" ],
215         outs       => [ "res" ],
216         mode       => $mode_gp,
217         modified_flags => 1,
218 },
219 Mul => {
220         # we should not rematrialize this node. It produces 2 results and has
221         # very strict constraints
222         state     => "exc_pinned",
223         reg_req   => { in  => [ "rax", "gp" ],
224                        out => [ "rax rdx" ] },
225         ins       => [ "left", "right" ],
226         emit      => '. mul %S2',
227         outs      => [ "res" ],
228         mode      => $mode_gp,
229         am        => "source,binary",
230         modified_flags => $status_flags
231 },
232 Sub => {
233         irn_flags  => "R",
234         state      => "exc_pinned",
235         reg_req    => { in => [ "gp", "gp" ],
236                         out => [ "gp" ] },
237         in         => [ "left", "right" ],
238         outs       => [ "res" ],
239         mode       => $mode_gp,
240         modified_flags => 1,
241 },
242 Neg => {
243         irn_flags => "R",
244         reg_req   => { in => [ "gp" ],
245                        out => [ "in_r1", "flags" ] },
246         emit      => '. neg %S1',
247         ins       => [ "val" ],
248         outs      => [ "res", "flags" ],
249         mode      => $mode_gp,
250         modified_flags => $status_flags
251 },
252 Immediate => {
253         op_flags  => "c",
254         attr      => "unsigned imm_value",
255         init_attr => "attr->ext.imm_value = imm_value;",
256         reg_req   => { out => [ "gp" ] },
257         emit      => '. mov %C, %D1',
258         mode      => $mode_gp,
259 },
260 SymConst => {
261         op_flags  => "c",
262         irn_flags => "R",
263         attr      => "ir_entity *entity",
264         attr_type => "amd64_SymConst_attr_t",
265         reg_req   => { out => [ "gp" ] },
266         outs      => [ "res" ],
267         mode      => $mode_gp,
268 },
269 Conv => {
270         state     => "exc_pinned",
271         attr      => "ir_mode *smaller_mode",
272         init_attr => "attr->ls_mode = smaller_mode;",
273         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
274         ins       => [ "val" ],
275         outs      => [ "res" ],
276         mode      => $mode_gp,
277 },
278 Jmp => {
279         state     => "pinned",
280         op_flags  => "X",
281         reg_req   => { out => [ "none" ] },
282         mode      => "mode_X",
283 },
284 Cmp => {
285         irn_flags => "R",
286         state     => "exc_pinned",
287         reg_req   => { in  => [ "gp", "gp" ],
288                        out => [ "flags" ] },
289         ins       => [ "left", "right" ],
290         outs      => [ "eflags" ],
291         emit      => '. cmp %S1, %S2',
292         attr      => "int ins_permuted, int cmp_unsigned",
293         init_attr => "attr->data.ins_permuted   = ins_permuted;\n".
294                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
295         mode      => $mode_flags,
296         modified_flags => 1,
297 },
298 Jcc => {
299         state     => "pinned",
300         op_flags  => "L|X|Y",
301         reg_req   => { in  => [ "eflags" ], out => [ "none", "none" ] },
302         ins       => [ "eflags" ],
303         outs      => [ "false", "true" ],
304         attr      => "pn_Cmp pnc",
305         init_attr => "attr->ext.pnc = pnc;",
306         mode      => "mode_T",
307 },
308 Load => {
309         op_flags  => "L|F",
310         state     => "exc_pinned",
311         reg_req   => { in => [ "gp", "none" ],
312                        out => [ "gp", "none" ] },
313         ins       => [ "ptr", "mem" ],
314         outs      => [ "res",  "M" ],
315         attr      => "ir_entity *entity",
316         attr_type => "amd64_SymConst_attr_t",
317         emit      => ". mov %O(%S1), %D1"
318 },
319 FrameAddr => {
320         op_flags  => "c",
321         irn_flags => "R",
322         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
323         ins       => [ "base" ],
324         attr      => "ir_entity *entity",
325         attr_type => "amd64_SymConst_attr_t",
326         mode      => $mode_gp,
327 },
328 Store => {
329         op_flags  => "L|F",
330         state     => "exc_pinned",
331         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
332         ins       => [ "ptr", "val", "mem" ],
333         outs      => [ "M" ],
334         attr      => "ir_entity *entity",
335         attr_type => "amd64_SymConst_attr_t",
336         mode      => "mode_M",
337         emit      => ". mov %S2, %O(%S1)"
338 },
339
340 #NoReg_GP => {
341 #       state     => "pinned",
342 #       op_flags  => "c|NB|NI",
343 #       reg_req   => { out => [ "gp_NOREG:I" ] },
344 #       units     => [],
345 #       emit      => "",
346 #       latency   => 0,
347 #       mode      => $mode_gp,
348 #},
349 );