3 # This is a template specification for the Firm-Backend
5 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
10 # the number of additional opcodes you want to register
11 #$additional_opcodes = 0;
20 $normal = 0; # no special type
21 $caller_save = 1; # caller save (register must be saved by the caller of a function)
22 $callee_save = 2; # callee save (register must be saved by the called function)
23 $ignore = 4; # ignore (do not assign this register)
24 $arbitrary = 8; # emitter can choose an arbitrary register of this class
25 $virtual = 16; # the register is a virtual one
26 $state = 32; # register represents a state
27 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
30 { "name" => "r0", "type" => $caller_save },
31 { "name" => "r1", "type" => $caller_save },
32 { "name" => "r2", "type" => $caller_save },
33 { "name" => "r3", "type" => $caller_save },
34 { "name" => "r4", "type" => $callee_save },
35 { "name" => "r5", "type" => $callee_save },
36 { "name" => "r6", "type" => $callee_save },
37 { "name" => "r7", "type" => $callee_save },
38 { "name" => "r8", "type" => $callee_save },
39 { "name" => "r9", "type" => $callee_save },
40 { "name" => "r10", "type" => $callee_save },
41 { "name" => "r11", "type" => $callee_save },
42 { "name" => "r12", "type" => $ignore | $callee_save }, # reserved for linker
43 { "name" => "sp", "type" => $ignore | $callee_save }, # this is our stack pointer
44 { "name" => "lr", "type" => $callee_save | $caller_save }, # this is our return address
45 { "name" => "pc", "type" => $ignore | $callee_save }, # this is our program counter
46 { name => "gp_UKNWN", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for Unknown nodes
47 { "mode" => $mode_gp }
50 { "name" => "f0", "type" => 1 },
51 { "name" => "f1", "type" => 1 },
52 { "name" => "f2", "type" => 1 },
53 { "name" => "f3", "type" => 1 },
54 { "name" => "f4", "type" => 1 },
55 { "name" => "f5", "type" => 1 },
56 { "name" => "f6", "type" => 1 },
57 { "name" => "f7", "type" => 1 },
58 { name => "fpa_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
59 { "mode" => $mode_fpa }
64 M => "${arch}_emit_mode(node);",
65 X => "${arch}_emit_shift(node);",
66 S0 => "${arch}_emit_source_register(node, 0);",
67 S1 => "${arch}_emit_source_register(node, 1);",
68 S2 => "${arch}_emit_source_register(node, 2);",
69 S3 => "${arch}_emit_source_register(node, 3);",
70 S4 => "${arch}_emit_source_register(node, 4);",
71 D0 => "${arch}_emit_dest_register(node, 0);",
72 D1 => "${arch}_emit_dest_register(node, 1);",
73 D2 => "${arch}_emit_dest_register(node, 2);",
74 C => "${arch}_emit_immediate(node);",
75 O => "${arch}_emit_offset(mode);",
78 #--------------------------------------------------#
81 # _ __ _____ __ _ _ __ ___ _ __ ___ #
82 # | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
83 # | | | | __/\ V V / | | | | (_) | |_) \__ \ #
84 # |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
87 #--------------------------------------------------#
89 $default_attr_type = "arm_attr_t";
90 $default_copy_attr = "arm_copy_attr";
93 arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
94 arm_SymConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
95 arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
96 arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
97 arm_fpaConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
101 arm_attr_t => "cmp_attr_arm",
102 arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
103 arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
104 arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
105 arm_fpaConst_attr_t => "cmp_attr_arm_fpaConst",
111 # comment => "blup di dup",
113 # emit => ". [%S0]-10",
115 # attr => "tarval *tv",
116 # init_attr => "(void) attri;",
118 # # cmp => "return 1;"
124 # reg_req => { in => [ "gp" ] },
125 # attr => "tarval *tv",
126 # init_attr => "(void) tv;",
132 # reg_req => { in => [ "gp", "gp" ] },
142 reg_req => { out => [ "gp_UKNWN:I" ] },
150 reg_req => { out => [ "fpa_UKNWN:I" ] },
155 #-----------------------------------------------------------------#
158 # _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
159 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
160 # | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
161 # |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
164 #-----------------------------------------------------------------#
166 # commutative operations
171 comment => "construct Add: Add(a, b) = Add(b, a) = a + b",
172 attr => "arm_shift_modifier mod, long shf",
173 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
174 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
175 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
176 emit => '. add %D0, %S0, %S1%X'
181 comment => "construct Add: Add(a, const) = Add(const, a) = a + const",
183 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
184 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
185 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
186 emit => '. add %D0, %S0, %C'
192 comment => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
193 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
194 emit =>'. mul %D0, %S0, %S1'
200 comment => "construct signed 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
201 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
202 emit =>'. smull %D0, %D1, %S0, %S1',
203 outs => [ "low", "high" ],
209 comment => "construct unsigned 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
210 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
211 emit =>'. umull %D0, %D1, %S0, %S1',
212 outs => [ "low", "high" ],
218 comment => "construct Mla: Mla(a, b, c) = a * b + c",
219 reg_req => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
220 emit =>'. mla %D0, %S0, %S1, %S2'
226 comment => "construct And: And(a, b) = And(b, a) = a AND b",
227 attr => "arm_shift_modifier mod, long shf",
228 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
229 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
230 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
231 emit => '. and %D0, %S0, %S1%X'
236 comment => "construct And: And(a, const) = And(const, a) = a AND const",
238 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
239 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
240 emit => '. and %D0, %S0, %C',
241 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
247 comment => "construct Or: Or(a, b) = Or(b, a) = a OR b",
248 attr => "arm_shift_modifier mod, long shf",
249 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
250 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
251 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
252 emit => '. orr %D0, %S0, %S1%X'
257 comment => "construct Or: Or(a, const) = Or(const, a) = a OR const",
259 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
260 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
261 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
262 emit => '. orr %D0, %S0, %C'
268 comment => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
269 attr => "arm_shift_modifier mod, long shf",
270 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
271 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
272 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
273 emit => '. eor %D0, %S0, %S1%X'
278 comment => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
280 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
281 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
282 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
283 emit => '. eor %D0, %S0, %C'
286 # not commutative operations
290 comment => "construct Bic: Bic(a, b) = a AND ~b",
291 attr => "arm_shift_modifier mod, long shf",
292 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
293 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
294 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
295 emit => '. bic %D0, %S0, %S1%X'
300 comment => "construct Bic: Bic(a, const) = a AND ~const",
302 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
303 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
304 emit => '. bic %D0, %S0, %C',
305 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
310 comment => "construct Sub: Sub(a, b) = a - b",
311 attr => "arm_shift_modifier mod, long shf",
312 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
313 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
314 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
315 emit => '. sub %D0, %S0, %S1%X'
320 comment => "construct Sub: Sub(a, const) = a - const",
322 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
323 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
324 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
325 emit => '. sub %D0, %S0, %C',
330 comment => "construct Rsb: Rsb(a, b) = b - a",
331 attr => "arm_shift_modifier mod, long shf",
332 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
333 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
334 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
335 emit => '. rsb %D0, %S0, %S1%X'
340 comment => "construct Rsb: Rsb(a, const) = const - a",
342 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
343 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
344 emit => '. rsb %D0, %S0, %C',
345 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
350 comment => "construct Shl: Shl(a, b) = a << b",
351 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
352 emit => '. mov %D0, %S0, lsl %S1'
357 comment => "construct Shr: Shr(a, b) = a >>u b",
358 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
359 emit => '. mov %D0, %S0, lsr %S1'
364 comment => "construct Shrs: Shrs(a, b) = a >>s b",
365 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
366 emit => '. mov %D0, %S0, asr %S1'
371 comment => "construct Ror: Ror(a, b) = a <<r>> b",
372 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
373 emit => '. mov %D0, %S0, ror %S1'
378 # comment => "construct RotL: RotL(a, b) = a ROTL b",
379 # reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
380 # emit => '. rol %S0, %S1, %D0'
385 # comment => "construct RotL: RotL(a, const) = a ROTL const",
386 # reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
387 # emit => '. rol %S0, %C, %D0'
392 comment => "construct Mov: a = b",
393 attr => "arm_shift_modifier mod, long shf",
394 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
395 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
396 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
397 emit => '. mov %D0, %S0%X'
402 comment => "represents an integer constant",
404 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
405 reg_req => { "out" => [ "gp" ] },
406 emit => '. mov %D0, %C',
407 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
412 comment => "construct Not: Not(a) = !a",
413 attr => "arm_shift_modifier mod, long shf",
414 init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
415 cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
416 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
417 emit => '. mvn %D0, %S0%X'
422 comment => "represents a negated integer constant",
424 init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
425 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
426 reg_req => { "out" => [ "gp" ] },
427 emit => '. mvn %D0, %C',
432 comment => "construct Abs: Abs(a) = |a|",
433 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
436 . rsbmi %D0, %S0, #0'
442 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
447 comment => "allocate an empty register for calculations",
448 reg_req => { "out" => [ "gp" ] },
449 emit => '. /* %D0 now available for calculations */',
450 cmp_attr => 'return 1;'
454 comment => "implements a register copy",
455 reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
461 comment => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
463 init_attr => 'attr->imm_value = imm;',
464 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
465 reg_req => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
472 comment => "represents a symbolic constant",
474 init_attr => "\tset_arm_symconst_id(res, id);",
475 reg_req => { "out" => [ "gp" ] },
476 attr_type => "arm_SymConst_attr_t",
482 comment => "construct conditional branch: CMP A, B && JMPxx LABEL",
484 attr => "int proj_num",
485 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
486 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
487 attr_type => "arm_CondJmp_attr_t",
493 comment => "construct conditional branch: TST A, B && JMPxx LABEL",
495 attr => "int proj_num",
496 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
497 reg_req => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
498 attr_type => "arm_CondJmp_attr_t",
504 comment => "construct switch",
506 attr => "int n_projs, long def_proj_num",
507 init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
508 "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
509 reg_req => { "in" => [ "gp" ], "out" => [ "none" ] },
510 attr_type => "arm_SwitchJmp_attr_t",
518 state => "exc_pinned",
519 comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
520 reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
521 emit => '. ldr %D0, [%S0, #0]',
522 outs => [ "res", "M" ],
528 state => "exc_pinned",
529 comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
530 reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
531 emit => '. ldrb %D0, [%S0, #0]',
532 outs => [ "res", "M" ],
538 state => "exc_pinned",
539 comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
540 reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
541 emit => '. ldrsb %D0, [%S0, #0]',
542 outs => [ "res", "M" ],
548 state => "exc_pinned",
549 comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
550 reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
551 emit => '. ldrh %D0, [%S0, #0]',
552 outs => [ "res", "M" ],
558 state => "exc_pinned",
559 comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
560 reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
561 emit => '. ldrsh %D0, [%S0, #0]',
562 outs => [ "res", "M" ],
568 state => "exc_pinned",
569 comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
570 reg_req => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
571 emit => '. strb %S1, [%S0, #0]',
578 state => "exc_pinned",
579 comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
580 reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
581 emit => '. strh %S1, [%S0, #0]',
588 state => "exc_pinned",
589 comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
590 reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
591 emit => '. str %S1, [%S0, #0]',
598 state => "exc_pinned",
599 comment => "construct Store: Push 4 Registers = ST ptr,val",
600 reg_req => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "sp:I|S", "none" ] },
601 emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
602 outs => [ "ptr", "M" ],
605 LoadStackM3Epilogue => {
608 state => "exc_pinned",
609 comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
610 reg_req => { "in" => [ "sp", "none" ], "out" => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
611 emit => '. ldmfd %S0, {%D0, %D1, %D2}',
612 outs => [ "res0", "res1", "res2", "M" ],
616 #---------------------------------------------------#
619 # | |_ _ __ __ _ _ __ ___ __| | ___ ___ #
620 # | _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __| #
621 # | | | |_) | (_| | | | | | (_) | (_| | __/\__ \ #
622 # |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/ #
625 #---------------------------------------------------#
627 # commutative operations
632 comment => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
633 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
634 emit => '. adf%M %D0, %S0, %S1',
639 comment => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
641 init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
642 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
643 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
644 emit => '. adf%M %D0, %S0, %C',
650 comment => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
651 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
652 emit =>'. muf%M %D0, %S0, %S1',
657 comment => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
659 init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
660 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
661 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
662 emit => '. muf%M %D0, %S0, %C',
668 comment => "construct FPA Fast Mul: Mul(a, b) = Mul(b, a) = a * b",
669 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
670 emit =>'. fml%M %D0, %S0, %S1',
676 comment => "construct FPA Max: Max(a, b) = Max(b, a) = a > b ? a : b",
677 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
678 emit =>'. fmax %S0, %S1, %D0',
684 comment => "construct FPA Min: Min(a, b) = Min(b, a) = a < b ? a : b",
685 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
686 emit =>'. fmin %S0, %S1, %D0',
689 # not commutative operations
693 comment => "construct FPA Sub: Sub(a, b) = a - b",
694 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
695 emit => '. suf%M %D0, %S0, %S1'
700 comment => "construct FPA Sub: Sub(a, b) = a - b",
702 init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
703 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
704 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
705 emit => '. suf%M %D0, %S0, %C'
710 comment => "construct FPA reverse Sub: Sub(a, b) = b - a",
711 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
712 emit => '. rsf%M %D0, %S0, %S1'
717 comment => "construct FPA reverse Sub: Sub(a, b) = b - a",
719 init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
720 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
721 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
722 emit => '. rsf%M %D0, %S0, %C'
726 comment => "construct FPA Div: Div(a, b) = a / b",
727 attr => "ir_mode *op_mode",
728 init_attr => "attr->op_mode = op_mode;",
729 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
730 emit =>'. dvf%M %D0, %S0, %S1',
731 outs => [ "res", "M" ],
735 comment => "construct FPA Div: Div(a, b) = a / b",
736 attr => "ir_mode *op_mode, long imm",
737 init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
738 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
739 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
740 emit =>'. dvf%M %D0, %S0, %C',
741 outs => [ "res", "M" ],
745 comment => "construct FPA reverse Div: Div(a, b) = b / a",
746 attr => "ir_mode *op_mode",
747 init_attr => "attr->op_mode = op_mode;",
748 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
749 emit =>'. rdf%M %D0, %S0, %S1',
750 outs => [ "res", "M" ],
754 comment => "construct FPA reverse Div: Div(a, b) = b / a",
755 attr => "ir_mode *op_mode, long imm",
756 init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
757 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
758 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
759 emit =>'. rdf%M %D0, %S0, %S1',
760 outs => [ "res", "M" ],
764 comment => "construct FPA Fast Div: Div(a, b) = a / b",
765 attr => "ir_mode *op_mode",
766 init_attr => "attr->op_mode = op_mode;",
767 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
768 emit =>'. fdv%M %D0, %S0, %S1',
769 outs => [ "res", "M" ],
773 comment => "construct FPA Fast Div: Div(a, b) = a / b",
774 attr => "ir_mode *op_mode, long imm",
775 init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
776 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
777 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
778 emit =>'. fdv%M %D0, %S0, %C',
779 outs => [ "res", "M" ],
783 comment => "construct FPA Fast reverse Div: Div(a, b) = b / a",
784 attr => "ir_mode *op_mode",
785 init_attr => "attr->op_mode = op_mode;",
786 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
787 emit =>'. frd%M %D0, %S0, %S1',
788 outs => [ "res", "M" ],
792 comment => "construct FPA Fast reverse Div: Div(a, b) = b / a",
793 attr => "ir_mode *op_mode, long imm",
794 init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
795 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
796 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
797 emit =>'. frd%M %D0, %S0, %C',
798 outs => [ "res", "M" ],
803 comment => "construct FPA Move: b = a",
804 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
805 emit => '. mvf%M %S0, %D0',
810 comment => "represents a float constant",
812 init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
813 reg_req => { "out" => [ "fpa" ] },
814 emit => '. mvf%M %D0, %C',
815 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
820 comment => "construct FPA Move Negated: b = -a",
821 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
822 emit => '. mnf%M %S0, %D0',
827 comment => "represents a float constant",
829 init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
830 reg_req => { "out" => [ "fpa" ] },
831 emit => '. mnf%M %D0, %C',
832 cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
837 comment => "construct FPA Absolute value: fAbsd(a) = |a|",
838 reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
839 emit => '. abs%M %D0, %S0',
846 comment => "construct a FPA integer->float conversion",
847 reg_req => { "in" => ["gp"], "out" => [ "fpa" ] },
848 emit => '. flt%M %D0, %S0',
853 comment => "construct a FPA float->integer conversion",
854 reg_req => { "in" => ["fpa"], "out" => [ "gp" ] },
855 emit => '. fix %D0, %S0',
861 comment => "construct floating point Compare and Branch: CMF A, B && JMPxx LABEL",
863 attr => "int proj_num",
864 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
865 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
866 attr_type => "arm_CondJmp_attr_t",
872 comment => "construct floating point Compare negative and Branch: CMF A, -B && JMPxx LABEL",
874 attr => "int proj_num",
875 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
876 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
877 attr_type => "arm_CondJmp_attr_t",
883 comment => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL",
885 attr => "int proj_num",
886 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
887 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
888 attr_type => "arm_CondJmp_attr_t",
894 comment => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL",
896 attr => "int proj_num",
897 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
898 reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
899 attr_type => "arm_CondJmp_attr_t",
907 state => "exc_pinned",
908 comment => "construct FPA Load: Load(ptr, mem) = LD ptr",
909 attr => "ir_mode *op_mode",
910 init_attr => "attr->op_mode = op_mode;",
911 reg_req => { "in" => [ "gp", "none" ], "out" => [ "fpa", "none" ] },
912 emit => '. ldf%M %D0, [%S0]',
913 outs => [ "res", "M" ],
919 state => "exc_pinned",
920 comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
921 attr => "ir_mode *op_mode",
922 init_attr => "attr->op_mode = op_mode;",
923 reg_req => { "in" => [ "gp", "fpa", "none" ], "out" => [ "none" ] },
924 emit => '. stf%M %S1, [%S0]',
931 comment => "construct fp double to 2 gp register transfer",
932 reg_req => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp", "none" ] },
933 outs => [ "low", "high", "M" ],
937 comment => "construct Add to stack pointer",
938 reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
939 emit => '. add %D0, %S0, %S1',
940 outs => [ "stack", "M" ],
944 comment => "construct Sub from stack pointer and copy to Register",
945 reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
946 ins => [ "stack", "size", "mem" ],
947 emit => ". sub %D0, %S0, %S1\n".
949 outs => [ "stack", "addr", "M" ],
954 comment => "load the TLS address",
955 reg_req => { out => [ "gp" ] },
960 # floating point constants
965 comment => "construct a floating point constant",
966 attr => "tarval *tv",
967 init_attr => "attr->tv = tv;",
968 mode => "get_tarval_mode(tv)",
969 reg_req => { "out" => [ "fpa" ] },
970 attr_type => "arm_fpaConst_attr_t",
973 #---------------------------------------------------#
976 # __ _| |_ _ __ _ __ ___ __| | ___ ___ #
977 # \ \ / / _| '_ \ | '_ \ / _ \ / _` |/ _ \/ __| #
978 # \ V /| | | |_) | | | | | (_) | (_| | __/\__ \ #
979 # \_/ |_| | .__/ |_| |_|\___/ \__,_|\___||___/ #
982 #---------------------------------------------------#