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