]> git.pld-linux.org Git - packages/crossavr-gcc.git/blob - 301-gcc-tiny-support.patch
- updated to 4.7.3 (4.7.2 and older fail to compile with ICE)
[packages/crossavr-gcc.git] / 301-gcc-tiny-support.patch
1 diff -Naurp gcc/config/avr/avr.c gcc/config/avr/avr.c
2 --- gcc/config/avr/avr.c        2013-01-21 18:26:07.000000000 +0530
3 +++ gcc/config/avr/avr.c        2013-01-21 18:40:04.000000000 +0530
4 @@ -78,6 +78,17 @@
5    ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM)           \
6     / SYMBOL_FLAG_MACH_DEP)
7  
8 +#define TINY_ADIW(REG1, REG2, I)                                \
9 +    "subi " #REG1 ",lo8(-(" #I "))" CR_TAB                        \
10 +    "sbci " #REG2 ",hi8(-(" #I "))"        
11 +
12 +#define TINY_SBIW(REG1, REG2, I)                                \
13 +    "subi " #REG1 ",lo8((" #I "))" CR_TAB                         \
14 +    "sbci " #REG2 ",hi8((" #I "))"        
15 +
16 +#define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
17 +#define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
18 +
19  /* Known address spaces.  The order must be the same as in the respective
20     enum from avr.h (or designated initialized must be used).  */
21  const avr_addrspace_t avr_addrspace[] =
22 @@ -157,6 +168,9 @@ static bool avr_rtx_costs (rtx, int, int
23  /* Allocate registers from r25 to r8 for parameters for function calls.  */
24  #define FIRST_CUM_REG 26
25  
26 +/* Last call saved register */
27 +#define LAST_CALLEE_SAVED_REG (AVR_TINY ? 21 : 17)
28 +
29  /* Implicit target register of LPM instruction (R0) */
30  extern GTY(()) rtx lpm_reg_rtx;
31  rtx lpm_reg_rtx;
32 @@ -306,7 +320,7 @@ avr_option_override (void)
33    avr_addr.rampy = 0x3A + avr_current_arch->sfr_offset;
34    avr_addr.rampx = 0x39 + avr_current_arch->sfr_offset;
35    avr_addr.rampd = 0x38 + avr_current_arch->sfr_offset;
36 -  avr_addr.ccp = 0x34 + avr_current_arch->sfr_offset;
37 +  avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_current_arch->sfr_offset;
38  
39    /* SP: Stack Pointer (SP_H:SP_L) */
40    avr_addr.sp_l = 0x3D + avr_current_arch->sfr_offset;
41 @@ -338,8 +352,8 @@ avr_init_expanders (void)
42      all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
43  
44    lpm_reg_rtx  = all_regs_rtx[LPM_REGNO];
45 -  tmp_reg_rtx  = all_regs_rtx[TMP_REGNO];
46 -  zero_reg_rtx = all_regs_rtx[ZERO_REGNO];
47 +  tmp_reg_rtx  = all_regs_rtx[AVR_TMP_REGNO];
48 +  zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
49  
50    lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
51  
52 @@ -351,6 +365,11 @@ avr_init_expanders (void)
53  
54    xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
55    xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
56 +
57 +  /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
58 +     to be present */
59 +  if (AVR_TINY)
60 +    avr_have_dimode = false; 
61  }
62  
63  
64 @@ -792,7 +811,7 @@ sequent_regs_live (void)
65    int live_seq=0;
66    int cur_seq=0;
67  
68 -  for (reg = 0; reg < 18; ++reg)
69 +  for (reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
70      {
71        if (fixed_regs[reg])
72          {
73 @@ -903,7 +922,7 @@ emit_push_sfr (rtx sfr, bool frame_relat
74      RTX_FRAME_RELATED_P (insn) = 1;
75    
76    /* PUSH __tmp_reg__ */
77 -  emit_push_byte (TMP_REGNO, frame_related_p);
78 +  emit_push_byte (AVR_TMP_REGNO, frame_related_p);
79  
80    if (clr_p)
81      {
82 @@ -929,7 +948,8 @@ avr_prologue_setup_frame (HOST_WIDE_INT 
83                     && live_seq
84                     && !isr_p
85                     && !cfun->machine->is_OS_task
86 -                   && !cfun->machine->is_OS_main);
87 +                   && !cfun->machine->is_OS_main
88 +                   && !AVR_TINY);
89    
90    if (minimize
91        && (frame_pointer_needed
92 @@ -966,11 +986,11 @@ avr_prologue_setup_frame (HOST_WIDE_INT 
93        /* Note that live_seq always contains r28+r29, but the other
94           registers to be saved are all below 18.  */
95  
96 -      first_reg = 18 - (live_seq - 2);
97 +      first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
98  
99        for (reg = 29, offset = -live_seq + 1;
100             reg >= first_reg;
101 -           reg = (reg == 28 ? 17 : reg - 1), ++offset)
102 +           reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
103          {
104            rtx m, r;
105  
106 @@ -1201,10 +1221,10 @@ expand_prologue (void)
107          emit_insn (gen_enable_interrupt ());
108          
109        /* Push zero reg.  */
110 -      emit_push_byte (ZERO_REGNO, true);
111 +      emit_push_byte (AVR_ZERO_REGNO, true);
112  
113        /* Push tmp reg.  */
114 -      emit_push_byte (TMP_REGNO, true);
115 +      emit_push_byte (AVR_TMP_REGNO, true);
116  
117        /* Push SREG.  */
118        /* ??? There's no dwarf2 column reserved for SREG.  */
119 @@ -1344,7 +1364,8 @@ expand_epilogue (bool sibcall_p)
120                && live_seq
121                && !isr_p
122                && !cfun->machine->is_OS_task
123 -              && !cfun->machine->is_OS_main);
124 +              && !cfun->machine->is_OS_main
125 +              && !AVR_TINY);
126    
127    if (minimize
128        && (live_seq > 4
129 @@ -1502,14 +1523,14 @@ expand_epilogue (bool sibcall_p)
130  
131        /* Restore SREG using tmp_reg as scratch.  */
132        
133 -      emit_pop_byte (TMP_REGNO);
134 +      emit_pop_byte (AVR_TMP_REGNO);
135        emit_move_insn (sreg_rtx, tmp_reg_rtx);
136  
137        /* Restore tmp REG.  */
138 -      emit_pop_byte (TMP_REGNO);
139 +      emit_pop_byte (AVR_TMP_REGNO);
140  
141        /* Restore zero REG.  */
142 -      emit_pop_byte (ZERO_REGNO);
143 +      emit_pop_byte (AVR_ZERO_REGNO);
144      }
145  
146    if (!sibcall_p)
147 @@ -2009,7 +2030,7 @@ avr_print_operand (FILE *file, rtx x, in
148              fprintf (file, "__RAMPX__");
149            else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
150              fprintf (file, "__RAMPD__");
151 -          else if (AVR_XMEGA && ival == avr_addr.ccp)
152 +          else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
153              fprintf (file, "__CCP__");
154            else if (ival == avr_addr.sreg)   fprintf (file, "__SREG__");
155            else if (ival == avr_addr.sp_l)   fprintf (file, "__SP_L__");
156 @@ -2052,6 +2073,13 @@ avr_print_operand (FILE *file, rtx x, in
157  
158           avr_print_operand (file, XEXP (addr, 1), 0);
159         }
160 +      else if (code == 'b')
161 +        {
162 +          if (GET_CODE (addr) != PLUS)
163 +               fatal_insn ("bad address, not (reg+disp):", addr);
164 +
165 +          avr_print_operand_address (file, XEXP (addr, 0));
166 +        }
167        else if (code == 'p' || code == 'r')
168          {
169            if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
170 @@ -2392,7 +2420,7 @@ avr_simplify_comparison_p (enum machine_
171  int
172  function_arg_regno_p(int r)
173  {
174 -  return (r >= 8 && r <= 25);
175 +  return (AVR_TINY ? r >= 20 && r <= 25 : r >= 8 && r <= 25);
176  }
177  
178  /* Initializing the variable cum for the state at the beginning
179 @@ -2402,7 +2430,7 @@ void
180  init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
181                       tree fndecl ATTRIBUTE_UNUSED)
182  {
183 -  cum->nregs = 18;
184 +  cum->nregs = AVR_TINY ? 6 : 18;
185    cum->regno = FIRST_CUM_REG;
186    if (!libname && stdarg_p (fntype))
187      cum->nregs = 0;
188 @@ -2900,6 +2928,25 @@ output_movhi (rtx insn, rtx xop[], int *
189    return "";
190  }
191  
192 +/* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
193 +static const char*
194 +avr_out_movqi_r_mr_reg_disp_tiny (rtx insn, rtx op[], int *plen)
195 +{
196 +  rtx dest = op[0];
197 +  rtx src = op[1];
198 +  rtx x = XEXP (src, 0);
199 +  op[2] = XEXP(x, 0);
200 +
201 +  avr_asm_len (TINY_ADIW (%A2, %B2, %o1) CR_TAB
202 +          "ld %0,%b1" , op, plen, -3);
203 +
204 +  if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
205 +          && !reg_unused_after (insn, XEXP (x,0)))
206 +      avr_asm_len (TINY_SBIW (%A2, %B2, %o1), op, plen, 2);
207 +
208 +  return "";
209 +}
210 +
211  static const char*
212  out_movqi_r_mr (rtx insn, rtx op[], int *plen)
213  {
214 @@ -2913,13 +2960,18 @@ out_movqi_r_mr (rtx insn, rtx op[], int 
215          ? avr_asm_len ("in %0,%i1", op, plen, -1)
216          : avr_asm_len ("lds %0,%m1", op, plen, -2);
217      }
218 -  else if (GET_CODE (x) == PLUS
219 +
220 +
221 +  if (GET_CODE (x) == PLUS
222             && REG_P (XEXP (x, 0))
223             && CONST_INT_P (XEXP (x, 1)))
224      {
225        /* memory access by reg+disp */
226  
227        int disp = INTVAL (XEXP (x, 1));
228 +
229 +      if (AVR_TINY)
230 +        return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
231        
232        if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
233          {
234 @@ -2941,25 +2993,105 @@ out_movqi_r_mr (rtx insn, rtx op[], int 
235          {
236            /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
237               it but I have this situation with extremal optimizing options.  */
238 -          
239 -          avr_asm_len ("adiw r26,%o1" CR_TAB
240 -                       "ld %0,X", op, plen, -2);
241 +
242 +            avr_asm_len ("adiw r26, %o1" CR_TAB
243 +                         "ld %0,X", op, plen, -2);
244            
245            if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
246                && !reg_unused_after (insn, XEXP (x,0)))
247              {
248 -              avr_asm_len ("sbiw r26,%o1", op, plen, 1);
249 +              avr_asm_len ("sbiw r26, %o1", op, plen, 1);
250              }
251  
252            return "";
253          }
254  
255 -      return avr_asm_len ("ldd %0,%1", op, plen, -1);
256 +        return avr_asm_len ("ldd %0,%1", op, plen, -1);
257      }
258    
259    return avr_asm_len ("ld %0,%1", op, plen, -1);
260  }
261  
262 +/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
263 +static const char*
264 +avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
265 +{
266 +  rtx dest = op[0];
267 +  rtx src = op[1];
268 +  rtx base = XEXP (src, 0);
269 +
270 +  int reg_dest = true_regnum (dest);
271 +  int reg_base = true_regnum (base);
272 +
273 +  op[2] = base;
274 +
275 +  if (reg_dest == reg_base)         /* R = (R) */
276 +      return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
277 +              "ld %B0,%1"          CR_TAB
278 +              "mov %A0,__tmp_reg__", op, plen, -3);
279 +
280 +  return avr_asm_len ("ld %A0,%1"             CR_TAB                        
281 +          TINY_ADIW (%A2, %B2, 1) CR_TAB                       
282 +          "ld %B0,%1"             CR_TAB                        
283 +          TINY_SBIW (%A2, %B2, 1), op, plen, -6);
284 +
285 +}
286 +
287 +/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
288 +static const char*
289 +avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
290 +{
291 +  rtx dest = op[0];
292 +  rtx src = op[1];
293 +  rtx base = XEXP (src, 0);
294 +
295 +  int reg_dest = true_regnum (dest);
296 +  int reg_base = true_regnum (XEXP (base, 0));
297 +  op[2] = XEXP (base, 0);
298 +
299 +  if (reg_base == reg_dest)
300 +  {
301 +      return avr_asm_len (TINY_ADIW (%A2, %B2, %o1) CR_TAB
302 +              "ld __tmp_reg__,%b1+"    CR_TAB
303 +              "ld %B0,%b1"             CR_TAB 
304 +              "mov %A0,__tmp_reg__", op, plen, -5);
305 +  }
306 +  else
307 +  {
308 +      return avr_asm_len (TINY_ADIW (%A2, %B2, %o1) CR_TAB
309 +              "ld %A0,%b1+"             CR_TAB
310 +              "ld %B0,%b1"              CR_TAB
311 +              TINY_SBIW (%A2, %B2, %o1+1), op, plen, -6);
312 +  }
313 +} 
314 +
315 +/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
316 +static const char*
317 +avr_out_movhi_r_mr_pre_dec_tiny (rtx insn, rtx op[], int *plen)
318 +{
319 +  int mem_volatile_p = 0;
320 +  rtx dest = op[0];
321 +  rtx src = op[1];
322 +  rtx base = XEXP (src, 0);
323 +  op[2] = XEXP (base, 0);
324 +
325 +  /* "volatile" forces reading low byte first, even if less efficient,
326 +     for correct operation with 16-bit I/O registers.  */
327 +  mem_volatile_p = MEM_VOLATILE_P (src);
328 +
329 +  if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
330 +      fatal_insn ("incorrect insn:", insn);
331 +
332 +  if (!mem_volatile_p)
333 +      return avr_asm_len ("ld %B0,%1" CR_TAB
334 +              "ld %A0,%1", op, plen, -2);
335 +
336 +  return avr_asm_len (TINY_SBIW (%A2, %B2, 2)  CR_TAB
337 +          "ld %A0,%p1+"   CR_TAB
338 +          "ld %B0,%p1"    CR_TAB
339 +          TINY_SBIW (%A2, %B2, 1), op, plen, -6);
340 +}
341 +
342  static const char*
343  out_movhi_r_mr (rtx insn, rtx op[], int *plen)
344  {
345 @@ -2974,20 +3106,27 @@ out_movhi_r_mr (rtx insn, rtx op[], int 
346  
347    if (reg_base > 0)
348      {
349 +      if (AVR_TINY)
350 +          return avr_out_movhi_r_mr_reg_no_disp_tiny (op, plen);
351 +
352        if (reg_dest == reg_base)         /* R = (R) */
353          return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
354                              "ld %B0,%1"          CR_TAB
355                              "mov %A0,__tmp_reg__", op, plen, -3);
356  
357        if (reg_base != REG_X)
358 +      {
359          return avr_asm_len ("ld %A0,%1" CR_TAB
360 -                            "ldd %B0,%1+1", op, plen, -2);
361 -      
362 +                         "ldd %B0,%1+1", op, plen, -2);
363 +      }
364 +          
365        avr_asm_len ("ld %A0,X+" CR_TAB
366                     "ld %B0,X", op, plen, -2);
367            
368        if (!reg_unused_after (insn, base))
369 +      {
370          avr_asm_len ("sbiw r26,1", op, plen, 1);
371 +      }
372  
373        return "";
374      }
375 @@ -2996,6 +3135,9 @@ out_movhi_r_mr (rtx insn, rtx op[], int 
376        int disp = INTVAL (XEXP (base, 1));
377        int reg_base = true_regnum (XEXP (base, 0));
378        
379 +      if (AVR_TINY)
380 +          return avr_out_movhi_r_mr_reg_disp_tiny (op, plen);
381 +
382        if (disp > MAX_LD_OFFSET (GET_MODE (src)))
383          {
384            if (REGNO (XEXP (base, 0)) != REG_Y)
385 @@ -3007,7 +3149,7 @@ out_movhi_r_mr (rtx insn, rtx op[], int 
386                             "ldd %B0,Y+63"    CR_TAB
387                             "sbiw r28,%o1-62", op, plen, -4)
388  
389 -            : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
390 +              : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
391                             "sbci r29,hi8(-%o1)" CR_TAB
392                             "ld %A0,Y"           CR_TAB
393                             "ldd %B0,Y+1"        CR_TAB
394 @@ -3041,6 +3183,9 @@ out_movhi_r_mr (rtx insn, rtx op[], int 
395      }
396    else if (GET_CODE (base) == PRE_DEC) /* (--R) */
397      {
398 +      if (AVR_TINY)
399 +          return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
400 +
401        if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
402          fatal_insn ("incorrect insn:", insn);
403  
404 @@ -3081,6 +3226,101 @@ out_movhi_r_mr (rtx insn, rtx op[], int 
405  }
406  
407  static const char*
408 +avr_out_movsi_r_mr_reg_no_disp_tiny (rtx insn, rtx op[], int *l)
409 +{
410 +  rtx dest = op[0];
411 +  rtx src = op[1];
412 +  rtx base = XEXP (src, 0);
413 +  int reg_dest = true_regnum (dest);
414 +  int reg_base = true_regnum (base);
415 +  op[2] = base;
416 +
417 +  if (reg_dest == reg_base)
418 +    {
419 +         /* "ld r26,-X" is undefined */
420 +      return *l=9, (TINY_ADIW (%A2, %B2, 3) CR_TAB
421 +                    "ld %D0,%1"             CR_TAB
422 +                    "ld %C0,-%1"            CR_TAB
423 +                    "ld __tmp_reg__,-%1"   CR_TAB
424 +                    TINY_SBIW (%A2, %B2, 1) CR_TAB
425 +                    "ld %A0,%1"             CR_TAB
426 +                    "mov %B0,__tmp_reg__");
427 +    }
428 +  else if (reg_dest == reg_base - 2)
429 +    {
430 +      return *l=5, ("ld %A0,%1+"            CR_TAB
431 +                    "ld %B0,%1+"            CR_TAB
432 +                    "ld __tmp_reg__,%1+"   CR_TAB
433 +                    "ld %D0,%1"            CR_TAB
434 +                    "mov %C0,__tmp_reg__");
435 +    }
436 +  else if (reg_unused_after (insn, base))
437 +    {
438 +      return *l=4, ("ld %A0,%1+"    CR_TAB
439 +                    "ld %B0,%1+"    CR_TAB 
440 +                    "ld %C0,%1+"    CR_TAB
441 +                    "ld %D0,%1");
442 +    }
443 +  else
444 +    {
445 +      return *l=6, ("ld %A0,%1+"    CR_TAB
446 +                    "ld %B0,%1+"    CR_TAB 
447 +                    "ld %C0,%1+"    CR_TAB
448 +                    "ld %D0,%1"     CR_TAB
449 +                    TINY_SBIW (%A2, %B2, 3));
450 +    }
451 +}
452 +
453 +static const char*
454 +avr_out_movsi_r_mr_reg_disp_tiny (rtx insn, rtx op[], int *l)
455 +{
456 +  rtx dest = op[0];
457 +  rtx src = op[1];
458 +  rtx base = XEXP (src, 0);
459 +  int reg_dest = true_regnum (dest);
460 +  int reg_base = true_regnum (XEXP (base, 0));
461 +  op[2] = XEXP (base, 0);
462 +
463 +  if (reg_dest == reg_base)
464 +    {
465 +         /* "ld r26,-X" is undefined */
466 +      return *l=9, (TINY_ADIW (%A2, %B2, %o1+3) CR_TAB
467 +                    "ld %D0,%b1"                 CR_TAB
468 +                    "ld %C0,-%b1"                CR_TAB
469 +                    "ld __tmp_reg__,-%b1"        CR_TAB
470 +                    TINY_SBIW (%A2, %B2, 1)     CR_TAB
471 +                    "ld %A0,%b1"                 CR_TAB
472 +                    "mov %B0,__tmp_reg__");
473 +    }
474 +  else if (reg_dest == reg_base - 2)
475 +    {
476 +      return *l=7, (TINY_ADIW (%A2, %B2, %o1) CR_TAB
477 +                    "ld %A0,%b1+"              CR_TAB
478 +                    "ld %B0,%b1+"              CR_TAB
479 +                    "ld __tmp_reg__,%b1+"      CR_TAB
480 +                    "ld %D0,%b1"               CR_TAB
481 +                    "mov %C0,__tmp_reg__");
482 +    }
483 +  else if (reg_unused_after (insn, XEXP (base, 0)))
484 +    {
485 +      return *l=6, (TINY_ADIW (%A2, %B2, %o1) CR_TAB
486 +                    "ld %A0,%b1+"              CR_TAB
487 +                    "ld %B0,%b1+"              CR_TAB 
488 +                    "ld %C0,%b1+"              CR_TAB
489 +                    "ld %D0,%b1");
490 +    }
491 +  else
492 +    {
493 +      return *l=8, (TINY_ADIW (%A2, %B2, %o1) CR_TAB
494 +                    "ld %A0,%b1+"              CR_TAB
495 +                    "ld %B0,%b1+"              CR_TAB 
496 +                    "ld %C0,%b1+"              CR_TAB
497 +                    "ld %D0,%b1"               CR_TAB
498 +                    TINY_SBIW (%A2, %B2, %o1+3));
499 +    }
500 +}
501 +
502 +static const char*
503  out_movsi_r_mr (rtx insn, rtx op[], int *l)
504  {
505    rtx dest = op[0];
506 @@ -3095,6 +3335,9 @@ out_movsi_r_mr (rtx insn, rtx op[], int 
507    
508    if (reg_base > 0)
509      {
510 +      if (AVR_TINY)
511 +        return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
512 +
513        if (reg_base == REG_X)        /* (R26) */
514          {
515            if (reg_dest == REG_X)
516 @@ -3149,6 +3392,9 @@ out_movsi_r_mr (rtx insn, rtx op[], int 
517      {
518        int disp = INTVAL (XEXP (base, 1));
519        
520 +      if (AVR_TINY)
521 +        return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
522 +
523        if (disp > MAX_LD_OFFSET (GET_MODE (src)))
524         {
525           if (REGNO (XEXP (base, 0)) != REG_Y)
526 @@ -3242,6 +3488,113 @@ out_movsi_r_mr (rtx insn, rtx op[], int 
527  }
528  
529  static const char*
530 +avr_out_movsi_mr_r_reg_no_disp_tiny (rtx insn, rtx op[], int *l)
531 +{
532 +  rtx dest = op[0];
533 +  rtx src = op[1];
534 +  rtx base = XEXP (dest, 0);
535 +  int reg_base = true_regnum (base);
536 +  int reg_src = true_regnum (src);
537 +  op[2] = base;
538 +  
539 +  if (reg_base == reg_src)
540 +    {
541 +         /* "ld r26,-X" is undefined */
542 +      if (reg_unused_after (insn, base))
543 +        { 
544 +          return *l=7, ("mov __tmp_reg__, %B1"  CR_TAB
545 +                        "st %0,%A1"             CR_TAB
546 +                        TINY_ADIW (%A2, %B2, 1) CR_TAB
547 +                        "st %0+,__tmp_reg__"    CR_TAB
548 +                        "st %0+,%C1"            CR_TAB
549 +                        "st %0+,%D1");
550 +        }
551 +      else
552 +        {
553 +          return *l=9, ("mov __tmp_reg__, %B1"  CR_TAB
554 +                        "st %0,%A1"             CR_TAB
555 +                        TINY_ADIW (%A2, %B2, 1) CR_TAB
556 +                        "st %0+,__tmp_reg__"    CR_TAB
557 +                        "st %0+,%C1"            CR_TAB
558 +                        "st %0+,%D1"            CR_TAB
559 +                        TINY_SBIW (%A2, %B2, 3));
560 +        }
561 +    }
562 +    else if (reg_base == reg_src + 2)
563 +      {
564 +        if (reg_unused_after (insn, base))
565 +          return *l=7, ("mov __zero_reg__,%C1" CR_TAB
566 +                        "mov __tmp_reg__,%D1"  CR_TAB
567 +                        "st %0+,%A1"           CR_TAB
568 +                        "st %0+,%B1"           CR_TAB
569 +                        "st %0+,__zero_reg__"  CR_TAB
570 +                        "st %0,__tmp_reg__"    CR_TAB
571 +                        "clr __zero_reg__");
572 +        else
573 +          return *l=9, ("mov __zero_reg__,%C1" CR_TAB
574 +                        "mov __tmp_reg__,%D1"  CR_TAB
575 +                        "st %0+,%A1"           CR_TAB
576 +                        "st %0+,%B1"           CR_TAB
577 +                        "st %0+,__zero_reg__"  CR_TAB
578 +                        "st %0,__tmp_reg__"    CR_TAB
579 +                        "clr __zero_reg__"     CR_TAB
580 +                        TINY_SBIW (%A2, %B2, 3));
581 +      }
582 +
583 +    return *l=6, ("st %0+,%A1" CR_TAB
584 +                  "st %0+,%B1" CR_TAB
585 +                  "st %0+,%C1" CR_TAB
586 +                  "st %0,%D1"  CR_TAB
587 +                  TINY_SBIW (%A2, %B2, 3));
588 +}
589 +
590 +static const char*
591 +avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
592 +{
593 +  rtx dest = op[0];
594 +  rtx src = op[1];
595 +  rtx base = XEXP (dest, 0);
596 +  int reg_base = REGNO (XEXP (base, 0));
597 +  int reg_src =true_regnum (src);
598 +
599 +  op[2] = XEXP (base, 0);
600 +
601 +  if (reg_base == reg_src)
602 +    {
603 +         *l = 11;
604 +         return ("mov __tmp_reg__,%A2"        CR_TAB
605 +                     "mov __zero_reg__,%B2"       CR_TAB
606 +              TINY_ADIW (%A2, %B2, %o0)    CR_TAB
607 +                     "st %b0+,__tmp_reg__"        CR_TAB
608 +                     "st %b0+,__zero_reg__"       CR_TAB
609 +                     "st %b0+,%C2"                CR_TAB
610 +                     "st %b0,%D2"                 CR_TAB
611 +                     "clr __zero_reg__"           CR_TAB
612 +                     TINY_SBIW (%A2, %B2, %o0+3));
613 +        }
614 +  else if (reg_src == reg_base - 2)
615 +    {
616 +         *l = 11;
617 +         return ("mov __tmp_reg__,%C2"         CR_TAB
618 +                     "mov __zero_reg__,%D2"        CR_TAB
619 +                     TINY_ADIW (%A2, %B2, %o0)     CR_TAB
620 +                     "st %b0+,%A0"                 CR_TAB
621 +                     "st %b0+,%B0"                 CR_TAB
622 +                     "st %b0+,__tmp_reg__"         CR_TAB
623 +                     "st %b0,__zero_reg__"         CR_TAB
624 +                     "clr __zero_reg__"            CR_TAB
625 +                     TINY_SBIW (%A2, %B2, %o0+3));
626 +           }
627 +  *l = 8;
628 +  return (TINY_ADIW (%A2, %B2, %o0)     CR_TAB
629 +                 "st %b0+,%A1"                 CR_TAB
630 +                 "st %b0+,%B1"                 CR_TAB
631 +                 "st %b0+,%C1"                 CR_TAB
632 +                 "st %b0,%D1"                  CR_TAB
633 +                 TINY_SBIW (%A2, %B2, %o0+3));
634 +}
635 +
636 +static const char*
637  out_movsi_mr_r (rtx insn, rtx op[], int *l)
638  {
639    rtx dest = op[0];
640 @@ -3261,6 +3614,9 @@ out_movsi_mr_r (rtx insn, rtx op[], int 
641                   "sts %m0+3,%D1");
642    if (reg_base > 0)                 /* (r) */
643      {
644 +      if (AVR_TINY)
645 +        return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
646 +
647        if (reg_base == REG_X)                /* (R26) */
648          {
649            if (reg_src == REG_X)
650 @@ -3317,6 +3673,10 @@ out_movsi_mr_r (rtx insn, rtx op[], int 
651    else if (GET_CODE (base) == PLUS) /* (R + i) */
652      {
653        int disp = INTVAL (XEXP (base, 1));
654 +
655 +      if (AVR_TINY)
656 +        return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
657 +
658        reg_base = REGNO (XEXP (base, 0));
659        if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
660         {
661 @@ -3476,6 +3836,75 @@ output_movsisf (rtx insn, rtx operands[]
662  /* Handle loads of 24-bit types from memory to register.  */
663  
664  static const char*
665 +avr_out_load_psi_reg_no_disp_tiny (rtx insn, rtx *op, int *plen)
666 +{
667 +  rtx dest = op[0];
668 +  rtx src = op[1];
669 +  rtx base = XEXP (src, 0);
670 +  int reg_dest = true_regnum (dest);
671 +  int reg_base = true_regnum (base);
672 +  op[2] = base;
673 +
674 +  if (reg_base == reg_dest)
675 +    {
676 +      return avr_asm_len (TINY_ADIW (%A2, %B2, 2)   CR_TAB
677 +                          "ld %C0,%1"               CR_TAB
678 +                          "ld __tmp_reg__,-%1"     CR_TAB
679 +                          TINY_SBIW (%A2, %B2, 1)   CR_TAB
680 +                          "ld %A0,%1"              CR_TAB
681 +                          "mov %B0,__tmp_reg__", op, plen, -8);
682 +    }
683 +  else
684 +    {
685 +      return avr_asm_len ("ld %A0,%1+"  CR_TAB
686 +                          "ld %B0,%1+"  CR_TAB
687 +                          "ld %C0,%1", op, plen, -3);
688 +
689 +      if (reg_dest != reg_base - 2 &&
690 +          !reg_unused_after (insn, base))
691 +        {
692 +          avr_asm_len (TINY_SBIW (%A2, %B2, 2), op, plen, 2);
693 +        }
694 +      return "";
695 +    }
696 +}
697 +
698 +static const char*
699 +avr_out_load_psi_reg_disp_tiny (rtx insn, rtx *op, int *plen)
700 +{
701 +  rtx dest = op[0];
702 +  rtx src = op[1];
703 +  rtx base = XEXP (src, 0);
704 +  int reg_dest = true_regnum (dest);
705 +  int reg_base = true_regnum (base);
706 +  op[2] = XEXP (base, 0);
707 +
708 +  reg_base = true_regnum (XEXP (base, 0));
709 +  if (reg_base == reg_dest)
710 +    {
711 +      return avr_asm_len (TINY_ADIW (%A2, %B2, %o1+2) CR_TAB
712 +                          "ld %C0,%b1"                CR_TAB
713 +                          "ld __tmp_reg__,-%b1"       CR_TAB
714 +                          TINY_SBIW (%A2, %B2, 1)     CR_TAB
715 +                          "ld %A0,%b1"                CR_TAB
716 +                          "mov %B0,__tmp_reg__", op, plen, -8);
717 +   }
718 +  else
719 +    {
720 +      avr_asm_len (TINY_ADIW (%A2, %B2, %o1)   CR_TAB
721 +                          "ld %A0,%b1+"              CR_TAB
722 +                          "ld %B0,%b1+"              CR_TAB  
723 +                          "ld %C0,%b1", op, plen, -5);
724 +
725 +      if (reg_dest != (reg_base - 2)
726 +          && !reg_unused_after (insn, XEXP (base, 0)))
727 +          avr_asm_len (TINY_SBIW (%A2, %B2, %o1+2), op, plen, 2);
728 +      
729 +      return "";
730 +    }
731 +}
732 +
733 +static const char*
734  avr_out_load_psi (rtx insn, rtx *op, int *plen)
735  {
736    rtx dest = op[0];
737 @@ -3486,6 +3915,9 @@ avr_out_load_psi (rtx insn, rtx *op, int
738    
739    if (reg_base > 0)
740      {
741 +      if (AVR_TINY)
742 +        return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
743 +
744        if (reg_base == REG_X)        /* (R26) */
745          {
746            if (reg_dest == REG_X)
747 @@ -3527,6 +3959,9 @@ avr_out_load_psi (rtx insn, rtx *op, int
748    else if (GET_CODE (base) == PLUS) /* (R + i) */
749      {
750        int disp = INTVAL (XEXP (base, 1));
751 +
752 +      if (AVR_TINY)
753 +        return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
754        
755        if (disp > MAX_LD_OFFSET (GET_MODE (src)))
756          {
757 @@ -3604,6 +4039,85 @@ avr_out_load_psi (rtx insn, rtx *op, int
758    return "";
759  }
760  
761 +
762 +static const char*
763 +avr_out_store_psi_reg_no_disp_tiny (rtx insn, rtx *op, int *plen)
764 +{
765 +  rtx dest = op[0];
766 +  rtx src = op[1];
767 +  rtx base = XEXP (dest, 0);
768 +  int reg_base = true_regnum (base);
769 +  int reg_src = true_regnum (src);
770 +  op[2] = base;
771 +
772 +  if (reg_base == reg_src)
773 +    {
774 +      avr_asm_len ("st %0,%A1"              CR_TAB
775 +                   "mov __tmp_reg__,%B1"    CR_TAB
776 +                   TINY_ADIW (%A2, %B2, 1)  CR_TAB /* st X+, r27 is undefined */
777 +                   "st %0+,__tmp_reg__"     CR_TAB
778 +                   "st %0,%C1", op, plen, -6);
779 +
780 +    }
781 +  else if (reg_src == reg_base - 2)
782 +    {
783 +      avr_asm_len ("st %0,%A1"              CR_TAB
784 +                   "mov __tmp_reg__,%C1"    CR_TAB
785 +                   TINY_ADIW (%A2, %B2, 1)  CR_TAB
786 +                   "st %0+,%B1"             CR_TAB
787 +                   "st %0,__tmp_reg__", op, plen, 6);
788 +    }
789 +  else
790 +    {
791 +      avr_asm_len ("st %0+,%A1"  CR_TAB
792 +                   "st %0+,%B1" CR_TAB
793 +                   "st %0,%C1", op, plen, -3);
794 +    }
795 +
796 +  if (!reg_unused_after (insn, base))
797 +    avr_asm_len (TINY_SBIW (%A2, %B2, 2), op, plen, 2);
798 +
799 +  return "";
800 +}
801 +
802 +static const char*
803 +avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
804 +{
805 +  rtx dest = op[0];
806 +  rtx src = op[1];
807 +  rtx base = XEXP (dest, 0);
808 +  int reg_base = REGNO (XEXP (base, 0));
809 +  int reg_src = true_regnum (src);
810 +  op[2] = XEXP (base, 0);
811 +
812 +  if (reg_src == reg_base)
813 +    {
814 +      return avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
815 +                          "mov __zero_reg__,%B1"         CR_TAB
816 +                          TINY_ADIW (%A2, %B2, %o0)      CR_TAB
817 +                          "st %b0+,__tmp_reg__"          CR_TAB
818 +                          "st %b0+,__zero_reg__"         CR_TAB
819 +                          "st %b0,%C1"                   CR_TAB
820 +                          "clr __zero_reg__"             CR_TAB
821 +                          TINY_SBIW (%A2, %B2, %o0+2), op, plen, -10);
822 +    }
823 +  else if (reg_src == reg_base - 2)
824 +    {
825 +      return avr_asm_len ("mov __tmp_reg__,%C1"          CR_TAB  
826 +                          TINY_ADIW (%A2, %B2, %o0)      CR_TAB
827 +                          "st %b0+,%A1"                  CR_TAB
828 +                          "st %b0+,%B1"                  CR_TAB
829 +                          "st %b0,__tmp_reg__"           CR_TAB
830 +                          TINY_SBIW (%A2, %B2, %o0+2), op, plen, -8);
831 +    }
832 +
833 +  return avr_asm_len (TINY_ADIW (%A2, %B2, %o0)      CR_TAB
834 +                          "st %b0+,%A1"                  CR_TAB
835 +                          "st %b0+,%B1"                  CR_TAB
836 +                          "st %b0,%C1"                   CR_TAB
837 +                          TINY_SBIW (%A2, %B2, %o0+2), op, plen, -7);
838 +}
839 +
840  /* Handle store of 24-bit type from register or zero to memory.  */
841  
842  static const char*
843 @@ -3621,6 +4135,9 @@ avr_out_store_psi (rtx insn, rtx *op, in
844    
845    if (reg_base > 0)                 /* (r) */
846      {
847 +      if (AVR_TINY)
848 +        return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
849 +
850        if (reg_base == REG_X)        /* (R26) */
851          {
852            gcc_assert (!reg_overlap_mentioned_p (base, src));
853 @@ -3642,6 +4159,10 @@ avr_out_store_psi (rtx insn, rtx *op, in
854    else if (GET_CODE (base) == PLUS) /* (R + i) */
855      {
856        int disp = INTVAL (XEXP (base, 1));
857 +
858 +      if (AVR_TINY)
859 +        return avr_out_store_psi_reg_disp_tiny (op, plen);
860 +
861        reg_base = REGNO (XEXP (base, 0));
862  
863        if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
864 @@ -3758,6 +4279,31 @@ avr_out_movpsi (rtx insn, rtx *op, int *
865    return "";
866  }
867  
868 +static const char*
869 +avr_out_movqi_mr_r_reg_disp_tiny (rtx insn, rtx op[], int *plen)
870 +{
871 +  rtx dest = op[0];
872 +  rtx src = op[1];
873 +  rtx x = XEXP (dest, 0);
874 +  op[2] = XEXP (x, 0);
875 +
876 +  if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
877 +    {
878 +      avr_asm_len ("mov __tmp_reg__,%1"      CR_TAB
879 +                   TINY_ADIW (%A2, %B2, %o0) CR_TAB
880 +                   "st %b0,__tmp_reg__", op, plen, -4);
881 +    }
882 +    else
883 +    {
884 +      avr_asm_len (TINY_ADIW (%A2, %B2, %o0) CR_TAB
885 +          "st %b0,%1" , op, plen, -3);
886 +    }
887 +
888 +  if (!reg_unused_after (insn, XEXP (x,0)))
889 +      avr_asm_len (TINY_SBIW (%A2, %B2, %o0), op, plen, 2);
890 +
891 +  return "";
892 +}
893  
894  static const char*
895  out_movqi_mr_r (rtx insn, rtx op[], int *plen)
896 @@ -3780,6 +4326,9 @@ out_movqi_mr_r (rtx insn, rtx op[], int 
897  
898        int disp = INTVAL (XEXP (x, 1));
899  
900 +      if (AVR_TINY)
901 +        return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
902 +
903        if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
904          {
905            if (REGNO (XEXP (x, 0)) != REG_Y)
906 @@ -3934,6 +4483,76 @@ avr_out_movhi_mr_r_xmega (rtx insn, rtx 
907    return "";
908  }
909  
910 +static const char*
911 +avr_out_movhi_mr_r_reg_no_disp_tiny (rtx insn, rtx op[], int *plen)
912 +{
913 +  rtx dest = op[0];
914 +  rtx src = op[1];
915 +  rtx base = XEXP (dest, 0);
916 +  int reg_base = true_regnum (base);
917 +  int reg_src = true_regnum (src);
918 +  int mem_volatile_p = MEM_VOLATILE_P (dest);
919 +  op[2] = base;
920 +
921 +  if (reg_base == reg_src)
922 +    {
923 +      return !mem_volatile_p && reg_unused_after (insn, src)
924 +        ? avr_asm_len ("mov __tmp_reg__,%B1"   CR_TAB
925 +                       "st %0,%A1"             CR_TAB
926 +                       TINY_ADIW (%A2, %B2, 1) CR_TAB
927 +                       "st %0,__tmp_reg__", op, plen, -5)
928 +        : avr_asm_len ("mov __tmp_reg__,%B1"   CR_TAB
929 +                       TINY_ADIW (%A2, %B2, 1) CR_TAB
930 +                       "st %0,__tmp_reg__"      CR_TAB
931 +                       TINY_SBIW (%A2, %B2, 1) CR_TAB
932 +                       "st %0, %A1", op, plen, -7);
933 +    }
934 +
935 +  return !mem_volatile_p && reg_unused_after (insn, base)
936 +      ? avr_asm_len ("st %0+,%A1" CR_TAB
937 +                     "st %0,%B1", op, plen, -2)
938 +      : avr_asm_len (TINY_ADIW (%A2, %B2, 1) CR_TAB
939 +                     "st %0,%B1"             CR_TAB
940 +                     "st -%0,%A1", op, plen, -4);
941 +}
942 +
943 +static const char*
944 +avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen)
945 +{
946 +  rtx dest = op[0];
947 +  rtx src = op[1];
948 +  rtx base = XEXP (dest, 0);
949 +  int reg_base = REGNO (XEXP (base, 0));
950 +  int reg_src = true_regnum (src);
951 +  op[2] = XEXP (base, 0);
952 +
953 +  return reg_src == reg_base
954 +        ? avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
955 +                       "mov __zero_reg__,%B1"         CR_TAB
956 +                       TINY_ADIW (%A2, %B2, %o0+1)    CR_TAB
957 +                       "st %b0,__zero_reg__"          CR_TAB
958 +                       "st -%b0,__tmp_reg__"          CR_TAB
959 +                       "clr __zero_reg__"             CR_TAB
960 +                       TINY_SBIW (%A2, %B2, %o0), op, plen, -9) 
961 +
962 +        : avr_asm_len (TINY_ADIW (%A2, %B2, %o0+1) CR_TAB
963 +                       "st %b0,%B1"                CR_TAB
964 +                       "st -%b0,%A1"               CR_TAB
965 +                       TINY_SBIW (%A2, %B2, %o0), op, plen, -6);
966 +}
967 +
968 +static const char*
969 +avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
970 +{
971 +  rtx dest = op[0];
972 +  rtx base = XEXP (dest, 0);
973 +  op[2] = XEXP (base, 0);
974 +
975 +  return avr_asm_len (TINY_ADIW (%A2, %B2, 1)  CR_TAB
976 +                      "st %p0,%B1"    CR_TAB
977 +                      "st -%p0,%A1"   CR_TAB
978 +                      TINY_ADIW (%A2, %B2, 2), op, plen, -6);
979 +}
980  
981  static const char*
982  out_movhi_mr_r (rtx insn, rtx op[], int *plen)
983 @@ -3964,6 +4583,9 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
984    
985    if (reg_base > 0)
986      {
987 +      if (AVR_TINY)
988 +        return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
989 +
990        if (reg_base != REG_X)
991          return avr_asm_len ("std %0+1,%B1" CR_TAB
992                              "st %0,%A1", op, plen, -2);
993 @@ -3992,6 +4614,10 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
994    else if (GET_CODE (base) == PLUS)
995      {
996        int disp = INTVAL (XEXP (base, 1));
997 +
998 +      if (AVR_TINY)
999 +        return avr_out_movhi_mr_r_reg_disp_tiny (op, plen);
1000 +
1001        reg_base = REGNO (XEXP (base, 0));
1002        if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
1003          {
1004 @@ -4040,6 +4666,8 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
1005        if (!mem_volatile_p)
1006          return avr_asm_len ("st %0,%A1"  CR_TAB
1007                              "st %0,%B1", op, plen, -2);
1008 +      if (AVR_TINY)
1009 +        return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
1010        
1011        return REGNO (XEXP (base, 0)) == REG_X
1012          ? avr_asm_len ("adiw r26,1"  CR_TAB
1013 @@ -4212,7 +4840,11 @@ avr_out_compare (rtx insn, rtx *xop, int
1014                && (val8 == 0
1015                    || reg_unused_after (insn, xreg)))
1016              {
1017 -              avr_asm_len ("sbiw %0,%1", xop, plen, 1);
1018 +              if (AVR_TINY)
1019 +                avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
1020 +              else
1021 +                avr_asm_len ("sbiw %0,%1", xop, plen, 1);
1022 +
1023                i++;
1024                continue;
1025              }
1026 @@ -4222,7 +4854,9 @@ avr_out_compare (rtx insn, rtx *xop, int
1027                && compare_eq_p (insn)
1028                && reg_unused_after (insn, xreg))
1029              {
1030 -              return avr_asm_len ("adiw %0,%n1", xop, plen, 1);
1031 +              return AVR_TINY
1032 +                  ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
1033 +                  : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
1034              }
1035          }
1036  
1037 @@ -7411,10 +8045,10 @@ avr_file_start (void)
1038      fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
1039    if (AVR_HAVE_RAMPD)
1040      fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
1041 -  if (AVR_XMEGA)
1042 +  if (AVR_XMEGA || AVR_TINY)
1043      fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
1044 -  fprintf (asm_out_file, "__tmp_reg__ = %d\n", TMP_REGNO);
1045 -  fprintf (asm_out_file, "__zero_reg__ = %d\n", ZERO_REGNO);
1046 +  fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
1047 +  fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
1048  }
1049  
1050  
1051 @@ -7461,6 +8095,17 @@ order_regs_for_local_alloc (void)
1052      0,1,
1053      32,33,34,35
1054    };
1055 +  static const int tiny_order_0[] = {
1056 +    24,25,
1057 +    22,23,
1058 +    30,31,
1059 +    26,27,
1060 +    28,29,
1061 +    21,20,19,18,
1062 +    16,17,
1063 +    32,33,34,35,
1064 +    15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
1065 +  };
1066    static const int order_1[] = {
1067      18,19,
1068      20,21,
1069 @@ -7473,6 +8118,17 @@ order_regs_for_local_alloc (void)
1070      0,1,
1071      32,33,34,35
1072    };
1073 +  static const int tiny_order_1[] = {
1074 +    22,23,
1075 +    24,25,
1076 +    30,31,
1077 +    26,27,
1078 +    28,29,
1079 +    21,20,19,18,
1080 +    16,17,
1081 +    32,33,34,35,
1082 +    15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
1083 +  };
1084    static const int order_2[] = {
1085      25,24,
1086      23,22,
1087 @@ -7487,9 +8143,14 @@ order_regs_for_local_alloc (void)
1088      32,33,34,35
1089    };
1090    
1091 -  const int *order = (TARGET_ORDER_1 ? order_1 :
1092 -                     TARGET_ORDER_2 ? order_2 :
1093 -                     order_0);
1094 +  /*
1095 +  Select specific register allocation order. Tiny Core (attiny4/5/9/10/20/40)
1096 +  devices has only 16 registers, so different allocation order should be used
1097 +  */ 
1098 +  const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1) :
1099 +             TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_1 : order_2) :
1100 +                                       (AVR_TINY ? tiny_order_0 : order_0));
1101 +
1102    for (i=0; i < ARRAY_SIZE (order_0); ++i)
1103        reg_alloc_order[i] = order[i];
1104  }
1105 @@ -9151,7 +9812,7 @@ output_reload_in_const (rtx *op, rtx clo
1106          {
1107            if (!clear_p)
1108              avr_asm_len (ldreg_p ? "ldi %0,0"
1109 -                         : ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
1110 +                         : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
1111                           : "mov %0,__zero_reg__",
1112                           &xdest[n], len, 1);
1113            continue;
1114 @@ -9350,6 +10011,50 @@ avr_output_addr_vec_elt (FILE *stream, i
1115      fprintf (stream, "\trjmp .L%d\n", value);
1116  }
1117  
1118 +static void
1119 +avr_conditional_register_usage(void) {
1120 +
1121 +  if (AVR_TINY) {
1122 +    unsigned int i;
1123 +
1124 +    const int tiny_reg_alloc_order[] = {
1125 +      24,25,
1126 +      22,23,
1127 +      30,31,
1128 +      26,27,
1129 +      28,29,
1130 +      21,20,19,18,
1131 +      16,17,
1132 +      32,33,34,35,
1133 +      15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
1134 +    };
1135 +
1136 +    /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
1137 +    - R0-R15 are not available in Tiny Core devices
1138 +    - R16 and R17 are fixed registers
1139 +    */
1140 +    for (i = 0;  i <= 17;  i++) {
1141 +      fixed_regs[i] = 1;
1142 +      call_used_regs[i] = 1;
1143 +    }
1144 +
1145 +    /* Set R18 to R21 as callee saved registers
1146 +    - R18, R19, R20 and R21 are the callee saved registers in Tiny Core devices
1147 +    */
1148 +    for (i = 18; i <= LAST_CALLEE_SAVED_REG; i++) {
1149 +      call_used_regs[i] = 0;
1150 +    }
1151 +
1152 +    /*update register allocation order for Tiny Core devices */
1153 +    for (i=0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++) {
1154 +      reg_alloc_order[i] = tiny_reg_alloc_order[i];
1155 +    }
1156 +
1157 +    CLEAR_HARD_REG_SET(reg_class_contents[(int)ADDW_REGS]);
1158 +    CLEAR_HARD_REG_SET(reg_class_contents[(int)NO_LD_REGS]);
1159 +  }
1160 +}
1161 +
1162  /* Returns true if SCRATCH are safe to be allocated as a scratch
1163     registers (for a define_peephole2) in the current function.  */
1164  
1165 @@ -9495,13 +10200,20 @@ avr_asm_out_dtor (rtx symbol, int priori
1166  static bool
1167  avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1168  {
1169 -  if (TYPE_MODE (type) == BLKmode)
1170 -    {
1171 -      HOST_WIDE_INT size = int_size_in_bytes (type);
1172 -      return (size == -1 || size > 8);
1173 -    }
1174 +  HOST_WIDE_INT size = int_size_in_bytes (type);
1175 +  HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;                                      
1176 +
1177 +  /* In avr, there are 8 return registers. But, for Tiny Core 
1178 +  (attiny4/5/9/10/20/40) devices, only 4 registers available.
1179 +  Return true if size is unknown or greater than the limit */
1180 +  if ((size == -1) || (size > ret_size_limit))
1181 +  {
1182 +    return true;
1183 +  }
1184    else
1185 +  {
1186      return false;
1187 +  }
1188  }
1189  
1190  /* Worker function for CASE_VALUES_THRESHOLD.  */
1191 @@ -10949,6 +11661,9 @@ avr_fold_builtin (tree fndecl, int n_arg
1192  #undef  TARGET_BUILTIN_SETJMP_FRAME_VALUE
1193  #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
1194  
1195 +#undef TARGET_CONDITIONAL_REGISTER_USAGE
1196 +#define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
1197 +
1198  #undef  TARGET_HARD_REGNO_SCRATCH_OK
1199  #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
1200  #undef  TARGET_CASE_VALUES_THRESHOLD
1201 diff -Naurp gcc/config/avr/avr-c.c gcc/config/avr/avr-c.c
1202 --- gcc/config/avr/avr-c.c      2012-09-05 17:49:47.000000000 +0530
1203 +++ gcc/config/avr/avr-c.c      2013-01-21 18:40:04.000000000 +0530
1204 @@ -113,6 +113,23 @@ avr_cpu_cpp_builtins (struct cpp_reader 
1205      }
1206    if (AVR_XMEGA)
1207      cpp_define (pfile, "__AVR_XMEGA__");
1208 +
1209 +  if (AVR_TINY)
1210 +    {
1211 +      cpp_define (pfile, "__AVR_TINY__");
1212 +
1213 +      /* Define macro "__AVR_TINY_PM_BASE_ADDRESS__" with mapped program memory
1214 +         start address. This macro shall be referred where mapped program memory
1215 +         is accessed. (Eg. copying data section (do_copy_data) contents to data
1216 +         memory region.
1217 +         NOTE:
1218 +         Program memory of AVR_TINY devices can not be accessed directly, it has
1219 +         been mapped to the data memory. For AVR_TINY devices (ATtiny4/ 5/ 9/ 10/
1220 +         20 and 40) mapped program memory starts at 0x4000.
1221 +      */
1222 +      cpp_define (pfile, "__AVR_TINY_PM_BASE_ADDRESS__=0x4000");
1223 +    }
1224 +
1225    if (avr_current_arch->have_eijmp_eicall)
1226      {
1227        cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
1228 diff -Naurp gcc/config/avr/avr-devices.c gcc/config/avr/avr-devices.c
1229 --- gcc/config/avr/avr-devices.c        2012-08-06 20:04:27.000000000 +0530
1230 +++ gcc/config/avr/avr-devices.c        2013-01-21 18:40:04.000000000 +0530
1231 @@ -30,29 +30,30 @@ const struct base_arch_s
1232  avr_arch_types[] =
1233  {
1234    /* unknown device specified */
1235 -  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL,              "avr2"  },
1236 +  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL,              "avr2"  },
1237    /*
1238 -    A  M  J  LM E  E  E  X  R   d S   S O   A
1239 -    S  U  M  PO L  L  I  M  A   a t   F ff  r
1240 -    M  L  P  MV P  P  J  E  M   t a   R s   c 
1241 -             XW M  M  M  G  P   a r     e   h
1242 -                   X  P  A  D     t     t   ID   */
1243 -  { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "1",   "avr1"  },
1244 -  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "2",   "avr2"  },
1245 -  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "25",  "avr25" },
1246 -  { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "3",   "avr3"  },
1247 -  { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, 32, "31",  "avr31" },
1248 -  { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, "35",  "avr35" },
1249 -  { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "4",   "avr4"  },
1250 -  { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, "5",   "avr5"  },
1251 -  { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, "51",  "avr51" },
1252 -  { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, 32, "6",   "avr6"  },
1253 +    A  M  J  LM E  E  E  X  R  T  d S   S O   A
1254 +    S  U  M  PO L  L  I  M  A  I  a t   F ff  r
1255 +    M  L  P  MV P  P  J  E  M  N  t a   R s   c 
1256 +             XW M  M  M  G  P  Y  a r     e   h
1257 +                   X  P  A  D       t     t   ID   */
1258 +  { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "1",   "avr1"  },
1259 +  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "2",   "avr2"  },
1260 +  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "25",  "avr25" },
1261 +  { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "3",   "avr3"  },
1262 +  { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "31",  "avr31" },
1263 +  { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "35",  "avr35" },
1264 +  { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "4",   "avr4"  },
1265 +  { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "5",   "avr5"  },
1266 +  { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0x0060, 32, "51",  "avr51" },
1267 +  { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, "6",   "avr6"  },
1268  
1269 -  { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0x2000,  0, "102", "avrxmega2" },
1270 -  { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0x2000,  0, "104", "avrxmega4" },
1271 -  { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0x2000,  0, "105", "avrxmega5" },
1272 -  { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000,  0, "106", "avrxmega6" },
1273 -  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0x2000,  0, "107", "avrxmega7" }
1274 +  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x0040,  0, "100", "avrtiny" },
1275 +  { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000,  0, "102", "avrxmega2" },
1276 +  { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0x2000,  0, "104", "avrxmega4" },
1277 +  { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0x2000,  0, "105", "avrxmega5" },
1278 +  { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0x2000,  0, "106", "avrxmega6" },
1279 +  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000,  0, "107", "avrxmega7" }
1280  };
1281  
1282  const struct mcu_type_s avr_mcu_types[] = {
1283 diff -Naurp gcc/config/avr/avr.h gcc/config/avr/avr.h
1284 --- gcc/config/avr/avr.h        2013-01-21 18:26:07.000000000 +0530
1285 +++ gcc/config/avr/avr.h        2013-01-21 18:40:04.000000000 +0530
1286 @@ -52,6 +52,9 @@ struct base_arch_s
1287    /* This core has the RAMPD special function register
1288       and thus also the RAMPX, RAMPY and RAMPZ registers.  */
1289    int have_rampd;
1290 +
1291 +  /* This is a TINY core.  */
1292 +  int tiny_p;
1293    
1294    /* Default start of data section address for architecture.  */
1295    int default_data_section_start;
1296 @@ -83,6 +86,7 @@ enum avr_arch
1297    ARCH_AVR5,
1298    ARCH_AVR51,
1299    ARCH_AVR6,
1300 +  ARCH_AVRTINY,
1301    ARCH_AVRXMEGA2,
1302    ARCH_AVRXMEGA4,
1303    ARCH_AVRXMEGA5,
1304 @@ -213,6 +217,7 @@ enum
1305  #define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL)
1306  
1307  #define AVR_XMEGA (avr_current_arch->xmega_p)
1308 +#define AVR_TINY  (avr_current_arch->tiny_p)
1309  
1310  #define BITS_BIG_ENDIAN 0
1311  #define BYTES_BIG_ENDIAN 0
1312 @@ -342,7 +347,6 @@ enum reg_class {
1313    ALL_REGS, LIM_REG_CLASSES
1314  };
1315  
1316 -
1317  #define N_REG_CLASSES (int)LIM_REG_CLASSES
1318  
1319  #define REG_CLASS_NAMES {                                      \
1320 @@ -417,7 +421,7 @@ enum reg_class {
1321  
1322  #define ARG_POINTER_REGNUM 34
1323  
1324 -#define STATIC_CHAIN_REGNUM 2
1325 +#define STATIC_CHAIN_REGNUM ((AVR_TINY) ? 18 :2)
1326  
1327  #define ELIMINABLE_REGS {                                      \
1328        {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},              \
1329 diff -Naurp gcc/config/avr/avr-mcus.def gcc/config/avr/avr-mcus.def
1330 --- gcc/config/avr/avr-mcus.def 2012-09-10 16:16:27.000000000 +0530
1331 +++ gcc/config/avr/avr-mcus.def 2013-01-21 18:40:04.000000000 +0530
1332 @@ -231,6 +231,14 @@ AVR_MCU ("atxmega256d3",     ARCH_AVRXME
1333  AVR_MCU ("avrxmega7",        ARCH_AVRXMEGA7, NULL,                       0, 0, 0x2000, 3, "x128a1")
1334  AVR_MCU ("atxmega128a1",     ARCH_AVRXMEGA7, "__AVR_ATxmega128A1__",     0, 0, 0x2000, 3, "x128a1")
1335  AVR_MCU ("atxmega128a1u",    ARCH_AVRXMEGA7, "__AVR_ATxmega128A1U__",    0, 0, 0x2000, 3, "x128a1u")
1336 +/* Tiny family */
1337 +AVR_MCU ("avrtiny",          ARCH_AVRTINY,   NULL,                       0, 0, 0x0040, 1, "tn10")
1338 +AVR_MCU ("attiny4",          ARCH_AVRTINY,   "__AVR_ATtiny4__",          0, 0, 0x0040, 1, "tn4")
1339 +AVR_MCU ("attiny5",          ARCH_AVRTINY,   "__AVR_ATtiny5__",          0, 0, 0x0040, 1, "tn5")
1340 +AVR_MCU ("attiny9",          ARCH_AVRTINY,   "__AVR_ATtiny9__",          0, 0, 0x0040, 1, "tn9") 
1341 +AVR_MCU ("attiny10",         ARCH_AVRTINY,   "__AVR_ATtiny10__",         0, 0, 0x0040, 1, "tn10")
1342 +AVR_MCU ("attiny20",         ARCH_AVRTINY,   "__AVR_ATtiny20__",         0, 0, 0x0040, 1, "tn20")
1343 +AVR_MCU ("attiny40",         ARCH_AVRTINY,   "__AVR_ATtiny40__",         0, 0, 0x0040, 1, "tn40")
1344  /* Assembler only.  */
1345  AVR_MCU ("avr1",                 ARCH_AVR1, NULL,                        0, 0, 0x0060, 1, "s1200")
1346  AVR_MCU ("at90s1200",            ARCH_AVR1, "__AVR_AT90S1200__",         0, 0, 0x0060, 1, "s1200")
1347 diff -Naurp gcc/config/avr/avr.md gcc/config/avr/avr.md
1348 --- gcc/config/avr/avr.md       2012-03-22 20:36:57.000000000 +0530
1349 +++ gcc/config/avr/avr.md       2013-01-21 18:40:04.000000000 +0530
1350 @@ -59,6 +59,11 @@
1351     (ZERO_REGNO  1)      ; zero register r1
1352     ])
1353  
1354 +(define_constants
1355 +  [ (TMP_REGNO_TINY 16)  ; r16 is temp register for TINY10
1356 +    (ZERO_REGNO_TINY 17) ; r17 is zero register for TINY10
1357 +  ])
1358 +
1359  (define_c_enum "unspec"
1360    [UNSPEC_STRLEN
1361     UNSPEC_MOVMEM
1362 @@ -158,9 +163,10 @@
1363  ;; lpm  : ISA has no LPMX                lpmx  : ISA has LPMX
1364  ;; elpm : ISA has ELPM but no ELPMX      elpmx : ISA has ELPMX
1365  ;; no_xmega: non-XMEGA core              xmega : XMEGA core
1366 +;; no_tiny:  non-TINY core               tiny  : TINY core
1367  
1368  (define_attr "isa"
1369 -  "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega,
1370 +  "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega, no_tiny,tiny,
1371     standard"
1372    (const_string "standard"))
1373  
1374 @@ -212,9 +218,18 @@
1375                (match_test "AVR_XMEGA"))
1376           (const_int 1)
1377  
1378 +         (and (eq_attr "isa" "tiny")
1379 +              (match_test "AVR_TINY"))
1380 +         (const_int 1)
1381 +
1382           (and (eq_attr "isa" "no_xmega")
1383                (match_test "!AVR_XMEGA"))
1384           (const_int 1)
1385 +
1386 +         (and (eq_attr "isa" "no_tiny")
1387 +              (match_test "!AVR_TINY"))
1388 +         (const_int 1)
1389 +
1390           ] (const_int 0)))
1391  
1392  
1393 @@ -5413,18 +5428,18 @@
1394     (set_attr "cc" "clobber")])
1395  
1396  (define_insn "delay_cycles_2"
1397 -  [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n")
1398 +  [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n,n")
1399                       (const_int 2)]
1400                      UNSPECV_DELAY_CYCLES)
1401     (set (match_operand:BLK 1 "" "")
1402         (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
1403 -   (clobber (match_scratch:HI 2 "=&w"))]
1404 +   (clobber (match_scratch:HI 2 "=&w,&d"))]
1405    ""
1406 -  "ldi %A2,lo8(%0)
1407 -       ldi %B2,hi8(%0)
1408 -       1: sbiw %A2,1
1409 -       brne 1b"
1410 -  [(set_attr "length" "4")
1411 +  "@
1412 +    ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\;1: sbiw %A2,1\;brne 1b
1413 +    ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\;1: subi %A2,1\;sbci %B2,0\;brne 1b"
1414 +  [(set_attr "length" "4,5")
1415 +   (set_attr "isa" "no_tiny,tiny")
1416     (set_attr "cc" "clobber")])
1417  
1418  (define_insn "delay_cycles_3"
1419 diff -Naurp gcc/config/avr/avr-tables.opt gcc/config/avr/avr-tables.opt
1420 --- gcc/config/avr/avr-tables.opt       2012-09-20 12:53:55.000000000 +0530
1421 +++ gcc/config/avr/avr-tables.opt       2013-01-21 18:40:04.000000000 +0530
1422 @@ -579,20 +579,41 @@ EnumValue
1423  Enum(avr_mcu) String(atxmega128a1u) Value(184)
1424  
1425  EnumValue
1426 -Enum(avr_mcu) String(avr1) Value(185)
1427 +Enum(avr_mcu) String(avrtiny) Value(185)
1428  
1429  EnumValue
1430 -Enum(avr_mcu) String(at90s1200) Value(186)
1431 +Enum(avr_mcu) String(attiny4) Value(186)
1432  
1433  EnumValue
1434 -Enum(avr_mcu) String(attiny11) Value(187)
1435 +Enum(avr_mcu) String(attiny5) Value(187)
1436  
1437  EnumValue
1438 -Enum(avr_mcu) String(attiny12) Value(188)
1439 +Enum(avr_mcu) String(attiny9) Value(188)
1440  
1441  EnumValue
1442 -Enum(avr_mcu) String(attiny15) Value(189)
1443 +Enum(avr_mcu) String(attiny10) Value(189)
1444  
1445  EnumValue
1446 -Enum(avr_mcu) String(attiny28) Value(190)
1447 +Enum(avr_mcu) String(attiny20) Value(190)
1448 +
1449 +EnumValue
1450 +Enum(avr_mcu) String(attiny40) Value(191)
1451 +
1452 +EnumValue
1453 +Enum(avr_mcu) String(avr1) Value(192)
1454 +
1455 +EnumValue
1456 +Enum(avr_mcu) String(at90s1200) Value(193)
1457 +
1458 +EnumValue
1459 +Enum(avr_mcu) String(attiny11) Value(194)
1460 +
1461 +EnumValue
1462 +Enum(avr_mcu) String(attiny12) Value(195)
1463 +
1464 +EnumValue
1465 +Enum(avr_mcu) String(attiny15) Value(196)
1466 +
1467 +EnumValue
1468 +Enum(avr_mcu) String(attiny28) Value(197)
1469  
1470 diff -Naurp gcc/config/avr/t-multilib gcc/config/avr/t-multilib
1471 --- gcc/config/avr/t-multilib   2012-09-20 12:53:55.000000000 +0530
1472 +++ gcc/config/avr/t-multilib   2013-01-21 18:40:04.000000000 +0530
1473 @@ -21,9 +21,9 @@
1474  # along with GCC; see the file COPYING3.  If not see
1475  # <http://www.gnu.org/licenses/>.
1476  
1477 -MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7 msp8
1478 +MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7/mmcu=avrtiny msp8
1479  
1480 -MULTILIB_DIRNAMES =  avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack avr25/tiny-stack
1481 +MULTILIB_DIRNAMES =  avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny tiny-stack avr25/tiny-stack
1482  
1483  MULTILIB_EXCEPTIONS = \
1484         mmcu=avr3/msp8 \
1485 @@ -37,7 +37,8 @@ MULTILIB_EXCEPTIONS = \
1486         mmcu=avrxmega4/msp8 \
1487         mmcu=avrxmega5/msp8 \
1488         mmcu=avrxmega6/msp8 \
1489 -       mmcu=avrxmega7/msp8
1490 +       mmcu=avrxmega7/msp8 \
1491 +       mmcu=avrtiny/msp8
1492  
1493  MULTILIB_MATCHES = \
1494         mmcu?avr2=mmcu?at90s2313 \
1495 @@ -210,4 +211,10 @@ MULTILIB_MATCHES = \
1496         mmcu?avrxmega6=mmcu?atxmega256a3bu \
1497         mmcu?avrxmega6=mmcu?atxmega256d3 \
1498         mmcu?avrxmega7=mmcu?atxmega128a1 \
1499 -       mmcu?avrxmega7=mmcu?atxmega128a1u
1500 +       mmcu?avrxmega7=mmcu?atxmega128a1u \
1501 +       mmcu?avrtiny=mmcu?attiny4 \
1502 +       mmcu?avrtiny=mmcu?attiny5 \
1503 +       mmcu?avrtiny=mmcu?attiny9 \
1504 +       mmcu?avrtiny=mmcu?attiny10 \
1505 +       mmcu?avrtiny=mmcu?attiny20 \
1506 +       mmcu?avrtiny=mmcu?attiny40
1507 diff -Naurp libgcc/config/avr/lib1funcs.S libgcc/config/avr/lib1funcs.S
1508 --- libgcc/config/avr/lib1funcs.S       2012-03-28 14:34:11.000000000 +0530
1509 +++ libgcc/config/avr/lib1funcs.S       2013-01-21 18:58:03.000000000 +0530
1510 @@ -22,8 +22,13 @@ a copy of the GCC Runtime Library Except
1511  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
1512  <http://www.gnu.org/licenses/>.  */
1513  
1514 +#if defined (__AVR_TINY__)
1515 +#define __zero_reg__ r17
1516 +#define __tmp_reg__ r16
1517 +#else
1518  #define __zero_reg__ r1
1519  #define __tmp_reg__ r0
1520 +#endif
1521  #define __SREG__ 0x3f
1522  #if defined (__AVR_HAVE_SPH__)
1523  #define __SP_H__ 0x3e
1524 @@ -80,6 +85,15 @@ see the files COPYING3 and COPYING.RUNTI
1525  #define XJMP  rjmp
1526  #endif
1527  
1528 +.macro wsubi r_arg1, i_arg2
1529 +#if defined (__AVR_TINY__)
1530 +    subi \r_arg1,   lo8(\i_arg2)
1531 +    sbci \r_arg1+1, hi8(\i_arg2)
1532 +#else
1533 +    sbiw \r_arg1, \i_arg2
1534 +#endif
1535 +.endm
1536 +
1537  .macro DEFUN name
1538  .global \name
1539  .func \name
1540 @@ -150,12 +164,12 @@ ENDF __umulqihi3
1541      Multiplication  16 x 16  without MUL
1542  *******************************************************/
1543  #if defined (L_mulhi3)
1544 -#define        r_arg1L r24             /* multiplier Low */
1545 -#define        r_arg1H r25             /* multiplier High */
1546 -#define        r_arg2L r22             /* multiplicand Low */
1547 -#define        r_arg2H r23             /* multiplicand High */
1548 +#define        r_arg1L 24              /* multiplier Low */
1549 +#define        r_arg1H 25              /* multiplier High */
1550 +#define        r_arg2L 22              /* multiplicand Low */
1551 +#define        r_arg2H 23              /* multiplicand High */
1552  #define r_resL __tmp_reg__     /* result Low */
1553 -#define r_resH  r21            /* result High */
1554 +#define r_resH  21             /* result High */
1555  
1556  DEFUN __mulhi3
1557         clr     r_resH          ; clear result
1558 @@ -175,7 +189,7 @@ __mulhi3_skip1:     
1559  
1560         lsr     r_arg1H         ; gets LSB of multiplier
1561         ror     r_arg1L
1562 -       sbiw    r_arg1L,0
1563 +       wsubi   r_arg1L,0
1564         brne    __mulhi3_loop   ; exit if multiplier = 0
1565  __mulhi3_exit:
1566         mov     r_arg1H,r_resH  ; result to return register
1567 @@ -230,22 +244,34 @@ ENDF __umulhisi3
1568  /*******************************************************
1569      Multiplication  32 x 32  without MUL
1570  *******************************************************/
1571 -#define r_arg1L  r22           /* multiplier Low */
1572 -#define r_arg1H  r23
1573 -#define        r_arg1HL r24
1574 -#define        r_arg1HH r25            /* multiplier High */
1575 -
1576 -#define        r_arg2L  r18            /* multiplicand Low */
1577 -#define        r_arg2H  r19    
1578 -#define        r_arg2HL r20
1579 -#define        r_arg2HH r21            /* multiplicand High */
1580 +#define r_arg1L  22            /* multiplier Low */
1581 +#define r_arg1H  23
1582 +#define        r_arg1HL 24
1583 +#define        r_arg1HH 25             /* multiplier High */
1584 +
1585 +#define        r_arg2L  18             /* multiplicand Low */
1586 +#define        r_arg2H  19     
1587 +#define        r_arg2HL 20
1588 +#define        r_arg2HH 21             /* multiplicand High */
1589         
1590 -#define r_resL  r26            /* result Low */
1591 -#define r_resH   r27
1592 -#define r_resHL         r30
1593 -#define r_resHH  r31           /* result High */
1594 +#define r_resL  26             /* result Low */
1595 +#define r_resH   27
1596 +#define r_resHL         30
1597 +#define r_resHH  31            /* result High */
1598  
1599  DEFUN __mulsi3
1600 +#if defined (__AVR_TINY__)
1601 +    in r26,__SP_L__ ; safe to use X, as it is r_resL/H
1602 +    in r27,__SP_H__
1603 +    subi r26, lo8(-3)   ; Add 3 to point past return address
1604 +    sbci r27, hi8(-3)
1605 +    push r_arg2L    ; save callee saved regs
1606 +    push r_arg2H
1607 +    ld r_arg2L,X+   ; load from caller stack 
1608 +    ld r_arg2H,X+
1609 +    ld r_arg2HL,X+
1610 +    ld r_arg2HH,X
1611 +#endif /* defined (__AVR_TINY__) */
1612         clr     r_resHH         ; clear result
1613         clr     r_resHL         ; clear result
1614         clr     r_resH          ; clear result
1615 @@ -268,7 +294,7 @@ __mulsi3_skip1:
1616         ror     r_arg1H
1617         ror     r_arg1L
1618         brne    __mulsi3_loop
1619 -       sbiw    r_arg1HL,0
1620 +       wsubi   r_arg1HL,0
1621         cpc     r_arg1H,r_arg1L
1622         brne    __mulsi3_loop           ; exit if multiplier = 0
1623  __mulsi3_exit:
1624 @@ -276,6 +302,10 @@ __mulsi3_exit:
1625         mov_l   r_arg1HL,r_resHL
1626         mov_h   r_arg1H,r_resH
1627         mov_l   r_arg1L,r_resL
1628 +#if defined (__AVR_TINY__)
1629 +    pop r_arg2H      ; restore callee saved regs
1630 +    pop r_arg2L
1631 +#endif  /* defined (__AVR_TINY__) */
1632         ret
1633  ENDF __mulsi3
1634  
1635 @@ -514,9 +544,12 @@ ENDF __mulpsi3
1636  #undef C0
1637  
1638  #else /* !HAVE_MUL */
1639 -
1640  ;; C[0..2]: Expand Result
1641 +#if defined (__AVR_TINY__)
1642 +#define C0  16
1643 +#else
1644  #define C0  0
1645 +#endif /* defined (__AVR_TINY__) */
1646  #define C1  C0+1
1647  #define C2  21
1648  
1649 @@ -524,6 +557,17 @@ ENDF __mulpsi3
1650  ;; Clobbers: __tmp_reg__, R18, R19, R20, R21
1651  
1652  DEFUN __mulpsi3
1653 +#if defined (__AVR_TINY__)
1654 +    in r26,__SP_L__ 
1655 +    in r27,__SP_H__
1656 +    subi r26, lo8(-3)   ; Add 3 to point past return address
1657 +    sbci r27, hi8(-3)
1658 +    push B0    ; save callee saved regs
1659 +    push B1
1660 +    ld B0,X+   ; load from caller stack 
1661 +    ld B1,X+
1662 +    ld B2,X+
1663 +#endif /* defined (__AVR_TINY__) */
1664  
1665      ;; C[] = 0
1666      clr     __tmp_reg__
1667 @@ -550,6 +594,10 @@ DEFUN __mulpsi3
1668      mov     A2, C2
1669  
1670      clr     __zero_reg__
1671 +#if defined (__AVR_TINY__)
1672 +    pop B1
1673 +    pop B0
1674 +#endif /* (__AVR_TINY__) */
1675      ret
1676  ENDF __mulpsi3
1677  
1678 @@ -618,6 +666,7 @@ ENDF __mulsqipsi3
1679         Multiplication 64 x 64
1680  *******************************************************/
1681  
1682 +#if !defined (__AVR_TINY__)
1683  #if defined (L_muldi3)
1684  
1685  ;; A[] = A[] * B[]
1686 @@ -855,6 +904,7 @@ ENDF __muldi3
1687  #undef A0
1688  
1689  #endif /* L_muldi3 */
1690 +#endif /* !defined (__AVR_TINY__) */
1691  
1692  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1693         
1694 @@ -1027,7 +1077,7 @@ ENDF __divmodhi4
1695  #define r_cnt   21
1696  
1697  #if defined (L_udivmodpsi4)
1698 -;; R24:R22 = R24:R22  udiv  R20:R18
1699 +;; R24:R22 = R24:R24  udiv  R20:R18
1700  ;; R20:R18 = R24:R22  umod  R20:R18
1701  ;; Clobbers: R21, R25, R26
1702  
1703 @@ -1248,6 +1298,10 @@ ENDF __divmodsi4
1704  #endif /* defined (L_divmodsi4) */
1705  
1706  
1707 +/* *di routines use registers below R19 and won't work with tiny arch
1708 +   right now. */
1709 +
1710 +#if !defined (__AVR_TINY__)
1711  /*******************************************************
1712         Division 64 / 64
1713         Modulo   64 % 64
1714 @@ -1665,12 +1719,15 @@ ENDF __negdi2
1715  #undef A1
1716  #undef A0
1717  
1718 +#endif /* !defined (__AVR_TINY__) */
1719 +
1720  \f
1721  .section .text.libgcc.prologue, "ax", @progbits
1722      
1723  /**********************************
1724   * This is a prologue subroutine
1725   **********************************/
1726 +#if !defined (__AVR_TINY__)
1727  #if defined (L_prologue)
1728  
1729  ;; This function does not clobber T-flag; 64-bit division relies on it
1730 @@ -1776,6 +1833,7 @@ DEFUN __epilogue_restores__
1731         ret
1732  ENDF __epilogue_restores__
1733  #endif /* defined (L_epilogue) */
1734 +#endif /* !defined (__AVR_TINY__) */
1735  
1736  #ifdef L_exit
1737         .section .fini9,"ax",@progbits
1738 @@ -1820,8 +1878,13 @@ DEFUN __tablejump__
1739  #else
1740         ijmp
1741  #endif
1742 -
1743 -#else /* !HAVE_LPMX */
1744 +#elif defined (__AVR_TINY__)
1745 +       wsubi 30, -(__AVR_TINY_PM_BASE_ADDRESS__) ; Add PM offset to Z
1746 +       ld __tmp_reg__, Z+
1747 +       ld r31, Z   ; Use ld instead of lpm to load Z
1748 +       mov r30, __tmp_reg__    
1749 +       ijmp
1750 +#else /* !HAVE_LPMX && !AVR_TINY */
1751         lpm
1752         adiw r30, 1
1753         push r0
1754 @@ -1836,6 +1899,26 @@ DEFUN __tablejump__
1755  ENDF __tablejump__
1756  #endif /* defined (L_tablejump) */
1757  
1758 +#if defined(__AVR_TINY__)
1759 +#ifdef L_copy_data
1760 +        .section .init4,"ax",@progbits
1761 +        .global __do_copy_data
1762 +__do_copy_data:
1763 +        ldi     r18, hi8(__data_end)
1764 +        ldi     r26, lo8(__data_start)
1765 +        ldi     r27, hi8(__data_start)
1766 +        ldi     r30, lo8(__data_load_start + __AVR_TINY_PM_BASE_ADDRESS__)
1767 +        ldi     r31, hi8(__data_load_start + __AVR_TINY_PM_BASE_ADDRESS__)
1768 +        rjmp    .L__do_copy_data_start
1769 +.L__do_copy_data_loop:
1770 +        ld      r19, z+
1771 +        st      X+, r19
1772 +.L__do_copy_data_start:
1773 +        cpi     r26, lo8(__data_end)
1774 +        cpc     r27, r18
1775 +        brne    .L__do_copy_data_loop
1776 +#endif
1777 +#else
1778  #ifdef L_copy_data
1779         .section .init4,"ax",@progbits
1780  DEFUN __do_copy_data
1781 @@ -1901,13 +1984,14 @@ DEFUN __do_copy_data
1782  #endif /* ELPM && RAMPD */
1783  ENDF __do_copy_data
1784  #endif /* L_copy_data */
1785 +#endif /* !defined (__AVR_TINY__) */
1786  
1787  /* __do_clear_bss is only necessary if there is anything in .bss section.  */
1788  
1789  #ifdef L_clear_bss
1790         .section .init4,"ax",@progbits
1791  DEFUN __do_clear_bss
1792 -       ldi     r17, hi8(__bss_end)
1793 +       ldi     r18, hi8(__bss_end)
1794         ldi     r26, lo8(__bss_start)
1795         ldi     r27, hi8(__bss_start)
1796         rjmp    .do_clear_bss_start
1797 @@ -1915,7 +1999,7 @@ DEFUN __do_clear_bss
1798         st      X+, __zero_reg__
1799  .do_clear_bss_start:
1800         cpi     r26, lo8(__bss_end)
1801 -       cpc     r27, r17
1802 +       cpc     r27, r18
1803         brne    .do_clear_bss_loop
1804  ENDF __do_clear_bss
1805  #endif /* L_clear_bss */
1806 @@ -1951,7 +2035,7 @@ DEFUN __do_global_ctors
1807         ldi     r29, hi8(__ctors_end)
1808         rjmp    .L__do_global_ctors_start
1809  .L__do_global_ctors_loop:
1810 -       sbiw    r28, 2
1811 +       wsubi   r28, 2
1812         mov_h   r31, r29
1813         mov_l   r30, r28
1814         XCALL   __tablejump__
1815 @@ -1994,7 +2078,11 @@ DEFUN __do_global_dtors
1816         mov_h   r31, r29
1817         mov_l   r30, r28
1818         XCALL   __tablejump__
1819 -       adiw    r28, 2
1820 +#if defined (__AVR_TINY__)
1821 +       wsubi   r28, -2
1822 +#else
1823 +       adiw    r28, 2
1824 +#endif
1825  .L__do_global_dtors_start:
1826         cpi     r28, lo8(__dtors_end)
1827         cpc     r29, r17
1828 @@ -2005,6 +2093,7 @@ ENDF __do_global_dtors
1829  
1830  .section .text.libgcc, "ax", @progbits
1831      
1832 +#if !defined (__AVR_TINY__)
1833  #ifdef L_tablejump_elpm
1834  DEFUN __tablejump_elpm__
1835  #if defined (__AVR_HAVE_ELPMX__)
1836 @@ -2035,7 +2124,9 @@ DEFUN __tablejump_elpm__
1837  #endif
1838  ENDF __tablejump_elpm__
1839  #endif /* defined (L_tablejump_elpm) */
1840 +#endif /* !defined (__AVR_TINY__) */
1841  
1842 +#if !defined (__AVR_TINY__)
1843  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1844  ;; Loading n bytes from Flash; n = 3,4
1845  ;; R22... = Flash[Z]
1846 @@ -2081,7 +2172,9 @@ ENDF __load_4
1847  #endif /* L_load_4 */
1848  
1849  #endif /* L_load_3 || L_load_3 */
1850 +#endif /* !defined (__AVR_TINY__) */
1851  
1852 +#if !defined (__AVR_TINY__)
1853  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1854  ;; Loading n bytes from Flash or RAM;  n = 1,2,3,4
1855  ;; R22... = Flash[R21:Z] or RAM[Z] depending on R21.7
1856 @@ -2207,7 +2300,9 @@ ENDF __xload_4
1857  #endif /* L_xload_4 */
1858  
1859  #endif /* L_xload_{1|2|3|4} */
1860 +#endif /* if !defined (__AVR_TINY__) */
1861  
1862 +#if !defined (__AVR_TINY__)
1863  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1864  ;; memcopy from Address Space __pgmx to RAM
1865  ;; R23:Z = Source Address
1866 @@ -2279,6 +2374,7 @@ ENDF __movmemx_hi
1867  #undef LOOP
1868  
1869  #endif /* L_movmemx */
1870 +#endif /* !defined (__AVR_TINY__) */ 
1871  
1872  \f
1873  .section .text.libgcc.builtins, "ax", @progbits
1874 diff -Naurp libgcc/config/avr/t-avr libgcc/config/avr/t-avr
1875 --- libgcc/config/avr/t-avr     2012-01-10 15:12:10.000000000 +0530
1876 +++ libgcc/config/avr/t-avr     2013-01-21 18:40:04.000000000 +0530
1877 @@ -1,13 +1,9 @@
1878  LIB1ASMSRC = avr/lib1funcs.S
1879 +
1880  LIB1ASMFUNCS = \
1881         _mulqi3 \
1882         _mulhi3 \
1883 -       _mulpsi3 _mulsqipsi3 \
1884 -       _mulhisi3 \
1885 -       _umulhisi3 \
1886 -       _usmulhisi3 \
1887 -       _muluhisi3 \
1888 -       _mulshisi3 \
1889 +    _mulpsi3 \
1890         _mulsi3 \
1891         _udivmodqi4 \
1892         _divmodqi4 \
1893 @@ -16,19 +12,9 @@ LIB1ASMFUNCS = \
1894         _divmodpsi4 _udivmodpsi4 \
1895         _udivmodsi4 \
1896         _divmodsi4 \
1897 -       _divdi3 _udivdi3 \
1898 -       _muldi3 \
1899 -       _udivmod64 \
1900 -       _negdi2 \
1901 -       _prologue \
1902 -       _epilogue \
1903         _exit \
1904         _cleanup \
1905         _tablejump \
1906 -       _tablejump_elpm \
1907 -       _load_3 _load_4 \
1908 -       _xload_1 _xload_2 _xload_3 _xload_4 \
1909 -       _movmemx \
1910         _copy_data \
1911         _clear_bss \
1912         _ctors \
1913 @@ -38,22 +24,52 @@ LIB1ASMFUNCS = \
1914         _loop_ffsqi2 \
1915         _ctzsi2 \
1916         _ctzhi2 \
1917 -       _clzdi2 \
1918         _clzsi2 \
1919         _clzhi2 \
1920 -       _paritydi2 \
1921         _paritysi2 \
1922         _parityhi2 \
1923         _popcounthi2 \
1924         _popcountsi2 \
1925 -       _popcountdi2 \
1926         _popcountqi2 \
1927         _bswapsi2 \
1928 +       _fmul _fmuls _fmulsu
1929 +
1930 +# The below functions either use registers that are not present
1931 +# in tiny core, or use a different register conventions (don't save
1932 +# callee saved regs, for example)
1933 +# _mulhisi3 and variations - clobber R18, R19
1934 +# All *di funcs - use regs < R16 or expect args in regs < R20
1935 +# _prologue and _epilogue save registers < R16
1936 +# _tablejump/_tablejump_elmp - expect lpm and elpm support
1937 +# _load ad _xload variations - expect lpm and elpm support
1938 +# _movmemx - expects elpm/lpm
1939 +
1940 +ifneq ($(MULTIFLAGS),-mmcu=avrtiny)
1941 +LIB1ASMFUNCS += \
1942 +    _mulsqipsi3 \
1943 +       _mulhisi3 \
1944 +       _umulhisi3 \
1945 +       _usmulhisi3 \
1946 +       _muluhisi3 \
1947 +       _mulshisi3 \
1948 +       _divdi3 _udivdi3 \
1949 +       _muldi3 \
1950 +       _udivmod64 \
1951 +       _negdi2 \
1952 +       _prologue \
1953 +       _epilogue \
1954 +       _tablejump_elpm \
1955 +       _load_3 _load_4 \
1956 +       _xload_1 _xload_2 _xload_3 _xload_4 \
1957 +       _movmemx \
1958 +       _clzdi2 \
1959 +       _paritydi2 \
1960 +       _popcountdi2 \
1961         _bswapdi2 \
1962         _ashldi3 _ashrdi3 _lshrdi3 _rotldi3 \
1963         _adddi3 _adddi3_s8 _subdi3 \
1964 -       _cmpdi2 _cmpdi2_s8 \
1965 -       _fmul _fmuls _fmulsu
1966 +       _cmpdi2 _cmpdi2_s8
1967 +endif
1968  
1969  LIB2FUNCS_EXCLUDE = \
1970         _moddi3 _umoddi3 \
This page took 0.295349 seconds and 3 git commands to generate.