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