]>
Commit | Line | Data |
---|---|---|
dbe7ab63 | 1 | diff -Naurp gcc/config/avr/avr.c gcc/config/avr/avr.c |
6ef8d480 PZ |
2 | --- gcc/config/avr/avr.c 2011-10-27 17:53:42.000000000 +0530 |
3 | +++ gcc/config/avr/avr.c 2011-10-27 18:00:50.000000000 +0530 | |
4 | @@ -29,6 +29,7 @@ | |
2bc38036 | 5 | #include "insn-config.h" |
6 | #include "conditions.h" | |
7 | #include "insn-attr.h" | |
8 | +#include "insn-codes.h" | |
9 | #include "flags.h" | |
10 | #include "reload.h" | |
11 | #include "tree.h" | |
6ef8d480 | 12 | @@ -38,7 +39,9 @@ |
2bc38036 | 13 | #include "obstack.h" |
14 | #include "function.h" | |
15 | #include "recog.h" | |
16 | +#include "optabs.h" | |
17 | #include "ggc.h" | |
18 | +#include "langhooks.h" | |
19 | #include "tm_p.h" | |
20 | #include "target.h" | |
21 | #include "target-def.h" | |
6ef8d480 | 22 | @@ -90,6 +93,8 @@ static bool avr_rtx_costs (rtx, int, int |
dbe7ab63 | 23 | static int avr_address_cost (rtx, bool); |
2bc38036 | 24 | static bool avr_return_in_memory (const_tree, const_tree); |
25 | static struct machine_function * avr_init_machine_status (void); | |
26 | +static void avr_init_builtins (void); | |
27 | +static rtx avr_expand_builtin (tree, rtx, rtx, enum machine_mode, int); | |
dbe7ab63 | 28 | static rtx avr_builtin_setjmp_frame_value (void); |
29 | static bool avr_hard_regno_scratch_ok (unsigned int); | |
30 | static unsigned int avr_case_values_threshold (void); | |
6ef8d480 | 31 | @@ -241,6 +246,13 @@ static const struct default_options avr_ |
dbe7ab63 | 32 | #undef TARGET_SCALAR_MODE_SUPPORTED_P |
33 | #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p | |
2bc38036 | 34 | |
35 | +#undef TARGET_INIT_BUILTINS | |
36 | +#define TARGET_INIT_BUILTINS avr_init_builtins | |
dbe7ab63 | 37 | + |
2bc38036 | 38 | +#undef TARGET_EXPAND_BUILTIN |
39 | +#define TARGET_EXPAND_BUILTIN avr_expand_builtin | |
40 | + | |
dbe7ab63 | 41 | + |
42 | /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */ | |
43 | static bool | |
44 | avr_scalar_mode_supported_p (enum machine_mode mode) | |
6ef8d480 | 45 | @@ -7506,4 +7518,237 @@ unsigned int avr_case_values_threshold ( |
dbe7ab63 | 46 | return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17; |
2bc38036 | 47 | } |
48 | ||
49 | +/* Codes for all the AVR builtins. */ | |
50 | + | |
51 | +enum avr_builtins | |
52 | +{ | |
53 | + AVR_BUILTIN_SEI, | |
54 | + AVR_BUILTIN_CLI, | |
55 | + AVR_BUILTIN_WDR, | |
56 | + AVR_BUILTIN_SLEEP, | |
57 | + AVR_BUILTIN_SWAP, | |
58 | + AVR_BUILTIN_FMUL, | |
59 | + AVR_BUILTIN_FMULS, | |
60 | + AVR_BUILTIN_FMULSU, | |
61 | + AVR_BUILTIN_DELAY_CYCLES | |
62 | +}; | |
63 | + | |
64 | +#define def_builtin(NAME, TYPE, CODE) \ | |
65 | +do { \ | |
66 | + add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \ | |
67 | + NULL, NULL_TREE); \ | |
68 | +} while (0) | |
69 | + | |
70 | +/* Set up all builtin functions for this target. */ | |
71 | + | |
72 | +static void | |
73 | +avr_init_builtins (void) | |
74 | +{ | |
75 | + tree void_ftype_void | |
76 | + = build_function_type (void_type_node, void_list_node); | |
77 | + tree uchar_ftype_uchar | |
78 | + = build_function_type_list (unsigned_char_type_node, | |
79 | + unsigned_char_type_node, | |
80 | + NULL_TREE); | |
81 | + tree uint_ftype_uchar_uchar | |
82 | + = build_function_type_list (unsigned_type_node, | |
83 | + unsigned_char_type_node, | |
84 | + unsigned_char_type_node, | |
85 | + NULL_TREE); | |
86 | + tree int_ftype_char_char | |
87 | + = build_function_type_list (integer_type_node, | |
88 | + char_type_node, | |
89 | + char_type_node, | |
90 | + NULL_TREE); | |
91 | + tree int_ftype_char_uchar | |
92 | + = build_function_type_list (integer_type_node, | |
93 | + char_type_node, | |
94 | + unsigned_char_type_node, | |
95 | + NULL_TREE); | |
96 | + tree void_ftype_ulong | |
97 | + = build_function_type_list (void_type_node, | |
98 | + long_unsigned_type_node, | |
99 | + NULL_TREE); | |
100 | + | |
101 | + def_builtin ("__builtin_avr_sei", void_ftype_void, AVR_BUILTIN_SEI); | |
102 | + def_builtin ("__builtin_avr_cli", void_ftype_void, AVR_BUILTIN_CLI); | |
103 | + def_builtin ("__builtin_avr_wdr", void_ftype_void, AVR_BUILTIN_WDR); | |
104 | + def_builtin ("__builtin_avr_sleep", void_ftype_void, AVR_BUILTIN_SLEEP); | |
105 | + | |
106 | + if (AVR_HAVE_MUL) | |
107 | + { | |
108 | + def_builtin ("__builtin_avr_fmul", uint_ftype_uchar_uchar, | |
109 | + AVR_BUILTIN_FMUL); | |
110 | + def_builtin ("__builtin_avr_fmuls", int_ftype_char_char, | |
111 | + AVR_BUILTIN_FMULS); | |
112 | + def_builtin ("__builtin_avr_fmulsu", int_ftype_char_uchar, | |
113 | + AVR_BUILTIN_FMULSU); | |
114 | + } | |
115 | + | |
116 | + def_builtin ("__builtin_avr_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP); | |
117 | + def_builtin ("__builtin_avr_delay_cycles", void_ftype_ulong, | |
118 | + AVR_BUILTIN_DELAY_CYCLES); | |
119 | +} | |
120 | + | |
121 | +struct builtin_description | |
122 | +{ | |
123 | + const enum insn_code icode; | |
124 | + const char *const name; | |
125 | + const enum avr_builtins code; | |
126 | +}; | |
127 | + | |
128 | +static const struct builtin_description bdesc_1arg[] = | |
129 | +{ | |
130 | + { CODE_FOR_swap, "__builtin_avr_swap", AVR_BUILTIN_SWAP } | |
131 | +}; | |
132 | + | |
133 | +static const struct builtin_description bdesc_2arg[] = | |
134 | +{ | |
135 | + { CODE_FOR_fmul, "__builtin_avr_fmul", AVR_BUILTIN_FMUL }, | |
136 | + { CODE_FOR_fmuls, "__builtin_avr_fmuls", AVR_BUILTIN_FMULS }, | |
137 | + { CODE_FOR_fmulsu, "__builtin_avr_fmulsu", AVR_BUILTIN_FMULSU } | |
138 | +}; | |
139 | + | |
140 | +/* Subroutine of avr_expand_builtin to take care of unop insns. */ | |
141 | + | |
142 | +static rtx | |
143 | +avr_expand_unop_builtin (enum insn_code icode, tree exp, | |
144 | + rtx target) | |
145 | +{ | |
146 | + rtx pat; | |
147 | + tree arg0 = CALL_EXPR_ARG (exp, 0); | |
148 | + rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); | |
149 | + enum machine_mode op0mode = GET_MODE (op0); | |
150 | + enum machine_mode tmode = insn_data[icode].operand[0].mode; | |
151 | + enum machine_mode mode0 = insn_data[icode].operand[1].mode; | |
152 | + | |
153 | + if (! target | |
154 | + || GET_MODE (target) != tmode | |
155 | + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) | |
156 | + target = gen_reg_rtx (tmode); | |
157 | + | |
158 | + if (op0mode == SImode && mode0 == HImode) | |
159 | + { | |
160 | + op0mode = HImode; | |
161 | + op0 = gen_lowpart (HImode, op0); | |
162 | + } | |
163 | + gcc_assert (op0mode == mode0 || op0mode == VOIDmode); | |
164 | + | |
165 | + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) | |
166 | + op0 = copy_to_mode_reg (mode0, op0); | |
167 | + | |
168 | + pat = GEN_FCN (icode) (target, op0); | |
169 | + if (! pat) | |
170 | + return 0; | |
171 | + emit_insn (pat); | |
172 | + return target; | |
173 | +} | |
174 | + | |
175 | +/* Subroutine of avr_expand_builtin to take care of binop insns. */ | |
176 | + | |
177 | +static rtx | |
178 | +avr_expand_binop_builtin (enum insn_code icode, tree exp, rtx target) | |
179 | +{ | |
180 | + rtx pat; | |
181 | + tree arg0 = CALL_EXPR_ARG (exp, 0); | |
182 | + tree arg1 = CALL_EXPR_ARG (exp, 1); | |
183 | + rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); | |
184 | + rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); | |
185 | + enum machine_mode op0mode = GET_MODE (op0); | |
186 | + enum machine_mode op1mode = GET_MODE (op1); | |
187 | + enum machine_mode tmode = insn_data[icode].operand[0].mode; | |
188 | + enum machine_mode mode0 = insn_data[icode].operand[1].mode; | |
189 | + enum machine_mode mode1 = insn_data[icode].operand[2].mode; | |
190 | + | |
191 | + if (! target | |
192 | + || GET_MODE (target) != tmode | |
193 | + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) | |
194 | + target = gen_reg_rtx (tmode); | |
195 | + | |
196 | + if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode) | |
197 | + { | |
dbe7ab63 | 198 | + op0mode = HImode; |
199 | + op0 = gen_lowpart (HImode, op0); | |
200 | + } | |
201 | + if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode) | |
202 | + { | |
203 | + op1mode = HImode; | |
204 | + op1 = gen_lowpart (HImode, op1); | |
205 | + } | |
206 | + /* In case the insn wants input operands in modes different from | |
207 | + the result, abort. */ | |
208 | + gcc_assert ((op0mode == mode0 || op0mode == VOIDmode) | |
209 | + && (op1mode == mode1 || op1mode == VOIDmode)); | |
210 | + | |
211 | + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) | |
212 | + op0 = copy_to_mode_reg (mode0, op0); | |
213 | + if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) | |
214 | + op1 = copy_to_mode_reg (mode1, op1); | |
215 | + | |
216 | + pat = GEN_FCN (icode) (target, op0, op1); | |
217 | + if (! pat) | |
218 | + return 0; | |
219 | + | |
220 | + emit_insn (pat); | |
221 | + return target; | |
222 | +} | |
223 | + | |
224 | +/* Expand an expression EXP that calls a built-in function, | |
225 | + with result going to TARGET if that's convenient | |
226 | + (and in mode MODE if that's convenient). | |
227 | + SUBTARGET may be used as the target for computing one of EXP's operands. | |
228 | + IGNORE is nonzero if the value is to be ignored. */ | |
229 | + | |
230 | +static rtx | |
231 | +avr_expand_builtin (tree exp, rtx target, | |
232 | + rtx subtarget ATTRIBUTE_UNUSED, | |
233 | + enum machine_mode mode ATTRIBUTE_UNUSED, | |
234 | + int ignore ATTRIBUTE_UNUSED) | |
235 | +{ | |
236 | + size_t i; | |
237 | + const struct builtin_description *d; | |
238 | + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); | |
239 | + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); | |
240 | + rtx pat; | |
241 | + tree arg0; | |
242 | + rtx op0; | |
243 | + | |
244 | + switch (fcode) | |
245 | + { | |
246 | + case AVR_BUILTIN_SEI: | |
247 | + emit_insn (gen_enable_interrupt ()); | |
248 | + return 0; | |
249 | + case AVR_BUILTIN_CLI: | |
250 | + emit_insn (gen_disable_interrupt ()); | |
251 | + return 0; | |
252 | + case AVR_BUILTIN_WDR: | |
253 | + emit_insn (gen_wdr ()); | |
254 | + return 0; | |
255 | + case AVR_BUILTIN_SLEEP: | |
256 | + emit_insn (gen_sleep ()); | |
257 | + return 0; | |
258 | + case AVR_BUILTIN_DELAY_CYCLES: | |
259 | + { | |
260 | + arg0 = CALL_EXPR_ARG (exp, 0); | |
261 | + op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); | |
262 | + | |
263 | + if (!CONSTANT_P (op0)) | |
264 | + error ("__builtin_avr_delay_cycles expects an integer constant."); | |
265 | + | |
266 | + emit_insn (gen_delay_cycles (op0)); | |
267 | + return 0; | |
268 | + } | |
269 | + } | |
270 | + | |
271 | + for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) | |
272 | + if (d->code == fcode) | |
273 | + return avr_expand_unop_builtin (d->icode, exp, target); | |
274 | + | |
275 | + for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) | |
276 | + if (d->code == fcode) | |
277 | + return avr_expand_binop_builtin (d->icode, exp, target); | |
278 | + | |
279 | + gcc_unreachable (); | |
280 | +} | |
281 | + | |
282 | #include "gt-avr.h" | |
283 | diff -Naurp gcc/config/avr/avr.md gcc/config/avr/avr.md | |
6ef8d480 PZ |
284 | --- gcc/config/avr/avr.md 2011-10-27 17:53:20.000000000 +0530 |
285 | +++ gcc/config/avr/avr.md 2011-10-27 18:00:50.000000000 +0530 | |
286 | @@ -50,14 +50,29 @@ | |
dbe7ab63 | 287 | |
288 | (UNSPEC_STRLEN 0) | |
289 | (UNSPEC_INDEX_JMP 1) | |
290 | - (UNSPEC_SEI 2) | |
291 | - (UNSPEC_CLI 3) | |
292 | + (UNSPEC_SWAP 2) | |
293 | + (UNSPEC_FMUL 3) | |
294 | + (UNSPEC_FMULS 4) | |
295 | + (UNSPEC_FMULSU 5) | |
296 | + | |
297 | ||
298 | (UNSPECV_PROLOGUE_SAVES 0) | |
299 | (UNSPECV_EPILOGUE_RESTORES 1) | |
300 | (UNSPECV_WRITE_SP_IRQ_ON 2) | |
301 | (UNSPECV_WRITE_SP_IRQ_OFF 3) | |
302 | - (UNSPECV_GOTO_RECEIVER 4)]) | |
303 | + (UNSPECV_GOTO_RECEIVER 4) | |
304 | + (UNSPECV_SEI 5) | |
305 | + (UNSPECV_CLI 6) | |
306 | + (UNSPECV_NOP 7) | |
307 | + (UNSPECV_NOP2 8) | |
308 | + (UNSPECV_SLEEP 9) | |
309 | + (UNSPECV_WDR 10) | |
310 | + | |
311 | + (UNSPECV_DELAY_CYCLES 100) | |
312 | + (UNSPECV_DELAY_CYCLES_1 101) | |
313 | + (UNSPECV_DELAY_CYCLES_2 102) | |
314 | + (UNSPECV_DELAY_CYCLES_3 103) | |
315 | + (UNSPECV_DELAY_CYCLES_4 104)]) | |
316 | ||
317 | (include "predicates.md") | |
318 | (include "constraints.md") | |
6ef8d480 | 319 | @@ -2820,13 +2835,6 @@ |
dbe7ab63 | 320 | (const_int 1)) |
321 | (const_int 3)])]) | |
322 | ||
323 | -(define_insn "nop" | |
324 | - [(const_int 0)] | |
325 | - "" | |
326 | - "nop" | |
327 | - [(set_attr "cc" "none") | |
328 | - (set_attr "length" "1")]) | |
329 | - | |
330 | ; indirect jump | |
331 | ||
332 | (define_expand "indirect_jump" | |
6ef8d480 | 333 | @@ -3220,7 +3228,7 @@ |
dbe7ab63 | 334 | |
335 | ;; Enable Interrupts | |
336 | (define_insn "enable_interrupt" | |
337 | - [(unspec [(const_int 0)] UNSPEC_SEI)] | |
338 | + [(unspec_volatile [(const_int 0)] UNSPECV_SEI)] | |
339 | "" | |
340 | "sei" | |
341 | [(set_attr "length" "1") | |
6ef8d480 | 342 | @@ -3229,7 +3237,7 @@ |
dbe7ab63 | 343 | |
344 | ;; Disable Interrupts | |
345 | (define_insn "disable_interrupt" | |
346 | - [(unspec [(const_int 0)] UNSPEC_CLI)] | |
347 | + [(unspec_volatile [(const_int 0)] UNSPECV_CLI)] | |
348 | "" | |
349 | "cli" | |
350 | [(set_attr "length" "1") | |
6ef8d480 | 351 | @@ -3329,3 +3337,219 @@ |
dbe7ab63 | 352 | expand_epilogue (); |
353 | DONE; | |
354 | }") | |
355 | + | |
356 | +;;delay_cycles_delay_cycles_delay_cycles_delay_cycles_delay_cycles_delay | |
357 | +;; delay_cycles | |
358 | + | |
359 | +(define_expand "delay_cycles" | |
360 | + [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")] | |
361 | + UNSPECV_DELAY_CYCLES)] | |
362 | + "" | |
363 | + " | |
364 | + rtx loop_reg; | |
365 | + unsigned int cycles = INTVAL (operands[0]); | |
366 | + if (IN_RANGE(cycles, 83886082, 0xFFFFFFFF)) | |
367 | + { | |
368 | + unsigned int loop_count = ((cycles - 9) / 6) + 1; | |
369 | + unsigned int cycles_used = (((loop_count - 1) * 6) + 9); | |
370 | + emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode))); | |
371 | + cycles -= cycles_used; | |
372 | + } | |
373 | + if (IN_RANGE(cycles, 262145, 83886081)) | |
374 | + { | |
375 | + unsigned int loop_count = ((cycles - 7) / 5) + 1; | |
376 | + if (loop_count > 0xFFFFFF) | |
377 | + loop_count = 0xFFFFFF; | |
378 | + unsigned int cycles_used = (((loop_count - 1) * 5) + 7); | |
379 | + emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode))); | |
380 | + cycles -= cycles_used; | |
381 | + } | |
382 | + if (IN_RANGE(cycles, 768, 262144)) | |
383 | + { | |
384 | + unsigned int loop_count = ((cycles - 5) / 4) + 1; | |
385 | + if (loop_count > 0xFFFF) | |
386 | + loop_count = 0xFFFF; | |
387 | + unsigned int cycles_used = (((loop_count - 1) * 4) + 5); | |
388 | + emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode))); | |
389 | + cycles -= cycles_used; | |
2bc38036 | 390 | + } |
dbe7ab63 | 391 | + if (IN_RANGE(cycles, 6, 767)) |
2bc38036 | 392 | + { |
dbe7ab63 | 393 | + unsigned int loop_count = (cycles/ 3); |
394 | + if (loop_count > 255) | |
395 | + loop_count = 255; | |
396 | + unsigned int cycles_used = (loop_count * 3); | |
397 | + emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode))); | |
398 | + cycles -= cycles_used; | |
2bc38036 | 399 | + } |
dbe7ab63 | 400 | + while (cycles >= 2) |
401 | + { | |
402 | + emit_insn (gen_nop2 ()); | |
403 | + cycles -= 2; | |
404 | + } | |
405 | + if (cycles == 1) | |
406 | + { | |
407 | + emit_insn (gen_nop ()); | |
408 | + cycles--; | |
409 | + } | |
410 | + DONE; | |
411 | + ") | |
2bc38036 | 412 | + |
dbe7ab63 | 413 | +(define_insn "delay_cycles_1" |
414 | +[(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_1) | |
415 | + (match_operand:QI 0 "immediate_operand" "") | |
416 | + (clobber (match_scratch:QI 1 "=&d"))] | |
417 | + "" | |
418 | + " ldi %1,lo8(%0) | |
419 | + 1:dec %1 | |
420 | + brne 1b" | |
421 | + [(set_attr "length" "3") | |
422 | + (set_attr "cc" "clobber")]) | |
2bc38036 | 423 | + |
dbe7ab63 | 424 | +(define_insn "delay_cycles_2" |
425 | + [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_2) | |
426 | + (match_operand:HI 0 "immediate_operand" "") | |
427 | + (clobber (match_scratch:HI 1 "=&w"))] | |
428 | + "" | |
429 | + " ldi %A1,lo8(%0) | |
430 | + ldi %B1,hi8(%0) | |
431 | + 1:sbiw %A1,1 | |
432 | + brne 1b" | |
433 | + [(set_attr "length" "4") | |
434 | + (set_attr "cc" "clobber")]) | |
2bc38036 | 435 | + |
dbe7ab63 | 436 | +(define_insn "delay_cycles_3" |
437 | + [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_3) | |
438 | + (match_operand:SI 0 "immediate_operand" "") | |
439 | + (clobber (match_scratch:SI 1 "=&d"))] | |
440 | + "" | |
441 | + " ldi %A1,lo8(%0) | |
442 | + ldi %B1,hi8(%0) | |
443 | + ldi %C1,hlo8(%0) | |
444 | + 1:subi %A1,1 | |
445 | + sbci %B1,0 | |
446 | + sbci %C1,0 | |
447 | + brne 1b" | |
448 | + [(set_attr "length" "7") | |
449 | + (set_attr "cc" "clobber")]) | |
2bc38036 | 450 | + |
dbe7ab63 | 451 | +(define_insn "delay_cycles_4" |
452 | + [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_4) | |
453 | + (match_operand:SI 0 "immediate_operand" "") | |
454 | + (clobber (match_scratch:SI 1 "=&d"))] | |
455 | + "" | |
456 | + " ldi %A1,lo8(%0) | |
457 | + ldi %B1,hi8(%0) | |
458 | + ldi %C1,hlo8(%0) | |
459 | + ldi %D1,hhi8(%0) | |
460 | + 1:subi %A1,1 | |
461 | + sbci %B1,0 | |
462 | + sbci %C1,0 | |
463 | + sbci %D1,0 | |
464 | + brne 1b" | |
465 | + [(set_attr "length" "9") | |
466 | + (set_attr "cc" "clobber")]) | |
2bc38036 | 467 | + |
dbe7ab63 | 468 | +;; CPU instructions |
2bc38036 | 469 | + |
dbe7ab63 | 470 | +;; NOP |
471 | +(define_insn "nop" | |
472 | + [(unspec_volatile [(const_int 0)] UNSPECV_NOP)] | |
473 | + "" | |
474 | + "nop" | |
475 | + [(set_attr "length" "1") | |
476 | + (set_attr "cc" "none")]) | |
2bc38036 | 477 | + |
dbe7ab63 | 478 | +;; NOP2 |
479 | +(define_insn "nop2" | |
480 | + [(unspec_volatile [(const_int 0)] UNSPECV_NOP2)] | |
481 | + "" | |
482 | + "rjmp ." | |
483 | + [(set_attr "length" "1") | |
484 | + (set_attr "cc" "none")]) | |
2bc38036 | 485 | + |
dbe7ab63 | 486 | +;; SEI, Enable Interrupts |
487 | +;(define_insn "sei" | |
488 | +; [(unspec_volatile [(const_int 0)] UNSPECV_SEI)] | |
489 | +; "" | |
490 | +; "sei" | |
491 | +; [(set_attr "length" "1") | |
492 | +; (set_attr "cc" "none") | |
493 | +; ]) | |
2bc38036 | 494 | + |
dbe7ab63 | 495 | +;; CLI, Disable Interrupts |
496 | +;(define_insn "cli" | |
497 | +; [(unspec_volatile [(const_int 0)] UNSPECV_CLI)] | |
498 | +; "" | |
499 | +; "cli" | |
500 | +; [(set_attr "length" "1") | |
501 | +; (set_attr "cc" "none") | |
502 | +; ]) | |
2bc38036 | 503 | + |
dbe7ab63 | 504 | +;; SLEEP |
505 | +(define_insn "sleep" | |
506 | + [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)] | |
507 | + "" | |
508 | + "sleep" | |
509 | + [(set_attr "length" "1") | |
510 | + (set_attr "cc" "none") | |
511 | + ]) | |
512 | + | |
513 | +;; WDR | |
514 | +(define_insn "wdr" | |
515 | + [(unspec_volatile [(const_int 0)] UNSPECV_WDR)] | |
516 | + "" | |
517 | + "wdr" | |
518 | + [(set_attr "length" "1") | |
519 | + (set_attr "cc" "none") | |
520 | + ]) | |
521 | + | |
522 | +;; SWAP | |
523 | +(define_insn "swap" | |
524 | + [(set (match_operand:QI 0 "register_operand" "=r") | |
525 | + (unspec:QI [(match_operand:QI 1 "register_operand" "0")] | |
526 | + UNSPEC_SWAP))] | |
527 | + "" | |
528 | + "swap %0" | |
529 | + [(set_attr "length" "1") | |
530 | + (set_attr "cc" "none")]) | |
2bc38036 | 531 | + |
dbe7ab63 | 532 | +;; FMUL |
533 | +(define_insn "fmul" | |
534 | + [(set (match_operand:HI 0 "a_register_operand" "=r") | |
535 | + (unspec:HI [(match_operand:QI 1 "a_register_operand" "r") | |
536 | + (match_operand:QI 2 "a_register_operand" "r")] | |
537 | + UNSPEC_FMUL))] | |
538 | + "AVR_HAVE_MUL" | |
539 | + "fmul %1,%2 | |
540 | + movw %0,r0 | |
541 | + clr r1" | |
542 | + [(set_attr "length" "3") | |
543 | + (set_attr "cc" "clobber")]) | |
2bc38036 | 544 | + |
dbe7ab63 | 545 | +;; FMULS |
546 | +(define_insn "fmuls" | |
547 | + [(set (match_operand:HI 0 "a_register_operand" "=r") | |
548 | + (unspec:HI [(match_operand:QI 1 "a_register_operand" "r") | |
549 | + (match_operand:QI 2 "a_register_operand" "r")] | |
550 | + UNSPEC_FMULS))] | |
551 | + "AVR_HAVE_MUL" | |
552 | + "fmuls %1,%2 | |
553 | + movw %0,r0 | |
554 | + clr r1" | |
555 | + [(set_attr "length" "3") | |
556 | + (set_attr "cc" "clobber")]) | |
557 | + | |
558 | +;; FMULSU | |
559 | +(define_insn "fmulsu" | |
560 | + [(set (match_operand:HI 0 "a_register_operand" "=r") | |
561 | + (unspec:HI [(match_operand:QI 1 "a_register_operand" "r") | |
562 | + (match_operand:QI 2 "a_register_operand" "r")] | |
563 | + UNSPEC_FMULSU))] | |
564 | + "AVR_HAVE_MUL" | |
565 | + "fmulsu %1,%2 | |
566 | + movw %0,r0 | |
567 | + clr r1" | |
568 | + [(set_attr "length" "3") | |
569 | + (set_attr "cc" "clobber")]) | |
570 | + | |
571 | diff -Naurp gcc/config/avr/predicates.md gcc/config/avr/predicates.md | |
6ef8d480 PZ |
572 | --- gcc/config/avr/predicates.md 2011-10-27 17:53:20.000000000 +0530 |
573 | +++ gcc/config/avr/predicates.md 2011-10-27 18:00:50.000000000 +0530 | |
dbe7ab63 | 574 | @@ -27,6 +27,11 @@ |
575 | (and (match_code "reg") | |
576 | (match_test "REGNO (op) >= 16 && REGNO (op) <= 31"))) | |
577 | ||
578 | +;; Registers from r16 to 24. | |
579 | +(define_predicate "a_register_operand" | |
580 | + (and (match_code "reg") | |
581 | + (match_test "REGNO (op) >= 16 && REGNO (op) <= 24"))) | |
582 | + | |
583 | (define_predicate "even_register_operand" | |
584 | (and (match_code "reg") | |
585 | (and (match_test "REGNO (op) <= 31") |