3 # This is a template specification for the Firm-Backend
5 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
10 # The node description is done as a perl hash initializer with the
11 # following structure:
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",
20 # { "type" => "type 1", "name" => "name 1" },
21 # { "type" => "type 2", "name" => "name 2" },
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"
31 # ... # (all nodes you need to describe)
33 # ); # close the %nodes initializer
35 # op_flags: flags for the operation, OPTIONAL (default is "N")
36 # the op_flags correspond to the firm irop_flags:
39 # C irop_flag_commutative
40 # X irop_flag_cfopcode
41 # I irop_flag_ip_cfopcode
44 # H irop_flag_highlevel
45 # c irop_flag_constlike
50 # I ignore for register allocation
52 # state: state of the operation, OPTIONAL (default is "floats")
54 # arity: arity of the operation, MUST NOT BE OMITTED
56 # args: the OPTIONAL arguments of the node constructor (debug, irg and block
57 # are always the first 3 arguments and are always autmatically
59 # If this key is missing the following arguments will be created:
60 # for i = 1 .. arity: ir_node *op_i
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
66 # comment: OPTIONAL comment for the node constructor
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
73 # This key is OPTIONAL. If omitted, the following constructor will
75 # if (!op_<arch>_<op-name>) assert(0);
79 # res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
82 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
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\
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" }
130 S0 => "${arch}_emit_source_register(env, node, 0);",
131 S1 => "${arch}_emit_source_register(env, node, 1);",
132 S2 => "${arch}_emit_source_register(env, node, 2);",
133 SI1 => "${arch}_emit_source_register_or_immediate(env, node, 1);",
134 D0 => "${arch}_emit_dest_register(env, node, 0);",
135 D1 => "${arch}_emit_dest_register(env, node, 1);",
136 D2 => "${arch}_emit_dest_register(env, node, 2);",
137 A0 => "${arch}_emit_load_store_address(env, node, 0);",
138 I => "${arch}_emit_immediate_suffix(env, node, 1);",
139 C => "${arch}_emit_immediate(env, node);",
140 JumpTarget => "${arch}_emit_jump_target(env, node);",
141 JumpTarget1 => "${arch}_emit_jump_target_proj(env, node, 1);",
142 JumpOrFallthrough => "${arch}_emit_jump_or_fallthrough(env, node, 0);",
145 $default_attr_type = "mips_attr_t";
146 $default_copy_attr = "mips_copy_attr";
148 $mode_gp = "mode_Iu";
151 mips_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
153 mips_immediate_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
154 "\tinit_mips_immediate_attributes(res, imm_type, entity, val);",
156 mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
157 "\tinit_mips_load_store_attributes(res, entity, offset);",
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",
166 #--------------------------------------------------#
169 # _ __ _____ __ _ _ __ ___ _ __ ___ #
170 # | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
171 # | | | | __/\ V V / | | | | (_) | |_) \__ \ #
172 # |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
175 #--------------------------------------------------#
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",
189 #-----------------------------------------------------------------#
192 # _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
193 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
194 # | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
195 # |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
198 #-----------------------------------------------------------------#
200 # commutative operations
204 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
205 ins => [ "left", "right" ],
206 emit => '. add%I%.u %D0, %S0, %SI1',
212 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
213 ins => [ "left", "right" ],
214 emit => '. and%I %D0, %S0, %SI1',
219 reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
220 ins => [ "left", "right" ],
221 outs => [ "lohi", "M" ],
222 emit => '. div %S0, %S1',
227 reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
228 ins => [ "left", "right" ],
229 outs => [ "lohi", "M" ],
230 emit => '. divu %S0, %S1',
235 reg_req => { in => [ "gp", "gp" ], out => [ "none" ] },
236 ins => [ "left", "right" ],
237 emit => '. mult %S0, %S1',
242 reg_req => { in => [ "gp", "gp" ], out => [ "none" ] },
243 ins => [ "left", "right" ],
244 emit => '. multu %S0, %S1',
250 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
251 emit => '. nor%I %D0, %S0, %SI1',
257 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
258 ins => [ "left", "right" ],
259 emit => '. or%I %D0, %S0, %SI1',
265 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
266 ins => [ "left", "right" ],
267 emit => '. sll %D0, %S0, %SI1',
273 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
274 ins => [ "left", "right" ],
275 emit => '. sra %D0, %S0, %SI1',
281 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
282 ins => [ "left", "right" ],
283 emit => '. srl %D0, %S0, %SI1',
289 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
290 ins => [ "left", "right" ],
291 emit => '. subu %D0, %S0, %S1',
297 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
298 ins => [ "left", "right" ],
299 emit => '. xor%I %D0, %S0, %SI1',
305 reg_req => { in => [ "gp" ], out => [ "gp" ] },
307 emit => '.seb %D0, %S0',
313 reg_req => { in => [ "gp" ], out => [ "gp" ] },
315 emit => '.seh %D0, %S0',
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",
331 reg_req => { in => [ "none" ], out => [ "gp" ] },
333 emit => '. mflo %D0',
339 reg_req => { in => [ "none" ], out => [ "gp" ] },
341 emit => '. mfhi %D0',
349 reg_req => { out => [ "zero" ] },
356 # | __ ) _ __ __ _ _ __ ___| |__ / / | |_ _ _ __ ___ _ __
357 # | _ \| '__/ _` | '_ \ / __| '_ \ / / | | | | | '_ ` _ \| '_ \
358 # | |_) | | | (_| | | | | (__| | | |/ / |_| | |_| | | | | | | |_) |
359 # |____/|_| \__,_|_| |_|\___|_| |_/_/ \___/ \__,_|_| |_| |_| .__/
365 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
366 emit => '. slt%I %D0, %S0, %SI1',
372 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
373 emit => '. slt%I%.u %D0, %S0, %SI1',
379 reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
380 outs => [ "false", "true" ],
381 emit => '. beq %S0, %S1, %JumpTarget1
382 . %JumpOrFallthrough'
387 reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
388 outs => [ "false", "true" ],
389 emit => '. bne %S0, %S1, %JumpTarget1
390 . %JumpOrFallthrough'
395 reg_req => { in => [ "gp" ], out => [ "none", "none" ] },
396 outs => [ "false", "true" ],
397 emit => '. bgtz %S0, %JumpTarget1
398 . %JumpOrFallthrough'
403 reg_req => { in => [ "gp" ], out => [ "none", "none" ] },
404 outs => [ "false", "true" ],
405 emit => '. blez %S0, %JumpTarget1
406 . %JumpOrFallthrough'
411 reg_req => { in => [ ], out => [ "none" ] },
412 emit => '. b %JumpTarget',
418 reg_req => { in => [ "gp" ], out => [ "none" ] },
425 reg_req => { in => [ "gp" ], out => [ "none" ] },
430 # | | ___ __ _ __| | / / ___|| |_ ___ _ __ ___
431 # | | / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
432 # | |__| (_) | (_| | (_| |/ / ___) | || (_) | | | __/
433 # |_____\___/ \__,_|\__,_/_/ |____/ \__\___/|_| \___|
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",
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",
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",
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",
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",
493 state => "exc_pinned",
494 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
495 ins => [ "ptr", "val", "mem" ],
496 emit => '. sw %S1, %A0',
498 attr_type => "mips_load_store_attr_t",
499 attr => "ir_entity *entity, long offset",
504 state => "exc_pinned",
505 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
506 ins => [ "ptr", "val", "mem" ],
507 emit => '. sh %S1, %A0',
509 attr_type => "mips_load_store_attr_t",
510 attr => "ir_entity *entity, long offset",
515 state => "exc_pinned",
516 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
517 ins => [ "ptr", "val", "mem" ],
518 emit => '. sb %S1, %A0',
520 attr_type => "mips_load_store_attr_t",
521 attr => "ir_entity *entity, long offset",
530 reg_req => { in => [], out => [ "none" ] },