872687cb1db147af94f6e1239db7a53c10433f2a
[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     S0 => "${arch}_emit_source_register(env, node, 0);",
130     S1 => "${arch}_emit_source_register(env, node, 1);",
131     S2 => "${arch}_emit_source_register(env, node, 2);",
132     D0 => "${arch}_emit_dest_register(env, node, 0);",
133     D1 => "${arch}_emit_dest_register(env, node, 1);",
134     D2 => "${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         JumpOrFallthrough => "${arch}_emit_jump_or_fallthrough(env, node, 0);",
139 );
140
141
142 #--------------------------------------------------#
143 #                        _                         #
144 #                       (_)                        #
145 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
146 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
147 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
148 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
149 #                                      | |         #
150 #                                      |_|         #
151 #--------------------------------------------------#
152
153 $default_cmp_attr = "return mips_compare_attr(attr_a, attr_b);";
154
155 %nodes = (
156
157 #-----------------------------------------------------------------#
158 #  _       _                                         _            #
159 # (_)     | |                                       | |           #
160 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
161 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
162 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
163 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
164 #                   __/ |                                         #
165 #                  |___/                                          #
166 #-----------------------------------------------------------------#
167
168 # commutative operations
169
170 addu => {
171         op_flags  => "C",
172         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
173         emit      => '. addu %D0, %S0, %S1',
174         mode      => "mode_Iu",
175 },
176
177 addiu => {
178         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
179         emit      => '. addiu %D0, %S0, %C',
180         cmp_attr  => 'return attr_a->tv != attr_b->tv;',
181         mode      => "mode_Iu",
182 },
183
184 and => {
185         op_flags  => "C",
186         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
187         emit      => '. and %D0, %S0, %S1',
188         mode      => "mode_Iu",
189 },
190
191 andi => {
192         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
193         emit      => '. andi %D0, %S0, %C',
194         cmp_attr  => 'return attr_a->tv != attr_b->tv;',
195         mode      => "mode_Iu",
196 },
197
198 div => {
199         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
200         emit      => '. div %S0, %S1',
201         mode      => "mode_M",
202 },
203
204 divu => {
205         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
206         emit      => '. divu %S0, %S1',
207         mode      => "mode_M",
208 },
209
210 mult => {
211         op_flags  => "C",
212         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
213         emit      => '. mult %S0, %S1',
214         mode      => "mode_M"
215 },
216
217 multu => {
218         op_flags  => "C",
219         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
220         emit      => '. multu %S0, %S1',
221         mode      => "mode_M",
222 },
223
224 nor => {
225         op_flags  => "C",
226         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
227         emit      => '. nor %D0, %S0, %S1',
228         mode      => "mode_Iu"
229 },
230
231 not => {
232         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
233         emit      => '. nor %D0, %S0, $zero',
234         mode      => "mode_Iu"
235 },
236
237 or => {
238         op_flags  => "C",
239         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
240         emit      => '. or %D0, %S0, %S1',
241         mode      => "mode_Iu"
242 },
243
244 ori => {
245         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
246         emit      => '. ori %D0, %S0, %C',
247         cmp_attr  => 'return attr_a->tv != attr_b->tv;',
248         mode      => "mode_Iu"
249 },
250
251 sl => {
252         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
253         emit      => '
254         if (mode_is_signed(get_irn_mode(node))) {
255                 . sal %D0, %S0, %S1
256         } else {
257                 . sll %D0, %S0, %S1
258         }
259 ',
260         mode      => "mode_Iu",
261 },
262
263 sli => {
264         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
265         emit      => '
266         if (mode_is_signed(get_irn_mode(node))) {
267                 . sal %D0, %S0, %C
268         } else {
269                 . sll %D0, %S0, %C
270         }
271 ',
272         mode      => "mode_Iu",
273 },
274
275 sra => {
276         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
277         emit      => '. sra %D0, %S0, %S1',
278         mode      => "mode_Iu"
279 },
280
281 srai => {
282         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
283         emit      => '. sra %D0, %S0, %C',
284         cmp_attr  => 'return attr_a->tv != attr_b->tv;',
285         mode      => "mode_Iu",
286 },
287
288 sr => {
289         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
290         emit      => '
291         if (mode_is_signed(get_irn_mode(node))) {
292                 . sra %D0, %S0, %S1
293         } else {
294                 . srl %D0, %S0, %S1
295         }
296 ',
297         mode      => "mode_Iu",
298 },
299
300 sri => {
301         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
302         emit      => '
303         if (mode_is_signed(get_irn_mode(node))) {
304                 . sra %D0, %S0, %C
305         } else {
306                 . srl %D0, %S0, %C
307         }
308 ',
309         mode      => "mode_Iu"
310 },
311
312 srlv => {
313         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
314         emit      => '. srlv %D0, %S0, %S1',
315         mode      => "mode_Iu"
316 },
317
318 sllv => {
319         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
320         emit      => '. sllv %D0, %S0, %S1',
321         mode      => "mode_Iu"
322 },
323
324 sub => {
325         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
326         emit      => '. subu %D0, %S0, %S1',
327         mode      => "mode_Iu"
328 },
329
330 subuzero => {
331         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
332         emit      => '. subu %D0, $zero, %S0',
333         mode      => "mode_Iu",
334 },
335
336 xor => {
337         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
338         emit      => '. xor %D0, %S0, %S1',
339         mode      => "mode_Iu",
340 },
341
342 xori => {
343         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
344         emit      => '. xori %D0, %S0, %C',
345         cmp_attr  => 'return attr_a->tv != attr_b->tv;',
346         mode      => "mode_Iu",
347 },
348
349 #   ____                _              _
350 #  / ___|___  _ __  ___| |_ __ _ _ __ | |_ ___
351 # | |   / _ \| '_ \/ __| __/ _` | '_ \| __/ __|
352 # | |__| (_) | | | \__ \ || (_| | | | | |_\__ \
353 #  \____\___/|_| |_|___/\__\__,_|_| |_|\__|___/
354 #
355
356 # load upper imediate
357 lui => {
358         op_flags  => "c",
359         reg_req   => { out => [ "gp" ] },
360         emit      => '. lui %D0, %C',
361         cmp_attr  => 'return attr_a->tv != attr_b->tv;',
362         mode      => "mode_Iu",
363 },
364
365 mflo => {
366         reg_req   => { in => [ "none" ], out => [ "gp" ] },
367         emit      => '. mflo %D0',
368         mode      => "mode_Iu"
369 },
370
371 mfhi => {
372         reg_req   => { in => [ "none" ], out => [ "gp" ] },
373         emit      => '. mfhi %D0',
374         mode      => "mode_Iu"
375 },
376
377 zero => {
378         state     => "pinned",
379         op_flags  => "c",
380         irn_flags => "I",
381         reg_req   => { out => [ "zero" ] },
382         emit      => '',
383         mode      => "mode_Iu"
384 },
385
386 #
387 #  ____                       _        __  _
388 # | __ ) _ __ __ _ _ __   ___| |__    / / | |_   _ _ __ ___  _ __
389 # |  _ \| '__/ _` | '_ \ / __| '_ \  / /  | | | | | '_ ` _ \| '_ \
390 # | |_) | | | (_| | | | | (__| | | |/ / |_| | |_| | | | | | | |_) |
391 # |____/|_|  \__,_|_| |_|\___|_| |_/_/ \___/ \__,_|_| |_| |_| .__/
392 #                                                           |_|
393 #
394
395 slt => {
396         reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
397         emit    => '. slt %D0, %S0, %S1',
398         mode    => "mode_Iu",
399 },
400
401 sltu => {
402         reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
403         emit    => '. sltu %D0, %S0, %S1',
404         mode    => "mode_Iu",
405 },
406
407 slti => {
408         reg_req => { in => [ "gp" ], out => [ "gp" ] },
409         emit    => '. slti %D0, %S0, %C',
410         mode    => "mode_Iu",
411 },
412
413 sltiu => {
414         reg_req => { in => [ "gp" ], out => [ "gp" ] },
415         emit    => '. slti %D0, %S0, %C',
416         mode    => "mode_Iu",
417 },
418
419 beq => {
420         op_flags => "X|Y",
421         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
422         outs     => [ "false", "true" ],
423         emit     => '. beq %S0, %S1, %JumpTarget1
424                      . %JumpOrFallthrough'
425 },
426
427 bne => {
428         op_flags => "X|Y",
429         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
430         outs     => [ "false", "true" ],
431         emit     => '. bne %S0, %S1, %JumpTarget1
432                      . %JumpOrFallthrough'
433 },
434
435 bgtz => {
436         op_flags => "X|Y",
437         reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
438         outs     => [ "false", "true" ],
439         emit     => '. bgtz %S0, %JumpTarget1
440                      . %JumpOrFallthrough'
441 },
442
443 blez => {
444         op_flags => "X|Y",
445         reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
446         outs     => [ "false", "true" ],
447         emit     => '. blez %S0, %JumpTarget1
448                      . %JumpOrFallthrough'
449 },
450
451 b => {
452         op_flags => "X",
453         reg_req  => { in => [ ], out => [ "none" ] },
454         emit     => '. b %JumpTarget',
455         mode     => 'mode_X'
456 },
457
458 jr => {
459         op_flags => "X",
460         reg_req  => { in => [ "gp" ], out => [ "none" ] },
461         emit     => '. jr %S0',
462         mode     => 'mode_X'
463 },
464
465 SwitchJump => {
466         op_flags => "X",
467         reg_req  => { in => [ "gp" ], out => [ "none" ] },
468         emit     => '. jr %S0'
469 },
470
471 #  _                    _    ______  _
472 # | |    ___   __ _  __| |  / / ___|| |_ ___  _ __ ___
473 # | |   / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
474 # | |__| (_) | (_| | (_| |/ /  ___) | || (_) | | |  __/
475 # |_____\___/ \__,_|\__,_/_/  |____/ \__\___/|_|  \___|
476 #
477
478 lw => {
479         op_flags => "L|F",
480         state    => "exc_pinned",
481         reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
482         outs     => [ "res", "M" ],
483         emit     => '. lw %D0, %C(%S1)',
484 },
485
486 lh => {
487         op_flags => "L|F",
488         state    => "exc_pinned",
489         reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
490         outs     => [ "res", "M" ],
491         emit     => '. lh %D0, %C(%S1)',
492 },
493
494 lhu => {
495         op_flags => "L|F",
496         state    => "exc_pinned",
497         reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
498         outs     => [ "res", "M" ],
499         emit     => '. lhu %D0, %C(%S1)',
500 },
501
502 lb => {
503         op_flags => "L|F",
504         state    => "exc_pinned",
505         reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
506         outs     => [ "res", "M" ],
507         emit     => '. lb %D0, %C(%S1)',
508 },
509
510 lbu => {
511         op_flags => "L|F",
512         state    => "exc_pinned",
513         reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
514         outs     => [ "res", "M" ],
515         emit     => '. lbu %D0, %C(%S1)',
516 },
517
518 sw => {
519         op_flags => "L|F",
520         state    => "exc_pinned",
521         reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
522         emit     => '. sw %S2, %C(%S1)',
523         mode     => 'mode_M',
524 },
525
526 sh => {
527         op_flags => "L|F",
528         state    => "exc_pinned",
529         reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
530         emit     => '. sh %S2, %C(%S1)',
531         mode     => 'mode_M',
532 },
533
534 sb => {
535         op_flags => "L|F",
536         state    => "exc_pinned",
537         reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
538         emit     => '. sb %S2, %C(%S1)',
539         mode     => 'mode_M',
540 },
541
542 move => {
543         reg_req  => { in => [ "gp" ], out => [ "gp" ] },
544         emit     => '. move %D0, %S0',
545         mode     => "mode_Iu"
546 },
547
548 #
549 # Miscelaneous
550 #
551
552 nop => {
553         op_flags => "K",
554         reg_req  => { in => [], out => [ "none" ] },
555         emit     => '. nop',
556 },
557
558 ); # end of %nodes