- add support for opcode specific hash function
[libfirm] / ir / be / mips / mips_spec.pl
1 # Creation: 2006/02/13
2 # $Id$
3 # This is a template specification for the Firm-Backend
4
5 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
6
7 $arch = "mips";
8 $new_emit_syntax = 1;
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",
17 #   "arity"     => "0|1|2|3 ... |variable|dynamic|any",
18 #   "state"     => "floats|pinned|mem_pinned|exc_pinned",
19 #   "args"      => [
20 #                    { "type" => "type 1", "name" => "name 1" },
21 #                    { "type" => "type 2", "name" => "name 2" },
22 #                    ...
23 #                  ],
24 #   comment   => "any comment for constructor",
25 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
26 #   cmp_attr  => "c source code for comparing node attributes",
27 #   outs      => { "out1", "out2" } # optional, creates pn_op_out1, ... consts
28 #   ins       => { "in1", "in2" }   # optional, creates n_op_in1, ... consts
29 #   mode      => "mode_Iu"          # optional, predefines the mode
30 #   emit      => "emit code with templates",
31 #   attr      => "attitional attribute arguments for constructor",
32 #   init_attr => "emit attribute initialization template",
33 #   rd_constructor => "c source code which constructs an ir_node",
34 #   hash_func => "name of the hash function for this operation",
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 #   R   rematerializeable
57 #   N   not spillable
58 #   I   ignore for register allocation
59 #
60 # state: state of the operation, OPTIONAL (default is "floats")
61 #
62 # arity: arity of the operation, MUST NOT BE OMITTED
63 #
64 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
65 #        are always the first 3 arguments and are always autmatically
66 #        created)
67 #        If this key is missing the following arguments will be created:
68 #        for i = 1 .. arity: ir_node *op_i
69 #        ir_mode *mode
70 #
71 # outs:  if a node defines more than one output, the names of the projections
72 #        nodes having outs having automatically the mode mode_T
73 #
74 # comment: OPTIONAL comment for the node constructor
75 #
76 # rd_constructor: for every operation there will be a
77 #      new_rd_<arch>_<op-name> function with the arguments from above
78 #      which creates the ir_node corresponding to the defined operation
79 #      you can either put the complete source code of this function here
80 #
81 #      This key is OPTIONAL. If omitted, the following constructor will
82 #      be created:
83 #      if (!op_<arch>_<op-name>) assert(0);
84 #      for i = 1 to arity
85 #         set in[i] = op_i
86 #      done
87 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
88 #      return res
89 #
90 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
91
92 # register types:
93 #   0 - no special type
94 #   1 - caller save (register must be saved by the caller of a function)
95 #   2 - callee save (register must be saved by the called function)
96 #   4 - ignore (do not assign this register)
97 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold\
98 %reg_classes = (
99         "gp" => [
100                 { name => "zero", type => 4+2 },  # always zero
101                 { name => "at", type => 4 }, # reserved for assembler
102                 { name => "v0", realname => "2", type => 1 }, # first return value
103                 { name => "v1", realname => "3", type => 1 }, # second return value
104                 { name => "a0", realname => "4", type => 1 }, # first argument
105                 { name => "a1", realname => "5", type => 1 }, # second argument
106                 { name => "a2", realname => "6", type => 1 }, # third argument
107                 { name => "a3", realname => "7", type => 1 }, # fourth argument
108                 { name => "t0", realname => "8", type => 1 },
109                 { name => "t1", realname => "9", type => 1 },
110                 { name => "t2", realname => "10", type => 1 },
111                 { name => "t3", realname => "11", type => 1 },
112                 { name => "t4", realname => "12", type => 1 },
113                 { name => "t5", realname => "13", type => 1 },
114                 { name => "t6", realname => "14", type => 1 },
115                 { name => "t7", realname => "15", type => 1 },
116                 { name => "s0", realname => "16", type => 2 },
117                 { name => "s1", realname => "17", type => 2 },
118                 { name => "s2", realname => "18", type => 2 },
119                 { name => "s3", realname => "19", type => 2 },
120                 { name => "s4", realname => "20", type => 2 },
121                 { name => "s5", realname => "21", type => 2 },
122                 { name => "s6", realname => "22", type => 2 },
123                 { name => "s7", realname => "23", type => 2 },
124                 { name => "t8", realname => "24", type => 1 },
125                 { name => "t9", realname => "25", type => 1 },
126                 { name => "kt0", type => 4 }, # reserved for OS
127                 { name => "kt1", type => 4 }, # reserved for OS
128                 { name => "gp", type => 4 }, # general purpose
129                 { name => "sp", type => 4 }, # stack pointer
130                 { name => "fp", type => 4 }, # frame pointer
131                 { name => "ra", type => 2+1 }, # return address
132                 { name => "gp_NOREG", realname => "!NOREG_INVALID!", type => 4 | 8 | 16 }, #dummy register for immediate nodes
133                 { mode => "mode_Iu" }
134         ],
135 ); # %reg_classes
136
137 %emit_templates = (
138     S0  => "${arch}_emit_source_register(node, 0);",
139     S1  => "${arch}_emit_source_register(node, 1);",
140     S2  => "${arch}_emit_source_register(node, 2);",
141         SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
142     D0  => "${arch}_emit_dest_register(node, 0);",
143     D1  => "${arch}_emit_dest_register(node, 1);",
144     D2  => "${arch}_emit_dest_register(node, 2);",
145         A0  => "${arch}_emit_load_store_address(node, 0);",
146         I   => "${arch}_emit_immediate_suffix(node, 1);",
147         C   => "${arch}_emit_immediate(node);",
148         JumpTarget => "${arch}_emit_jump_target(node);",
149         JumpTarget1 => "${arch}_emit_jump_target_proj(node, 1);",
150         JumpOrFallthrough => "${arch}_emit_jump_or_fallthrough(node, 0);",
151 );
152
153 $default_attr_type = "mips_attr_t";
154 $default_copy_attr = "mips_copy_attr";
155
156 $mode_gp = "mode_Iu";
157
158 %init_attr = (
159         mips_attr_t            => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
160
161         mips_immediate_attr_t  => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
162                                  "\tinit_mips_immediate_attributes(res, imm_type, entity, val);",
163
164         mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
165                                  "\tinit_mips_load_store_attributes(res, entity, offset);",
166 );
167
168 %compare_attr = (
169         mips_attr_t            => "mips_compare_nodes_attr",
170         mips_immediate_attr_t  => "mips_compare_immediate_attr",
171         mips_load_store_attr_t => "mips_compare_load_store_attr",
172 );
173
174 #--------------------------------------------------#
175 #                        _                         #
176 #                       (_)                        #
177 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
178 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
179 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
180 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
181 #                                      | |         #
182 #                                      |_|         #
183 #--------------------------------------------------#
184
185 %nodes = (
186
187 Immediate => {
188         state     => "pinned",
189         op_flags  => "c",
190         irn_flags => "I",
191         reg_req   => { out => [ "gp_NOREG" ] },
192         attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
193         attr_type => "mips_immediate_attr_t",
194         mode      => $mode_gp,
195 },
196
197 #-----------------------------------------------------------------#
198 #  _       _                                         _            #
199 # (_)     | |                                       | |           #
200 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
201 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
202 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
203 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
204 #                   __/ |                                         #
205 #                  |___/                                          #
206 #-----------------------------------------------------------------#
207
208 # commutative operations
209
210 addu => {
211         op_flags  => "R",
212         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
213         ins       => [ "left", "right" ],
214         emit      => '. add%I%.u %D0, %S0, %SI1',
215         mode      => $mode_gp,
216 },
217
218 and => {
219         op_flags  => "R",
220         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
221         ins       => [ "left", "right" ],
222         emit      => '. and%I %D0, %S0, %SI1',
223         mode      => $mode_gp,
224 },
225
226 div => {
227         reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
228         ins       => [ "left", "right" ],
229         outs      => [ "lohi", "M" ],
230         emit      => '. div %S0, %S1',
231         mode      => "mode_M",
232 },
233
234 divu => {
235         reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
236         ins       => [ "left", "right" ],
237         outs      => [ "lohi", "M" ],
238         emit      => '. divu %S0, %S1',
239         mode      => "mode_M",
240 },
241
242 mult => {
243         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
244         ins       => [ "left", "right" ],
245         emit      => '. mult %S0, %S1',
246         mode      => "mode_M"
247 },
248
249 multu => {
250         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
251         ins       => [ "left", "right" ],
252         emit      => '. multu %S0, %S1',
253         mode      => "mode_M",
254 },
255
256 nor => {
257         op_flags  => "R",
258         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
259         emit      => '. nor%I %D0, %S0, %SI1',
260         mode      => $mode_gp
261 },
262
263 or => {
264         op_flags  => "R",
265         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
266         ins       => [ "left", "right" ],
267         emit      => '. or%I %D0, %S0, %SI1',
268         mode      => $mode_gp
269 },
270
271 sll => {
272         op_flags  => "R",
273         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
274         ins       => [ "left", "right" ],
275         emit      => '. sll %D0, %S0, %SI1',
276         mode      => $mode_gp,
277 },
278
279 sra => {
280         op_flags  => "R",
281         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
282         ins       => [ "left", "right" ],
283         emit      => '. sra %D0, %S0, %SI1',
284         mode      => $mode_gp
285 },
286
287 srl => {
288         op_flags  => "R",
289         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
290         ins       => [ "left", "right" ],
291         emit      => '. srl %D0, %S0, %SI1',
292         mode      => $mode_gp,
293 },
294
295 subu => {
296         op_flags  => "R",
297         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
298         ins       => [ "left", "right" ],
299         emit      => '. subu %D0, %S0, %S1',
300         mode      => $mode_gp
301 },
302
303 xor => {
304         op_flags  => "R",
305         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
306         ins       => [ "left", "right" ],
307         emit      => '. xor%I %D0, %S0, %SI1',
308         mode      => $mode_gp,
309 },
310
311 seb => {
312         op_flags  => "R",
313         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
314         ins       => [ "val" ],
315         emit      => '.seb %D0, %S0',
316         mode      => $mode_gp,
317 },
318
319 seh => {
320         op_flags  => "R",
321         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
322         ins       => [ "val" ],
323         emit      => '.seh %D0, %S0',
324         mode      => $mode_gp,
325 },
326
327 lui => {
328         op_flags  => "c",
329         irn_flags => "R",
330         reg_req   => { out => [ "gp" ] },
331         emit      => '.lui %D0, %C',
332         attr_type => "mips_immediate_attr_t",
333         attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
334         mode      => $mode_gp,
335 },
336
337 mflo => {
338         irn_flags => "R",
339         reg_req   => { in => [ "none" ], out => [ "gp" ] },
340         ins       => [ "lohi" ],
341         emit      => '. mflo %D0',
342         mode      => $mode_gp
343 },
344
345 mfhi => {
346         irn_flags => "R",
347         reg_req   => { in => [ "none" ], out => [ "gp" ] },
348         ins       => [ "lohi" ],
349         emit      => '. mfhi %D0',
350         mode      => $mode_gp
351 },
352
353 zero => {
354         state     => "pinned",
355         op_flags  => "c",
356         irn_flags => "I",
357         reg_req   => { out => [ "zero" ] },
358         emit      => '',
359         mode      => $mode_gp
360 },
361
362 #
363 #  ____                       _        __  _
364 # | __ ) _ __ __ _ _ __   ___| |__    / / | |_   _ _ __ ___  _ __
365 # |  _ \| '__/ _` | '_ \ / __| '_ \  / /  | | | | | '_ ` _ \| '_ \
366 # | |_) | | | (_| | | | | (__| | | |/ / |_| | |_| | | | | | | |_) |
367 # |____/|_|  \__,_|_| |_|\___|_| |_/_/ \___/ \__,_|_| |_| |_| .__/
368 #                                                           |_|
369 #
370
371 slt => {
372         op_flags => "R",
373         reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
374         emit    => '. slt%I %D0, %S0, %SI1',
375         mode    => $mode_gp,
376 },
377
378 sltu => {
379         op_flags => "R",
380         reg_req  => { in => [ "gp", "gp" ], out => [ "gp" ] },
381         emit     => '. slt%I%.u %D0, %S0, %SI1',
382         mode     => $mode_gp,
383 },
384
385 beq => {
386         op_flags => "X|Y",
387         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
388         outs     => [ "false", "true" ],
389         emit     => '. beq %S0, %S1, %JumpTarget1
390                      . %JumpOrFallthrough'
391 },
392
393 bne => {
394         op_flags => "X|Y",
395         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
396         outs     => [ "false", "true" ],
397         emit     => '. bne %S0, %S1, %JumpTarget1
398                      . %JumpOrFallthrough'
399 },
400
401 bgtz => {
402         op_flags => "X|Y",
403         reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
404         outs     => [ "false", "true" ],
405         emit     => '. bgtz %S0, %JumpTarget1
406                      . %JumpOrFallthrough'
407 },
408
409 blez => {
410         op_flags => "X|Y",
411         reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
412         outs     => [ "false", "true" ],
413         emit     => '. blez %S0, %JumpTarget1
414                      . %JumpOrFallthrough'
415 },
416
417 b => {
418         op_flags => "X",
419         reg_req  => { in => [ ], out => [ "none" ] },
420         emit     => '. b %JumpTarget',
421         mode     => 'mode_X'
422 },
423
424 jr => {
425         op_flags => "X",
426         reg_req  => { in => [ "gp" ], out => [ "none" ] },
427         emit     => '. jr %S0',
428         mode     => 'mode_X'
429 },
430
431 SwitchJump => {
432         op_flags => "X",
433         reg_req  => { in => [ "gp" ], out => [ "none" ] },
434         emit     => '. jr %S0'
435 },
436
437 #  _                    _    ______  _
438 # | |    ___   __ _  __| |  / / ___|| |_ ___  _ __ ___
439 # | |   / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
440 # | |__| (_) | (_| | (_| |/ /  ___) | || (_) | | |  __/
441 # |_____\___/ \__,_|\__,_/_/  |____/ \__\___/|_|  \___|
442 #
443
444 lw => {
445         op_flags  => "L|F",
446         state     => "exc_pinned",
447         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
448         ins       => [ "ptr", "mem" ],
449         outs      => [ "res", "M" ],
450         emit      => '. lw %D0, %A0',
451         attr_type => "mips_load_store_attr_t",
452         attr      => "ir_entity *entity, long offset",
453 },
454
455 lh => {
456         op_flags  => "L|F",
457         state     => "exc_pinned",
458         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
459         ins       => [ "ptr", "mem" ],
460         outs      => [ "res", "M" ],
461         emit      => '. lh %D0, %A0',
462         attr_type => "mips_load_store_attr_t",
463         attr      => "ir_entity *entity, long offset",
464 },
465
466 lhu => {
467         op_flags  => "L|F",
468         state     => "exc_pinned",
469         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
470         ins       => [ "ptr", "mem" ],
471         outs      => [ "res", "M" ],
472         emit      => '. lhu %D0, %A0',
473         attr_type => "mips_load_store_attr_t",
474         attr      => "ir_entity *entity, long offset",
475 },
476
477 lb => {
478         op_flags  => "L|F",
479         state     => "exc_pinned",
480         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
481         ins       => [ "ptr", "mem" ],
482         outs      => [ "res", "M" ],
483         emit      => '. lb %D0, %A0',
484         attr_type => "mips_load_store_attr_t",
485         attr      => "ir_entity *entity, long offset",
486 },
487
488 lbu => {
489         op_flags  => "L|F",
490         state     => "exc_pinned",
491         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
492         ins       => [ "ptr", "mem" ],
493         outs      => [ "res", "M" ],
494         emit      => '. lbu %D0, %A0',
495         attr_type => "mips_load_store_attr_t",
496         attr      => "ir_entity *entity, long offset",
497 },
498
499 sw => {
500         op_flags  => "L|F",
501         state     => "exc_pinned",
502         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
503         ins       => [ "ptr", "val", "mem" ],
504         emit      => '. sw %S1, %A0',
505         mode      => 'mode_M',
506         attr_type => "mips_load_store_attr_t",
507         attr      => "ir_entity *entity, long offset",
508 },
509
510 sh => {
511         op_flags  => "L|F",
512         state     => "exc_pinned",
513         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
514         ins       => [ "ptr", "val", "mem" ],
515         emit      => '. sh %S1, %A0',
516         mode      => 'mode_M',
517         attr_type => "mips_load_store_attr_t",
518         attr      => "ir_entity *entity, long offset",
519 },
520
521 sb => {
522         op_flags  => "L|F",
523         state     => "exc_pinned",
524         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
525         ins       => [ "ptr", "val", "mem" ],
526         emit      => '. sb %S1, %A0',
527         mode      => 'mode_M',
528         attr_type => "mips_load_store_attr_t",
529         attr      => "ir_entity *entity, long offset",
530 },
531
532 #
533 # Miscelaneous
534 #
535
536 nop => {
537         op_flags => "K",
538         reg_req  => { in => [], out => [ "none" ] },
539         emit     => '. nop',
540 },
541
542 ); # end of %nodes