Get rid of be_SetSP.
[libfirm] / ir / be / ia32 / ia32_spec.pl
1 # Creation: 2005/10/19
2 # $Id$
3 # This is the specification for the ia32 assembler Firm-operations
4
5 use File::Basename;
6
7 $new_emit_syntax = 1;
8 my $myname = $0;
9
10 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
11 $arch = "ia32";
12
13 # The node description is done as a perl hash initializer with the
14 # following structure:
15 #
16 # %nodes = (
17 #
18 # <op-name> => {
19 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
20 #   irn_flags => "R|N|I|S"
21 #   arity     => "0|1|2|3 ... |variable|dynamic|any",
22 #   state     => "floats|pinned|mem_pinned|exc_pinned",
23 #   args      => [
24 #                    { type => "type 1", name => "name 1" },
25 #                    { type => "type 2", name => "name 2" },
26 #                    ...
27 #                  ],
28 #   comment   => "any comment for constructor",
29 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
30 #   cmp_attr  => "c source code for comparing node attributes",
31 #   emit      => "emit code with templates",
32 #   attr      => "attitional attribute arguments for constructor"
33 #   init_attr => "emit attribute initialization template"
34 #   rd_constructor => "c source code which constructs an ir_node"
35 #   latency   => "latency of this operation (can be float)"
36 #   attr_type => "name of the attribute struct",
37 # },
38 #
39 # ... # (all nodes you need to describe)
40 #
41 # ); # close the %nodes initializer
42
43 # op_flags: flags for the operation, OPTIONAL (default is "N")
44 # the op_flags correspond to the firm irop_flags:
45 #   N   irop_flag_none
46 #   L   irop_flag_labeled
47 #   C   irop_flag_commutative
48 #   X   irop_flag_cfopcode
49 #   I   irop_flag_ip_cfopcode
50 #   F   irop_flag_fragile
51 #   Y   irop_flag_forking
52 #   H   irop_flag_highlevel
53 #   c   irop_flag_constlike
54 #   K   irop_flag_keep
55 #
56 # irn_flags: special node flags, OPTIONAL (default is 0)
57 # following irn_flags are supported:
58 #   R   rematerializeable
59 #   N   not spillable
60 #   I   ignore for register allocation
61 #   S   modifies stack pointer
62 #
63 # state: state of the operation, OPTIONAL (default is "floats")
64 #
65 # arity: arity of the operation, MUST NOT BE OMITTED
66 #
67 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
68 #        are always the first 3 arguments and are always autmatically
69 #        created)
70 #        If this key is missing the following arguments will be created:
71 #        for i = 1 .. arity: ir_node *op_i
72 #        ir_mode *mode
73 #
74 # outs:  if a node defines more than one output, the names of the projections
75 #        nodes having outs having automatically the mode mode_T
76 #        One can also annotate some flags for each out, additional to irn_flags.
77 #        They are separated from name with a colon ':', and concatenated by pipe '|'
78 #        Only I and S are available at the moment (same meaning as in irn_flags).
79 #        example: [ "frame:I", "stack:I|S", "M" ]
80 #
81 # comment: OPTIONAL comment for the node constructor
82 #
83 # rd_constructor: for every operation there will be a
84 #      new_rd_<arch>_<op-name> function with the arguments from above
85 #      which creates the ir_node corresponding to the defined operation
86 #      you can either put the complete source code of this function here
87 #
88 #      This key is OPTIONAL. If omitted, the following constructor will
89 #      be created:
90 #      if (!op_<arch>_<op-name>) assert(0);
91 #      for i = 1 to arity
92 #         set in[i] = op_i
93 #      done
94 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
95 #      return res
96 #
97 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
98 #
99 # latency: the latency of the operation, default is 1
100 #
101
102 # register types:
103 #   0 - no special type
104 #   1 - caller save (register must be saved by the caller of a function)
105 #   2 - callee save (register must be saved by the called function)
106 #   4 - ignore (do not assign this register)
107 #   8 - emitter can choose an arbitrary register of this class
108 #  16 - the register is a virtual one
109 #  32 - register represents a state
110 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
111 %reg_classes = (
112         gp => [
113                 { name => "eax", type => 1 },
114                 { name => "edx", type => 1 },
115                 { name => "ebx", type => 2 },
116                 { name => "ecx", type => 1 },
117                 { name => "esi", type => 2 },
118                 { name => "edi", type => 2 },
119                 { name => "ebp", type => 2 },
120                 { name => "esp", type => 4 },
121                 { name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
122                 { name => "gp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
123                 { mode => "mode_Iu" }
124         ],
125         mmx => [
126                 { name => "mm0", type => 4 },
127                 { name => "mm1", type => 4 },
128                 { name => "mm2", type => 4 },
129                 { name => "mm3", type => 4 },
130                 { name => "mm4", type => 4 },
131                 { name => "mm5", type => 4 },
132                 { name => "mm6", type => 4 },
133                 { name => "mm7", type => 4 },
134                 { mode => "mode_E", flags => "manual_ra"  }
135         ],
136         xmm => [
137                 { name => "xmm0", type => 1 },
138                 { name => "xmm1", type => 1 },
139                 { name => "xmm2", type => 1 },
140                 { name => "xmm3", type => 1 },
141                 { name => "xmm4", type => 1 },
142                 { name => "xmm5", type => 1 },
143                 { name => "xmm6", type => 1 },
144                 { name => "xmm7", type => 1 },
145                 { name => "xmm_NOREG", type => 4 | 16 },     # we need a dummy register for NoReg nodes
146                 { name => "xmm_UKNWN", type => 4 | 8 | 16},  # we need a dummy register for Unknown nodes
147                 { mode => "mode_E" }
148         ],
149         vfp => [
150                 { name => "vf0", type => 1 | 16 },
151                 { name => "vf1", type => 1 | 16 },
152                 { name => "vf2", type => 1 | 16 },
153                 { name => "vf3", type => 1 | 16 },
154                 { name => "vf4", type => 1 | 16 },
155                 { name => "vf5", type => 1 | 16 },
156                 { name => "vf6", type => 1 | 16 },
157                 { name => "vf7", type => 1 | 16 },
158                 { name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
159                 { name => "vfp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
160                 { mode => "mode_E" }
161         ],
162         st => [
163                 { name => "st0", realname => "st",    type => 4 },
164                 { name => "st1", realname => "st(1)", type => 4 },
165                 { name => "st2", realname => "st(2)", type => 4 },
166                 { name => "st3", realname => "st(3)", type => 4 },
167                 { name => "st4", realname => "st(4)", type => 4 },
168                 { name => "st5", realname => "st(5)", type => 4 },
169                 { name => "st6", realname => "st(6)", type => 4 },
170                 { name => "st7", realname => "st(7)", type => 4 },
171                 { mode => "mode_E", flags => "manual_ra"  }
172         ],
173         fp_cw => [      # the floating point control word
174                 { name => "fpcw", type => 4 | 32},
175                 { mode => "mode_fpcw", flags => "manual_ra|state"  }
176         ],
177         flags => [
178                 { name => "eflags", type => 4 },
179                 { mode => "mode_Iu", flags => "manual_ra"  }
180         ],
181 ); # %reg_classes
182
183 %cpu = (
184         GP     => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
185         SSE    => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
186         VFP    => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
187         BRANCH => [ 1, "BRANCH1", "BRANCH2" ],
188 ); # %cpu
189
190 %vliw = (
191         bundle_size       => 1,
192         bundels_per_cycle => 1
193 ); # vliw
194
195 %emit_templates = (
196         S0 => "${arch}_emit_source_register(env, node, 0);",
197         S1 => "${arch}_emit_source_register(env, node, 1);",
198         S2 => "${arch}_emit_source_register(env, node, 2);",
199         S3 => "${arch}_emit_source_register(env, node, 3);",
200         S4 => "${arch}_emit_source_register(env, node, 4);",
201         S5 => "${arch}_emit_source_register(env, node, 5);",
202         SB1 => "${arch}_emit_8bit_source_register(env, node, 1);",
203         SB2 => "${arch}_emit_8bit_source_register(env, node, 2);",
204         SB3 => "${arch}_emit_8bit_source_register(env, node, 3);",
205         SW0 => "${arch}_emit_16bit_source_register(env, node, 0);",
206         SI0 => "${arch}_emit_source_register_or_immediate(env, node, 0);",
207         SI1 => "${arch}_emit_source_register_or_immediate(env, node, 1);",
208         SI2 => "${arch}_emit_source_register_or_immediate(env, node, 2);",
209         SI3 => "${arch}_emit_source_register_or_immediate(env, node, 3);",
210         D0 => "${arch}_emit_dest_register(env, node, 0);",
211         D1 => "${arch}_emit_dest_register(env, node, 1);",
212         D2 => "${arch}_emit_dest_register(env, node, 2);",
213         D3 => "${arch}_emit_dest_register(env, node, 3);",
214         D4 => "${arch}_emit_dest_register(env, node, 4);",
215         D5 => "${arch}_emit_dest_register(env, node, 5);",
216         X0 => "${arch}_emit_x87_name(env, node, 0);",
217         X1 => "${arch}_emit_x87_name(env, node, 1);",
218         X2 => "${arch}_emit_x87_name(env, node, 2);",
219         SE => "${arch}_emit_extend_suffix(env, get_ia32_ls_mode(node));",
220         ME => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
221                    ia32_emit_mode_suffix(env, node);",
222         M  => "${arch}_emit_mode_suffix(env, node);",
223         XM => "${arch}_emit_x87_mode_suffix(env, node);",
224         XXM => "${arch}_emit_xmm_mode_suffix(env, node);",
225         XSD => "${arch}_emit_xmm_mode_suffix_s(env, node);",
226         AM => "${arch}_emit_am(env, node);",
227         unop0 => "${arch}_emit_unop(env, node, 0);",
228         unop1 => "${arch}_emit_unop(env, node, 1);",
229         unop2 => "${arch}_emit_unop(env, node, 2);",
230         unop3 => "${arch}_emit_unop(env, node, 3);",
231         unop4 => "${arch}_emit_unop(env, node, 4);",
232         unop5 => "${arch}_emit_unop(env, node, 5);",
233         DAM0  => "${arch}_emit_am_or_dest_register(env, node, 0);",
234         DAM1  => "${arch}_emit_am_or_dest_register(env, node, 1);",
235         binop => "${arch}_emit_binop(env, node);",
236         x87_binop => "${arch}_emit_x87_binop(env, node);",
237 );
238
239 #--------------------------------------------------#
240 #                        _                         #
241 #                       (_)                        #
242 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
243 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
244 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
245 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
246 #                                      | |         #
247 #                                      |_|         #
248 #--------------------------------------------------#
249
250 $default_attr_type = "ia32_attr_t";
251 $default_copy_attr = "ia32_copy_attr";
252
253 sub ia32_custom_init_attr {
254         my $node = shift;
255         my $name = shift;
256         my $res = "";
257         if(defined($node->{modified_flags})) {
258                 $res .= "\tset_ia32_flags(res, get_ia32_flags(res) | arch_irn_flags_modify_flags);\n";
259         }
260         if(defined($node->{am})) {
261                 my $am = $node->{am};
262                 if($am eq "full,binary") {
263                         $res .= "\tset_ia32_am_support(res, ia32_am_Full, ia32_am_binary);";
264                 } elsif($am eq "full,unary") {
265                         $res .= "\tset_ia32_am_support(res, ia32_am_Full, ia32_am_unary);";
266                 } elsif($am eq "source,binary") {
267                         $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_binary);";
268                 } elsif($am eq "dest,unary") {
269                         $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_unary);";
270                 } elsif($am eq "dest,binary") {
271                         $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_binary);";
272                 } elsif($am eq "dest,ternary") {
273                         $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_ternary);";
274                 } elsif($am eq "source,ternary") {
275                         $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_ternary);";
276                 } elsif($am eq "none") {
277                         # nothing to do
278                 } else {
279                         die("Invalid address mode '$am' specified on op $name");
280                 }
281         }
282         return $res;
283 }
284 $custom_init_attr_func = \&ia32_custom_init_attr;
285
286 %init_attr = (
287         ia32_attr_t     => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
288         ia32_x87_attr_t =>
289                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
290                 "\tinit_ia32_x87_attributes(res);",
291         ia32_asm_attr_t =>
292                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
293                 "\tinit_ia32_x87_attributes(res);".
294                 "\tinit_ia32_asm_attributes(res);",
295         ia32_immediate_attr_t =>
296                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
297                 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);"
298 );
299
300 %compare_attr = (
301         ia32_attr_t           => "ia32_compare_nodes_attr",
302         ia32_x87_attr_t       => "ia32_compare_x87_attr",
303         ia32_asm_attr_t       => "ia32_compare_asm_attr",
304         ia32_immediate_attr_t => "ia32_compare_immediate_attr",
305 );
306
307 %operands = (
308 );
309
310 $mode_xmm     = "mode_E";
311 $mode_gp      = "mode_Iu";
312 $mode_fpcw    = "mode_fpcw";
313 $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
314 $fpcw_flags   = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
315                   "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
316
317 %nodes = (
318
319 Immediate => {
320         state     => "pinned",
321         op_flags  => "c",
322         irn_flags => "I",
323         reg_req   => { out => [ "gp_NOREG" ] },
324         attr      => "ir_entity *symconst, int symconst_sign, long offset",
325         attr_type => "ia32_immediate_attr_t",
326         latency   => 0,
327         mode      => $mode_gp,
328 },
329
330 Asm => {
331         mode      => "mode_T",
332         arity     => "variable",
333         out_arity => "variable",
334         attr_type => "ia32_asm_attr_t",
335         latency   => 100,
336 },
337
338 ProduceVal => {
339         op_flags  => "c",
340         irn_flags => "R",
341         reg_req   => { out => [ "gp" ] },
342         emit      => "",
343         units     => [ ],
344         latency   => 0,
345         mode      => $mode_gp,
346         cmp_attr  => "return 1;",
347 },
348
349 #-----------------------------------------------------------------#
350 #  _       _                                         _            #
351 # (_)     | |                                       | |           #
352 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
353 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
354 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
355 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
356 #                   __/ |                                         #
357 #                  |___/                                          #
358 #-----------------------------------------------------------------#
359
360 # commutative operations
361
362 Add => {
363         irn_flags => "R",
364         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4", "none", "flags" ] },
365         ins       => [ "base", "index", "mem", "left", "right" ],
366         emit      => '. add%M %binop',
367         am        => "full,binary",
368         units     => [ "GP" ],
369         mode      => $mode_gp,
370         modified_flags => $status_flags
371 },
372
373 AddMem => {
374         irn_flags => "R",
375         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
376         ins       => [ "base", "index", "mem", "val" ],
377         emit      => ". add%M %SI3, %AM",
378         units     => [ "GP" ],
379         mode      => "mode_M",
380         modified_flags => $status_flags
381 },
382
383 Adc => {
384         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4" ] },
385         ins       => [ "base", "index", "mem", "left", "right", "eflags" ],
386         emit      => '. adc%M %binop',
387         am        => "full,binary",
388         units     => [ "GP" ],
389         mode      => $mode_gp,
390         modified_flags => $status_flags
391 },
392
393 l_Add => {
394         op_flags  => "C",
395         reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
396         ins       => [ "left", "right" ],
397 },
398
399 l_Adc => {
400         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
401         ins       => [ "left", "right", "eflags" ],
402 },
403
404 Add64Bit => {
405         irn_flags => "R",
406         arity     => 4,
407         reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
408         emit      => '
409 . movl %S0, %D0
410 . movl %S1, %D1
411 . addl %SI2, %D0
412 . adcl %SI3, %D1
413 ',
414         outs      => [ "low_res", "high_res" ],
415         units     => [ "GP" ],
416         modified_flags => $status_flags
417 },
418
419 Mul => {
420         # we should not rematrialize this node. It produces 2 results and has
421         # very strict constrains
422         reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] },
423         ins       => [ "base", "index", "mem", "val_high", "val_low" ],
424         emit      => '. mul%M %unop4',
425         outs      => [ "EAX", "EDX", "M" ],
426         am        => "source,binary",
427         latency   => 10,
428         units     => [ "GP" ],
429         modified_flags => $status_flags
430 },
431
432 l_Mul => {
433         # we should not rematrialize this node. It produces 2 results and has
434         # very strict constrains
435         op_flags  => "C",
436         cmp_attr  => "return 1;",
437         outs      => [ "EAX", "EDX", "M" ],
438         arity     => 2
439 },
440
441 IMul => {
442         irn_flags => "R",
443         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
444         ins       => [ "base", "index", "mem", "left", "right" ],
445         emit      => '. imul%M %binop',
446         am        => "source,binary",
447         latency   => 5,
448         units     => [ "GP" ],
449         mode      => $mode_gp,
450         modified_flags => $status_flags
451 },
452
453 IMul1OP => {
454         irn_flags => "R",
455         reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] },
456         ins       => [ "base", "index", "mem", "val_high", "val_low" ],
457         emit      => '. imul%M %unop4',
458         outs      => [ "EAX", "EDX", "M" ],
459         am        => "source,binary",
460         latency   => 5,
461         units     => [ "GP" ],
462         modified_flags => $status_flags
463 },
464
465 l_IMul => {
466         # we should not rematrialize this node. It produces 2 results and has
467         # very strict constrains
468         op_flags  => "C",
469         cmp_attr  => "return 1;",
470         outs      => [ "EAX", "EDX", "M" ],
471         arity     => 2
472 },
473
474 And => {
475         irn_flags => "R",
476         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
477         ins       => [ "base", "index", "mem", "left", "right" ],
478         am        => "full,binary",
479         emit      => '. and%M %binop',
480         units     => [ "GP" ],
481         mode      => $mode_gp,
482         modified_flags => $status_flags
483 },
484
485 AndMem => {
486         irn_flags => "R",
487         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
488         ins       => [ "base", "index", "mem", "val" ],
489         emit      => '. and%M %SI3, %AM',
490         units     => [ "GP" ],
491         mode      => "mode_M",
492         modified_flags => $status_flags
493 },
494
495 Or => {
496         irn_flags => "R",
497         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
498         ins       => [ "base", "index", "mem", "left", "right" ],
499         am        => "full,binary",
500         emit      => '. or%M %binop',
501         units     => [ "GP" ],
502         mode      => $mode_gp,
503         modified_flags => $status_flags
504 },
505
506 OrMem => {
507         irn_flags => "R",
508         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
509         ins       => [ "base", "index", "mem", "val" ],
510         emit      => '. or%M %SI3, %AM',
511         units     => [ "GP" ],
512         mode      => "mode_M",
513         modified_flags => $status_flags
514 },
515
516 Xor => {
517         irn_flags => "R",
518         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
519         ins       => [ "base", "index", "mem", "left", "right" ],
520         am        => "full,binary",
521         emit      => '. xor%M %binop',
522         units     => [ "GP" ],
523         mode      => $mode_gp,
524         modified_flags => $status_flags
525 },
526
527 XorMem => {
528         irn_flags => "R",
529         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
530         ins       => [ "base", "index", "mem", "val" ],
531         emit      => '. xor%M %SI3, %AM',
532         units     => [ "GP" ],
533         mode      => "mode_M",
534         modified_flags => $status_flags
535 },
536
537 # not commutative operations
538
539 Sub => {
540         irn_flags => "R",
541         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
542         ins       => [ "base", "index", "mem", "left", "right" ],
543         am        => "full,binary",
544         emit      => '. sub%M %binop',
545         units     => [ "GP" ],
546         mode      => $mode_gp,
547         modified_flags => $status_flags
548 },
549
550 SubMem => {
551         irn_flags => "R",
552         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
553         ins       => [ "base", "index", "mem", "val" ],
554         emit      => '. sub%M %SI3, %AM',
555         units     => [ "GP" ],
556         mode      => 'mode_M',
557         modified_flags => $status_flags
558 },
559
560 Sbb => {
561         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 !in_r5" ] },
562         ins       => [ "base", "index", "mem", "left", "right" ],
563         am        => "full,binary",
564         emit      => '. sbb%M %binop',
565         units     => [ "GP" ],
566         mode      => $mode_gp,
567         modified_flags => $status_flags
568 },
569
570 Sub64Bit => {
571         irn_flags => "R",
572         arity     => 4,
573         reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
574         emit      => '
575 . movl %S0, %D0
576 . movl %S1, %D1
577 . subl %SI2, %D0
578 . sbbl %SI3, %D1
579 ',
580         outs      => [ "low_res", "high_res" ],
581         units     => [ "GP" ],
582         modified_flags => $status_flags
583 },
584
585 IDiv => {
586         op_flags  => "F|L",
587         state     => "exc_pinned",
588         reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
589         ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
590         outs      => [ "div_res", "mod_res", "M" ],
591         attr      => "ia32_op_flavour_t dm_flav",
592         am        => "source,ternary",
593         init_attr => "attr->data.op_flav = dm_flav;",
594         emit      => ". idiv%M %unop5",
595         latency   => 25,
596         units     => [ "GP" ],
597         modified_flags => $status_flags
598 },
599
600 Div => {
601         op_flags  => "F|L",
602         state     => "exc_pinned",
603         reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
604         ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
605         outs      => [ "div_res", "mod_res", "M" ],
606         attr      => "ia32_op_flavour_t dm_flav",
607         am        => "source,ternary",
608         init_attr => "attr->data.op_flav = dm_flav;",
609         emit      => ". div%M %unop5",
610         latency   => 25,
611         units     => [ "GP" ],
612         modified_flags => $status_flags
613 },
614
615 Shl => {
616         irn_flags => "R",
617         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
618         ins       => [ "left", "right" ],
619         am        => "dest,binary",
620         emit      => '. shl %SB1, %S0',
621         units     => [ "GP" ],
622         mode      => $mode_gp,
623         modified_flags => $status_flags
624 },
625
626 ShlMem => {
627         irn_flags => "R",
628         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
629         ins       => [ "base", "index", "mem", "count" ],
630         emit      => '. shl%M %SB3, %AM',
631         units     => [ "GP" ],
632         mode      => "mode_M",
633         modified_flags => $status_flags
634 },
635
636 l_ShlDep => {
637         cmp_attr  => "return 1;",
638         # value, cnt, dependency
639         arity     => 3
640 },
641
642 ShlD => {
643         # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shl
644         #
645         # Out requirements is: different from all in
646         # This is because, out must be different from LowPart and ShiftCount.
647         # We could say "!ecx !in_r4" but it can occur, that all values live through
648         # this Shift and the only value dying is the ShiftCount. Then there would be a
649         # register missing, as result must not be ecx and all other registers are
650         # occupied. What we should write is "!in_r4 !in_r5", but this is not supported
651         # (and probably never will). So we create artificial interferences of the result
652         # with all inputs, so the spiller can always assure a free register.
653         # reg_req   => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
654
655         irn_flags => "R",
656         reg_req   => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r3" ] },
657         ins       => [ "left_high", "left_low", "right" ],
658         am        => "dest,ternary",
659         emit      => '. shld%M %SB2, %S1, %S0',
660         latency   => 6,
661         units     => [ "GP" ],
662         mode      => $mode_gp,
663         modified_flags => $status_flags
664 },
665
666 l_ShlD => {
667         cmp_attr  => "return 1;",
668         arity     => 3,
669 },
670
671 Shr => {
672         irn_flags => "R",
673         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
674         ins       => [ "val", "count" ],
675         am        => "dest,binary",
676         emit      => '. shr %SB1, %S0',
677         units     => [ "GP" ],
678         mode      => $mode_gp,
679         modified_flags => $status_flags
680 },
681
682 ShrMem => {
683         irn_flags => "R",
684         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
685         ins       => [ "base", "index", "mem", "count" ],
686         emit      => '. shr%M %SB3, %AM',
687         units     => [ "GP" ],
688         mode      => "mode_M",
689         modified_flags => $status_flags
690 },
691
692 l_ShrDep => {
693         cmp_attr  => "return 1;",
694         # value, cnt, dependency
695         arity     => 3
696 },
697
698 ShrD => {
699         # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shr
700         #
701         # Out requirements is: different from all in
702         # This is because, out must be different from LowPart and ShiftCount.
703         # We could say "!ecx !in_r4" but it can occur, that all values live through
704         # this Shift and the only value dying is the ShiftCount. Then there would be a
705         # register missing, as result must not be ecx and all other registers are
706         # occupied. What we should write is "!in_r4 !in_r5", but this is not supported
707         # (and probably never will). So we create artificial interferences of the result
708         # with all inputs, so the spiller can always assure a free register.
709         # reg_req   => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
710
711         irn_flags => "R",
712         reg_req   => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r3" ] },
713         ins       => [ "left_high", "left_low", "right" ],
714         am        => "dest,ternary",
715         emit      => '. shrd%M %SB2, %S1, %S0',
716         latency   => 6,
717         units     => [ "GP" ],
718         mode      => $mode_gp,
719         modified_flags => $status_flags
720 },
721
722 l_ShrD => {
723         cmp_attr  => "return 1;",
724         arity     => 3
725 },
726
727 Sar => {
728         irn_flags => "R",
729         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
730         ins       => [ "val", "count" ],
731         am        => "dest,binary",
732         emit      => '. sar %SB1, %S0',
733         units     => [ "GP" ],
734         mode      => $mode_gp,
735         modified_flags => $status_flags
736 },
737
738 SarMem => {
739         irn_flags => "R",
740         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
741         ins       => [ "base", "index", "mem", "count" ],
742         emit      => '. sar%M %SB3, %AM',
743         units     => [ "GP" ],
744         mode      => "mode_M",
745         modified_flags => $status_flags
746 },
747
748 l_Sar => {
749         cmp_attr  => "return 1;",
750         # value, cnt
751         arity     => 2
752 },
753
754 l_SarDep => {
755         cmp_attr  => "return 1;",
756         # value, cnt, dependency
757         arity     => 3
758 },
759
760 Ror => {
761         irn_flags => "R",
762         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
763         ins       => [ "val", "count" ],
764         am        => "dest,binary",
765         emit      => '. ror %SB1, %S0',
766         units     => [ "GP" ],
767         mode      => $mode_gp,
768         modified_flags => $status_flags
769 },
770
771 RorMem => {
772         irn_flags => "R",
773         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
774         ins       => [ "base", "index", "mem", "count" ],
775         emit      => '. ror%M %SB3, %AM',
776         units     => [ "GP" ],
777         mode      => "mode_M",
778         modified_flags => $status_flags
779 },
780
781 Rol => {
782         irn_flags => "R",
783         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
784         ins       => [ "val", "count" ],
785         am        => "dest,binary",
786         emit      => '. rol %SB1, %S0',
787         units     => [ "GP" ],
788         mode      => $mode_gp,
789         modified_flags => $status_flags
790 },
791
792 RolMem => {
793         irn_flags => "R",
794         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
795         ins       => [ "base", "index", "mem", "count" ],
796         emit      => '. rol%M %SB3, %AM',
797         units     => [ "GP" ],
798         mode      => "mode_M",
799         modified_flags => $status_flags
800 },
801
802 # unary operations
803
804 Neg => {
805         irn_flags => "R",
806         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
807         emit      => '. neg %S0',
808         ins       => [ "val" ],
809         am        => "dest,unary",
810         units     => [ "GP" ],
811         mode      => $mode_gp,
812         modified_flags => $status_flags
813 },
814
815 NegMem => {
816         irn_flags => "R",
817         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
818         ins       => [ "base", "index", "mem" ],
819         emit      => '. neg%M %AM',
820         units     => [ "GP" ],
821         mode      => "mode_M",
822         modified_flags => $status_flags
823 },
824
825 Minus64Bit => {
826         irn_flags => "R",
827         reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1", "gp" ] },
828         outs      => [ "low_res", "high_res" ],
829         units     => [ "GP" ],
830         modified_flags => $status_flags
831 },
832
833
834 l_Neg => {
835         cmp_attr  => "return 1;",
836         arity     => 1,
837 },
838
839 Inc => {
840         irn_flags => "R",
841         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
842         am        => "dest,unary",
843         emit      => '. inc %S0',
844         units     => [ "GP" ],
845         mode      => $mode_gp,
846         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
847 },
848
849 IncMem => {
850         irn_flags => "R",
851         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
852         ins       => [ "base", "index", "mem" ],
853         emit      => '. inc%M %AM',
854         units     => [ "GP" ],
855         mode      => "mode_M",
856         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
857 },
858
859 Dec => {
860         irn_flags => "R",
861         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
862         am        => "dest,unary",
863         emit      => '. dec %S0',
864         units     => [ "GP" ],
865         mode      => $mode_gp,
866         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
867 },
868
869 DecMem => {
870         irn_flags => "R",
871         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
872         ins       => [ "base", "index", "mem" ],
873         emit      => '. dec%M %AM',
874         units     => [ "GP" ],
875         mode      => "mode_M",
876         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
877 },
878
879 Not => {
880         irn_flags => "R",
881         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
882         ins       => [ "val" ],
883         am        => "dest,unary",
884         emit      => '. not %S0',
885         units     => [ "GP" ],
886         mode      => $mode_gp,
887 },
888
889 NotMem => {
890         irn_flags => "R",
891         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
892         ins       => [ "base", "index", "mem" ],
893         emit      => '. not%M %AM',
894         units     => [ "GP" ],
895         mode      => "mode_M",
896 },
897
898 # other operations
899
900 CmpJmp => {
901         state     => "pinned",
902         op_flags  => "L|X|Y",
903         reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ], out => [ "none", "none"] },
904         ins       => [ "base", "index", "mem", "left", "right" ],
905         outs      => [ "false", "true" ],
906         attr      => "long pnc",
907         am        => "source,binary",
908         init_attr => "attr->pn_code = pnc;",
909         latency   => 3,
910         units     => [ "BRANCH" ],
911 },
912
913 CmpJmp8Bit => {
914         state     => "pinned",
915         op_flags  => "L|X|Y",
916         reg_req   => { in  => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "none", "none"] },
917         ins       => [ "base", "index", "mem", "left", "right" ],
918         outs      => [ "false", "true" ],
919         attr      => "long pnc",
920         am        => "source,binary",
921         init_attr => "attr->pn_code = pnc;",
922         latency   => 3,
923         units     => [ "BRANCH" ],
924 },
925
926 TestJmp => {
927         state     => "pinned",
928         op_flags  => "L|X|Y",
929         reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ], out => [ "none", "none" ] },
930         ins       => [ "base", "index", "mem", "left", "right" ],
931         outs      => [ "false", "true" ],
932         attr      => "long pnc",
933         am        => "source,binary",
934         init_attr => "attr->pn_code = pnc;",
935         latency   => 3,
936         units     => [ "BRANCH" ],
937 },
938
939 TestJmp8Bit => {
940         state     => "pinned",
941         op_flags  => "L|X|Y",
942         reg_req   => { in  => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "none", "none" ] },
943         ins       => [ "base", "index", "mem", "left", "right" ],
944         outs      => [ "false", "true" ],
945         attr      => "long pnc",
946         am        => "source,binary",
947         init_attr => "attr->pn_code = pnc;",
948         latency   => 3,
949         units     => [ "BRANCH" ],
950 },
951
952 SwitchJmp => {
953         state     => "pinned",
954         op_flags  => "L|X|Y",
955         reg_req   => { in => [ "gp" ], out => [ "none" ] },
956         latency   => 3,
957         units     => [ "BRANCH" ],
958         mode      => "mode_T",
959 },
960
961 IJmp => {
962         state     => "pinned",
963         op_flags  => "X",
964         reg_req   => { in => [ "gp" ] },
965         emit      => '. jmp *%S0',
966         units     => [ "BRANCH" ],
967         mode      => "mode_X",
968 },
969
970 Const => {
971         op_flags  => "c",
972         irn_flags => "R",
973         reg_req   => { out => [ "gp" ] },
974         units     => [ "GP" ],
975         attr      => "ir_entity *symconst, int symconst_sign, long offset",
976         attr_type => "ia32_immediate_attr_t",
977         mode      => $mode_gp,
978 },
979
980 Unknown_GP => {
981         state     => "pinned",
982         op_flags  => "c",
983         irn_flags => "I",
984         reg_req   => { out => [ "gp_UKNWN" ] },
985         units     => [],
986         emit      => "",
987         mode      => $mode_gp
988 },
989
990 Unknown_VFP => {
991         state     => "pinned",
992         op_flags  => "c",
993         irn_flags => "I",
994         reg_req   => { out => [ "vfp_UKNWN" ] },
995         units     => [],
996         emit      => "",
997         mode      => "mode_E",
998         attr_type => "ia32_x87_attr_t",
999 },
1000
1001 Unknown_XMM => {
1002         state     => "pinned",
1003         op_flags  => "c",
1004         irn_flags => "I",
1005         reg_req   => { out => [ "xmm_UKNWN" ] },
1006         units     => [],
1007         emit      => "",
1008         mode      => "mode_E"
1009 },
1010
1011 NoReg_GP => {
1012         state     => "pinned",
1013         op_flags  => "c",
1014         irn_flags => "I",
1015         reg_req   => { out => [ "gp_NOREG" ] },
1016         units     => [],
1017         emit      => "",
1018         mode      => $mode_gp
1019 },
1020
1021 NoReg_VFP => {
1022         state     => "pinned",
1023         op_flags  => "c",
1024         irn_flags => "I",
1025         reg_req   => { out => [ "vfp_NOREG" ] },
1026         units     => [],
1027         emit      => "",
1028         mode      => "mode_E",
1029         attr_type => "ia32_x87_attr_t",
1030 },
1031
1032 NoReg_XMM => {
1033         state     => "pinned",
1034         op_flags  => "c",
1035         irn_flags => "I",
1036         reg_req   => { out => [ "xmm_NOREG" ] },
1037         units     => [],
1038         emit      => "",
1039         mode      => "mode_E"
1040 },
1041
1042 ChangeCW => {
1043         state     => "pinned",
1044         op_flags  => "c",
1045         irn_flags => "I",
1046         reg_req   => { out => [ "fp_cw" ] },
1047         mode      => $mode_fpcw,
1048         latency   => 3,
1049         units     => [ "GP" ],
1050         modified_flags => $fpcw_flags
1051 },
1052
1053 FldCW => {
1054         op_flags  => "L|F",
1055         state     => "pinned",
1056         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
1057         ins       => [ "base", "index", "mem" ],
1058         latency   => 5,
1059         emit      => ". fldcw %AM",
1060         mode      => $mode_fpcw,
1061         units     => [ "GP" ],
1062         modified_flags => $fpcw_flags
1063 },
1064
1065 FnstCW => {
1066         op_flags  => "L|F",
1067         state     => "pinned",
1068         reg_req   => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1069         ins       => [ "base", "index", "mem", "fpcw" ],
1070         latency   => 5,
1071         emit      => ". fnstcw %AM",
1072         mode      => "mode_M",
1073         units     => [ "GP" ],
1074 },
1075
1076 Cltd => {
1077         # we should not rematrialize this node. It produces 2 results and has
1078         # very strict constrains
1079         reg_req   => { in => [ "eax", "edx" ], out => [ "edx" ] },
1080         ins       => [ "val", "globbered" ],
1081         emit      => '. cltd',
1082         mode      => $mode_gp,
1083         units     => [ "GP" ],
1084 },
1085
1086 # Load / Store
1087 #
1088 # Note that we add additional latency values depending on address mode, so a
1089 # lateny of 0 for load is correct
1090
1091 Load => {
1092         op_flags  => "L|F",
1093         state     => "exc_pinned",
1094         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
1095         ins       => [ "base", "index", "mem" ],
1096         outs      => [ "res", "M" ],
1097         latency   => 0,
1098         emit      => ". mov%SE%ME%.l %AM, %D0",
1099         units     => [ "GP" ],
1100 },
1101
1102 l_Load => {
1103         op_flags  => "L|F",
1104         cmp_attr  => "return 1;",
1105         outs      => [ "res", "M" ],
1106         arity     => 2,
1107 },
1108
1109 l_Store => {
1110         op_flags  => "L|F",
1111         cmp_attr  => "return 1;",
1112         state     => "exc_pinned",
1113         arity     => 3,
1114         mode      => "mode_M",
1115 },
1116
1117 Store => {
1118         op_flags  => "L|F",
1119         state     => "exc_pinned",
1120         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
1121         ins       => [ "base", "index", "mem", "val" ],
1122         emit      => '. mov%M %SI3, %AM',
1123         latency   => 2,
1124         units     => [ "GP" ],
1125         mode      => "mode_M",
1126 },
1127
1128 Store8Bit => {
1129         op_flags  => "L|F",
1130         state     => "exc_pinned",
1131         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none" ] },
1132         ins       => [ "base", "index", "mem", "val" ],
1133         emit      => '. mov%M %SB3, %AM',
1134         latency   => 2,
1135         units     => [ "GP" ],
1136         mode      => "mode_M",
1137 },
1138
1139 Lea => {
1140         irn_flags => "R",
1141         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
1142         ins       => [ "base", "index" ],
1143         emit      => '. leal %AM, %D0',
1144         latency   => 2,
1145         units     => [ "GP" ],
1146         mode      => $mode_gp,
1147 },
1148
1149 Push => {
1150         reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] },
1151         ins       => [ "base", "index", "mem", "val", "stack" ],
1152         emit      => '. push%M %unop3',
1153         outs      => [ "stack:I|S", "M" ],
1154         am        => "source,binary",
1155         latency   => 2,
1156         units     => [ "GP" ],
1157 },
1158
1159 Pop => {
1160         reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "esp", "gp", "none" ] },
1161         emit      => '. pop%M %DAM1',
1162         outs      => [ "stack:I|S", "res", "M" ],
1163         ins       => [ "base", "index", "mem", "stack" ],
1164         am        => "dest,unary",
1165         latency   => 3, # Pop is more expensive than Push on Athlon
1166         units     => [ "GP" ],
1167 },
1168
1169 Enter => {
1170         reg_req   => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] },
1171         emit      => '. enter',
1172         outs      => [ "frame:I", "stack:I|S", "M" ],
1173         latency   => 15,
1174         units     => [ "GP" ],
1175 },
1176
1177 Leave => {
1178         reg_req   => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] },
1179         emit      => '. leave',
1180         outs      => [ "frame:I", "stack:I|S" ],
1181         latency   => 3,
1182         units     => [ "GP" ],
1183 },
1184
1185 AddSP => {
1186         irn_flags => "I",
1187         state     => "pinned",
1188         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] },
1189         ins       => [ "base", "index", "mem", "stack", "size" ],
1190         am        => "source,binary",
1191         emit      => '. addl %binop',
1192         outs      => [ "stack:S", "M" ],
1193         units     => [ "GP" ],
1194         modified_flags => $status_flags
1195 },
1196
1197 SubSP => {
1198 #irn_flags => "I",
1199         state     => "pinned",
1200         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] },
1201         ins       => [ "base", "index", "mem", "stack", "size" ],
1202         am        => "source,binary",
1203         emit      => ". subl %binop\n".
1204                      ". movl %%esp, %D1",
1205         outs      => [ "stack:I|S", "addr", "M" ],
1206         units     => [ "GP" ],
1207         modified_flags => $status_flags
1208 },
1209
1210 LdTls => {
1211         irn_flags => "R",
1212         reg_req   => { out => [ "gp" ] },
1213         units     => [ "GP" ],
1214 },
1215
1216 # the int instruction
1217 int => {
1218         reg_req   => { in => [ "gp" ], out => [ "none" ] },
1219         mode      => "mode_M",
1220         emit      => '. int %SI0',
1221         units     => [ "GP" ],
1222         cmp_attr  => "return 1;",
1223 },
1224
1225
1226 #-----------------------------------------------------------------------------#
1227 #   _____ _____ ______    __ _             _                     _            #
1228 #  / ____/ ____|  ____|  / _| |           | |                   | |           #
1229 # | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1230 #  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1231 #  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1232 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1233 #-----------------------------------------------------------------------------#
1234
1235 xZero => {
1236         irn_flags => "R",
1237         reg_req   => { out => [ "xmm" ] },
1238         emit      => '. xorp%XSD %D1, %D1',
1239         latency   => 3,
1240         units     => [ "SSE" ],
1241         mode      => "mode_E",
1242 },
1243
1244 # commutative operations
1245
1246 xAdd => {
1247         irn_flags => "R",
1248         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1249         ins       => [ "base", "index", "mem", "left", "right" ],
1250         emit      => '. add%XXM %binop',
1251         latency   => 4,
1252         units     => [ "SSE" ],
1253         mode      => "mode_E",
1254 },
1255
1256 xMul => {
1257         irn_flags => "R",
1258         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1259         ins       => [ "base", "index", "mem", "left", "right" ],
1260         emit      => '. mul%XXM %binop',
1261         latency   => 4,
1262         units     => [ "SSE" ],
1263         mode      => "mode_E",
1264 },
1265
1266 xMax => {
1267         irn_flags => "R",
1268         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1269         ins       => [ "base", "index", "mem", "left", "right" ],
1270         emit      => '. max%XXM %binop',
1271         latency   => 2,
1272         units     => [ "SSE" ],
1273         mode      => "mode_E",
1274 },
1275
1276 xMin => {
1277         irn_flags => "R",
1278         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1279         ins       => [ "base", "index", "mem", "left", "right" ],
1280         emit      => '. min%XXM %binop',
1281         latency   => 2,
1282         units     => [ "SSE" ],
1283         mode      => "mode_E",
1284 },
1285
1286 xAnd => {
1287         irn_flags => "R",
1288         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1289         ins       => [ "base", "index", "mem", "left", "right" ],
1290         emit      => '. andp%XSD %binop',
1291         latency   => 3,
1292         units     => [ "SSE" ],
1293         mode      => "mode_E",
1294 },
1295
1296 xOr => {
1297         irn_flags => "R",
1298         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1299         ins       => [ "base", "index", "mem", "left", "right" ],
1300         emit      => '. orp%XSD %binop',
1301         units     => [ "SSE" ],
1302         mode      => "mode_E",
1303 },
1304
1305 xXor => {
1306         irn_flags => "R",
1307         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1308         ins       => [ "base", "index", "mem", "left", "right" ],
1309         emit      => '. xorp%XSD %binop',
1310         latency   => 3,
1311         units     => [ "SSE" ],
1312         mode      => "mode_E",
1313 },
1314
1315 # not commutative operations
1316
1317 xAndNot => {
1318         irn_flags => "R",
1319         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
1320         ins       => [ "base", "index", "mem", "left", "right" ],
1321         emit      => '. andnp%XSD %binop',
1322         latency   => 3,
1323         units     => [ "SSE" ],
1324         mode      => "mode_E",
1325 },
1326
1327 xSub => {
1328         irn_flags => "R",
1329         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1330         ins       => [ "base", "index", "mem", "left", "right" ],
1331         emit      => '. sub%XXM %binop',
1332         latency   => 4,
1333         units     => [ "SSE" ],
1334         mode      => "mode_E",
1335 },
1336
1337 xDiv => {
1338         irn_flags => "R",
1339         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
1340         ins       => [ "base", "index", "mem", "left", "right" ],
1341         outs      => [ "res", "M" ],
1342         emit      => '. div%XXM %binop',
1343         latency   => 16,
1344         units     => [ "SSE" ],
1345 },
1346
1347 # other operations
1348
1349 xCmp => {
1350         irn_flags => "R",
1351         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
1352         ins       => [ "base", "index", "mem", "left", "right" ],
1353         latency   => 3,
1354         units     => [ "SSE" ],
1355         mode      => "mode_E",
1356 },
1357
1358 xCmpJmp => {
1359         state     => "pinned",
1360         op_flags  => "L|X|Y",
1361         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "none", "none" ] },
1362         ins       => [ "base", "index", "mem", "left", "right" ],
1363         outs      => [ "false", "true" ],
1364         attr      => "long pnc",
1365         init_attr => "attr->pn_code = pnc;",
1366         latency   => 5,
1367         units     => [ "SSE" ],
1368 },
1369
1370 # Load / Store
1371
1372 xLoad => {
1373         op_flags  => "L|F",
1374         state     => "exc_pinned",
1375         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
1376         ins       => [ "base", "index", "mem" ],
1377         emit      => '. mov%XXM %AM, %D0',
1378         attr      => "ir_mode *load_mode",
1379         init_attr => "attr->ls_mode = load_mode;",
1380         outs      => [ "res", "M" ],
1381         latency   => 0,
1382         units     => [ "SSE" ],
1383 },
1384
1385 xStore => {
1386         op_flags => "L|F",
1387         state    => "exc_pinned",
1388         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1389         ins       => [ "base", "index", "mem", "val" ],
1390         emit     => '. mov%XXM %S3, %AM',
1391         latency  => 0,
1392         units    => [ "SSE" ],
1393         mode     => "mode_M",
1394 },
1395
1396 xStoreSimple => {
1397         op_flags => "L|F",
1398         state    => "exc_pinned",
1399         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1400         ins      => [ "base", "index", "mem", "val" ],
1401         emit     => '. mov%XXM %S3, %AM',
1402         latency  => 0,
1403         units    => [ "SSE" ],
1404         mode     => "mode_M",
1405 },
1406
1407 CvtSI2SS => {
1408         op_flags => "L|F",
1409         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1410         ins      => [ "base", "index", "mem", "val" ],
1411         emit     => '. cvtsi2ss %D0, %AM',
1412         latency  => 2,
1413         units    => [ "SSE" ],
1414         mode     => $mode_xmm
1415 },
1416
1417 CvtSI2SD => {
1418         op_flags => "L|F",
1419         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1420         ins      => [ "base", "index", "mem", "val" ],
1421         emit     => '. cvtsi2sd %unop3',
1422         latency  => 2,
1423         units    => [ "SSE" ],
1424         mode     => $mode_xmm
1425 },
1426
1427
1428 l_X87toSSE => {
1429         op_flags => "L|F",
1430         cmp_attr => "return 1;",
1431         arity    => 3,
1432 },
1433
1434 l_SSEtoX87 => {
1435         op_flags => "L|F",
1436         cmp_attr => "return 1;",
1437         arity    => 3,
1438 },
1439
1440 # CopyB
1441
1442 CopyB => {
1443         op_flags => "F|H",
1444         state    => "pinned",
1445         reg_req  => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
1446         outs     => [ "DST", "SRC", "CNT", "M" ],
1447         units    => [ "GP" ],
1448 # we don't care about this flag, so no need to mark this node
1449 #       modified_flags => [ "DF" ]
1450 },
1451
1452 CopyB_i => {
1453         op_flags => "F|H",
1454         state    => "pinned",
1455         reg_req  => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
1456         outs     => [ "DST", "SRC", "M" ],
1457         units    => [ "GP" ],
1458 # we don't care about this flag, so no need to mark this node
1459 #       modified_flags => [ "DF" ]
1460 },
1461
1462 # Conversions
1463
1464 Conv_I2I => {
1465         state     => "exc_pinned",
1466         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "in_r4", "none" ] },
1467         ins       => [ "base", "index", "mem", "val" ],
1468         units     => [ "GP" ],
1469         attr      => "ir_mode *smaller_mode",
1470         init_attr => "attr->ls_mode = smaller_mode;",
1471         mode      => $mode_gp,
1472         modified_flags => $status_flags
1473 },
1474
1475 Conv_I2I8Bit => {
1476         state     => "exc_pinned",
1477         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "in_r4", "none" ] },
1478         ins       => [ "base", "index", "mem", "val" ],
1479         units     => [ "GP" ],
1480         attr      => "ir_mode *smaller_mode",
1481         init_attr => "attr->ls_mode = smaller_mode;",
1482         mode      => $mode_gp,
1483         modified_flags => $status_flags
1484 },
1485
1486 Conv_I2FP => {
1487         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
1488         ins      => [ "base", "index", "mem", "val" ],
1489         latency  => 10,
1490         units    => [ "SSE" ],
1491         mode     => "mode_E",
1492 },
1493
1494 Conv_FP2I => {
1495         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
1496         ins      => [ "base", "index", "mem", "val" ],
1497         latency  => 10,
1498         units    => [ "SSE" ],
1499         mode     => $mode_gp,
1500 },
1501
1502 Conv_FP2FP => {
1503         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
1504         ins      => [ "base", "index", "mem", "val" ],
1505         latency  => 8,
1506         units    => [ "SSE" ],
1507         mode     => "mode_E",
1508 },
1509
1510 CmpCMov => {
1511         irn_flags => "R",
1512         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] },
1513         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
1514         attr      => "pn_Cmp pn_code",
1515         init_attr => "attr->pn_code = pn_code;",
1516         latency   => 2,
1517         units     => [ "GP" ],
1518         mode      => $mode_gp,
1519 },
1520
1521 CmpCMov8Bit => {
1522         irn_flags => "R",
1523         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] },
1524         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
1525         attr      => "pn_Cmp pn_code",
1526         init_attr => "attr->pn_code = pn_code;",
1527         latency   => 2,
1528         units     => [ "GP" ],
1529         mode      => $mode_gp,
1530 },
1531
1532 TestCMov => {
1533         irn_flags => "R",
1534         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] },
1535         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
1536         attr      => "pn_Cmp pn_code",
1537         init_attr => "attr->pn_code = pn_code;",
1538         latency   => 2,
1539         units     => [ "GP" ],
1540         mode      => $mode_gp,
1541 },
1542
1543 TestCMov8Bit => {
1544         irn_flags => "R",
1545         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] },
1546         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
1547         attr      => "pn_Cmp pn_code",
1548         init_attr => "attr->pn_code = pn_code;",
1549         latency   => 2,
1550         units     => [ "GP" ],
1551         mode      => $mode_gp,
1552 },
1553
1554 xCmpCMov => {
1555         irn_flags => "R",
1556         reg_req   => { in => [ "xmm", "xmm", "gp", "gp" ], out => [ "in_r4" ] },
1557         latency   => 5,
1558         units     => [ "SSE" ],
1559         mode      => $mode_gp,
1560 },
1561
1562 vfCmpCMov => {
1563         irn_flags => "R",
1564         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "gp", "gp" ], out => [ "in_r7" ] },
1565         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
1566         latency   => 10,
1567         units     => [ "VFP", "GP" ],
1568         mode      => $mode_gp,
1569         attr_type => "ia32_x87_attr_t",
1570 },
1571
1572 CmpSet => {
1573         irn_flags => "R",
1574         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "eax ebx ecx edx" ] },
1575         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
1576         attr      => "pn_Cmp pn_code",
1577         init_attr => "attr->pn_code = pn_code;",
1578         latency   => 2,
1579         units     => [ "GP" ],
1580         mode      => $mode_gp,
1581 },
1582
1583 CmpSet8Bit => {
1584         irn_flags => "R",
1585         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "eax ebx ecx edx" ] },
1586         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
1587         attr      => "pn_Cmp pn_code",
1588         init_attr => "attr->pn_code = pn_code;",
1589         latency   => 2,
1590         units     => [ "GP" ],
1591         mode      => $mode_gp,
1592 },
1593
1594 TestSet => {
1595         irn_flags => "R",
1596         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "eax ebx ecx edx" ] },
1597         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
1598         attr      => "pn_Cmp pn_code",
1599         init_attr => "attr->pn_code = pn_code;",
1600         latency   => 2,
1601         units     => [ "GP" ],
1602         mode      => $mode_gp,
1603 },
1604
1605 TestSet8Bit => {
1606         irn_flags => "R",
1607         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "eax ebx ecx edx" ] },
1608         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
1609         attr      => "pn_Cmp pn_code",
1610         init_attr => "attr->pn_code = pn_code;",
1611         latency   => 2,
1612         units     => [ "GP" ],
1613         mode      => $mode_gp,
1614 },
1615
1616 xCmpSet => {
1617         irn_flags => "R",
1618         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eax ebx ecx edx" ] },
1619         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
1620         latency   => 5,
1621         units     => [ "SSE" ],
1622         mode      => $mode_gp,
1623 },
1624
1625 vfCmpSet => {
1626         irn_flags => "R",
1627         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp" ], out => [ "eax ebx ecx edx" ] },
1628         ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
1629         latency   => 10,
1630         units     => [ "VFP" ],
1631         mode      => $mode_gp,
1632         attr_type => "ia32_x87_attr_t",
1633 },
1634
1635 vfCMov => {
1636         irn_flags => "R",
1637         reg_req   => { in => [ "vfp", "vfp", "vfp", "vfp" ], out => [ "vfp" ] },
1638         latency   => 10,
1639         units     => [ "VFP" ],
1640         mode      => "mode_E",
1641         attr_type => "ia32_x87_attr_t",
1642 },
1643
1644 #----------------------------------------------------------#
1645 #        _      _               _    __ _             _    #
1646 #       (_)    | |             | |  / _| |           | |   #
1647 # __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
1648 # \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
1649 #  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
1650 #   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
1651 #                 | |                                      #
1652 #  _ __   ___   __| | ___  ___                             #
1653 # | '_ \ / _ \ / _` |/ _ \/ __|                            #
1654 # | | | | (_) | (_| |  __/\__ \                            #
1655 # |_| |_|\___/ \__,_|\___||___/                            #
1656 #----------------------------------------------------------#
1657
1658 vfadd => {
1659         irn_flags => "R",
1660         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1661         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1662         latency   => 4,
1663         units     => [ "VFP" ],
1664         mode      => "mode_E",
1665         attr_type => "ia32_x87_attr_t",
1666 },
1667
1668 vfmul => {
1669         irn_flags => "R",
1670         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1671         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1672         latency   => 4,
1673         units     => [ "VFP" ],
1674         mode      => "mode_E",
1675         attr_type => "ia32_x87_attr_t",
1676 },
1677
1678 l_vfmul => {
1679         op_flags  => "C",
1680         cmp_attr  => "return 1;",
1681         arity     => 2,
1682 },
1683
1684 vfsub => {
1685         irn_flags => "R",
1686         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1687         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1688         latency   => 4,
1689         units     => [ "VFP" ],
1690         mode      => "mode_E",
1691         attr_type => "ia32_x87_attr_t",
1692 },
1693
1694 l_vfsub => {
1695         cmp_attr  => "return 1;",
1696         arity     => 2,
1697 },
1698
1699 vfdiv => {
1700         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
1701         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1702         outs      => [ "res", "M" ],
1703         latency   => 20,
1704         units     => [ "VFP" ],
1705         attr_type => "ia32_x87_attr_t",
1706 },
1707
1708 l_vfdiv => {
1709         cmp_attr  => "return 1;",
1710         outs      => [ "res", "M" ],
1711         arity     => 2,
1712 },
1713
1714 vfprem => {
1715         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1716         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1717         latency   => 20,
1718         units     => [ "VFP" ],
1719         mode      => "mode_E",
1720         attr_type => "ia32_x87_attr_t",
1721 },
1722
1723 l_vfprem => {
1724         cmp_attr  => "return 1;",
1725         arity     => 2,
1726 },
1727
1728 vfabs => {
1729         irn_flags => "R",
1730         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1731         ins       => [ "value" ],
1732         latency   => 2,
1733         units     => [ "VFP" ],
1734         mode      => "mode_E",
1735         attr_type => "ia32_x87_attr_t",
1736 },
1737
1738 vfchs => {
1739         irn_flags => "R",
1740         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1741         ins       => [ "value" ],
1742         latency   => 2,
1743         units     => [ "VFP" ],
1744         mode      => "mode_E",
1745         attr_type => "ia32_x87_attr_t",
1746 },
1747
1748 # virtual Load and Store
1749
1750 vfld => {
1751         op_flags  => "L|F",
1752         state     => "exc_pinned",
1753         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1754         ins       => [ "base", "index", "mem" ],
1755         outs      => [ "res", "M" ],
1756         attr      => "ir_mode *load_mode",
1757         init_attr => "attr->attr.ls_mode = load_mode;",
1758         latency   => 2,
1759         units     => [ "VFP" ],
1760         attr_type => "ia32_x87_attr_t",
1761 },
1762
1763 vfst => {
1764         op_flags  => "L|F",
1765         state     => "exc_pinned",
1766         reg_req   => { in => [ "gp", "gp", "none", "vfp" ] },
1767         ins       => [ "base", "index", "mem", "val" ],
1768         attr      => "ir_mode *store_mode",
1769         init_attr => "attr->attr.ls_mode = store_mode;",
1770         latency   => 2,
1771         units     => [ "VFP" ],
1772         mode      => "mode_M",
1773         attr_type => "ia32_x87_attr_t",
1774 },
1775
1776 # Conversions
1777
1778 vfild => {
1779         state     => "exc_pinned",
1780         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1781         outs      => [ "res", "M" ],
1782         ins       => [ "base", "index", "mem" ],
1783         latency   => 4,
1784         units     => [ "VFP" ],
1785         attr_type => "ia32_x87_attr_t",
1786 },
1787
1788 l_vfild => {
1789         cmp_attr  => "return 1;",
1790         outs      => [ "res", "M" ],
1791         arity     => 2,
1792 },
1793
1794 vfist => {
1795         state     => "exc_pinned",
1796         reg_req   => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
1797         ins       => [ "base", "index", "mem", "val", "fpcw" ],
1798         latency   => 4,
1799         units     => [ "VFP" ],
1800         mode      => "mode_M",
1801         attr_type => "ia32_x87_attr_t",
1802 },
1803
1804 l_vfist => {
1805         cmp_attr  => "return 1;",
1806         state     => "exc_pinned",
1807         arity     => 3,
1808         mode      => "mode_M",
1809 },
1810
1811
1812 # constants
1813
1814 vfldz => {
1815         irn_flags => "R",
1816         reg_req   => { out => [ "vfp" ] },
1817         latency   => 4,
1818         units     => [ "VFP" ],
1819         mode      => "mode_E",
1820         attr_type => "ia32_x87_attr_t",
1821 },
1822
1823 vfld1 => {
1824         irn_flags => "R",
1825         reg_req   => { out => [ "vfp" ] },
1826         latency   => 4,
1827         units     => [ "VFP" ],
1828         mode      => "mode_E",
1829         attr_type => "ia32_x87_attr_t",
1830 },
1831
1832 vfldpi => {
1833         irn_flags => "R",
1834         reg_req   => { out => [ "vfp" ] },
1835         latency   => 4,
1836         units     => [ "VFP" ],
1837         mode      => "mode_E",
1838         attr_type => "ia32_x87_attr_t",
1839 },
1840
1841 vfldln2 => {
1842         irn_flags => "R",
1843         reg_req   => { out => [ "vfp" ] },
1844         latency   => 4,
1845         units     => [ "VFP" ],
1846         mode      => "mode_E",
1847         attr_type => "ia32_x87_attr_t",
1848 },
1849
1850 vfldlg2 => {
1851         irn_flags => "R",
1852         reg_req   => { out => [ "vfp" ] },
1853         latency   => 4,
1854         units     => [ "VFP" ],
1855         mode      => "mode_E",
1856         attr_type => "ia32_x87_attr_t",
1857 },
1858
1859 vfldl2t => {
1860         irn_flags => "R",
1861         reg_req   => { out => [ "vfp" ] },
1862         latency   => 4,
1863         units     => [ "VFP" ],
1864         mode      => "mode_E",
1865         attr_type => "ia32_x87_attr_t",
1866 },
1867
1868 vfldl2e => {
1869         irn_flags => "R",
1870         reg_req   => { out => [ "vfp" ] },
1871         latency   => 4,
1872         units     => [ "VFP" ],
1873         mode      => "mode_E",
1874         attr_type => "ia32_x87_attr_t",
1875 },
1876
1877 # other
1878
1879 vfCmpJmp => {
1880         state     => "pinned",
1881         op_flags  => "L|X|Y",
1882         reg_req   => { in => [ "vfp", "vfp" ], out => [ "none", "none", "eax" ] },
1883         ins       => [ "left", "right" ],
1884         outs      => [ "false", "true", "temp_reg_eax" ],
1885         attr      => "long pnc",
1886         init_attr => "attr->attr.pn_code = pnc;",
1887         latency   => 10,
1888         units     => [ "VFP" ],
1889         attr_type => "ia32_x87_attr_t",
1890 },
1891
1892 #------------------------------------------------------------------------#
1893 #       ___ _____    __ _             _                     _            #
1894 # __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1895 # \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1896 #  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1897 # /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1898 #------------------------------------------------------------------------#
1899
1900 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
1901 #       are swapped, we work this around in the emitter...
1902
1903 fadd => {
1904         op_flags  => "R",
1905         rd_constructor => "NONE",
1906         reg_req   => { },
1907         emit      => '. fadd%XM %x87_binop',
1908         attr_type => "ia32_x87_attr_t",
1909 },
1910
1911 faddp => {
1912         op_flags  => "R",
1913         rd_constructor => "NONE",
1914         reg_req   => { },
1915         emit      => '. faddp%XM %x87_binop',
1916         attr_type => "ia32_x87_attr_t",
1917 },
1918
1919 fmul => {
1920         op_flags  => "R",
1921         rd_constructor => "NONE",
1922         reg_req   => { },
1923         emit      => '. fmul%XM %x87_binop',
1924         attr_type => "ia32_x87_attr_t",
1925 },
1926
1927 fmulp => {
1928         op_flags  => "R",
1929         rd_constructor => "NONE",
1930         reg_req   => { },
1931         emit      => '. fmulp%XM %x87_binop',,
1932         attr_type => "ia32_x87_attr_t",
1933 },
1934
1935 fsub => {
1936         op_flags  => "R",
1937         rd_constructor => "NONE",
1938         reg_req   => { },
1939         emit      => '. fsub%XM %x87_binop',
1940         attr_type => "ia32_x87_attr_t",
1941 },
1942
1943 fsubp => {
1944         op_flags  => "R",
1945         rd_constructor => "NONE",
1946         reg_req   => { },
1947 # see note about gas bugs
1948         emit      => '. fsubrp%XM %x87_binop',
1949         attr_type => "ia32_x87_attr_t",
1950 },
1951
1952 fsubr => {
1953         op_flags  => "R",
1954         rd_constructor => "NONE",
1955         irn_flags => "R",
1956         reg_req   => { },
1957         emit      => '. fsubr%XM %x87_binop',
1958         attr_type => "ia32_x87_attr_t",
1959 },
1960
1961 fsubrp => {
1962         op_flags  => "R",
1963         rd_constructor => "NONE",
1964         irn_flags => "R",
1965         reg_req   => { },
1966 # see note about gas bugs
1967         emit      => '. fsubp%XM %x87_binop',
1968         attr_type => "ia32_x87_attr_t",
1969 },
1970
1971 fprem => {
1972         op_flags  => "R",
1973         rd_constructor => "NONE",
1974         reg_req   => { },
1975         emit      => '. fprem1',
1976         attr_type => "ia32_x87_attr_t",
1977 },
1978
1979 # this node is just here, to keep the simulator running
1980 # we can omit this when a fprem simulation function exists
1981 fpremp => {
1982         op_flags  => "R",
1983         rd_constructor => "NONE",
1984         reg_req   => { },
1985         emit      => '. fprem1',
1986         attr_type => "ia32_x87_attr_t",
1987 },
1988
1989 fdiv => {
1990         op_flags  => "R",
1991         rd_constructor => "NONE",
1992         reg_req   => { },
1993         emit      => '. fdiv%XM %x87_binop',
1994         attr_type => "ia32_x87_attr_t",
1995 },
1996
1997 fdivp => {
1998         op_flags  => "R",
1999         rd_constructor => "NONE",
2000         reg_req   => { },
2001 # see note about gas bugs
2002         emit      => '. fdivrp%XM %x87_binop',
2003         attr_type => "ia32_x87_attr_t",
2004 },
2005
2006 fdivr => {
2007         op_flags  => "R",
2008         rd_constructor => "NONE",
2009         reg_req   => { },
2010         emit      => '. fdivr%XM %x87_binop',
2011         attr_type => "ia32_x87_attr_t",
2012 },
2013
2014 fdivrp => {
2015         op_flags  => "R",
2016         rd_constructor => "NONE",
2017         reg_req   => { },
2018 # see note about gas bugs
2019         emit      => '. fdivp%XM %x87_binop',
2020         attr_type => "ia32_x87_attr_t",
2021 },
2022
2023 fabs => {
2024         op_flags  => "R",
2025         rd_constructor => "NONE",
2026         reg_req   => { },
2027         emit      => '. fabs',
2028         attr_type => "ia32_x87_attr_t",
2029 },
2030
2031 fchs => {
2032         op_flags  => "R|K",
2033         rd_constructor => "NONE",
2034         reg_req   => { },
2035         emit      => '. fchs',
2036         attr_type => "ia32_x87_attr_t",
2037 },
2038
2039 # x87 Load and Store
2040
2041 fld => {
2042         rd_constructor => "NONE",
2043         op_flags  => "R|L|F",
2044         state     => "exc_pinned",
2045         reg_req   => { },
2046         emit      => '. fld%XM %AM',
2047         attr_type => "ia32_x87_attr_t",
2048 },
2049
2050 fst => {
2051         rd_constructor => "NONE",
2052         op_flags  => "R|L|F",
2053         state     => "exc_pinned",
2054         reg_req   => { },
2055         emit      => '. fst%XM %AM',
2056         mode      => "mode_M",
2057         attr_type => "ia32_x87_attr_t",
2058 },
2059
2060 fstp => {
2061         rd_constructor => "NONE",
2062         op_flags  => "R|L|F",
2063         state     => "exc_pinned",
2064         reg_req   => { },
2065         emit      => '. fstp%XM %AM',
2066         mode      => "mode_M",
2067         attr_type => "ia32_x87_attr_t",
2068 },
2069
2070 # Conversions
2071
2072 fild => {
2073         op_flags  => "R",
2074         rd_constructor => "NONE",
2075         reg_req   => { },
2076         emit      => '. fild%M %AM',
2077         attr_type => "ia32_x87_attr_t",
2078 },
2079
2080 fist => {
2081         op_flags  => "R",
2082         state     => "exc_pinned",
2083         rd_constructor => "NONE",
2084         reg_req   => { },
2085         emit      => '. fist%M %AM',
2086         mode      => "mode_M",
2087         attr_type => "ia32_x87_attr_t",
2088 },
2089
2090 fistp => {
2091         op_flags  => "R",
2092         state     => "exc_pinned",
2093         rd_constructor => "NONE",
2094         reg_req   => { },
2095         emit      => '. fistp%M %AM',
2096         mode      => "mode_M",
2097         attr_type => "ia32_x87_attr_t",
2098 },
2099
2100 # constants
2101
2102 fldz => {
2103         op_flags  => "R|c|K",
2104         irn_flags  => "R",
2105         reg_req   => { },
2106         emit      => '. fldz',
2107         attr_type => "ia32_x87_attr_t",
2108 },
2109
2110 fld1 => {
2111         op_flags  => "R|c|K",
2112         irn_flags  => "R",
2113         reg_req   => { },
2114         emit      => '. fld1',
2115         attr_type => "ia32_x87_attr_t",
2116 },
2117
2118 fldpi => {
2119         op_flags  => "R|c|K",
2120         irn_flags  => "R",
2121         reg_req   => { },
2122         emit      => '. fldpi',
2123         attr_type => "ia32_x87_attr_t",
2124 },
2125
2126 fldln2 => {
2127         op_flags  => "R|c|K",
2128         irn_flags  => "R",
2129         reg_req   => { },
2130         emit      => '. fldln2',
2131         attr_type => "ia32_x87_attr_t",
2132 },
2133
2134 fldlg2 => {
2135         op_flags  => "R|c|K",
2136         irn_flags  => "R",
2137         reg_req   => { },
2138         emit      => '. fldlg2',
2139         attr_type => "ia32_x87_attr_t",
2140 },
2141
2142 fldl2t => {
2143         op_flags  => "R|c|K",
2144         irn_flags  => "R",
2145         reg_req   => { },
2146         emit      => '. fldll2t',
2147         attr_type => "ia32_x87_attr_t",
2148 },
2149
2150 fldl2e => {
2151         op_flags  => "R|c|K",
2152         irn_flags  => "R",
2153         reg_req   => { },
2154         emit      => '. fldl2e',
2155         attr_type => "ia32_x87_attr_t",
2156 },
2157
2158 # fxch, fpush, fpop
2159 # Note that it is NEVER allowed to do CSE on these nodes
2160 # Moreover, note the virtual register requierements!
2161
2162 fxch => {
2163         op_flags  => "R|K",
2164         reg_req   => { },
2165         cmp_attr  => "return 1;",
2166         emit      => '. fxch %X0',
2167         attr_type => "ia32_x87_attr_t",
2168 },
2169
2170 fpush => {
2171         op_flags  => "R|K",
2172         reg_req   => {},
2173         cmp_attr  => "return 1;",
2174         emit      => '. fld %X0',
2175         attr_type => "ia32_x87_attr_t",
2176 },
2177
2178 fpushCopy => {
2179         op_flags  => "R",
2180         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
2181         cmp_attr  => "return 1;",
2182         emit      => '. fld %X0',
2183         attr_type => "ia32_x87_attr_t",
2184 },
2185
2186 fpop => {
2187         op_flags  => "K",
2188         reg_req   => { },
2189         cmp_attr  => "return 1;",
2190         emit      => '. fstp %X0',
2191         attr_type => "ia32_x87_attr_t",
2192 },
2193
2194 ffreep => {
2195         op_flags  => "K",
2196         reg_req   => { },
2197         cmp_attr  => "return 1;",
2198         emit      => '. ffreep %X0',
2199         attr_type => "ia32_x87_attr_t",
2200 },
2201
2202 emms => {
2203         op_flags  => "K",
2204         reg_req   => { },
2205         cmp_attr  => "return 1;",
2206         emit      => '. emms',
2207         attr_type => "ia32_x87_attr_t",
2208 },
2209
2210 femms => {
2211         op_flags  => "K",
2212         reg_req   => { },
2213         cmp_attr  => "return 1;",
2214         emit      => '. femms',
2215         attr_type => "ia32_x87_attr_t",
2216 },
2217
2218 # compare
2219
2220 fcomJmp => {
2221         op_flags  => "L|X|Y",
2222         reg_req   => { },
2223         attr_type => "ia32_x87_attr_t",
2224 },
2225
2226 fcompJmp => {
2227         op_flags  => "L|X|Y",
2228         reg_req   => { },
2229         attr_type => "ia32_x87_attr_t",
2230 },
2231
2232 fcomppJmp => {
2233         op_flags  => "L|X|Y",
2234         reg_req   => { },
2235         attr_type => "ia32_x87_attr_t",
2236 },
2237
2238 fcomrJmp => {
2239         op_flags  => "L|X|Y",
2240         reg_req   => { },
2241         attr_type => "ia32_x87_attr_t",
2242 },
2243
2244 fcomrpJmp => {
2245         op_flags  => "L|X|Y",
2246         reg_req   => { },
2247         attr_type => "ia32_x87_attr_t",
2248 },
2249
2250 fcomrppJmp => {
2251         op_flags  => "L|X|Y",
2252         reg_req   => { },
2253         attr_type => "ia32_x87_attr_t",
2254 },
2255
2256
2257 # -------------------------------------------------------------------------------- #
2258 #  ____ ____  _____                  _                               _             #
2259 # / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___   #
2260 # \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|  #
2261 #  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \  #
2262 # |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/  #
2263 #                                                                                  #
2264 # -------------------------------------------------------------------------------- #
2265
2266
2267 # Spilling and reloading of SSE registers, hardcoded, not generated #
2268
2269 xxLoad => {
2270         op_flags  => "L|F",
2271         state     => "exc_pinned",
2272         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2273         emit      => '. movdqu %D0, %AM',
2274         outs      => [ "res", "M" ],
2275         units     => [ "SSE" ],
2276 },
2277
2278 xxStore => {
2279         op_flags => "L|F",
2280         state    => "exc_pinned",
2281         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
2282         ins      => [ "base", "index", "mem", "val" ],
2283         emit     => '. movdqu %binop',
2284         units    => [ "SSE" ],
2285         mode     => "mode_M",
2286 },
2287
2288 ); # end of %nodes
2289
2290 # Include the generated SIMD node specification written by the SIMD optimization
2291 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2292 unless ($return = do $my_script_name) {
2293         warn "couldn't parse $my_script_name: $@" if $@;
2294         warn "couldn't do $my_script_name: $!"    unless defined $return;
2295         warn "couldn't run $my_script_name"       unless $return;
2296 }