- Spillslot coalescing now collects all nodes that have class spill/reload
[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
9 $comment_string = "#";
10
11 # The node description is done as a perl hash initializer with the
12 # following structure:
13 #
14 # %nodes = (
15 #
16 # <op-name> => {
17 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
18 #   "arity"     => "0|1|2|3 ... |variable|dynamic|any",
19 #   "state"     => "floats|pinned|mem_pinned|exc_pinned",
20 #   "args"      => [
21 #                    { "type" => "type 1", "name" => "name 1" },
22 #                    { "type" => "type 2", "name" => "name 2" },
23 #                    ...
24 #                  ],
25 #   "comment"   => "any comment for constructor",
26 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
27 #   "cmp_attr"  => "c source code for comparing node attributes",
28 #   emit      => "emit code with templates",
29 #   "rd_constructor" => "c source code which constructs an ir_node"
30 # },
31 #
32 # ... # (all nodes you need to describe)
33 #
34 # ); # close the %nodes initializer
35
36 # op_flags: flags for the operation, OPTIONAL (default is "N")
37 # the op_flags correspond to the firm irop_flags:
38 #   N   irop_flag_none
39 #   L   irop_flag_labeled
40 #   C   irop_flag_commutative
41 #   X   irop_flag_cfopcode
42 #   I   irop_flag_ip_cfopcode
43 #   F   irop_flag_fragile
44 #   Y   irop_flag_forking
45 #   H   irop_flag_highlevel
46 #   c   irop_flag_constlike
47 #   K   irop_flag_keep
48 #
49 #   R   rematerializeable
50 #   N   not spillable
51 #   I   ignore for register allocation
52 #
53 # state: state of the operation, OPTIONAL (default is "floats")
54 #
55 # arity: arity of the operation, MUST NOT BE OMITTED
56 #
57 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
58 #        are always the first 3 arguments and are always autmatically
59 #        created)
60 #        If this key is missing the following arguments will be created:
61 #        for i = 1 .. arity: ir_node *op_i
62 #        ir_mode *mode
63 #
64 # outs:  if a node defines more than one output, the names of the projections
65 #        nodes having outs having automatically the mode mode_T
66 #
67 # comment: OPTIONAL comment for the node constructor
68 #
69 # rd_constructor: for every operation there will be a
70 #      new_rd_<arch>_<op-name> function with the arguments from above
71 #      which creates the ir_node corresponding to the defined operation
72 #      you can either put the complete source code of this function here
73 #
74 #      This key is OPTIONAL. If omitted, the following constructor will
75 #      be created:
76 #      if (!op_<arch>_<op-name>) assert(0);
77 #      for i = 1 to arity
78 #         set in[i] = op_i
79 #      done
80 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
81 #      return res
82 #
83 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
84
85 # register types:
86 #   0 - no special type
87 #   1 - caller save (register must be saved by the caller of a function)
88 #   2 - callee save (register must be saved by the called function)
89 #   4 - ignore (do not assign this register)
90 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold\
91 %reg_classes = (
92   "gp" => [
93                          { name => "zero", type => 4+2 },  # always zero
94                          { name => "at", type => 4 }, # reserved for assembler
95                          { name => "v0", type => 1 }, # first return value
96                          { name => "v1", type => 1 }, # second return value
97                          { name => "a0", type => 1 }, # first argument
98                          { name => "a1", type => 1 }, # second argument
99                          { name => "a2", type => 1 }, # third argument
100                          { name => "a3", type => 1 }, # fourth argument
101                          { name => "t0", type => 1 },
102                          { name => "t1", type => 1 },
103                          { name => "t2", type => 1 },
104                          { name => "t3", type => 1 },
105                          { name => "t4", type => 1 },
106                          { name => "t5", type => 1 },
107                          { name => "t6", type => 1 },
108                          { name => "t7", type => 1 },
109                          { name => "s0", type => 2 },
110                          { name => "s1", type => 2 },
111                          { name => "s2", type => 2 },
112                          { name => "s3", type => 2 },
113                          { name => "s4", type => 2 },
114                          { name => "s5", type => 2 },
115                          { name => "s6", type => 2 },
116                          { name => "s7", type => 2 },
117                          { name => "t8", type => 1 },
118                          { name => "t9", type => 1 },
119                          { name => "k0", type => 4 }, # reserved for OS
120                          { name => "k1", type => 4 }, # reserved for OS
121                          { name => "gp", type => 4 }, # general purpose
122                          { name => "sp", type => 4+2 }, # stack pointer
123                          { name => "fp", type => 4+2 }, # frame pointer
124                          { name => "ra", type => 2+1 }, # return address. This is also caller save, because
125                                                                                                                         # the jla instruction that is used for calls modifies
126                                                                                                                         # the ra register. It is callee save too, because at the last
127                                                                                                                         # command of a function (the ja $ra) it needs to have it's
128                                                                                                                         # old value.
129                          { mode => "mode_P" }
130                        ],
131 ); # %reg_classes
132
133 #--------------------------------------------------#
134 #                        _                         #
135 #                       (_)                        #
136 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
137 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
138 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
139 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
140 #                                      | |         #
141 #                                      |_|         #
142 #--------------------------------------------------#
143
144 %nodes = (
145
146 #-----------------------------------------------------------------#
147 #  _       _                                         _            #
148 # (_)     | |                                       | |           #
149 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
150 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
151 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
152 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
153 #                   __/ |                                         #
154 #                  |___/                                          #
155 #-----------------------------------------------------------------#
156
157 # commutative operations
158
159 add => {
160   op_flags  => "C",
161   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
162   emit      => '. addu %D1, %S1, %S2'
163 },
164
165 addi => {
166   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
167   emit      => '. addiu %D1, %S1, %C',
168   cmp_attr => 'return attr_a->tv != attr_b->tv;',
169 },
170
171 and => {
172   op_flags  => "C",
173   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
174   emit      => '. and %D1, %S1, %S2',
175 },
176
177 andi => {
178   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
179   emit      => '. andi %D1, %S1, %C',
180   cmp_attr => 'return attr_a->tv != attr_b->tv;',
181 },
182
183 div => {
184   reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none", "none", "none" ] },
185   emit      => '
186         mips_attr_t *attr = get_mips_attr(n);
187         if (attr->modes.original_mode->sign) {
188 2.              div %S1, %S2
189         } else {
190 2.              divu %S1, %S2
191         }
192 ',
193 },
194
195 mult => {
196   op_flags  => "C",
197   reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
198   emit      => '
199         if (mode_is_signed(get_irn_mode(n))) {
200 2.              mult %S1, %S2
201         }
202         else {
203 2.              multu %S1, %S2
204         }
205 ',
206 },
207
208 nor => {
209   op_flags  => "C",
210   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
211   emit      => '. nor %D1, %S1, %S2'
212 },
213
214 not => {
215   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
216   emit      => '. nor %D1, %S1, $zero'
217 },
218
219 or => {
220   op_flags  => "C",
221   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
222   emit      => '. or %D1, %S1, %S2'
223 },
224
225 ori => {
226   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
227   emit      => '. ori %D1, %S1, %C',
228   cmp_attr => 'return attr_a->tv != attr_b->tv;',
229 },
230
231 sl => {
232   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
233   emit      => '
234         if (mode_is_signed(get_irn_mode(n))) {
235 2.              sal %D1, %S1, %S2
236         }
237         else {
238 2.              sll %D1, %S1, %S2
239         }
240 ',
241 },
242
243 sli => {
244   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
245   emit      => '
246         if (mode_is_signed(get_irn_mode(n))) {
247 2.              sal %D1, %S1, %C
248         }
249         else {
250 2.              sll %D1, %S1, %C
251         }
252 ',
253 },
254
255 sra => {
256   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
257   emit      => '. sra %D1, %S1, %S2',
258 },
259
260 srai => {
261   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
262   emit      => '. sra %D1, %S1, %C',
263   cmp_attr => 'return attr_a->tv != attr_b->tv;',
264 },
265
266 sr => {
267   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
268   emit      => '
269         if (mode_is_signed(get_irn_mode(n))) {
270 2.              sra %D1, %S1, %S2
271         }
272         else {
273 2.              srl %D1, %S1, %S2
274         }
275 ',
276 },
277
278 sri => {
279   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
280   emit      => '
281         if (mode_is_signed(get_irn_mode(n))) {
282 2.              sra %D1, %S1, %C
283         }
284         else {
285 2.              srl %D1, %S1, %C
286         }
287 ',
288 },
289
290 srlv => {
291   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
292   emit      => '. srlv %D1, %S1, %S2',
293 },
294
295 sllv => {
296   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
297   emit      => '. sllv %D1, %S1, %S2',
298 },
299
300 sub => {
301   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
302   emit      => '. subu %D1, %S1, %S2',
303 },
304
305 subuzero => {
306   reg_req       => { in => [ "gp" ], out => [ "gp" ] },
307   emit => '. subu %D1, $zero, %S1',
308 },
309
310 xor => {
311   reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
312   emit      => '. xor %D1, %S1, %S2'
313 },
314
315 xori => {
316   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
317   emit      => '. xori %D1, %S1, %C',
318   cmp_attr => 'return attr_a->tv != attr_b->tv;',
319 },
320
321 #   ____                _              _
322 #  / ___|___  _ __  ___| |_ __ _ _ __ | |_ ___
323 # | |   / _ \| '_ \/ __| __/ _` | '_ \| __/ __|
324 # | |__| (_) | | | \__ \ || (_| | | | | |_\__ \
325 #  \____\___/|_| |_|___/\__\__,_|_| |_|\__|___/
326 #
327
328 # load upper imediate
329 lui => {
330   op_flags      => "c",
331   reg_req   => { out => [ "gp" ] },
332   emit      => '. lui %D1, %C',
333   cmp_attr => 'return attr_a->tv != attr_b->tv;',
334 },
335
336 # load lower immediate
337 lli => {
338   op_flags      => "c",
339   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
340   emit      => '. ori %D1, %S1, %C',
341   cmp_attr => 'return attr_a->tv != attr_b->tv;',
342 },
343
344 la => {
345   op_flags      => "c",
346   reg_req   => { out => [ "gp" ] },
347   emit      => '. la %D1, %C',
348   cmp_attr => 'return attr_a->symconst_id != attr_b->symconst_id;',
349 },
350
351 mflo => {
352   reg_req => { in => [ "none" ], out => [ "gp" ] },
353   emit    => '. mflo %D1'
354 },
355
356 mfhi => {
357   reg_req => { in => [ "none" ], out => [ "gp" ] },
358   emit    => '. mfhi %D1'
359 },
360
361 zero => {
362   reg_req => { out => [ "zero" ] },
363   emit => '',
364 },
365
366 #
367 #  ____                       _        __  _
368 # | __ ) _ __ __ _ _ __   ___| |__    / / | |_   _ _ __ ___  _ __
369 # |  _ \| '__/ _` | '_ \ / __| '_ \  / /  | | | | | '_ ` _ \| '_ \
370 # | |_) | | | (_| | | | | (__| | | |/ / |_| | |_| | | | | | | |_) |
371 # |____/|_|  \__,_|_| |_|\___|_| |_/_/ \___/ \__,_|_| |_| |_| .__/
372 #                                                           |_|
373 #
374
375 slt => {
376         reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
377         emit => '
378         if (mode_is_signed(get_irn_mode(n))) {
379 2.              slt %D1, %S1, %S2
380         }
381         else {
382 2.              sltu %D1, %S1, %S2
383         }
384 ',
385 },
386
387 slti => {
388         reg_req => { in => [ "gp" ], out => [ "gp" ] },
389         emit => '
390         if (mode_is_signed(get_irn_mode(n))) {
391 2.              slti %D1, %S1, %C
392         }
393         else {
394 2.              sltiu %D1, %S1, %C
395         }
396 ',
397   cmp_attr => 'return attr_a->tv != attr_b->tv;',
398 },
399
400 beq => {
401         op_flags  => "X|Y",
402         # TxT -> TxX
403         reg_req => { in => [ "gp", "gp" ], out => [ "in_r0", "none" ] },
404         emit => '
405         ir_node *jumpblock = mips_get_jump_block(n, 1);
406         assert(jumpblock != NULL);
407
408         lc_efprintf(arg_env, F, "\tbeq %1S, %2S, BLOCK_%d\n", n, n, get_irn_node_nr(jumpblock));
409 '
410 },
411
412 bne => {
413         op_flags  => "X|Y",
414         # TxT -> TxX
415         reg_req => { in => [ "gp", "gp" ], out => [ "in_r0", "none" ] },
416         emit => '
417         ir_node *jumpblock = mips_get_jump_block(n, 1);
418         assert(jumpblock != NULL);
419
420         lc_efprintf(arg_env, F, "\tbne %1S, %2S, BLOCK_%d\n", n, n, get_irn_node_nr(jumpblock));
421 '
422 },
423
424 bgtz => {
425         op_flags  => "X|Y",
426         # TxT -> TxX
427         reg_req => { in => [ "gp" ], out => [ "in_r0", "none" ] },
428         emit => '
429         ir_node *jumpblock = mips_get_jump_block(n, 1);
430         assert(jumpblock != NULL);
431
432         lc_efprintf(arg_env, F, "\tbgtz %1S, BLOCK_%d\n", n, get_irn_node_nr(jumpblock));
433 '
434 },
435
436 blez => {
437         op_flags  => "X|Y",
438         # TxT -> TxX
439         reg_req => { in => [ "gp" ], out => [ "in_r0", "none" ] },
440         emit => '
441         ir_node *jumpblock = mips_get_jump_block(n, 1);
442         assert(jumpblock != NULL);
443
444         lc_efprintf(arg_env, F, "\tblez %1S, BLOCK_%d\n", n, get_irn_node_nr(jumpblock));
445 '
446 },
447
448 j => {
449   op_flags => "X",
450   reg_req => { in => [ "gp" ] },
451   emit => '. j %S1',
452 },
453
454 b => {
455   op_flags => "X",
456   # -> X
457   reg_req => { in => [ ], out => [ "none" ] },
458   emit => '
459         ir_node *jumpblock = get_irn_link(n);
460         assert(jumpblock != NULL);
461
462         lc_efprintf(arg_env, F, "\tb BLOCK_%d\t\t\t# mips_b\n", get_irn_node_nr(jumpblock));
463 '
464 },
465
466 fallthrough => {
467   op_flags => "X",
468   # -> X
469   reg_req => { in => [ ], out => [ "none" ] },
470   emit => '. # fallthrough'
471 },
472
473 SwitchJump => {
474   op_flags => "X",
475   # -> X,X,...
476   reg_req => { in => [ "gp" ], out => [ "none" ] },
477   emit => '. j %S1'
478 },
479
480 #  _                    _
481 # | |    ___   __ _  __| |
482 # | |   / _ \ / _` |/ _` |
483 # | |__| (_) | (_| | (_| |
484 # |_____\___/ \__,_|\__,_|
485 #
486
487 load_r => {
488   reg_req       => { in => [ "none", "gp" ], out => [ "none", "none", "gp" ] },
489   emit          => '
490         mips_attr_t* attr = get_mips_attr(n);
491         ir_mode *mode;
492
493         mode = attr->modes.load_store_mode;
494
495         switch (get_mode_size_bits(mode)) {
496         case 8:
497                 if (mode_is_signed(mode)) {
498 3.                      lb %D3, %C(%S2)
499                 }
500                 else {
501 3.                      lbu %D3, %C(%S2)
502                 }
503                 break;
504         case 16:
505                 if (mode_is_signed(mode)) {
506 3.                      lh %D3, %C(%S2)
507                 }
508                 else {
509 3.                      lhu %D3, %C(%S2)
510                 }
511                 break;
512         case 32:
513 2.              lw %D3, %C(%S2)
514                 break;
515         default:
516                 assert(! "Only 8, 16 and 32 bit loads supported");
517                 break;
518         }
519 ',
520   cmp_attr => 'return attr_a->tv != attr_b->tv || attr_a->stack_entity != attr_b->stack_entity;',
521 },
522
523
524 #  _                    _    ______  _
525 # | |    ___   __ _  __| |  / / ___|| |_ ___  _ __ ___
526 # | |   / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
527 # | |__| (_) | (_| | (_| |/ /  ___) | || (_) | | |  __/
528 # |_____\___/ \__,_|\__,_/_/  |____/ \__\___/|_|  \___|
529 #
530
531 store_r => {
532   reg_req       => { in => [ "none", "gp", "gp" ], out => [ "none", "none" ] },
533   emit          => '
534         mips_attr_t* attr = get_mips_attr(n);
535         ir_mode* mode;
536
537         mode = attr->modes.load_store_mode;
538
539         switch (get_mode_size_bits(mode)) {
540         case 8:
541                 if (mode_is_signed(mode))
542 2.              sb %S3, %C(%S2)
543                 break;
544         case 16:
545                 if (mode_is_signed(mode))
546 2.              sh %S3, %C(%S2)
547                 break;
548         case 32:
549 2.              sw %S3, %C(%S2)
550                 break;
551         default:
552                 assert(! "Only 8, 16 and 32 bit stores supported");
553                 break;
554         }
555 ',
556   cmp_attr => 'return attr_a->tv != attr_b->tv;',
557 },
558
559 store_i => {
560   reg_req       => { in => [ "none", "none", "gp" ], out => [ "none", "none" ] },
561   emit          => '
562         mips_attr_t* attr = get_mips_attr(n);
563         ir_mode *mode;
564
565         mode = attr->modes.load_store_mode;
566
567         switch (get_mode_size_bits(mode)) {
568         case 8:
569 2.              sb %S3, %C
570                 break;
571         case 16:
572 2.              sh %S3, %C
573                 break;
574         case 32:
575 2.              sw %S3, %C
576                 break;
577         default:
578                 assert(! "Only 8, 16 and 32 bit stores supported");
579                 break;
580         }
581 ',
582   cmp_attr => '
583         return attr_a->stack_entity != attr_b->stack_entity;
584 ',
585 },
586
587 move => {
588   reg_req   => { in => [ "gp" ], out => [ "gp" ] },
589   emit      => '. or %D1, $zero, %S1'
590 },
591
592 #
593 # Conversion
594 #
595
596 reinterpret_conv => {
597   reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
598   emit      => '. # reinterpret %S1 -> %D1',
599 },
600
601 #
602 # Miscelaneous
603 #
604
605 nop => {
606   op_flags  => "K",
607   reg_req       => { in => [], out => [ "none" ] },
608   emit          => '. nop  # nop',
609 },
610
611 ); # end of %nodes