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