3 # This is a template specification for the Firm-Backend
5 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
10 # this strings mark the beginning and the end of a comment in emit
11 $comment_string = "/*";
12 $comment_string_end = "*/";
14 # the number of additional opcodes you want to register
15 #$additional_opcodes = 0;
17 # The node description is done as a perl hash initializer with the
18 # following structure:
23 # "op_flags" => "N|L|C|X|I|F|Y|H|c|K",
24 # "irn_flags" => "R|N|I"
25 # "arity" => "0|1|2|3 ... |variable|dynamic|any",
26 # "state" => "floats|pinned|mem_pinned|exc_pinned",
28 # { "type" => "type 1", "name" => "name 1" },
29 # { "type" => "type 2", "name" => "name 2" },
32 # "comment" => "any comment for constructor",
33 # "reg_req" => { "in" => [ "reg_class|register" ], "out" => [ "reg_class|register|in_rX" ] },
34 # "cmp_attr" => "c source code for comparing node attributes",
35 # "emit" => "emit code with templates",
36 # "attr" => "attitional attribute arguments for constructor"
37 # "init_attr" => "emit attribute initialization template"
38 # "rd_constructor" => "c source code which constructs an ir_node"
41 # ... # (all nodes you need to describe)
43 # ); # close the %nodes initializer
45 # op_flags: flags for the operation, OPTIONAL (default is "N")
46 # the op_flags correspond to the firm irop_flags:
49 # C irop_flag_commutative
50 # X irop_flag_cfopcode
51 # I irop_flag_ip_cfopcode
54 # H irop_flag_highlevel
55 # c irop_flag_constlike
58 # irn_flags: special node flags, OPTIONAL (default is 0)
59 # following irn_flags are supported:
62 # I ignore for register allocation
64 # state: state of the operation, OPTIONAL (default is "floats")
66 # arity: arity of the operation, MUST NOT BE OMITTED
68 # args: the OPTIONAL arguments of the node constructor (debug, irg and block
69 # are always the first 3 arguments and are always autmatically
71 # If this key is missing the following arguments will be created:
72 # for i = 1 .. arity: ir_node *op_i
75 # outs: if a node defines more than one output, the names of the projections
76 # nodes having outs having automatically the mode mode_T
78 # comment: OPTIONAL comment for the node constructor
80 # rd_constructor: for every operation there will be a
81 # new_rd_<arch>_<op-name> function with the arguments from above
82 # which creates the ir_node corresponding to the defined operation
83 # you can either put the complete source code of this function here
85 # This key is OPTIONAL. If omitted, the following constructor will
87 # if (!op_<arch>_<op-name>) assert(0);
91 # res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
94 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
98 # 1 - caller save (register must be saved by the caller of a function)
99 # 2 - callee save (register must be saved by the called function)
100 # 4 - ignore (do not assign this register)
101 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
104 { "name" => "r0", "type" => 1 },
105 { "name" => "r1", "type" => 1 },
106 { "name" => "r2", "type" => 1 },
107 { "name" => "r3", "type" => 1 },
108 { "name" => "r4", "type" => 2 },
109 { "name" => "r5", "type" => 2 },
110 { "name" => "r6", "type" => 2 },
111 { "name" => "r7", "type" => 2 },
112 { "name" => "r8", "type" => 2 },
113 { "name" => "r9", "type" => 2 },
114 { "name" => "r10", "type" => 2 },
115 { "name" => "r11", "type" => 2 },
116 { "name" => "r12", "type" => 6 }, # reserved for linker
117 { "name" => "sp", "realname" => "r13", "type" => 6 }, # this is our stack pointer
118 { "name" => "lr", "realname" => "r14", "type" => 3 }, # this is our return address
119 { "name" => "pc", "realname" => "r15", "type" => 6 }, # this is our program counter
120 { "mode" => "mode_Iu" }
123 { "name" => "f0", "type" => 1 },
124 { "name" => "f1", "type" => 1 },
125 { "name" => "f2", "type" => 1 },
126 { "name" => "f3", "type" => 1 },
127 { "name" => "f4", "type" => 2 },
128 { "name" => "f5", "type" => 2 },
129 { "name" => "f6", "type" => 2 },
130 { "name" => "f7", "type" => 2 },
131 { "mode" => "mode_E" }
136 M => "${arch}_emit_mode(env, node);",
137 X => "${arch}_emit_shift(env, node);",
138 S0 => "${arch}_emit_source_register(env, node, 0);",
139 S1 => "${arch}_emit_source_register(env, node, 1);",
140 S2 => "${arch}_emit_source_register(env, node, 2);",
141 S3 => "${arch}_emit_source_register(env, node, 3);",
142 S4 => "${arch}_emit_source_register(env, node, 4);",
143 D0 => "${arch}_emit_dest_register(env, node, 0);",
144 D1 => "${arch}_emit_dest_register(env, node, 1);",
145 D2 => "${arch}_emit_dest_register(env, node, 2);",
146 C => "${arch}_emit_immediate(env, node);",
147 O => "${arch}_emit_offset(env, mode);",
150 #--------------------------------------------------#
153 # _ __ _____ __ _ _ __ ___ _ __ ___ #
154 # | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
155 # | | | | __/\ V V / | | | | (_) | |_) \__ \ #
156 # |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
159 #--------------------------------------------------#
163 #-----------------------------------------------------------------#
166 # _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
167 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
168 # | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
169 # |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
172 #-----------------------------------------------------------------#
174 # commutative operations
179 "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b",
180 "attr" => "arm_shift_modifier mod, tarval *shf",
181 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
182 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
183 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
184 "emit" => '. add %D0, %S0, %S1%X'
189 "comment" => "construct Add: Add(a, const) = Add(const, a) = a + const",
190 "attr" => "tarval *tv",
191 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
192 "cmp_attr" => 'return attr_a->value != attr_b->value;',
193 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
194 "emit" => '. add %D0, %S0, %C'
200 "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
201 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
202 "emit" =>'. mul %D0, %S0, %S1'
208 "comment" => "construct signed 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
209 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
210 "emit" =>'. smull %D0, %D1, %S0, %S1',
211 "outs" => [ "low", "high" ],
217 "comment" => "construct unsigned 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
218 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
219 "emit" =>'. umull %D0, %D1, %S0, %S1',
220 "outs" => [ "low", "high" ],
226 "comment" => "construct Mla: Mla(a, b, c) = a * b + c",
227 "reg_req" => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
228 "emit" =>'. mla %D0, %S0, %S1, %S2'
234 "comment" => "construct And: And(a, b) = And(b, a) = a AND b",
235 "attr" => "arm_shift_modifier mod, tarval *shf",
236 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
237 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
238 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
239 "emit" => '. and %D0, %S0, %S1%X'
244 "comment" => "construct And: And(a, const) = And(const, a) = a AND const",
245 "attr" => "tarval *tv",
246 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
247 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
248 "emit" => '. and %D0, %S0, %C',
249 "cmp_attr" => 'return attr_a->value != attr_b->value;'
255 "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b",
256 "attr" => "arm_shift_modifier mod, tarval *shf",
257 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
258 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
259 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
260 "emit" => '. orr %D0, %S0, %S1%X'
265 "comment" => "construct Or: Or(a, const) = Or(const, a) = a OR const",
266 "attr" => "tarval *tv",
267 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
268 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
269 "cmp_attr" => 'return attr_a->value != attr_b->value;',
270 "emit" => '. orr %D0, %S0, %C'
276 "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
277 "attr" => "arm_shift_modifier mod, tarval *shf",
278 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
279 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
280 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
281 "emit" => '. eor %D0, %S0, %S1%X'
286 "comment" => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
287 "attr" => "tarval *tv",
288 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
289 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
290 "cmp_attr" => 'return attr_a->value != attr_b->value;',
291 "emit" => '. eor %D0, %S0, %C'
294 # not commutative operations
298 "comment" => "construct Bic: Bic(a, b) = a AND ~b",
299 "attr" => "arm_shift_modifier mod, tarval *shf",
300 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
301 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
302 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
303 "emit" => '. bic %D0, %S0, %S1%X'
308 "comment" => "construct Bic: Bic(a, const) = a AND ~const",
309 "attr" => "tarval *tv",
310 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
311 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
312 "emit" => '. bic %D0, %S0, %C',
313 "cmp_attr" => 'return attr_a->value != attr_b->value;'
318 "comment" => "construct Sub: Sub(a, b) = a - b",
319 "attr" => "arm_shift_modifier mod, tarval *shf",
320 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
321 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
322 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
323 "emit" => '. sub %D0, %S0, %S1%X'
328 "comment" => "construct Sub: Sub(a, const) = a - const",
329 "attr" => "tarval *tv",
330 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
331 "cmp_attr" => 'return attr_a->value != attr_b->value;',
332 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
333 "emit" => '. sub %D0, %S0, %C',
338 "comment" => "construct Rsb: Rsb(a, b) = b - a",
339 "attr" => "arm_shift_modifier mod, tarval *shf",
340 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
341 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
342 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
343 "emit" => '. rsb %D0, %S0, %S1%X'
348 "comment" => "construct Rsb: Rsb(a, const) = const - a",
349 "attr" => "tarval *tv",
350 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
351 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
352 "emit" => '. rsb %D0, %S0, %C',
353 "cmp_attr" => 'return attr_a->value != attr_b->value;'
358 "comment" => "construct Shl: Shl(a, b) = a << b",
359 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
360 "emit" => '. mov %D0, %S0, lsl %S1'
365 "comment" => "construct Shr: Shr(a, b) = a >> b",
366 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
367 "emit" => '. mov %D0, %S0, lsr %S1'
372 "comment" => "construct Shrs: Shrs(a, b) = a >> b",
373 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
374 "emit" => '. mov %D0, %S0, asr %S1'
378 # "irn_flags" => "R",
379 # "comment" => "construct RotR: RotR(a, b) = a ROTR b",
380 # "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
381 # "emit" => '. mov %D0, %S0, ror %S1 /* RotR(%S0, %S1) -> %D0, (%A1, %A2) */'
382 ## "emit" => '. ror %S0, %S1, %D0'
386 # "irn_flags" => "R",
387 # "comment" => "construct RotL: RotL(a, b) = a ROTL b",
388 # "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
389 # "emit" => '. rol %S0, %S1, %D0'
393 # "irn_flags" => "R",
394 # "comment" => "construct RotL: RotL(a, const) = a ROTL const",
395 # "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
396 # "emit" => '. rol %S0, %C, %D0'
401 "comment" => "construct Mov: a = b",
402 "attr" => "arm_shift_modifier mod, tarval *shf",
403 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
404 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
405 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
406 "emit" => '. mov %D0, %S0%X'
411 "comment" => "represents an integer constant",
412 "attr" => "tarval *tv",
413 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
414 "reg_req" => { "out" => [ "gp" ] },
415 "emit" => '. mov %D0, %C',
416 "cmp_attr" => 'return attr_a->value != attr_b->value;'
421 "comment" => "construct Not: Not(a) = !a",
422 "attr" => "arm_shift_modifier mod, tarval *shf",
423 "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;',
424 "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);',
425 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
426 "emit" => '. mvn %D0, %S0%X'
431 "comment" => "represents a negated integer constant",
432 "attr" => "tarval *tv",
433 "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;',
434 "cmp_attr" => 'return attr_a->value != attr_b->value;',
435 "reg_req" => { "out" => [ "gp" ] },
436 "emit" => '. mvn %D0, %C',
441 "comment" => "construct Abs: Abs(a) = |a|",
442 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
444 '. movs %S0, %S0, #0 /* set condition flag */\n
445 . rsbmi %D0, %S0, #0'
453 "comment" => "allocate an empty register for calculations",
454 "reg_req" => { "out" => [ "gp" ] },
455 "emit" => '. /* %D0 now available for calculations */',
456 "cmp_attr" => 'return 1;'
460 "comment" => "implements a register copy",
461 "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] },
467 "comment" => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
468 "reg_req" => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
474 "comment" => "represents a symbolic constant",
475 "attr" => "const char *label",
476 "init_attr" => ' attr->symconst_label = label;',
477 "reg_req" => { "out" => [ "gp" ] },
479 ' /* should be identical but ...*/
480 return strcmp(attr_a->symconst_label, attr_b->symconst_label);'
484 "op_flags" => "L|X|Y",
485 "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL",
486 "cmp_attr" => " return arm_comp_condJmp(attr_a, attr_b);\n",
487 "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
491 "op_flags" => "L|X|Y",
492 "comment" => "construct switch",
493 "reg_req" => { "in" => [ "gp" ], "out" => [ "none" ] },
494 "cmp_attr" => " return 0;\n",
502 "state" => "exc_pinned",
503 "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
504 "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
505 "emit" => '. ldr %D0, [%S0, #0]',
506 "outs" => [ "res", "M" ],
512 "state" => "exc_pinned",
513 "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
514 "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
515 "emit" => '. ldrb %D0, [%S0, #0]',
516 "outs" => [ "res", "M" ],
522 "state" => "exc_pinned",
523 "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
524 "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
525 "emit" => '. ldrsb %D0, [%S0, #0]',
526 "outs" => [ "res", "M" ],
532 "state" => "exc_pinned",
533 "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
534 "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
535 "emit" => '. ldrh %D0, [%S0, #0]',
536 "outs" => [ "res", "M" ],
542 "state" => "exc_pinned",
543 "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
544 "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
545 "emit" => '. ldrsh %D0, [%S0, #0]',
546 "outs" => [ "res", "M" ],
552 "state" => "exc_pinned",
553 "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
554 "reg_req" => { "in" => [ "gp", "gp", "none" ] },
555 "emit" => '. strb %S1, [%S0, #0]',
562 "state" => "exc_pinned",
563 "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
564 "reg_req" => { "in" => [ "gp", "gp", "none" ] },
565 "emit" => '. strsb %S1, [%S0, #0]',
572 "state" => "exc_pinned",
573 "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
574 "reg_req" => { "in" => [ "gp", "gp", "none" ] },
575 "emit" => '. strh %S1, [%S0, #0]',
582 "state" => "exc_pinned",
583 "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
584 "reg_req" => { "in" => [ "gp", "gp", "none" ] },
585 "emit" => '. strhs %S1, [%S0, #0]',
592 "state" => "exc_pinned",
593 "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
594 "reg_req" => { "in" => [ "gp", "gp", "none" ] },
595 "emit" => '. str %S1, [%S0, #0]',
599 "StoreStackM4Inc" => {
602 "state" => "exc_pinned",
603 "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
604 "reg_req" => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "gp", "none" ] },
605 "emit" => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
606 "outs" => [ "ptr", "M" ],
612 "state" => "exc_pinned",
613 "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
614 "reg_req" => { "in" => [ "sp", "none" ], "out" => [ "gp", "gp", "gp", "none" ] },
615 "emit" => '. ldmfd %S0, {%D0, %D1, %D2}',
616 "outs" => [ "res0", "res1", "res2", "M" ],
620 #---------------------------------------------------#
623 # | |_ _ __ __ _ _ __ ___ __| | ___ ___ #
624 # | _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __| #
625 # | | | |_) | (_| | | | | | (_) | (_| | __/\__ \ #
626 # |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/ #
629 #---------------------------------------------------#
631 # commutative operations
636 "comment" => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
637 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
638 "emit" => '. adf%M %D0, %S0, %S1',
643 "comment" => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
644 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
645 "emit" =>'. muf%M %D0, %S0, %S1',
650 "comment" => "construct FPA Fast Mul: Mul(a, b) = Mul(b, a) = a * b",
651 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
652 "emit" =>'. fml%M %D0, %S0, %S1',
658 "comment" => "construct FPA Max: Max(a, b) = Max(b, a) = a > b ? a : b",
659 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
660 "emit" =>'. fmax %S0, %S1, %D0',
666 "comment" => "construct FPA Min: Min(a, b) = Min(b, a) = a < b ? a : b",
667 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
668 "emit" =>'. fmin %S0, %S1, %D0',
671 # not commutative operations
675 "comment" => "construct FPA Sub: Sub(a, b) = a - b",
676 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
677 "emit" => '. suf%M %D0, %S0, %S1'
682 "comment" => "construct FPA reverse Sub: Sub(a, b) = b - a",
683 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
684 "emit" => '. rsf%M %D0, %S0, %S1'
688 "comment" => "construct FPA Div: Div(a, b) = a / b",
689 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
690 "emit" =>'. dvf%M %D0, %S0, %S1',
694 "comment" => "construct FPA reverse Div: Div(a, b) = b / a",
695 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
696 "emit" =>'. rdf%M %D0, %S0, %S1',
700 "comment" => "construct FPA Fast Div: Div(a, b) = a / b",
701 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
702 "emit" =>'. fdv%M %D0, %S0, %S1',
706 "comment" => "construct FPA Fast reverse Div: Div(a, b) = b / a",
707 "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
708 "emit" =>'. frd%M %D0, %S0, %S1',
713 "comment" => "construct FPA Move: b = a",
714 "reg_req" => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
715 "emit" => '. mvf%M %S0, %D0',
720 "comment" => "construct FPA Move Negated: b = -a",
721 "reg_req" => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
722 "emit" => '. mnf%M %S0, %D0',
727 "comment" => "construct FPA Absolute value: fAbsd(a) = |a|",
728 "reg_req" => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
729 "emit" => '. abs%M %D0, %S0',
737 "comment" => "represents a FPA constant",
738 "attr" => "tarval *val",
739 "init_attr" => 'attr->value = val;',
740 "reg_req" => { "out" => [ "fpa" ] },
741 "emit" => '. fmov %D0, %C',
742 "cmp_attr" => 'return attr_a->value != attr_b->value;',
747 "comment" => "construct a FPA integer->float conversion",
748 "reg_req" => { "in" => ["gp"], "out" => [ "fpa" ] },
749 "emit" => '. flt%M %D0, %S0',
754 "comment" => "construct a FPA float->integer conversion",
755 "reg_req" => { "in" => ["fpa"], "out" => [ "gp" ] },
756 "emit" => '. fix %D0, %S0',
764 "state" => "exc_pinned",
765 "comment" => "construct FPA Load: Load(ptr, mem) = LD ptr",
766 "attr" => "ir_mode *op_mode",
767 "init_attr" => "attr->op_mode = op_mode;",
768 "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "fpa", "none" ] },
769 "emit" => '. ldf%M %D0, [%S0, #0]',
770 "outs" => [ "res", "M" ],
776 "state" => "exc_pinned",
777 "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
778 "attr" => "ir_mode *op_mode",
779 "init_attr" => "attr->op_mode = op_mode;",
780 "reg_req" => { "in" => [ "gp", "fpa", "none" ] },
781 "emit" => '. stf%M [%S1, #0], %S0',
788 "state" => "exc_pinned",
789 "comment" => "construct fp double to 2 gp register transfer",
790 "reg_req" => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp" ] },
791 "outs" => [ "low", "high", "M" ],
795 #---------------------------------------------------#
798 # __ _| |_ _ __ _ __ ___ __| | ___ ___ #
799 # \ \ / / _| '_ \ | '_ \ / _ \ / _` |/ _ \/ __| #
800 # \ V /| | | |_) | | | | | (_) | (_| | __/\__ \ #
801 # \_/ |_| | .__/ |_| |_|\___/ \__,_|\___||___/ #
804 #---------------------------------------------------#