bbb1e509ad63ca232bb31d6d9aa26fc81850e353
[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                 { name => "gp_NOREG", realname => "!NOREG_INVALID!", type => 4 | 8 | 16 }, #dummy register for immediate nodes
125                 { mode => "mode_Iu" }
126         ],
127 ); # %reg_classes
128
129 %emit_templates = (
130     S0  => "${arch}_emit_source_register(node, 0);",
131     S1  => "${arch}_emit_source_register(node, 1);",
132     S2  => "${arch}_emit_source_register(node, 2);",
133         SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
134     D0  => "${arch}_emit_dest_register(node, 0);",
135     D1  => "${arch}_emit_dest_register(node, 1);",
136     D2  => "${arch}_emit_dest_register(node, 2);",
137         A0  => "${arch}_emit_load_store_address(node, 0);",
138         I   => "${arch}_emit_immediate_suffix(node, 1);",
139         C   => "${arch}_emit_immediate(node);",
140         JumpTarget => "${arch}_emit_jump_target(node);",
141         JumpTarget1 => "${arch}_emit_jump_target_proj(node, 1);",
142         JumpOrFallthrough => "${arch}_emit_jump_or_fallthrough(node, 0);",
143 );
144
145 $default_attr_type = "mips_attr_t";
146 $default_copy_attr = "mips_copy_attr";
147
148 $mode_gp = "mode_Iu";
149
150 %init_attr = (
151         mips_attr_t            => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
152
153         mips_immediate_attr_t  => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
154                                  "\tinit_mips_immediate_attributes(res, imm_type, entity, val);",
155
156         mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
157                                  "\tinit_mips_load_store_attributes(res, entity, offset);",
158 );
159
160 %compare_attr = (
161         mips_attr_t            => "mips_compare_nodes_attr",
162         mips_immediate_attr_t  => "mips_compare_immediate_attr",
163         mips_load_store_attr_t => "mips_compare_load_store_attr",
164 );
165
166 #--------------------------------------------------#
167 #                        _                         #
168 #                       (_)                        #
169 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
170 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
171 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
172 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
173 #                                      | |         #
174 #                                      |_|         #
175 #--------------------------------------------------#
176
177 %nodes = (
178
179 Immediate => {
180         state     => "pinned",
181         op_flags  => "c",
182         irn_flags => "I",
183         reg_req   => { out => [ "gp_NOREG" ] },
184         attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
185         attr_type => "mips_immediate_attr_t",
186         mode      => $mode_gp,
187 },
188
189 #-----------------------------------------------------------------#
190 #  _       _                                         _            #
191 # (_)     | |                                       | |           #
192 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
193 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
194 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
195 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
196 #                   __/ |                                         #
197 #                  |___/                                          #
198 #-----------------------------------------------------------------#
199
200 # commutative operations
201
202 addu => {
203         op_flags  => "R",
204         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
205         ins       => [ "left", "right" ],
206         emit      => '. add%I%.u %D0, %S0, %SI1',
207         mode      => $mode_gp,
208 },
209
210 and => {
211         op_flags  => "R",
212         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
213         ins       => [ "left", "right" ],
214         emit      => '. and%I %D0, %S0, %SI1',
215         mode      => $mode_gp,
216 },
217
218 div => {
219         reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
220         ins       => [ "left", "right" ],
221         outs      => [ "lohi", "M" ],
222         emit      => '. div %S0, %S1',
223         mode      => "mode_M",
224 },
225
226 divu => {
227         reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
228         ins       => [ "left", "right" ],
229         outs      => [ "lohi", "M" ],
230         emit      => '. divu %S0, %S1',
231         mode      => "mode_M",
232 },
233
234 mult => {
235         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
236         ins       => [ "left", "right" ],
237         emit      => '. mult %S0, %S1',
238         mode      => "mode_M"
239 },
240
241 multu => {
242         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
243         ins       => [ "left", "right" ],
244         emit      => '. multu %S0, %S1',
245         mode      => "mode_M",
246 },
247
248 nor => {
249         op_flags  => "R",
250         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
251         emit      => '. nor%I %D0, %S0, %SI1',
252         mode      => $mode_gp
253 },
254
255 or => {
256         op_flags  => "R",
257         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
258         ins       => [ "left", "right" ],
259         emit      => '. or%I %D0, %S0, %SI1',
260         mode      => $mode_gp
261 },
262
263 sll => {
264         op_flags  => "R",
265         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
266         ins       => [ "left", "right" ],
267         emit      => '. sll %D0, %S0, %SI1',
268         mode      => $mode_gp,
269 },
270
271 sra => {
272         op_flags  => "R",
273         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
274         ins       => [ "left", "right" ],
275         emit      => '. sra %D0, %S0, %SI1',
276         mode      => $mode_gp
277 },
278
279 srl => {
280         op_flags  => "R",
281         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
282         ins       => [ "left", "right" ],
283         emit      => '. srl %D0, %S0, %SI1',
284         mode      => $mode_gp,
285 },
286
287 subu => {
288         op_flags  => "R",
289         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
290         ins       => [ "left", "right" ],
291         emit      => '. subu %D0, %S0, %S1',
292         mode      => $mode_gp
293 },
294
295 xor => {
296         op_flags  => "R",
297         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
298         ins       => [ "left", "right" ],
299         emit      => '. xor%I %D0, %S0, %SI1',
300         mode      => $mode_gp,
301 },
302
303 seb => {
304         op_flags  => "R",
305         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
306         ins       => [ "val" ],
307         emit      => '.seb %D0, %S0',
308         mode      => $mode_gp,
309 },
310
311 seh => {
312         op_flags  => "R",
313         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
314         ins       => [ "val" ],
315         emit      => '.seh %D0, %S0',
316         mode      => $mode_gp,
317 },
318
319 lui => {
320         op_flags  => "c",
321         irn_flags => "R",
322         reg_req   => { out => [ "gp" ] },
323         emit      => '.lui %D0, %C',
324         attr_type => "mips_immediate_attr_t",
325         attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
326         mode      => $mode_gp,
327 },
328
329 mflo => {
330         irn_flags => "R",
331         reg_req   => { in => [ "none" ], out => [ "gp" ] },
332         ins       => [ "lohi" ],
333         emit      => '. mflo %D0',
334         mode      => $mode_gp
335 },
336
337 mfhi => {
338         irn_flags => "R",
339         reg_req   => { in => [ "none" ], out => [ "gp" ] },
340         ins       => [ "lohi" ],
341         emit      => '. mfhi %D0',
342         mode      => $mode_gp
343 },
344
345 zero => {
346         state     => "pinned",
347         op_flags  => "c",
348         irn_flags => "I",
349         reg_req   => { out => [ "zero" ] },
350         emit      => '',
351         mode      => $mode_gp
352 },
353
354 #
355 #  ____                       _        __  _
356 # | __ ) _ __ __ _ _ __   ___| |__    / / | |_   _ _ __ ___  _ __
357 # |  _ \| '__/ _` | '_ \ / __| '_ \  / /  | | | | | '_ ` _ \| '_ \
358 # | |_) | | | (_| | | | | (__| | | |/ / |_| | |_| | | | | | | |_) |
359 # |____/|_|  \__,_|_| |_|\___|_| |_/_/ \___/ \__,_|_| |_| |_| .__/
360 #                                                           |_|
361 #
362
363 slt => {
364         op_flags => "R",
365         reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
366         emit    => '. slt%I %D0, %S0, %SI1',
367         mode    => $mode_gp,
368 },
369
370 sltu => {
371         op_flags => "R",
372         reg_req  => { in => [ "gp", "gp" ], out => [ "gp" ] },
373         emit     => '. slt%I%.u %D0, %S0, %SI1',
374         mode     => $mode_gp,
375 },
376
377 beq => {
378         op_flags => "X|Y",
379         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
380         outs     => [ "false", "true" ],
381         emit     => '. beq %S0, %S1, %JumpTarget1
382                      . %JumpOrFallthrough'
383 },
384
385 bne => {
386         op_flags => "X|Y",
387         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
388         outs     => [ "false", "true" ],
389         emit     => '. bne %S0, %S1, %JumpTarget1
390                      . %JumpOrFallthrough'
391 },
392
393 bgtz => {
394         op_flags => "X|Y",
395         reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
396         outs     => [ "false", "true" ],
397         emit     => '. bgtz %S0, %JumpTarget1
398                      . %JumpOrFallthrough'
399 },
400
401 blez => {
402         op_flags => "X|Y",
403         reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
404         outs     => [ "false", "true" ],
405         emit     => '. blez %S0, %JumpTarget1
406                      . %JumpOrFallthrough'
407 },
408
409 b => {
410         op_flags => "X",
411         reg_req  => { in => [ ], out => [ "none" ] },
412         emit     => '. b %JumpTarget',
413         mode     => 'mode_X'
414 },
415
416 jr => {
417         op_flags => "X",
418         reg_req  => { in => [ "gp" ], out => [ "none" ] },
419         emit     => '. jr %S0',
420         mode     => 'mode_X'
421 },
422
423 SwitchJump => {
424         op_flags => "X",
425         reg_req  => { in => [ "gp" ], out => [ "none" ] },
426         emit     => '. jr %S0'
427 },
428
429 #  _                    _    ______  _
430 # | |    ___   __ _  __| |  / / ___|| |_ ___  _ __ ___
431 # | |   / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
432 # | |__| (_) | (_| | (_| |/ /  ___) | || (_) | | |  __/
433 # |_____\___/ \__,_|\__,_/_/  |____/ \__\___/|_|  \___|
434 #
435
436 lw => {
437         op_flags  => "L|F",
438         state     => "exc_pinned",
439         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
440         ins       => [ "ptr", "mem" ],
441         outs      => [ "res", "M" ],
442         emit      => '. lw %D0, %A0',
443         attr_type => "mips_load_store_attr_t",
444         attr      => "ir_entity *entity, long offset",
445 },
446
447 lh => {
448         op_flags  => "L|F",
449         state     => "exc_pinned",
450         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
451         ins       => [ "ptr", "mem" ],
452         outs      => [ "res", "M" ],
453         emit      => '. lh %D0, %A0',
454         attr_type => "mips_load_store_attr_t",
455         attr      => "ir_entity *entity, long offset",
456 },
457
458 lhu => {
459         op_flags  => "L|F",
460         state     => "exc_pinned",
461         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
462         ins       => [ "ptr", "mem" ],
463         outs      => [ "res", "M" ],
464         emit      => '. lhu %D0, %A0',
465         attr_type => "mips_load_store_attr_t",
466         attr      => "ir_entity *entity, long offset",
467 },
468
469 lb => {
470         op_flags  => "L|F",
471         state     => "exc_pinned",
472         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
473         ins       => [ "ptr", "mem" ],
474         outs      => [ "res", "M" ],
475         emit      => '. lb %D0, %A0',
476         attr_type => "mips_load_store_attr_t",
477         attr      => "ir_entity *entity, long offset",
478 },
479
480 lbu => {
481         op_flags  => "L|F",
482         state     => "exc_pinned",
483         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
484         ins       => [ "ptr", "mem" ],
485         outs      => [ "res", "M" ],
486         emit      => '. lbu %D0, %A0',
487         attr_type => "mips_load_store_attr_t",
488         attr      => "ir_entity *entity, long offset",
489 },
490
491 sw => {
492         op_flags  => "L|F",
493         state     => "exc_pinned",
494         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
495         ins       => [ "ptr", "val", "mem" ],
496         emit      => '. sw %S1, %A0',
497         mode      => 'mode_M',
498         attr_type => "mips_load_store_attr_t",
499         attr      => "ir_entity *entity, long offset",
500 },
501
502 sh => {
503         op_flags  => "L|F",
504         state     => "exc_pinned",
505         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
506         ins       => [ "ptr", "val", "mem" ],
507         emit      => '. sh %S1, %A0',
508         mode      => 'mode_M',
509         attr_type => "mips_load_store_attr_t",
510         attr      => "ir_entity *entity, long offset",
511 },
512
513 sb => {
514         op_flags  => "L|F",
515         state     => "exc_pinned",
516         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
517         ins       => [ "ptr", "val", "mem" ],
518         emit      => '. sb %S1, %A0',
519         mode      => 'mode_M',
520         attr_type => "mips_load_store_attr_t",
521         attr      => "ir_entity *entity, long offset",
522 },
523
524 #
525 # Miscelaneous
526 #
527
528 nop => {
529         op_flags => "K",
530         reg_req  => { in => [], out => [ "none" ] },
531         emit     => '. nop',
532 },
533
534 ); # end of %nodes