- Part1 of backend reorganisation:
[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 # register types:
11 #   0 - no special type
12 #   1 - caller save (register must be saved by the caller of a function)
13 #   2 - callee save (register must be saved by the called function)
14 #   4 - ignore (do not assign this register)
15 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold\
16 %reg_classes = (
17         "gp" => [
18                 { name => "zero", type => 4 },  # always zero
19                 { name => "at", type => 4 }, # reserved for assembler
20                 { name => "v0", realname => "2", type => 1 }, # first return value
21                 { name => "v1", realname => "3", type => 1 }, # second return value
22                 { name => "a0", realname => "4", type => 1 }, # first argument
23                 { name => "a1", realname => "5", type => 1 }, # second argument
24                 { name => "a2", realname => "6", type => 1 }, # third argument
25                 { name => "a3", realname => "7", type => 1 }, # fourth argument
26                 { name => "t0", realname => "8", type => 1 },
27                 { name => "t1", realname => "9", type => 1 },
28                 { name => "t2", realname => "10", type => 1 },
29                 { name => "t3", realname => "11", type => 1 },
30                 { name => "t4", realname => "12", type => 1 },
31                 { name => "t5", realname => "13", type => 1 },
32                 { name => "t6", realname => "14", type => 1 },
33                 { name => "t7", realname => "15", type => 1 },
34                 { name => "s0", realname => "16", type => 2 },
35                 { name => "s1", realname => "17", type => 2 },
36                 { name => "s2", realname => "18", type => 2 },
37                 { name => "s3", realname => "19", type => 2 },
38                 { name => "s4", realname => "20", type => 2 },
39                 { name => "s5", realname => "21", type => 2 },
40                 { name => "s6", realname => "22", type => 2 },
41                 { name => "s7", realname => "23", type => 2 },
42                 { name => "t8", realname => "24", type => 1 },
43                 { name => "t9", realname => "25", type => 1 },
44                 { name => "kt0", type => 4 }, # reserved for OS
45                 { name => "kt1", type => 4 }, # reserved for OS
46                 { name => "gp", type => 4 }, # general purpose
47                 { name => "sp", type => 4 }, # stack pointer
48                 { name => "fp", type => 4 }, # frame pointer
49                 { name => "ra", type => 2+1 }, # return address
50                 { name => "gp_NOREG", realname => "!NOREG_INVALID!", type => 4 | 8 | 16 }, #dummy register for immediate nodes
51                 { mode => "mode_Iu" }
52         ],
53 ); # %reg_classes
54
55 %emit_templates = (
56     S0  => "${arch}_emit_source_register(node, 0);",
57     S1  => "${arch}_emit_source_register(node, 1);",
58     S2  => "${arch}_emit_source_register(node, 2);",
59         SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
60     D0  => "${arch}_emit_dest_register(node, 0);",
61     D1  => "${arch}_emit_dest_register(node, 1);",
62     D2  => "${arch}_emit_dest_register(node, 2);",
63         A0  => "${arch}_emit_load_store_address(node, 0);",
64         I   => "${arch}_emit_immediate_suffix(node, 1);",
65         C   => "${arch}_emit_immediate(node);",
66         JumpTarget => "${arch}_emit_jump_target(node);",
67         JumpTarget1 => "${arch}_emit_jump_target_proj(node, 1);",
68         JumpOrFallthrough => "${arch}_emit_jump_or_fallthrough(node, 0);",
69 );
70
71 $default_attr_type = "mips_attr_t";
72 $default_copy_attr = "mips_copy_attr";
73
74 $mode_gp = "mode_Iu";
75
76 %init_attr = (
77         mips_attr_t            => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
78
79         mips_immediate_attr_t  => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
80                                  "\tinit_mips_immediate_attributes(res, imm_type, entity, val);",
81
82         mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
83                                  "\tinit_mips_load_store_attributes(res, entity, offset);",
84 );
85
86 %compare_attr = (
87         mips_attr_t            => "mips_compare_nodes_attr",
88         mips_immediate_attr_t  => "mips_compare_immediate_attr",
89         mips_load_store_attr_t => "mips_compare_load_store_attr",
90 );
91
92 #--------------------------------------------------#
93 #                        _                         #
94 #                       (_)                        #
95 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
96 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
97 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
98 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
99 #                                      | |         #
100 #                                      |_|         #
101 #--------------------------------------------------#
102
103 %nodes = (
104
105 Immediate => {
106         state     => "pinned",
107         op_flags  => "c",
108         reg_req   => { out => [ "gp_NOREG:I" ] },
109         attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
110         attr_type => "mips_immediate_attr_t",
111         mode      => $mode_gp,
112 },
113
114 #-----------------------------------------------------------------#
115 #  _       _                                         _            #
116 # (_)     | |                                       | |           #
117 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
118 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
119 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
120 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
121 #                   __/ |                                         #
122 #                  |___/                                          #
123 #-----------------------------------------------------------------#
124
125 # commutative operations
126
127 addu => {
128         op_flags  => "R",
129         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
130         ins       => [ "left", "right" ],
131         emit      => '. add%I%.u %D0, %S0, %SI1',
132         mode      => $mode_gp,
133 },
134
135 and => {
136         op_flags  => "R",
137         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
138         ins       => [ "left", "right" ],
139         emit      => '. and%I %D0, %S0, %SI1',
140         mode      => $mode_gp,
141 },
142
143 div => {
144         reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
145         ins       => [ "left", "right" ],
146         outs      => [ "lohi", "M" ],
147         emit      => '. div %S0, %S1',
148         mode      => "mode_M",
149 },
150
151 divu => {
152         reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
153         ins       => [ "left", "right" ],
154         outs      => [ "lohi", "M" ],
155         emit      => '. divu %S0, %S1',
156         mode      => "mode_M",
157 },
158
159 mult => {
160         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
161         ins       => [ "left", "right" ],
162         emit      => '. mult %S0, %S1',
163         mode      => "mode_M"
164 },
165
166 multu => {
167         reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
168         ins       => [ "left", "right" ],
169         emit      => '. multu %S0, %S1',
170         mode      => "mode_M",
171 },
172
173 nor => {
174         op_flags  => "R",
175         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
176         emit      => '. nor%I %D0, %S0, %SI1',
177         mode      => $mode_gp
178 },
179
180 or => {
181         op_flags  => "R",
182         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
183         ins       => [ "left", "right" ],
184         emit      => '. or%I %D0, %S0, %SI1',
185         mode      => $mode_gp
186 },
187
188 sll => {
189         op_flags  => "R",
190         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
191         ins       => [ "left", "right" ],
192         emit      => '. sll %D0, %S0, %SI1',
193         mode      => $mode_gp,
194 },
195
196 sra => {
197         op_flags  => "R",
198         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
199         ins       => [ "left", "right" ],
200         emit      => '. sra %D0, %S0, %SI1',
201         mode      => $mode_gp
202 },
203
204 srl => {
205         op_flags  => "R",
206         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
207         ins       => [ "left", "right" ],
208         emit      => '. srl %D0, %S0, %SI1',
209         mode      => $mode_gp,
210 },
211
212 subu => {
213         op_flags  => "R",
214         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
215         ins       => [ "left", "right" ],
216         emit      => '. subu %D0, %S0, %S1',
217         mode      => $mode_gp
218 },
219
220 xor => {
221         op_flags  => "R",
222         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
223         ins       => [ "left", "right" ],
224         emit      => '. xor%I %D0, %S0, %SI1',
225         mode      => $mode_gp,
226 },
227
228 seb => {
229         op_flags  => "R",
230         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
231         ins       => [ "val" ],
232         emit      => '.seb %D0, %S0',
233         mode      => $mode_gp,
234 },
235
236 seh => {
237         op_flags  => "R",
238         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
239         ins       => [ "val" ],
240         emit      => '.seh %D0, %S0',
241         mode      => $mode_gp,
242 },
243
244 lui => {
245         op_flags  => "c",
246         irn_flags => "R",
247         reg_req   => { out => [ "gp" ] },
248         emit      => '.lui %D0, %C',
249         attr_type => "mips_immediate_attr_t",
250         attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
251         mode      => $mode_gp,
252 },
253
254 mflo => {
255         irn_flags => "R",
256         reg_req   => { in => [ "none" ], out => [ "gp" ] },
257         ins       => [ "lohi" ],
258         emit      => '. mflo %D0',
259         mode      => $mode_gp
260 },
261
262 mfhi => {
263         irn_flags => "R",
264         reg_req   => { in => [ "none" ], out => [ "gp" ] },
265         ins       => [ "lohi" ],
266         emit      => '. mfhi %D0',
267         mode      => $mode_gp
268 },
269
270 zero => {
271         state     => "pinned",
272         op_flags  => "c",
273         reg_req   => { out => [ "zero:I" ] },
274         emit      => '',
275         mode      => $mode_gp
276 },
277
278 #
279 #  ____                       _        __  _
280 # | __ ) _ __ __ _ _ __   ___| |__    / / | |_   _ _ __ ___  _ __
281 # |  _ \| '__/ _` | '_ \ / __| '_ \  / /  | | | | | '_ ` _ \| '_ \
282 # | |_) | | | (_| | | | | (__| | | |/ / |_| | |_| | | | | | | |_) |
283 # |____/|_|  \__,_|_| |_|\___|_| |_/_/ \___/ \__,_|_| |_| |_| .__/
284 #                                                           |_|
285 #
286
287 slt => {
288         op_flags => "R",
289         reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
290         emit    => '. slt%I %D0, %S0, %SI1',
291         mode    => $mode_gp,
292 },
293
294 sltu => {
295         op_flags => "R",
296         reg_req  => { in => [ "gp", "gp" ], out => [ "gp" ] },
297         emit     => '. slt%I%.u %D0, %S0, %SI1',
298         mode     => $mode_gp,
299 },
300
301 beq => {
302         op_flags => "X|Y",
303         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
304         outs     => [ "false", "true" ],
305         emit     => '. beq %S0, %S1, %JumpTarget1
306                      . %JumpOrFallthrough'
307 },
308
309 bne => {
310         op_flags => "X|Y",
311         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
312         outs     => [ "false", "true" ],
313         emit     => '. bne %S0, %S1, %JumpTarget1
314                      . %JumpOrFallthrough'
315 },
316
317 bgtz => {
318         op_flags => "X|Y",
319         reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
320         outs     => [ "false", "true" ],
321         emit     => '. bgtz %S0, %JumpTarget1
322                      . %JumpOrFallthrough'
323 },
324
325 blez => {
326         op_flags => "X|Y",
327         reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
328         outs     => [ "false", "true" ],
329         emit     => '. blez %S0, %JumpTarget1
330                      . %JumpOrFallthrough'
331 },
332
333 b => {
334         op_flags => "X",
335         reg_req  => { in => [ ], out => [ "none" ] },
336         emit     => '. b %JumpTarget',
337         mode     => 'mode_X'
338 },
339
340 jr => {
341         op_flags => "X",
342         reg_req  => { in => [ "gp" ], out => [ "none" ] },
343         emit     => '. jr %S0',
344         mode     => 'mode_X'
345 },
346
347 SwitchJump => {
348         op_flags => "X",
349         reg_req  => { in => [ "gp" ], out => [ "none" ] },
350         emit     => '. jr %S0'
351 },
352
353 #  _                    _    ______  _
354 # | |    ___   __ _  __| |  / / ___|| |_ ___  _ __ ___
355 # | |   / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
356 # | |__| (_) | (_| | (_| |/ /  ___) | || (_) | | |  __/
357 # |_____\___/ \__,_|\__,_/_/  |____/ \__\___/|_|  \___|
358 #
359
360 lw => {
361         op_flags  => "L|F",
362         state     => "exc_pinned",
363         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
364         ins       => [ "ptr", "mem" ],
365         outs      => [ "res", "M" ],
366         emit      => '. lw %D0, %A0',
367         attr_type => "mips_load_store_attr_t",
368         attr      => "ir_entity *entity, long offset",
369 },
370
371 lh => {
372         op_flags  => "L|F",
373         state     => "exc_pinned",
374         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
375         ins       => [ "ptr", "mem" ],
376         outs      => [ "res", "M" ],
377         emit      => '. lh %D0, %A0',
378         attr_type => "mips_load_store_attr_t",
379         attr      => "ir_entity *entity, long offset",
380 },
381
382 lhu => {
383         op_flags  => "L|F",
384         state     => "exc_pinned",
385         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
386         ins       => [ "ptr", "mem" ],
387         outs      => [ "res", "M" ],
388         emit      => '. lhu %D0, %A0',
389         attr_type => "mips_load_store_attr_t",
390         attr      => "ir_entity *entity, long offset",
391 },
392
393 lb => {
394         op_flags  => "L|F",
395         state     => "exc_pinned",
396         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
397         ins       => [ "ptr", "mem" ],
398         outs      => [ "res", "M" ],
399         emit      => '. lb %D0, %A0',
400         attr_type => "mips_load_store_attr_t",
401         attr      => "ir_entity *entity, long offset",
402 },
403
404 lbu => {
405         op_flags  => "L|F",
406         state     => "exc_pinned",
407         reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
408         ins       => [ "ptr", "mem" ],
409         outs      => [ "res", "M" ],
410         emit      => '. lbu %D0, %A0',
411         attr_type => "mips_load_store_attr_t",
412         attr      => "ir_entity *entity, long offset",
413 },
414
415 sw => {
416         op_flags  => "L|F",
417         state     => "exc_pinned",
418         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
419         ins       => [ "ptr", "val", "mem" ],
420         emit      => '. sw %S1, %A0',
421         mode      => 'mode_M',
422         attr_type => "mips_load_store_attr_t",
423         attr      => "ir_entity *entity, long offset",
424 },
425
426 sh => {
427         op_flags  => "L|F",
428         state     => "exc_pinned",
429         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
430         ins       => [ "ptr", "val", "mem" ],
431         emit      => '. sh %S1, %A0',
432         mode      => 'mode_M',
433         attr_type => "mips_load_store_attr_t",
434         attr      => "ir_entity *entity, long offset",
435 },
436
437 sb => {
438         op_flags  => "L|F",
439         state     => "exc_pinned",
440         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
441         ins       => [ "ptr", "val", "mem" ],
442         emit      => '. sb %S1, %A0',
443         mode      => 'mode_M',
444         attr_type => "mips_load_store_attr_t",
445         attr      => "ir_entity *entity, long offset",
446 },
447
448 #
449 # Miscelaneous
450 #
451
452 nop => {
453         op_flags => "K",
454         reg_req  => { in => [], out => [ "none" ] },
455         emit     => '. nop',
456 },
457
458 ); # end of %nodes