change backend node specification to use whole words instead of cryptical 1-char...
[libfirm] / ir / be / sparc / sparc_spec.pl
1 # Creation: 2006/02/13
2 # $Id$
3
4 $arch = "sparc";
5
6 $mode_gp      = "mode_Iu";
7 $mode_flags   = "mode_Bu";
8 $mode_fp      = "mode_D";
9
10 # The node description is done as a perl hash initializer with the
11 # following structure:
12 #
13 # %nodes = (
14 #
15 # <op-name> => {
16 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",                 # optional
17 #   irn_flags => "R|N|I"                                # optional
18 #   arity     => "0|1|2|3 ... |variable|dynamic|any",   # optional
19 #   state     => "floats|pinned|mem_pinned|exc_pinned", # optional
20 #   args      => [
21 #                    { type => "type 1", name => "name 1" },
22 #                    { type => "type 2", name => "name 2" },
23 #                    ...
24 #                  ],
25 #   comment   => "any comment for constructor",  # optional
26 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
27 #   cmp_attr  => "c source code for comparing node attributes", # optional
28 #   outs      => { "out1", "out2" },# optional, creates pn_op_out1, ... consts
29 #   ins       => { "in1", "in2" },  # optional, creates n_op_in1, ... consts
30 #   mode      => "mode_Iu",         # optional, predefines the mode
31 #   emit      => "emit code with templates",   # optional for virtual nodes
32 #   attr      => "additional attribute arguments for constructor", # optional
33 #   init_attr => "emit attribute initialization template",         # optional
34 #   rd_constructor => "c source code which constructs an ir_node", # optional
35 #   hash_func => "name of the hash function for this operation",   # optional, get the default hash function else
36 #   latency   => "latency of this operation (can be float)"        # optional
37 #   attr_type => "name of the attribute struct",                   # optional
38 # },
39 #
40 # ... # (all nodes you need to describe)
41 #
42 # ); # close the %nodes initializer
43
44 # state: state of the operation, OPTIONAL (default is "floats")
45 #
46 # arity: arity of the operation, MUST NOT BE OMITTED
47 #
48 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
49 #        are always the first 3 arguments and are always autmatically
50 #        created)
51 #        If this key is missing the following arguments will be created:
52 #        for i = 1 .. arity: ir_node *op_i
53 #        ir_mode *mode
54 #
55 # outs:  if a node defines more than one output, the names of the projections
56 #        nodes having outs having automatically the mode mode_T
57 #
58 # comment: OPTIONAL comment for the node constructor
59 #
60 # rd_constructor: for every operation there will be a
61 #      new_rd_<arch>_<op-name> function with the arguments from above
62 #      which creates the ir_node corresponding to the defined operation
63 #      you can either put the complete source code of this function here
64 #
65 #      This key is OPTIONAL. If omitted, the following constructor will
66 #      be created:
67 #      if (!op_<arch>_<op-name>) assert(0);
68 #      for i = 1 to arity
69 #         set in[i] = op_i
70 #      done
71 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
72 #      return res
73 #
74 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
75
76 # register types:
77 #   0 - no special type
78 #   1 - caller save (register must be saved by the caller of a function)
79 #   2 - callee save (register must be saved by the called function)
80 #   4 - ignore (do not assign this register)
81 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
82
83 # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
84 %reg_classes = (
85         gp => [
86                 { name => "g0", realname => "g0", type => 4 }, # hardwired 0, behaves like /dev/null
87                 { name => "g1", realname => "g1", type => 1 }, # temp. value
88                 { name => "g2", realname => "g2", type => 1 },
89                 { name => "g3", realname => "g3", type => 1 },
90                 { name => "g4", realname => "g4", type => 1 },
91                 { name => "g5", realname => "g5", type => 4 }, # reserved by SPARC ABI
92                 { name => "g6", realname => "g6", type => 4 }, # reserved by SPARC ABI
93                 { name => "g7", realname => "g7", type => 4 }, # reserved by SPARC ABI
94
95                 # window's out registers
96                 { name => "o0", realname => "o0", type => 1 }, # param 1 / return value from callee
97                 { name => "o1", realname => "o1", type => 1 }, # param 2
98                 { name => "o2", realname => "o2", type => 1 }, # param 3
99                 { name => "o3", realname => "o3", type => 1 }, # param 4
100                 { name => "o4", realname => "o4", type => 1 }, # param 5
101                 { name => "o5", realname => "o5", type => 1 }, # param 6
102                 { name => "sp", realname => "sp", type => 4 }, # our stackpointer
103                 { name => "o7", realname => "o6", type => 4 }, # temp. value / address of CALL instr.
104
105                 # window's local registers
106                 { name => "l0", realname => "l0", type => 0 },
107                 { name => "l1", realname => "l1", type => 0 },
108                 { name => "l2", realname => "l2", type => 0 },
109                 { name => "l3", realname => "l3", type => 0 },
110                 { name => "l4", realname => "l4", type => 0 },
111                 { name => "l5", realname => "l5", type => 0 },
112                 { name => "l6", realname => "l6", type => 0 },
113                 { name => "l7", realname => "l7", type => 0 },
114
115                 # window's in registers
116                 { name => "i0", realname => "i0", type => 0 }, # incoming param1 / return value to caller
117                 { name => "i1", realname => "i1", type => 0 }, # param 2
118                 { name => "i2", realname => "i2", type => 0 }, # param 3
119                 { name => "i3", realname => "i3", type => 0 }, # param 4
120                 { name => "i4", realname => "i4", type => 0 }, # param 5
121                 { name => "i5", realname => "i5", type => 0 }, # param 6
122                 { name => "fp", realname => "fp", type => 4 }, # our framepointer
123                 { name => "i7", realname => "i7", type => 4 }, # return address - 8
124                 { mode => $mode_gp }
125         ],
126         flags => [
127                 { name => "y", realname => "y", type => 4 },  # the multiply/divide state register
128                 { mode => $mode_flags, flags => "manual_ra" }
129         ],
130 #       cpu => [
131 #               { name => "psr", realname => "psr", type => 4 },  # the processor state register
132 #               { name => "wim", realname => "wim", type => 4 },  # the window invalid mask register
133 #               { name => "tbr", realname => "tbr", type => 4 },  # the trap base register
134 #               { name => "pc", realname => "pc", type => 4 },  # the program counter register
135 #               { name => "npc", realname => "npc", type => 4 },  # the next instruction addr. (PC + 1) register
136 #               { mode => "mode_Iu", flags => "manual_ra" }
137 #       ],
138
139         # fp registers can be accessed any time
140         fp  => [
141                 { name => "f0", type => 1 },
142                 { name => "f1", type => 1 },
143                 { name => "f2", type => 1 },
144                 { name => "f3", type => 1 },
145                 { name => "f4", type => 1 },
146                 { name => "f5", type => 1 },
147                 { name => "f6", type => 1 },
148                 { name => "f7", type => 1 },
149                 { name => "f8", type => 1 },
150                 { name => "f9", type => 1 },
151                 { name => "f10", type => 1 },
152                 { name => "f11", type => 1 },
153                 { name => "f12", type => 1 },
154                 { name => "f13", type => 1 },
155                 { name => "f14", type => 1 },
156                 { name => "f15", type => 1 },
157                 { name => "f16", type => 1 },
158                 { name => "f17", type => 1 },
159                 { name => "f18", type => 1 },
160                 { name => "f19", type => 1 },
161                 { name => "f20", type => 1 },
162                 { name => "f21", type => 1 },
163                 { name => "f22", type => 1 },
164                 { name => "f23", type => 1 },
165                 { name => "f24", type => 1 },
166                 { name => "f25", type => 1 },
167                 { name => "f26", type => 1 },
168                 { name => "f27", type => 1 },
169                 { name => "f28", type => 1 },
170                 { name => "f29", type => 1 },
171                 { name => "f30", type => 1 },
172                 { name => "f31", type => 1 },
173                 { mode => $mode_fp }
174         ]
175 ); # %reg_classes
176
177 %emit_templates = (
178 # emit source reg or imm dep. on node's arity
179     RI => "${arch}_emit_reg_or_imm(node, -1);",
180     R1I => "${arch}_emit_reg_or_imm(node, 0);",
181     R2I => "${arch}_emit_reg_or_imm(node, 1);",
182     R3I => "${arch}_emit_reg_or_imm(node, 2);",
183 # simple reg emitters
184     S1 => "${arch}_emit_source_register(node, 0);",
185     S2 => "${arch}_emit_source_register(node, 1);",
186     S3 => "${arch}_emit_source_register(node, 2);",
187     S4 => "${arch}_emit_source_register(node, 3);",
188     S5 => "${arch}_emit_source_register(node, 4);",
189     S6 => "${arch}_emit_source_register(node, 5);",
190     D1 => "${arch}_emit_dest_register(node, 0);",
191     D2 => "${arch}_emit_dest_register(node, 1);",
192     D3 => "${arch}_emit_dest_register(node, 2);",
193     D4 => "${arch}_emit_dest_register(node, 3);",
194     D5 => "${arch}_emit_dest_register(node, 4);",
195     D6 => "${arch}_emit_dest_register(node, 5);",
196 # more custom emitters
197         C  => "${arch}_emit_immediate(node);",
198         LM  => "${arch}_emit_load_mode(node);",
199         SM  => "${arch}_emit_store_mode(node);",
200         EXTPREF  => "${arch}_emit_mode_sign_prefix(node);",
201         FPM  => "${arch}_emit_fp_mode_suffix(node);",
202         FPLM  => "${arch}_emit_fp_load_mode(node);",
203         FPSM  => "${arch}_emit_fp_store_mode(node);",
204         O  => "${arch}_emit_offset(node);",
205 );
206
207 $default_attr_type = "sparc_attr_t";
208 $default_copy_attr = "sparc_copy_attr";
209
210
211 %init_attr = (
212                 sparc_attr_t                            => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
213                 sparc_load_store_attr_t                 => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
214                                                                                         "\tinit_sparc_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
215                 sparc_symconst_attr_t                   => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
216                                                                 "\tinit_sparc_symconst_attributes(res, entity);",
217                 sparc_cmp_attr_t                        => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n",
218                 sparc_jmp_cond_attr_t                   => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
219                 sparc_jmp_switch_attr_t                 => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
220                 sparc_save_attr_t                       => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
221
222 );
223
224 %compare_attr = (
225                 sparc_attr_t            => "cmp_attr_sparc",
226                 sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
227                 sparc_symconst_attr_t   => "cmp_attr_sparc_symconst",
228                 sparc_jmp_cond_attr_t   => "cmp_attr_sparc_jmp_cond",
229                 sparc_jmp_switch_attr_t => "cmp_attr_sparc_jmp_switch",
230                 sparc_cmp_attr_t        => "cmp_attr_sparc_cmp",
231                 sparc_save_attr_t       => "cmp_attr_sparc_save",
232 );
233
234
235 # addressing modes: imm, reg, reg +/- imm, reg + reg
236 # max. imm = 13 bits signed (-4096 ... 4096)
237
238
239 my %cmp_operand_constructors = (
240     imm => {
241         attr       => "int immediate_value, bool ins_permuted, bool is_unsigned",
242         custominit => "sparc_set_attr_imm(res, immediate_value);" .
243                                                 "\tinit_sparc_cmp_attr(res, ins_permuted, is_unsigned);",
244         reg_req    => { in => [ "gp" ], out => [ "flags" ] },
245         ins        => [ "left" ],
246     },
247     reg => {
248         attr       => "bool ins_permuted, bool is_unsigned",
249         custominit => "init_sparc_cmp_attr(res, ins_permuted, is_unsigned);",
250         reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
251         ins        => [ "left", "right" ],
252     },
253 );
254
255 my %unop_operand_constructors = (
256     imm => {
257         attr       => "int immediate_value",
258         custominit => "sparc_set_attr_imm(res, immediate_value);",
259         reg_req    => { in => [], out => [ "gp" ] },
260     },
261     reg => {
262         reg_req    => { in => [ "gp" ], out => [ "gp" ] },
263     },
264 );
265
266 my %binop_operand_constructors = (
267     imm => {
268         attr       => "int immediate_value",
269         custominit => "sparc_set_attr_imm(res, immediate_value);",
270         reg_req    => { in => [ "gp" ], out => [ "gp" ] },
271         ins        => [ "left" ],
272     },
273     reg => {
274         reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
275         ins        => [ "left", "right" ],
276     },
277 );
278
279 %nodes = (
280
281 Add => {
282   irn_flags => [ "rematerializable" ],
283   comment   => "construct Add: Add(a, b) = Add(b, a) = a + b",
284   mode          => $mode_gp,
285   emit      => '. add %S1, %R2I, %D1',
286   constructors => \%binop_operand_constructors,
287 },
288
289 Sub => {
290   irn_flags => [ "rematerializable" ],
291   comment   => "construct Sub: Sub(a, b) = a - b",
292   mode          => $mode_gp,
293   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
294   emit      => '. sub %S1, %R2I, %D1',
295   constructors => \%binop_operand_constructors,
296 },
297
298
299 # Load / Store
300 Load => {
301   op_flags  => [ "labeled", "fragile" ],
302   comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
303   state     => "exc_pinned",
304   ins       => [ "ptr", "mem" ],
305   outs      => [ "res", "M" ],
306   reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
307   attr_type => "sparc_load_store_attr_t",
308   attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
309   emit      => '. ld%LM [%S1%O], %D1'
310 },
311
312 LoadHi => {
313   op_flags  => [ "labeled", "fragile" ],
314   comment   => "construct LoadHi: Load(ptr, mem) = sethi hi(ptr) -> reg",
315   state     => "exc_pinned",
316   ins       => [ "ptr", "mem" ],
317   outs      => [ "res", "M" ],
318   reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
319   attr_type => "sparc_load_store_attr_t",
320   attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
321   emit      => '. sethi %%hi(%S1), %D1',
322 },
323
324 HiImm => {
325   irn_flags => [ "rematerializable" ],
326   comment   => "construct LoadHi: Load(imm, mem) = sethi hi(imm) -> reg",
327   state     => "exc_pinned",
328   outs      => [ "res" ],
329   mode      => $mode_gp,
330   reg_req   => { in => [], out => [ "gp" ] },
331   #attr_type => "sparc_load_store_attr_t",
332   attr       => "int immediate_value",
333   custominit => "sparc_set_attr_imm(res, immediate_value);",
334
335 },
336
337 LoImm => {
338   irn_flags => [ "rematerializable" ],
339   comment   => "construct LoadHi: Load(imm, mem) = sethi hi(imm) -> reg",
340   state     => "exc_pinned",
341   ins       => [ "hireg" ],
342   outs      => [ "res" ],
343   mode      => $mode_gp,
344   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
345   #attr_type => "sparc_load_store_attr_t",
346   attr       => "int immediate_value",
347   custominit => "sparc_set_attr_imm(res, immediate_value);",
348
349 },
350
351 LoadLo => {
352   op_flags  => [ "labeled", "fragile" ],
353   comment   => "construct LoadLo: Or(in, ptr, mem) = or in lo(ptr) -> reg",
354   state     => "exc_pinned",
355   ins       => [ "hireg", "ptr", "mem" ],
356   outs      => [ "res", "M" ],
357   reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
358   attr_type => "sparc_load_store_attr_t",
359   attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
360   emit      => '. or %S1, %%lo(%S2), %D1'
361 },
362
363 Store => {
364   op_flags  => [ "labeled", "fragile" ],
365   comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
366   mode          => "mode_M",
367   state     => "exc_pinned",
368   ins       => [ "ptr", "val", "mem" ],
369   outs      => [ "mem" ],
370   reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
371   attr_type => "sparc_load_store_attr_t",
372   attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
373   emit      => '. st%SM %S2, [%S1%O]'
374 },
375
376 Mov => {
377   irn_flags => [ "rematerializable" ],
378   comment   => "construct Mov: Mov(src, dest) = MV src,dest",
379   arity     => "variable",
380   emit      => '. mov %R1I, %D1',
381   mode      => $mode_gp,
382   constructors => \%unop_operand_constructors,
383 },
384
385 Save => {
386         comment => "function prolog instruction. autom. saves sp & shifts the register window. previous out regs become the new in regs",
387         reg_req   => {
388                         in => [ "sp", "none"],
389                         out => [ "sp:I|S","none" ]
390         },
391         ins       => [ "stack", "mem" ],
392         outs      => [ "stack", "mem" ],
393         attr      => "int initial_stacksize",
394         attr_type => "sparc_save_attr_t",
395         init_attr => "\tinit_sparc_save_attr(res, initial_stacksize);",
396 },
397
398 AddSP => {
399         comment => "alloc stack space",
400         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
401         ins       => [ "stack", "size", "mem" ],
402         outs      => [ "stack", "addr", "M" ],
403         emit      => ". sub %S1, %S2, %D1\n",
404 },
405
406 SubSP => {
407         comment => "free stack space",
408         reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
409         ins       => [ "stack", "size", "mem" ],
410         outs      => [ "stack", "M" ],
411         emit      => ". add %S1, %S2, %D1\n",
412 },
413
414 SymConst => {
415         op_flags  => [ "constlike" ],
416         irn_flags => [ "rematerializable" ],
417         attr      => "ir_entity *entity",
418         reg_req   => { out => [ "gp" ] },
419         attr_type => "sparc_symconst_attr_t",
420         mode      => $mode_gp,
421 },
422
423 FrameAddr => {
424         op_flags  => [ "constlike" ],
425         irn_flags => [ "rematerializable" ],
426         attr      => "ir_entity *entity",
427         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
428         ins       => [ "base" ],
429         attr_type => "sparc_symconst_attr_t",
430         mode      => $mode_gp,
431 },
432
433 Branch => {
434         op_flags  => [ "labeled", "cfopcode", "forking" ],
435         state     => "pinned",
436         mode      => "mode_T",
437         reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
438         attr      => "int proj_num",
439         attr_type => "sparc_jmp_cond_attr_t",
440         init_attr => "\tset_sparc_jmp_cond_proj_num(res, proj_num);",
441 },
442
443 Jmp => {
444         state     => "pinned",
445         op_flags  => [ "cfopcode" ],
446         irn_flags => [ "simple_jump" ],
447         reg_req   => { out => [ "none" ] },
448         mode      => "mode_X",
449 },
450
451 Cmp => {
452         irn_flags    => [ "rematerializable", "modify_flags" ],
453         emit         => '. cmp %S1, %R2I',
454         mode         => $mode_flags,
455         attr_type    => "sparc_cmp_attr_t",
456         constructors => \%cmp_operand_constructors,
457 },
458
459 Tst => {
460         irn_flags    => [ "rematerializable", "modify_flags" ],
461         emit         => '. tst %S1',
462         mode         => $mode_flags,
463         attr_type    => "sparc_cmp_attr_t",
464         attr         => "bool ins_permuted, bool is_unsigned",
465         custominit   => "init_sparc_cmp_attr(res, ins_permuted, is_unsigned);",
466         reg_req      => { in => [ "gp" ], out => [ "flags" ] },
467         ins          => [ "left" ],
468 },
469
470 SwitchJmp => {
471         op_flags  => [ "labeled", "cfopcode", "forking" ],
472         state     => "pinned",
473         mode      => "mode_T",
474         attr      => "int n_projs, long def_proj_num",
475         init_attr => "\tset_sparc_jmp_switch_n_projs(res, n_projs);\n".
476                                         "\tset_sparc_jmp_switch_default_proj_num(res, def_proj_num);",
477         reg_req   => { in => [ "gp" ], out => [ "none" ] },
478         attr_type => "sparc_jmp_switch_attr_t",
479 },
480
481 ShiftLL => {
482   irn_flags => [ "rematerializable" ],
483   comment   => "construct shift logical left",
484   mode          => $mode_gp,
485   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
486   emit      => '. sll %S1, %R2I, %D1',
487   constructors => \%binop_operand_constructors,
488 },
489
490 ShiftLR => {
491   irn_flags => [ "rematerializable" ],
492   comment   => "construct shift logical right",
493   mode          => $mode_gp,
494   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
495   emit      => '. srl %S1, %R2I, %D1',
496   constructors => \%binop_operand_constructors,
497 },
498
499 ShiftRA => {
500   irn_flags => [ "rematerializable" ],
501   comment   => "construct shift right arithmetical",
502   mode          => $mode_gp,
503   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
504   emit      => '. sra %S1, %R2I, %D1',
505   constructors => \%binop_operand_constructors,
506 },
507
508 And => {
509   irn_flags => [ "rematerializable" ],
510   comment   => "construct logical and",
511   mode          => $mode_gp,
512   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
513   emit      => '. and %S1, %R2I, %D1',
514   constructors => \%binop_operand_constructors,
515 },
516
517 Or => {
518   irn_flags => [ "rematerializable" ],
519   comment   => "construct logical or",
520   mode          => $mode_gp,
521   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
522   emit      => '. or %S1, %R2I, %D1',
523   constructors => \%binop_operand_constructors,
524 },
525
526 Xor => {
527   irn_flags => [ "rematerializable" ],
528   comment   => "construct logical xor",
529   mode          => $mode_gp,
530   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
531   emit      => '. xor %S1, %R2I, %D1',
532   constructors => \%binop_operand_constructors,
533 },
534
535 Mul => {
536   state     => "exc_pinned",
537   comment   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
538   reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] },
539   outs      => [ "low", "high" ],
540   constructors => \%binop_operand_constructors,
541 #  emit      =>'. mul %S1, %R2I, %D1'
542 },
543
544 Mulh => {
545   state     => "exc_pinned",
546   comment   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
547   reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
548   outs      => [ "low", "high" ],
549   constructors => \%binop_operand_constructors,
550 },
551
552 Div => {
553   irn_flags => [ "rematerializable" ],
554   state     => "exc_pinned",
555 #  mode     => $mode_gp,
556   comment   => "construct Div: Div(a, b) = a / b",
557   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
558   outs      => [ "res" ],
559   constructors => \%binop_operand_constructors,
560 #  emit      =>'. div %S1, %R2I, %D1'
561 },
562
563 Minus => {
564   irn_flags => [ "rematerializable" ],
565   mode      => $mode_gp,
566   comment   => "construct Minus: Minus(a) = -a",
567   #reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
568   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
569   emit      => ". sub %%g0, %S1, %D1"
570 },
571
572 Not => {
573   irn_flags   => [ "rematerializable" ],
574   mode        => $mode_gp,
575   comment     => "construct Not: Not(a) = !a",
576   reg_req     => { in => [ "gp" ], out => [ "gp" ] },
577   emit        => '. xnor %S1, %%g0, %D1'
578 },
579
580 Nop => {
581         op_flags => [ "keep" ],
582         reg_req  => { in => [], out => [ "none" ] },
583         emit     => '. nop',
584 },
585
586 #Mul_i => {
587 #  irn_flags => "R",
588 #  comment   => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
589 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
590 #  emit      => '. mul %S1, %C, %D1'
591 #},
592 #
593 #And => {
594 #  op_flags  => "C",
595 #  irn_flags => "R",
596 #  comment   => "construct And: And(a, b) = And(b, a) = a AND b",
597 #  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
598 #  emit      => '. and %S1, %S2, %D1'
599 #},
600 #
601 #And_i => {
602 #  irn_flags => "R",
603 #  comment   => "construct And: And(a, const) = And(const, a) = a AND const",
604 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
605 #  emit      => '. and %S1, %C, %D1'
606 #},
607 #
608 #Or => {
609 #  op_flags  => "C",
610 #  irn_flags => "R",
611 #  comment   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
612 #  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
613 #  emit      => '. or %S1, %S2, %D1'
614 #},
615 #
616 #Or_i => {
617 #  op_flags  => "C",
618 #  irn_flags => "R",
619 #  comment   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
620 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
621 #  emit      => '. or %S1, %C, %D1'
622 #},
623 #
624 #Eor => {
625 #  op_flags  => "C",
626 #  irn_flags => "R",
627 #  comment   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
628 #  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
629 #  emit      => '. xor %S1, %S2, %D1'
630 #},
631 #
632 #Eor_i => {
633 #  irn_flags => "R",
634 #  comment   => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
635 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
636 #  emit      => '. xor %S1, %C, %D1'
637 #},
638
639 # not commutative operations
640 #Shl => {
641 #  irn_flags => "R",
642 #  comment   => "construct Shl: Shl(a, b) = a << b",
643 #  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
644 #  emit      => '. shl %S1, %S2, %D1'
645 #},
646 #
647 #Shl_i => {
648 #  irn_flags => "R",
649 #  comment   => "construct Shl: Shl(a, const) = a << const",
650 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
651 #  emit      => '. shl %S1, %C, %D1'
652 #},
653 #
654 #Shr => {
655 #  irn_flags => "R",
656 #  comment   => "construct Shr: Shr(a, b) = a >> b",
657 #  reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1" ] },
658 #  emit      => '. shr %S2, %D1'
659 #},
660 #
661 #Shr_i => {
662 #  irn_flags => "R",
663 #  comment   => "construct Shr: Shr(a, const) = a >> const",
664 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
665 #  emit      => '. shr %S1, %C, %D1'
666 #},
667 #
668 #RotR => {
669 #  irn_flags => "R",
670 #  comment   => "construct RotR: RotR(a, b) = a ROTR b",
671 #  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
672 #  emit      => '. ror %S1, %S2, %D1'
673 #},
674 #
675 #RotL => {
676 #  irn_flags => "R",
677 #  comment   => "construct RotL: RotL(a, b) = a ROTL b",
678 #  reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
679 #  emit      => '. rol %S1, %S2, %D1'
680 #},
681 #
682 #RotL_i => {
683 #  irn_flags => "R",
684 #  comment   => "construct RotL: RotL(a, const) = a ROTL const",
685 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
686 #  emit      => '. rol %S1, %C, %D1'
687 #},
688 #
689 #Minus => {
690 #  irn_flags => "R",
691 #  comment   => "construct Minus: Minus(a) = -a",
692 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
693 #  emit      => '. neg %S1, %D1'
694 #},
695 #
696 #Inc => {
697 #  irn_flags => "R",
698 #  comment   => "construct Increment: Inc(a) = a++",
699 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
700 #  emit      => '. inc %S1, %D1'
701 #},
702 #
703 #Dec => {
704 #  irn_flags => "R",
705 #  comment   => "construct Decrement: Dec(a) = a--",
706 #  reg_req   => { in => [ "gp" ], out => [ "gp" ] },
707 #  emit      => '. dec %S1, %D1'
708 #},
709 #
710 #Not => {
711 #  arity       => 1,
712 #  remat       => 1,
713 #  comment     => "construct Not: Not(a) = !a",
714 #  reg_req     => { in => [ "gp" ], out => [ "gp" ] },
715 #  emit        => '. not %S1, %D1'
716 #},
717
718 fAdd => {
719   op_flags  => [ "commutative" ],
720   irn_flags => [ "rematerializable" ],
721   comment   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
722   reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
723   emit      => '. fadd%FPM %S1, %S2, %D1'
724 },
725
726 fMul => {
727   op_flags  => [ "commutative" ],
728   comment   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
729   reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
730   emit      =>'. fmul%FPM %S1, %S2, %D1'
731 },
732
733 fsMuld => {
734   op_flags  => [ "commutative" ],
735   comment   => "construct FP single to double precision Mul: Mul(a, b) = Mul(b, a) = a * b",
736   reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
737   emit      =>'. fsmuld %S1, %S2, %D1'
738 },
739
740 FpSToFpD => {
741   irn_flags => [ "rematerializable" ],
742   comment   => "convert FP (single) to FP (double)",
743   reg_req   => { in => [ "fp" ], out => [ "fp" ] },
744   emit      =>'. FsTOd %S1, %D1'
745 },
746
747 FpDToFpS => {
748   irn_flags => [ "rematerializable" ],
749   comment   => "convert FP (double) to FP (single)",
750   reg_req   => { in => [ "fp" ], out => [ "fp" ] },
751   emit      =>'. FdTOs %S1, %D1'
752 },
753
754 FpSToInt => {
755   irn_flags => [ "rematerializable" ],
756   comment   => "convert integer to FP",
757   reg_req   => { in => [ "fp" ], out => [ "gp" ] },
758   emit      =>'. FiTOs %S1, %D1'
759 },
760
761 FpDToInt => {
762   irn_flags => [ "rematerializable" ],
763   comment   => "convert integer to FP",
764   reg_req   => { in => [ "fp" ], out => [ "gp" ] },
765   emit      =>'. FiTOd %S1, %D1'
766 },
767
768 IntToFpS => {
769   irn_flags => [ "rematerializable" ],
770   comment   => "convert FP (single) to integer",
771   reg_req   => { in => [ "gp" ], out => [ "fp" ] },
772   emit      =>'. FsTOi %S1, %D1'
773 },
774
775 IntToFpD => {
776   irn_flags => [ "rematerializable" ],
777   comment   => "convert FP (double) to integer",
778   reg_req   => { in => [ "gp" ], out => [ "fp" ] },
779   emit      =>'. FdTOi %S1, %D1'
780 },
781
782
783 #
784 #fMax => {
785 #  op_flags  => "C",
786 #  irn_flags => "R",
787 #  comment   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
788 #  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
789 #  emit      =>'. fmax %S1, %S2, %D1'
790 #},
791 #
792 #fMin => {
793 #  op_flags  => "C",
794 #  irn_flags => "R",
795 #  comment   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
796 #  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
797 #  emit      =>'. fmin %S1, %S2, %D1'
798 #},
799 #
800 ## not commutative operations
801 #
802 #fSub => {
803 #  irn_flags => "R",
804 #  comment   => "construct FP Sub: Sub(a, b) = a - b",
805 #  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
806 #  emit      => '. fsub %S1, %S2, %D1'
807 #},
808 #
809 #fDiv => {
810 #  comment   => "construct FP Div: Div(a, b) = a / b",
811 #  reg_req   => { in => [ "fp", "fp" ], out => [ "fp" ] },
812 #  emit      => '. fdiv %S1, %S2, %D1'
813 #},
814 #
815 #fMinus => {
816 #  irn_flags => "R",
817 #  comment   => "construct FP Minus: Minus(a) = -a",
818 #  reg_req   => { in => [ "fp" ], out => [ "fp" ] },
819 #  emit      => '. fneg %S1, %D1'
820 #},
821 #
822 ## other operations
823 #
824 #fConst => {
825 #  op_flags  => "c",
826 #  irn_flags => "R",
827 #  comment   => "represents a FP constant",
828 #  reg_req   => { out => [ "fp" ] },
829 #  emit      => '. fmov %C, %D1',
830 #  cmp_attr  =>
831 #'
832 #       /* TODO: compare fConst attributes */
833 #       return 1;
834 #'
835 #},
836 #
837 ## Load / Store
838 #
839 #fLoad => {
840 #  op_flags  => [ "labeled", "fragile" ],
841 #  irn_flags => "R",
842 #  state     => "exc_pinned",
843 #  comment   => "construct FP Load: Load(ptr, mem) = LD ptr",
844 #  reg_req   => { in => [ "gp", "none" ], out => [ "fp" ] },
845 #  emit      => '. fmov (%S1), %D1'
846 #},
847 #
848 #fStore => {
849 #  op_flags  => [ "labeled", "fragile" ],
850 #  irn_flags => "R",
851 #  state     => "exc_pinned",
852 #  comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
853 #  reg_req   => { in => [ "gp", "fp", "none" ] },
854 #  emit      => '. fmov %S2, (%S1)'
855 #},
856
857 ); # end of %nodes