3 # This is a template specification for the Firm-Backend
5 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
11 # The node description is done as a perl hash initializer with the
12 # following structure:
17 # op_flags => "N|L|C|X|I|F|Y|H|c|K",
18 # "arity" => "0|1|2|3 ... |variable|dynamic|any",
19 # "state" => "floats|pinned|mem_pinned|exc_pinned",
21 # { "type" => "type 1", "name" => "name 1" },
22 # { "type" => "type 2", "name" => "name 2" },
25 # "comment" => "any comment for constructor",
26 # reg_req => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
27 # "cmp_attr" => "c source code for comparing node attributes",
28 # emit => "emit code with templates",
29 # "rd_constructor" => "c source code which constructs an ir_node"
32 # ... # (all nodes you need to describe)
34 # ); # close the %nodes initializer
36 # op_flags: flags for the operation, OPTIONAL (default is "N")
37 # the op_flags correspond to the firm irop_flags:
40 # C irop_flag_commutative
41 # X irop_flag_cfopcode
42 # I irop_flag_ip_cfopcode
45 # H irop_flag_highlevel
46 # c irop_flag_constlike
51 # I ignore for register allocation
53 # state: state of the operation, OPTIONAL (default is "floats")
55 # arity: arity of the operation, MUST NOT BE OMITTED
57 # args: the OPTIONAL arguments of the node constructor (debug, irg and block
58 # are always the first 3 arguments and are always autmatically
60 # If this key is missing the following arguments will be created:
61 # for i = 1 .. arity: ir_node *op_i
64 # comment: OPTIONAL comment for the node constructor
66 # rd_constructor: for every operation there will be a
67 # new_rd_<arch>_<op-name> function with the arguments from above
68 # which creates the ir_node corresponding to the defined operation
69 # you can either put the complete source code of this function here
71 # This key is OPTIONAL. If omitted, the following constructor will
73 # if (!op_<arch>_<op-name>) assert(0);
77 # res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
80 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
84 # 1 - caller save (register must be saved by the caller of a function)
85 # 2 - callee save (register must be saved by the called function)
86 # 4 - ignore (do not assign this register)
87 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold\
89 "general_purpose" => [
90 { name => "zero", type => 4+2 }, # always zero
91 { name => "at", type => 4 }, # reserved for assembler
92 { name => "v0", type => 1 }, # first return value
93 { name => "v1", type => 1 }, # second return value
94 { name => "a0", type => 1 }, # first argument
95 { name => "a1", type => 1 }, # second argument
96 { name => "a2", type => 1 }, # third argument
97 { name => "a3", type => 1 }, # fourth argument
98 { name => "t0", type => 1 },
99 { name => "t1", type => 1 },
100 { name => "t2", type => 1 },
101 { name => "t3", type => 1 },
102 { name => "t4", type => 1 },
103 { name => "t5", type => 1 },
104 { name => "t6", type => 1 },
105 { name => "t7", type => 1 },
106 { name => "s0", type => 2 },
107 { name => "s1", type => 2 },
108 { name => "s2", type => 2 },
109 { name => "s3", type => 2 },
110 { name => "s4", type => 2 },
111 { name => "s5", type => 2 },
112 { name => "s6", type => 2 },
113 { name => "s7", type => 2 },
114 { name => "t8", type => 1 },
115 { name => "t9", type => 1 },
116 { name => "k0", type => 4 }, # reserved for OS
117 { name => "k1", type => 4 }, # reserved for OS
118 { name => "gp", type => 4 }, # general purpose
119 { name => "sp", type => 4+2 }, # stack pointer
120 { name => "fp", type => 4+2 }, # frame pointer
121 { name => "ra", type => 2+1 }, # return address. This is also caller save, because
122 # the jla instruction that is used for calls modifies
123 # the ra register. It is callee save too, because at the last
124 # command of a function (the ja $ra) it needs to have it's
130 #--------------------------------------------------#
133 # _ __ _____ __ _ _ __ ___ _ __ ___ #
134 # | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
135 # | | | | __/\ V V / | | | | (_) | |_) \__ \ #
136 # |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
139 #--------------------------------------------------#
143 #-----------------------------------------------------------------#
146 # _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
147 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
148 # | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
149 # |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
152 #-----------------------------------------------------------------#
154 # commutative operations
158 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
160 if (mode_is_signed(get_irn_mode(n)))
163 2. addu %D1, %S1, %S2
168 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
170 if (mode_is_signed(get_irn_mode(n)))
173 2. addiu %D1, %S1, %C
175 cmp_attr => 'return attr_a->tv != attr_b->tv;',
180 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
181 emit => '. and %D1, %S1, %S2',
185 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
186 emit => '. andi %D1, %S1, %C',
187 cmp_attr => 'return attr_a->tv != attr_b->tv;',
191 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "none", "none", "none", "none" ] },
193 mips_attr_t *attr = get_mips_attr(n);
194 if(attr->modes.original_mode->sign) {
204 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "none" ] },
206 if (mode_is_signed(get_irn_mode(n)))
215 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
216 emit => '. nor %D1, %S1, %S2'
220 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
222 assert(get_mode_size_bits(get_irn_mode(n)) == 32);
223 . nor %D1, %S1, $zero
229 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
230 emit => '. or %D1, %S1, %S2'
234 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
235 emit => '. ori %D1, %S1, %C',
236 cmp_attr => 'return attr_a->tv != attr_b->tv;',
240 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
242 if (mode_is_signed(get_irn_mode(n)))
245 2. sll %D1, %S1, %S2',
249 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
251 if (mode_is_signed(get_irn_mode(n)))
254 2. sll %D1, %S1, %C',
258 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
259 emit => '. sra %D1, %S1, %S2',
263 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
264 emit => '. sra %D1, %S1, %C',
265 cmp_attr => 'return attr_a->tv != attr_b->tv;',
269 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
271 if (mode_is_signed(get_irn_mode(n)))
279 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
281 if (mode_is_signed(get_irn_mode(n)))
289 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
290 emit => '. srlv %D1, %S1, %S2',
294 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
295 emit => '. sllv %D1, %S1, %S2',
299 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
300 emit => '. sub %D1, %S1, %S2'
304 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
305 emit => '. subu %D1, %S1, %S2',
309 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
310 emit => '. subu %D1, $zero, %S1',
314 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
315 emit => '. xor %D1, %S1, %S2'
319 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
320 emit => '. xori %D1, %S1, %C',
321 cmp_attr => 'return attr_a->tv != attr_b->tv;',
325 # / ___|___ _ __ ___| |_ __ _ _ __ | |_ ___
326 # | | / _ \| '_ \/ __| __/ _` | '_ \| __/ __|
327 # | |__| (_) | | | \__ \ || (_| | | | | |_\__ \
328 # \____\___/|_| |_|___/\__\__,_|_| |_|\__|___/
331 # load upper imediate
334 reg_req => { out => [ "general_purpose" ] },
335 emit => '. lui %D1, %C',
336 cmp_attr => 'return attr_a->tv != attr_b->tv;',
339 # load lower immediate
342 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
343 emit => '. ori %D1, %S1, %C',
344 cmp_attr => 'return attr_a->tv != attr_b->tv;',
349 reg_req => { out => [ "general_purpose" ] },
350 emit => '. la %D1, %C',
351 cmp_attr => 'return attr_a->symconst_id != attr_b->symconst_id;',
355 reg_req => { in => [ "none" ], out => [ "general_purpose" ] },
360 reg_req => { in => [ "none" ], out => [ "general_purpose" ] },
365 reg_req => { out => [ "zero" ] },
371 # | __ ) _ __ __ _ _ __ ___| |__ / / | |_ _ _ __ ___ _ __
372 # | _ \| '__/ _` | '_ \ / __| '_ \ / / | | | | | '_ ` _ \| '_ \
373 # | |_) | | | (_| | | | | (__| | | |/ / |_| | |_| | | | | | | |_) |
374 # |____/|_| \__,_|_| |_|\___|_| |_/_/ \___/ \__,_|_| |_| |_| .__/
379 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "general_purpose" ] },
381 if (mode_is_signed(get_irn_mode(n)))
384 2. sltu %D1, %S1, %S2
389 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
391 if (mode_is_signed(get_irn_mode(n)))
394 2. sltiu %D1, %S1, %C
396 cmp_attr => 'return attr_a->tv != attr_b->tv;',
402 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "in_r0", "none" ] },
404 ir_node *jumpblock = mips_get_jump_block(n, 1);
405 assert(jumpblock != NULL);
407 lc_efprintf(arg_env, F, "\tbeq %1S, %2S, BLOCK_%d\n", n, n, get_irn_node_nr(jumpblock));
414 reg_req => { in => [ "general_purpose", "general_purpose" ], out => [ "in_r0", "none" ] },
416 ir_node *jumpblock = mips_get_jump_block(n, 1);
417 assert(jumpblock != NULL);
419 lc_efprintf(arg_env, F, "\tbne %1S, %2S, BLOCK_%d\n", n, n, get_irn_node_nr(jumpblock));
426 reg_req => { in => [ "general_purpose" ], out => [ "in_r0", "none" ] },
428 ir_node *jumpblock = mips_get_jump_block(n, 1);
429 assert(jumpblock != NULL);
431 lc_efprintf(arg_env, F, "\tbgtz %1S, BLOCK_%d\n", n, get_irn_node_nr(jumpblock));
438 reg_req => { in => [ "general_purpose" ], out => [ "in_r0", "none" ] },
440 ir_node *jumpblock = mips_get_jump_block(n, 1);
441 assert(jumpblock != NULL);
443 lc_efprintf(arg_env, F, "\tblez %1S, BLOCK_%d\n", n, get_irn_node_nr(jumpblock));
449 reg_req => { in => [ "general_purpose" ] },
456 reg_req => { in => [ ], out => [ "none" ] },
458 ir_node *jumpblock = get_irn_link(n);
459 assert(jumpblock != NULL);
461 lc_efprintf(arg_env, F, "\tb BLOCK_%d\t\t\t# mips_b\n", get_irn_node_nr(jumpblock));
468 reg_req => { in => [ ], out => [ "none" ] },
469 emit => '. # fallthrough'
475 reg_req => { in => [ "general_purpose" ], out => [ "none" ] },
481 # | | / _ \ / _` |/ _` |
482 # | |__| (_) | (_| | (_| |
483 # |_____\___/ \__,_|\__,_|
487 reg_req => { in => [ "none", "general_purpose" ], out => [ "none", "none", "general_purpose" ] },
489 mips_attr_t* attr = get_mips_attr(n);
492 mode = attr->modes.load_store_mode;
494 switch (get_mode_size_bits(mode)) {
496 if (mode_is_signed(mode))
502 if (mode_is_signed(mode))
511 assert(! "Only 8, 16 and 32 bit loads supported");
515 cmp_attr => 'return attr_a->tv != attr_b->tv || attr_a->stack_entity != attr_b->stack_entity;',
520 # | | ___ __ _ __| | / / ___|| |_ ___ _ __ ___
521 # | | / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
522 # | |__| (_) | (_| | (_| |/ / ___) | || (_) | | | __/
523 # |_____\___/ \__,_|\__,_/_/ |____/ \__\___/|_| \___|
527 reg_req => { in => [ "none", "general_purpose", "general_purpose" ], out => [ "none", "none" ] },
529 mips_attr_t* attr = get_mips_attr(n);
532 mode = attr->modes.load_store_mode;
534 switch (get_mode_size_bits(mode)) {
536 if (mode_is_signed(mode))
540 if (mode_is_signed(mode))
547 assert(! "Only 8, 16 and 32 bit stores supported");
551 cmp_attr => 'return attr_a->tv != attr_b->tv;',
555 reg_req => { in => [ "none", "none", "general_purpose" ], out => [ "none", "none" ] },
557 mips_attr_t* attr = get_mips_attr(n);
560 mode = attr->modes.load_store_mode;
562 switch (get_mode_size_bits(mode)) {
573 assert(! "Only 8, 16 and 32 bit stores supported");
578 return attr_a->stack_entity != attr_b->stack_entity;
583 reg_req => { in => [ "general_purpose" ], out => [ "general_purpose" ] },
584 emit => '. or %D1, $zero, %S1'
591 reinterpret_conv => {
592 reg_req => { in => [ "general_purpose" ], out => [ "in_r1" ] },
593 emit => '. # reinterpret %S1 -> %D1',
602 reg_req => { in => [], out => [ "none" ] },
603 emit => '. nop # nop',