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