7 $mode_flags = "mode_Bu";
8 $mode_fpflags = "mode_Bu";
11 $normal = 0; # no special type
12 $caller_save = 1; # caller save (register must be saved by the caller of a function)
13 $callee_save = 2; # callee save (register must be saved by the called function)
14 $ignore = 4; # ignore (do not assign this register)
15 $arbitrary = 8; # emitter can choose an arbitrary register of this class
16 $virtual = 16; # the register is a virtual one
17 $state = 32; # register represents a state
19 # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
22 { name => "g0", type => $ignore }, # hardwired 0, behaves like /dev/null
23 { name => "g1", type => $caller_save }, # temp. value
24 { name => "g2", type => $caller_save },
25 { name => "g3", type => $caller_save },
26 { name => "g4", type => $caller_save },
27 { name => "g5", type => $ignore }, # reserved by SPARC ABI
28 { name => "g6", type => $ignore }, # reserved by SPARC ABI
29 { name => "g7", type => $ignore }, # reserved by SPARC ABI
31 # window's out registers
32 { name => "o0", type => $caller_save }, # param 1 / return value from callee
33 { name => "o1", type => $caller_save }, # param 2
34 { name => "o2", type => $caller_save }, # param 3
35 { name => "o3", type => $caller_save }, # param 4
36 { name => "o4", type => $caller_save }, # param 5
37 { name => "o5", type => $caller_save }, # param 6
38 { name => "sp", type => $ignore }, # our stackpointer
39 { name => "o7", type => $ignore }, # temp. value / address of CALL instr.
41 # window's local registers
42 { name => "l0", type => 0 },
43 { name => "l1", type => 0 },
44 { name => "l2", type => 0 },
45 { name => "l3", type => 0 },
46 { name => "l4", type => 0 },
47 { name => "l5", type => 0 },
48 { name => "l6", type => 0 },
49 { name => "l7", type => 0 },
51 # window's in registers
52 { name => "i0", type => 0 }, # incoming param1 / return value to caller
53 { name => "i1", type => 0 }, # param 2
54 { name => "i2", type => 0 }, # param 3
55 { name => "i3", type => 0 }, # param 4
56 { name => "i4", type => 0 }, # param 5
57 { name => "i5", type => 0 }, # param 6
58 { name => "frame_pointer", realname => "fp", type => $ignore }, # our framepointer
59 { name => "i7", type => $ignore }, # return address - 8
63 { name => "fpflags", type => $ignore },
64 { mode => $mode_fpflags, flags => "manual_ra" }
67 { name => "flags", type => $ignore },
68 { mode => $mode_flags, flags => "manual_ra" }
71 { name => "y", type => $ignore },
72 { mode => $mode_gp, flags => "manual_ra" }
74 # fp registers can be accessed any time
76 { name => "f0", type => $caller_save },
77 { name => "f1", type => $caller_save },
78 { name => "f2", type => $caller_save },
79 { name => "f3", type => $caller_save },
80 { name => "f4", type => $caller_save },
81 { name => "f5", type => $caller_save },
82 { name => "f6", type => $caller_save },
83 { name => "f7", type => $caller_save },
84 { name => "f8", type => $caller_save },
85 { name => "f9", type => $caller_save },
86 { name => "f10", type => $caller_save },
87 { name => "f11", type => $caller_save },
88 { name => "f12", type => $caller_save },
89 { name => "f13", type => $caller_save },
90 { name => "f14", type => $caller_save },
91 { name => "f15", type => $caller_save },
92 { name => "f16", type => $caller_save },
93 { name => "f17", type => $caller_save },
94 { name => "f18", type => $caller_save },
95 { name => "f19", type => $caller_save },
96 { name => "f20", type => $caller_save },
97 { name => "f21", type => $caller_save },
98 { name => "f22", type => $caller_save },
99 { name => "f23", type => $caller_save },
100 { name => "f24", type => $caller_save },
101 { name => "f25", type => $caller_save },
102 { name => "f26", type => $caller_save },
103 { name => "f27", type => $caller_save },
104 { name => "f28", type => $caller_save },
105 { name => "f29", type => $caller_save },
106 { name => "f30", type => $caller_save },
107 { name => "f31", type => $caller_save },
113 # emit source reg or imm dep. on node's arity
114 RI => "${arch}_emit_reg_or_imm(node, -1);",
115 R1I => "${arch}_emit_reg_or_imm(node, 0);",
116 R2I => "${arch}_emit_reg_or_imm(node, 1);",
117 R3I => "${arch}_emit_reg_or_imm(node, 2);",
118 S1 => "${arch}_emit_source_register(node, 0);",
119 S2 => "${arch}_emit_source_register(node, 1);",
120 S3 => "${arch}_emit_source_register(node, 2);",
121 S4 => "${arch}_emit_source_register(node, 3);",
122 S5 => "${arch}_emit_source_register(node, 4);",
123 S6 => "${arch}_emit_source_register(node, 5);",
124 D1 => "${arch}_emit_dest_register(node, 0);",
125 D2 => "${arch}_emit_dest_register(node, 1);",
126 D3 => "${arch}_emit_dest_register(node, 2);",
127 D4 => "${arch}_emit_dest_register(node, 3);",
128 D5 => "${arch}_emit_dest_register(node, 4);",
129 D6 => "${arch}_emit_dest_register(node, 5);",
130 IM => "${arch}_emit_immediate(node);",
131 LM => "${arch}_emit_load_mode(node);",
132 SM => "${arch}_emit_store_mode(node);",
133 FPM => "${arch}_emit_fp_mode_suffix(node);",
134 FCONVS => "${arch}_emit_fp_conv_source(node);",
135 FCONVD => "${arch}_emit_fp_conv_destination(node);",
136 O => "${arch}_emit_offset(node);",
139 $default_attr_type = "sparc_attr_t";
140 $default_copy_attr = "sparc_copy_attr";
144 sparc_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
145 sparc_load_store_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
146 "\tinit_sparc_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
147 sparc_symconst_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
148 "\tinit_sparc_symconst_attributes(res, entity);",
149 sparc_jmp_cond_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
150 sparc_jmp_switch_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
151 sparc_save_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);",
152 sparc_fp_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);\n".
153 "\tinit_sparc_fp_attributes(res, fp_mode);\n",
154 sparc_fp_conv_attr_t => "\tinit_sparc_attributes(res, flags, in_reqs, exec_units, n_res);".
155 "\tinit_sparc_fp_conv_attributes(res, src_mode, dest_mode);\n",
159 sparc_attr_t => "cmp_attr_sparc",
160 sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
161 sparc_symconst_attr_t => "cmp_attr_sparc_symconst",
162 sparc_jmp_cond_attr_t => "cmp_attr_sparc_jmp_cond",
163 sparc_jmp_switch_attr_t => "cmp_attr_sparc_jmp_switch",
164 sparc_save_attr_t => "cmp_attr_sparc_save",
165 sparc_fp_attr_t => "cmp_attr_sparc_fp",
166 sparc_fp_conv_attr_t => "cmp_attr_sparc_fp_conv",
169 # addressing modes: imm, reg, reg +/- imm, reg + reg
170 # max. imm = 13 bits signed (-4096 ... 4096)
172 my %cmp_operand_constructors = (
174 attr => "int immediate_value",
175 custominit => "sparc_set_attr_imm(res, immediate_value);",
176 reg_req => { in => [ "gp" ], out => [ "flags" ] },
180 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
181 ins => [ "left", "right" ],
185 my %unop_operand_constructors = (
187 attr => "int immediate_value",
188 custominit => "sparc_set_attr_imm(res, immediate_value);",
189 reg_req => { in => [], out => [ "gp" ] },
192 reg_req => { in => [ "gp" ], out => [ "gp" ] },
196 my %binop_operand_constructors = (
198 attr => "int immediate_value",
199 custominit => "sparc_set_attr_imm(res, immediate_value);",
200 reg_req => { in => [ "gp" ], out => [ "gp" ] },
204 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
205 ins => [ "left", "right" ],
212 irn_flags => [ "rematerializable" ],
214 emit => '. add %S1, %R2I, %D1',
215 constructors => \%binop_operand_constructors,
219 irn_flags => [ "rematerializable" ],
221 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
222 emit => '. sub %S1, %R2I, %D1',
223 constructors => \%binop_operand_constructors,
229 op_flags => [ "labeled", "fragile" ],
230 state => "exc_pinned",
231 ins => [ "ptr", "mem" ],
232 outs => [ "res", "M" ],
233 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
234 attr_type => "sparc_load_store_attr_t",
235 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
236 emit => '. ld%LM [%S1%O], %D1'
240 irn_flags => [ "rematerializable" ],
241 state => "exc_pinned",
244 reg_req => { in => [], out => [ "gp" ] },
245 attr => "int immediate_value",
246 custominit => "sparc_set_attr_imm(res, immediate_value);",
250 irn_flags => [ "rematerializable" ],
251 state => "exc_pinned",
255 reg_req => { in => [ "gp" ], out => [ "gp" ] },
256 attr => "int immediate_value",
257 custominit => "sparc_set_attr_imm(res, immediate_value);",
261 op_flags => [ "labeled", "fragile" ],
263 state => "exc_pinned",
264 ins => [ "ptr", "val", "mem" ],
266 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
267 attr_type => "sparc_load_store_attr_t",
268 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
269 emit => '. st%SM %S2, [%S1%O]'
273 irn_flags => [ "rematerializable" ],
275 emit => '. mov %R1I, %D1',
277 constructors => \%unop_operand_constructors,
282 in => [ "sp", "none"],
283 out => [ "sp:I|S", "frame_pointer:I", "none" ]
285 ins => [ "stack", "mem" ],
286 outs => [ "stack", "frame", "mem" ],
287 attr => "int initial_stacksize",
288 attr_type => "sparc_save_attr_t",
289 init_attr => "\tinit_sparc_save_attributes(res, initial_stacksize);",
293 reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
294 ins => [ "stack", "size", "mem" ],
295 outs => [ "stack", "addr", "M" ],
296 emit => ". sub %S1, %S2, %D1\n",
300 reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
301 ins => [ "stack", "size", "mem" ],
302 outs => [ "stack", "M" ],
303 emit => ". add %S1, %S2, %D1\n",
307 op_flags => [ "constlike" ],
308 irn_flags => [ "rematerializable" ],
309 attr => "ir_entity *entity",
310 reg_req => { out => [ "gp" ] },
311 attr_type => "sparc_symconst_attr_t",
316 op_flags => [ "constlike" ],
317 irn_flags => [ "rematerializable" ],
318 attr => "ir_entity *entity",
319 reg_req => { in => [ "gp" ], out => [ "gp" ] },
321 attr_type => "sparc_symconst_attr_t",
326 op_flags => [ "labeled", "cfopcode", "forking" ],
329 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
330 attr => "int proj_num, bool is_unsigned",
331 attr_type => "sparc_jmp_cond_attr_t",
332 init_attr => "\tinit_sparc_jmp_cond_attr(res, proj_num, is_unsigned);",
337 op_flags => [ "cfopcode" ],
338 irn_flags => [ "simple_jump" ],
339 reg_req => { out => [ "none" ] },
344 irn_flags => [ "modify_flags" ],
345 state => "exc_pinned",
347 out_arity => "variable",
350 attr => "ir_entity *entity, long offset",
351 custominit => "get_sparc_attr(res)->immediate_value_entity = entity;",
353 out_arity => "variable",
357 out_arity => "variable",
363 irn_flags => [ "rematerializable", "modify_flags" ],
364 emit => '. cmp %S1, %R2I',
365 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
366 ins => [ "left", "right" ],
368 constructors => \%cmp_operand_constructors,
372 irn_flags => [ "rematerializable", "modify_flags" ],
375 reg_req => { in => [ "gp" ], out => [ "flags" ] },
380 op_flags => [ "labeled", "cfopcode", "forking" ],
383 attr => "int n_projs, long def_proj_num",
384 init_attr => "\tset_sparc_jmp_switch_n_projs(res, n_projs);\n".
385 "\tset_sparc_jmp_switch_default_proj_num(res, def_proj_num);",
386 reg_req => { in => [ "gp" ], out => [ "none" ] },
387 attr_type => "sparc_jmp_switch_attr_t",
391 irn_flags => [ "rematerializable" ],
393 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
394 emit => '. sll %S1, %R2I, %D1',
395 constructors => \%binop_operand_constructors,
399 irn_flags => [ "rematerializable" ],
401 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
402 emit => '. srl %S1, %R2I, %D1',
403 constructors => \%binop_operand_constructors,
407 irn_flags => [ "rematerializable" ],
409 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
410 emit => '. sra %S1, %R2I, %D1',
411 constructors => \%binop_operand_constructors,
415 irn_flags => [ "rematerializable" ],
417 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
418 emit => '. and %S1, %R2I, %D1',
419 constructors => \%binop_operand_constructors,
423 irn_flags => [ "rematerializable" ],
425 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
426 emit => '. or %S1, %R2I, %D1',
427 constructors => \%binop_operand_constructors,
431 irn_flags => [ "rematerializable" ],
433 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
434 emit => '. xor %S1, %R2I, %D1',
435 constructors => \%binop_operand_constructors,
439 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "y" ] },
440 constructors => \%binop_operand_constructors,
441 emit => '. mul %S1, %R2I, %D1',
446 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
447 outs => [ "low", "high" ],
448 constructors => \%binop_operand_constructors,
451 # The div instructions are kinda hacky. Things to improve:
452 # * Make high-value input explicitely. Either as a gp at first or ideally
453 # as an explicit y-register
456 irn_flags => [ "rematerializable" ],
457 state => "exc_pinned",
458 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "none" ] },
459 ins => [ "dividend_low", "divisor" ],
460 outs => [ "res", "M" ],
461 constructors => \%binop_operand_constructors,
465 irn_flags => [ "rematerializable" ],
466 state => "exc_pinned",
467 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "none" ] },
468 ins => [ "dividend_low", "divisor" ],
469 outs => [ "res", "M" ],
470 constructors => \%binop_operand_constructors,
474 irn_flags => [ "rematerializable" ],
476 reg_req => { in => [ "gp" ], out => [ "gp" ] },
477 emit => ". sub %%g0, %S1, %D1"
481 irn_flags => [ "rematerializable" ],
483 reg_req => { in => [ "gp" ], out => [ "gp" ] },
484 emit => '. xnor %S1, %%g0, %D1'
488 op_flags => [ "keep" ],
489 reg_req => { in => [], out => [ "none" ] },
494 op_flags => [ "commutative" ],
495 irn_flags => [ "rematerializable" ],
496 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
497 emit => '. fadd%FPM %S1, %S2, %D1',
498 attr_type => "sparc_fp_attr_t",
499 attr => "ir_mode *fp_mode",
504 irn_flags => [ "rematerializable" ],
505 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
506 emit => '. fsub%FPM %S1, %S2, %D1',
507 attr_type => "sparc_fp_attr_t",
508 attr => "ir_mode *fp_mode",
513 irn_flags => [ "rematerializable" ],
514 op_flags => [ "commutative" ],
515 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
516 emit =>'. fmul%FPM %S1, %S2, %D1',
517 attr_type => "sparc_fp_attr_t",
518 attr => "ir_mode *fp_mode",
523 irn_flags => [ "rematerializable" ],
524 reg_req => { in => [ "fp", "fp" ], out => [ "fp", "none" ] },
525 emit => '. fdiv%FPM %S1, %S2, %D1',
526 attr_type => "sparc_fp_attr_t",
527 attr => "ir_mode *fp_mode",
528 outs => [ "res", "M" ],
532 irn_flags => [ "rematerializable" ],
533 reg_req => { in => [ "fp" ], out => [ "fp" ] },
534 emit => '. fneg%FPM %S1, %D1',
535 attr_type => "sparc_fp_attr_t",
536 attr => "ir_mode *fp_mode",
541 irn_flags => [ "rematerializable" ],
542 reg_req => { in => [ "fp" ], out => [ "fp" ] },
543 emit => '. fabs%FPM %S1, %D1',
544 attr_type => "sparc_fp_attr_t",
545 attr => "ir_mode *fp_mode",
550 irn_flags => [ "rematerializable" ],
551 reg_req => { in => [ "fp" ], out => [ "fp" ] },
552 emit => '. f%FCONVS.to%FCONVD %S1, %D1',
553 attr_type => "sparc_fp_conv_attr_t",
554 attr => "ir_mode *src_mode, ir_mode *dest_mode",
559 irn_flags => [ "rematerializable" ],
560 reg_req => { in => [ "gp" ], out => [ "fp" ] },
561 emit => '. fito%FPM %S1, %D1',
562 attr_type => "sparc_fp_attr_t",
563 attr => "ir_mode *fp_mode",
568 irn_flags => [ "rematerializable" ],
569 reg_req => { in => [ "fp" ], out => [ "gp" ] },
570 emit => '. f%FPM.toi %S1, %D1',
571 attr_type => "sparc_fp_attr_t",
572 attr => "ir_mode *fp_mode",
577 op_flags => [ "labeled", "fragile" ],
578 state => "exc_pinned",
579 ins => [ "ptr", "mem" ],
580 outs => [ "res", "M" ],
581 reg_req => { in => [ "gp", "none" ], out => [ "fp", "none" ] },
582 attr_type => "sparc_load_store_attr_t",
583 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
584 emit => '. ld [%S1%O], %D1'
588 op_flags => [ "labeled", "fragile" ],
589 state => "exc_pinned",
590 ins => [ "ptr", "val", "mem" ],
592 reg_req => { in => [ "gp", "fp", "none" ], out => [ "none" ] },
593 attr_type => "sparc_load_store_attr_t",
594 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
595 emit => '. st %S2, [%S1%O]',