This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

avr port: support `movw', call convention changed, etc


2000-07-01  Marek Michalkiewicz  <marekm@linux.org.pl>

	* config/avr/avr.c (out_adj_frame_ptr): Make "frame pointer
	change too big for -mtiny-stack" a warning, if larger than 63.
	(out_set_stack_ptr): Change the logic so -mno-interrupts is
	always safe to use on possible future devices.
	(function_prologue): Write SPH before SPL, for consistency.
	If interrupt_func_p true, we know we have enabled interrupts.
	(avr_num_arg_regs): New function.  Round up to even number of
	bytes if no -mpack-args or if calling a libgcc function.
	(function_arg, function_arg_advance): Use it.
	(output_movsisf, ashlsi3_out, ashrsi3_out, lshrsi3_out):
	Output "movw" if available.
	(out_tsthi, out_tstsi, ashlqi3_out, lshrqi3_out): Change uses
	of TEST_HARD_REG_CLASS macro to test_hard_reg_class function.
	(asm_output_section_name): Add blanks for consistent output.
	(encode_section_info): Set TREE_READONLY for progmem data to
	avoid gas warnings about changed section attributes.
	(avr_hard_regno_mode_ok): Force non-QImode data to start in
	even numbered registers on devices with "movw".
	* config/avr/avr.h (MASK_*): Define bits for target_flags.
	(TARGET_SWITCHES): Mark help strings for translation.
	Add new -mpack-args and -menhanced switches.
	(TARGET_OPTIONS): Mark help strings for translation.
	(progmem_section): Add section attributes.
	* config/avr/avr.md (*movhi, call_insn, call_value_insn):
	Output "movw" if available.
	(mulqi3, mulqihi3, umulqihi3, mulhi3, *tablejump_enh):
	New patterns.
	* config/avr/libgcc.S (_mulqi3, _divqi3): Update to the new
	call convention (arguments aligned on even registers).
	(_cleanup, _exit): Make weak symbols libc can override.


diff -Nrc3p orig/egcs/gcc/config/avr/avr.c egcs/gcc/config/avr/avr.c
*** orig/egcs/gcc/config/avr/avr.c	Sat Jun 24 20:33:48 2000
--- egcs/gcc/config/avr/avr.c	Sat Jul  1 14:42:38 2000
*************** static int    signal_function_p    PARAM
*** 49,54 ****
--- 49,55 ----
  static int    sequent_regs_live    PARAMS ((void));
  static char * ptrreg_to_str        PARAMS ((int));
  static char * cond_string          PARAMS ((enum rtx_code));
+ static int    avr_num_arg_regs     PARAMS ((enum machine_mode, tree));
  static int    out_adj_frame_ptr    PARAMS ((FILE *, int));
  static int    out_set_stack_ptr    PARAMS ((FILE *, int, int));
  
*************** out_adj_frame_ptr (file, adj)
*** 347,376 ****
  
    if (adj)
      {
!       /* For -mtiny-stack, the high byte (r29) does not change -
! 	 prefer "subi" (1 cycle) over "sbiw" (2 cycles).  */
! 
!       if (adj < -63 || adj > 63 || TARGET_TINY_STACK)
  	{
! 	  fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB), adj);
! 	  size++;
  
! 	  if (TARGET_TINY_STACK)
! 	    {
! 	      /* In addition to any local data, each level of function calls
! 		 needs at least 4 more bytes of stack space for the saved
! 		 frame pointer and return address.  So, (255 - 16) leaves
! 		 room for 4 levels of function calls.  */
! 
! 	      if (adj < -(255 - 16) || adj > (255 - 16))
! 		fatal ("Frame pointer change (%d) too big for -mtiny-stack",
! 		       adj);
! 	    }
! 	  else
! 	    {
! 	      fprintf (file, (AS2 (sbci, r29, hi8(%d)) CR_TAB), adj);
! 	      size++;
! 	    }
  	}
        else if (adj < 0)
  	{
--- 348,370 ----
  
    if (adj)
      {
!       if (TARGET_TINY_STACK)
  	{
! 	  if (adj < -63 || adj > 63)
! 	    warning ("large frame pointer change (%d) with -mtiny-stack", adj);
  
! 	  /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
! 	     over "sbiw" (2 cycles, same size).  */
! 
! 	  fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
! 	  size++;
! 	}
!       else if (adj < -63 || adj > 63)
! 	{
! 	  fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
! 			  AS2 (sbci, r29, hi8(%d)) CR_TAB),
! 			 adj, adj);
! 	  size += 2;
  	}
        else if (adj < 0)
  	{
*************** out_set_stack_ptr (file, before, after)
*** 398,414 ****
       int before;
       int after;
  {
!   int do_sph, do_cli, do_save, size;
  
!   if (TARGET_NO_INTERRUPTS)
!     {
!       before = 0;
!       after = 0;
!     }
  
    do_sph = !TARGET_TINY_STACK;
!   do_cli = (before != 0 && (after == 0 || do_sph));
!   do_save = (before == -1 && after == -1 && do_cli);
    size = 1;
  
    if (do_save)
--- 392,409 ----
       int before;
       int after;
  {
!   int do_sph, do_cli, do_save, do_sei, lock_sph, size;
  
!   /* The logic here is so that -mno-interrupts actually means
!      "it is safe to write SPH in one instruction, then SPL in the
!      next instruction, without disabling interrupts first".
!      The after != -1 case (interrupt/signal) is not affected.  */
  
    do_sph = !TARGET_TINY_STACK;
!   lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
!   do_cli = (before != 0 && (after == 0 || lock_sph));
!   do_save = (do_cli && before == -1 && after == -1);
!   do_sei = ((do_cli || before != 1) && after == 1);
    size = 1;
  
    if (do_save)
*************** out_set_stack_ptr (file, before, after)
*** 424,431 ****
      }
  
    /* Do SPH first - maybe this will disable interrupts for one instruction
!      someday, much like x86 does when changing SS (a suggestion has been
!      sent to avr@atmel.com for consideration in future devices).  */
    if (do_sph)
      {
        fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
--- 419,426 ----
      }
  
    /* Do SPH first - maybe this will disable interrupts for one instruction
!      someday (a suggestion has been sent to avr@atmel.com for consideration
!      in future devices - that would make -mno-interrupts always safe).  */
    if (do_sph)
      {
        fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
*************** out_set_stack_ptr (file, before, after)
*** 440,446 ****
        fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
        size++;
      }
!   else if (after == 1 && (before != 1 || do_cli))
      {
        fprintf (file, "sei" CR_TAB);
        size++;
--- 435,441 ----
        fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
        size++;
      }
!   else if (do_sei)
      {
        fprintf (file, "sei" CR_TAB);
        size++;
*************** function_prologue (FILE *file, int size)
*** 503,510 ****
        fprintf (file, ("\t" 
  		      AS2 (ldi, r28, lo8(%s - %d)) CR_TAB
  		      AS2 (ldi, r29, hi8(%s - %d)) CR_TAB
! 		      AS2 (out,__SP_L__,r28)       CR_TAB
! 		      AS2 (out,__SP_H__,r29) "\n"),
  	       initial_stack, size, initial_stack, size);
        
        prologue_size += 4;
--- 498,505 ----
        fprintf (file, ("\t" 
  		      AS2 (ldi, r28, lo8(%s - %d)) CR_TAB
  		      AS2 (ldi, r29, hi8(%s - %d)) CR_TAB
! 		      AS2 (out, __SP_H__, r29)     CR_TAB
! 		      AS2 (out, __SP_L__, r28) "\n"),
  	       initial_stack, size, initial_stack, size);
        
        prologue_size += 4;
*************** function_prologue (FILE *file, int size)
*** 569,575 ****
  
  		if (interrupt_func_p)
  		  {
! 		    prologue_size += out_set_stack_ptr (file, -1, 1);
  		  }
  		else if (signal_func_p)
  		  {
--- 564,570 ----
  
  		if (interrupt_func_p)
  		  {
! 		    prologue_size += out_set_stack_ptr (file, 1, 1);
  		  }
  		else if (signal_func_p)
  		  {
*************** init_cumulative_args (cum, fntype, libna
*** 1288,1293 ****
--- 1283,1315 ----
      }
  }
  
+ /* Returns the number of registers to allocate for a function argument.  */
+ 
+ static int
+ avr_num_arg_regs (mode, type)
+      enum machine_mode mode;
+      tree type;
+ {
+   int size;
+ 
+   if (mode == BLKmode)
+     size = int_size_in_bytes (type);
+   else
+     size = GET_MODE_SIZE (mode);
+ 
+   /* Align all function arguments to start in even-numbered registers,
+      for "movw" on the enhanced core (to keep call conventions the same
+      on all devices, do it even if "movw" is not available).  Odd-sized
+      arguments leave holes above them - registers still available for
+      other uses.  Use -mpack-args for compatibility with old asm code
+      (the new convention will still be used for libgcc calls).  */
+ 
+   if (!(type && TARGET_PACK_ARGS))
+     size += size & 1;
+ 
+   return size;
+ }
+ 
  /* Controls whether a function argument is passed
     in a register, and which register. */
  
*************** function_arg (cum, mode, type, named)
*** 1298,1309 ****
       tree type;
       int named ATTRIBUTE_UNUSED;
  {
!   int bytes;
! 
!   bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
  
    if (cum->nregs && bytes <= cum->nregs)
      return gen_rtx (REG, mode, cum->regno - bytes);
    return NULL_RTX;
  }
  
--- 1320,1330 ----
       tree type;
       int named ATTRIBUTE_UNUSED;
  {
!   int bytes = avr_num_arg_regs (mode, type);
  
    if (cum->nregs && bytes <= cum->nregs)
      return gen_rtx (REG, mode, cum->regno - bytes);
+ 
    return NULL_RTX;
  }
  
*************** function_arg_advance (cum, mode, type, n
*** 1317,1325 ****
       tree type;                 /* type of the argument or 0 if lib support */
       int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
  {
!   int bytes;
  
-   bytes = (mode == BLKmode ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
    cum->nregs -= bytes;
    cum->regno -= bytes;
  
--- 1338,1345 ----
       tree type;                 /* type of the argument or 0 if lib support */
       int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
  {
!   int bytes = avr_num_arg_regs (mode, type);
  
    cum->nregs -= bytes;
    cum->regno -= bytes;
  
*************** function_arg_advance (cum, mode, type, n
*** 1328,1335 ****
        cum->nregs = 0;
        cum->regno = FIRST_CUM_REG;
      }
- 
-   return;
  }
  
  /***********************************************************************
--- 1348,1353 ----
*************** output_movsisf(insn, operands, which_alt
*** 1788,1803 ****
      {
      case 0: /* mov r,r */
        if (true_regnum (operands[0]) > true_regnum (operands[1]))
!         return (AS2 (mov,%D0,%D1) CR_TAB
! 	        AS2 (mov,%C0,%C1) CR_TAB
! 		AS2 (mov,%B0,%B1) CR_TAB
! 		AS2 (mov,%A0,%A1));
!       else
!         return (AS2 (mov,%A0,%A1) CR_TAB
! 	        AS2 (mov,%B0,%B1) CR_TAB
! 		AS2 (mov,%C0,%C1) CR_TAB
! 		AS2 (mov,%D0,%D1));
      case 1:  /* mov r,L */
        return (AS1 (clr,%A0) CR_TAB
  	      AS1 (clr,%B0) CR_TAB
  	      AS1 (clr,%C0) CR_TAB
--- 1806,1838 ----
      {
      case 0: /* mov r,r */
        if (true_regnum (operands[0]) > true_regnum (operands[1]))
! 	{
! 	  if (TARGET_ENHANCED)
! 	    return (AS2 (movw,%C0,%C1) CR_TAB
! 		    AS2 (movw,%A0,%A1));  /* FIXME: length = 4 -> 2 */
! 	  else
! 	    return (AS2 (mov,%D0,%D1) CR_TAB
! 		    AS2 (mov,%C0,%C1) CR_TAB
! 		    AS2 (mov,%B0,%B1) CR_TAB
! 		    AS2 (mov,%A0,%A1));
! 	}
!       else
! 	{
! 	  if (TARGET_ENHANCED)
! 	    return (AS2 (movw,%A0,%A1) CR_TAB
! 		    AS2 (movw,%C0,%C1));  /* FIXME: length = 4 -> 2 */
! 	  else
! 	    return (AS2 (mov,%A0,%A1) CR_TAB
! 		    AS2 (mov,%B0,%B1) CR_TAB
! 		    AS2 (mov,%C0,%C1) CR_TAB
! 		    AS2 (mov,%D0,%D1));
! 	}
      case 1:  /* mov r,L */
+       if (TARGET_ENHANCED)
+ 	return (AS1 (clr,%A0) CR_TAB
+ 		AS1 (clr,%B0) CR_TAB
+ 		AS2 (movw,%C0,%A0));  /* FIXME: length = 4 -> 3 */
+ 
        return (AS1 (clr,%A0) CR_TAB
  	      AS1 (clr,%B0) CR_TAB
  	      AS1 (clr,%C0) CR_TAB
*************** out_tsthi (insn,l)
*** 2052,2058 ****
        if (l) *l = 1;
        return AS1 (tst,%B0);
      }
!   if (TEST_HARD_REG_CLASS (ADDW_REGS, true_regnum (SET_SRC (PATTERN (insn)))))
      {
        if (l) *l = 1;
        return AS2 (sbiw,%0,0);
--- 2087,2093 ----
        if (l) *l = 1;
        return AS1 (tst,%B0);
      }
!   if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
      {
        if (l) *l = 1;
        return AS2 (sbiw,%0,0);
*************** out_tstsi (insn,l)
*** 2080,2086 ****
        if (l) *l = 1;
        return AS1 (tst,%D0);
      }
!   if (TEST_HARD_REG_CLASS (ADDW_REGS, true_regnum (SET_SRC (PATTERN (insn)))))
      {
        if (l) *l = 3;
        return (AS2 (sbiw,%A0,0) CR_TAB
--- 2115,2121 ----
        if (l) *l = 1;
        return AS1 (tst,%D0);
      }
!   if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
      {
        if (l) *l = 3;
        return (AS2 (sbiw,%A0,0) CR_TAB
*************** out_shift_with_cnt (template,insn,operan
*** 2142,2148 ****
  	  *len = mov_len + 1;
  	}
      }
!   else if (register_operand (operands[2],QImode))
      {
        if (reg_unused_after (insn, operands[2]))
  	op[3] = op[2];
--- 2177,2183 ----
  	  *len = mov_len + 1;
  	}
      }
!   else if (register_operand (operands[2], QImode))
      {
        if (reg_unused_after (insn, operands[2]))
  	op[3] = op[2];
*************** ashlqi3_out (insn,operands,len)
*** 2211,2217 ****
  		  AS1 (lsl,%0));
  
  	case 4:
! 	  if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
  	    {
  	      *len = 2;
  	      return (AS1 (swap,%0) CR_TAB
--- 2246,2252 ----
  		  AS1 (lsl,%0));
  
  	case 4:
! 	  if (test_hard_reg_class (LD_REGS, operands[0]))
  	    {
  	      *len = 2;
  	      return (AS1 (swap,%0) CR_TAB
*************** ashlqi3_out (insn,operands,len)
*** 2224,2230 ****
  		  AS1 (lsl,%0));
  
  	case 5:
! 	  if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
  	    {
  	      *len = 3;
  	      return (AS1 (swap,%0) CR_TAB
--- 2259,2265 ----
  		  AS1 (lsl,%0));
  
  	case 5:
! 	  if (test_hard_reg_class (LD_REGS, operands[0]))
  	    {
  	      *len = 3;
  	      return (AS1 (swap,%0) CR_TAB
*************** ashlqi3_out (insn,operands,len)
*** 2239,2245 ****
  		  AS1 (lsl,%0));
  
  	case 6:
! 	  if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
  	    {
  	      *len = 4;
  	      return (AS1 (swap,%0) CR_TAB
--- 2274,2280 ----
  		  AS1 (lsl,%0));
  
  	case 6:
! 	  if (test_hard_reg_class (LD_REGS, operands[0]))
  	    {
  	      *len = 4;
  	      return (AS1 (swap,%0) CR_TAB
*************** ashlsi3_out (insn,operands,len)
*** 2376,2381 ****
--- 2411,2423 ----
  	    int reg0 = true_regnum (operands[0]);
  	    int reg1 = true_regnum (operands[1]);
  	    *len = 4;
+ 	    if (TARGET_ENHANCED && (reg0 + 2 != reg1))
+ 	      {
+ 		*len = 3;
+ 		return (AS2 (movw,%C0,%A1) CR_TAB
+ 			AS1 (clr,%B0)      CR_TAB
+ 			AS1 (clr,%A0));
+ 	      }
  	    if (reg0 + 1 >= reg1)
  	      return (AS2 (mov,%D0,%B1)  CR_TAB
  		      AS2 (mov,%C0,%A1)  CR_TAB
*************** ashrsi3_out (insn,operands,len)
*** 2610,2615 ****
--- 2652,2666 ----
  	    int reg0 = true_regnum (operands[0]);
  	    int reg1 = true_regnum (operands[1]);
  	    *len=6;
+ 	    if (TARGET_ENHANCED && (reg0 != reg1 + 2))
+ 	      {
+ 		*len = 5;
+ 		return (AS2 (movw,%A0,%C1) CR_TAB
+ 			AS1 (clr,%D0)      CR_TAB
+ 			AS2 (sbrc,%B0,7)   CR_TAB
+ 			AS1 (com,%D0)      CR_TAB
+ 			AS2 (mov,%C0,%D0));
+ 	      }
  	    if (reg0 <= reg1 + 1)
  	      return (AS2 (mov,%A0,%C1) CR_TAB
  		      AS2 (mov,%B0,%D1) CR_TAB
*************** lshrqi3_out (insn,operands,len)
*** 2693,2699 ****
  		  AS1 (lsr,%0));
  	  
  	case 4:
! 	  if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
  	    {
  	      *len=2;
  	      return (AS1 (swap,%0) CR_TAB
--- 2744,2750 ----
  		  AS1 (lsr,%0));
  	  
  	case 4:
! 	  if (test_hard_reg_class (LD_REGS, operands[0]))
  	    {
  	      *len=2;
  	      return (AS1 (swap,%0) CR_TAB
*************** lshrqi3_out (insn,operands,len)
*** 2706,2712 ****
  		  AS1 (lsr,%0));
  	  
  	case 5:
! 	  if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
  	    {
  	      *len = 3;
  	      return (AS1 (swap,%0) CR_TAB
--- 2757,2763 ----
  		  AS1 (lsr,%0));
  	  
  	case 5:
! 	  if (test_hard_reg_class (LD_REGS, operands[0]))
  	    {
  	      *len = 3;
  	      return (AS1 (swap,%0) CR_TAB
*************** lshrqi3_out (insn,operands,len)
*** 2721,2727 ****
  		  AS1 (lsr,%0));
  	  
  	case 6:
! 	  if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
  	    {
  	      *len = 4;
  	      return (AS1 (swap,%0) CR_TAB
--- 2772,2778 ----
  		  AS1 (lsr,%0));
  	  
  	case 6:
! 	  if (test_hard_reg_class (LD_REGS, operands[0]))
  	    {
  	      *len = 4;
  	      return (AS1 (swap,%0) CR_TAB
*************** lshrsi3_out (insn,operands,len)
*** 2860,2865 ****
--- 2911,2923 ----
  	    int reg0 = true_regnum (operands[0]);
  	    int reg1 = true_regnum (operands[1]);
  	    *len = 4;
+ 	    if (TARGET_ENHANCED && (reg0 != reg1 + 2))
+ 	      {
+ 		*len = 3;
+ 		return (AS2 (movw,%A0,%C1) CR_TAB
+ 			AS1 (clr,%C0)      CR_TAB
+ 			AS1 (clr,%D0));
+ 	      }
  	    if (reg0 <= reg1 + 1)
  	      return (AS2 (mov,%A0,%C1) CR_TAB
  		      AS2 (mov,%B0,%D1) CR_TAB
*************** asm_output_section_name(file, decl, name
*** 3275,3281 ****
       const char *name;
       int reloc ATTRIBUTE_UNUSED;
  {
!   fprintf (file, ".section\t%s,\"%s\",@progbits\n", name, \
  	   decl && TREE_CODE (decl) == FUNCTION_DECL ? "ax" :
  	   decl && TREE_READONLY (decl) ? "a" : "aw");
  }
--- 3333,3339 ----
       const char *name;
       int reloc ATTRIBUTE_UNUSED;
  {
!   fprintf (file, ".section %s, \"%s\", @progbits\n", name,
  	   decl && TREE_CODE (decl) == FUNCTION_DECL ? "ax" :
  	   decl && TREE_READONLY (decl) ? "a" : "aw");
  }
*************** valid_machine_type_attribute(type, attri
*** 3407,3415 ****
     Valid attributes:
     progmem - put data to program memory;
     signal - make a function to be hardware interrupt. After function
!    epilogue interrupts are disabled;
     interrupt - make a function to be hardware interrupt. After function
!    epilogue interrupts are enabled;
     naked     - don't generate function prologue/epilogue and `ret' command.  */
  
  int
--- 3465,3473 ----
     Valid attributes:
     progmem - put data to program memory;
     signal - make a function to be hardware interrupt. After function
!    prologue interrupts are disabled;
     interrupt - make a function to be hardware interrupt. After function
!    prologue interrupts are enabled;
     naked     - don't generate function prologue/epilogue and `ret' command.  */
  
  int
*************** valid_machine_decl_attribute (decl, attr
*** 3440,3446 ****
  
  
  /* Look for attribute `progmem' in DECL
!    founded - 1 otherwise 0 */
  
  int
  avr_progmem_p (decl)
--- 3498,3504 ----
  
  
  /* Look for attribute `progmem' in DECL
!    if found return 1, otherwise 0.  */
  
  int
  avr_progmem_p (decl)
*************** encode_section_info (decl)
*** 3481,3486 ****
--- 3539,3545 ----
      {
        char * dsec = ".progmem.data";
        DECL_SECTION_NAME (decl) = build_string (strlen (dsec), dsec);
+       TREE_READONLY (decl) = 1;
      }
  }   
  
*************** avr_function_value (type,func)
*** 3864,3870 ****
    return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
  }
  
! /* Returns non-zero if number MASK have only one setted bit */
  
  int
  mask_one_bit_p (mask)
--- 3923,3929 ----
    return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
  }
  
! /* Returns non-zero if the number MASK has only one bit set.  */
  
  int
  mask_one_bit_p (mask)
*************** mask_one_bit_p (mask)
*** 3892,3898 ****
     in class CLASS.  */
  
  enum reg_class
! preferred_reload_class(x,class)
       rtx x;
       enum reg_class class;
  {
--- 3951,3957 ----
     in class CLASS.  */
  
  enum reg_class
! preferred_reload_class (x, class)
       rtx x;
       enum reg_class class;
  {
*************** preferred_reload_class(x,class)
*** 3908,3914 ****
  }
  
  int
! test_hard_reg_class(class, x)
       enum reg_class class;
       rtx x;
  {
--- 3967,3973 ----
  }
  
  int
! test_hard_reg_class (class, x)
       enum reg_class class;
       rtx x;
  {
*************** jump_over_one_insn_p (insn, dest)
*** 3946,3954 ****
  }
  
  /* Returns 1 if a value of mode MODE can be stored starting with hard
!    register number REGNO.  On the enhanced core, it should be a win to
!    align modes larger than QI on even register numbers (even if < 24).
!    so that the "movw" instruction can be used on them.  */
  
  int
  avr_hard_regno_mode_ok (regno, mode)
--- 4005,4013 ----
  }
  
  /* Returns 1 if a value of mode MODE can be stored starting with hard
!    register number REGNO.  On the enhanced core, anything larger than
!    1 byte must start in even numbered register for "movw" to work
!    (this way we don't have to check for odd registers everywhere).  */
  
  int
  avr_hard_regno_mode_ok (regno, mode)
*************** avr_hard_regno_mode_ok (regno, mode)
*** 3957,3963 ****
  {
    if (mode == QImode)
      return 1;
!   if (regno < 24 /* && !TARGET_ENHANCED */ )
      return 1;
    return !(regno & 1);
  }
--- 4016,4022 ----
  {
    if (mode == QImode)
      return 1;
!   if (regno < 24 && !TARGET_ENHANCED)
      return 1;
    return !(regno & 1);
  }
diff -Nrc3p orig/egcs/gcc/config/avr/avr.h egcs/gcc/config/avr/avr.h
*** orig/egcs/gcc/config/avr/avr.h	Sat Jun 24 20:33:48 2000
--- egcs/gcc/config/avr/avr.h	Sat Jul  1 14:42:38 2000
*************** Boston, MA 02111-1307, USA.  */
*** 46,64 ****
  /* This declaration should be present. */
  extern int target_flags;
  
! #define TARGET_ORDER_1		(target_flags &  0x1000)
! #define TARGET_ORDER_2		(target_flags &  0x4000)
! #define TARGET_INT8  		(target_flags & 0x10000)
! #define TARGET_NO_INTERRUPTS	(target_flags & 0x20000)
! #define TARGET_INSN_SIZE_DUMP	(target_flags &  0x2000)
! #define TARGET_CALL_PROLOGUES	(target_flags & 0x40000)
! #define TARGET_TINY_STACK	(target_flags & 0x80000)
  
  /* Dump each assembler insn's rtl into the output file.
     This is for debugging the compiler itself.  */
  
! #define TARGET_RTL_DUMP		(target_flags &   0x010)
! #define TARGET_ALL_DEBUG 	(target_flags &   0xfe0)
  
  /* `TARGET_...'
     This series of macros is to allow compiler command arguments to
--- 46,78 ----
  /* This declaration should be present. */
  extern int target_flags;
  
! #define MASK_RTL_DUMP		0x00000010
! #define MASK_ALL_DEBUG		0x00000FE0
! #define MASK_ORDER_1		0x00001000
! #define MASK_INSN_SIZE_DUMP	0x00002000
! #define MASK_ORDER_2		0x00004000
! #define MASK_INT8		0x00010000
! #define MASK_NO_INTERRUPTS	0x00020000
! #define MASK_CALL_PROLOGUES	0x00040000
! #define MASK_TINY_STACK		0x00080000
! #define MASK_PACK_ARGS		0x00100000
! #define MASK_ENHANCED		0x00200000
! 
! #define TARGET_ORDER_1		(target_flags & MASK_ORDER_1)
! #define TARGET_ORDER_2		(target_flags & MASK_ORDER_2)
! #define TARGET_INT8  		(target_flags & MASK_INT8)
! #define TARGET_NO_INTERRUPTS	(target_flags & MASK_NO_INTERRUPTS)
! #define TARGET_INSN_SIZE_DUMP	(target_flags & MASK_INSN_SIZE_DUMP)
! #define TARGET_CALL_PROLOGUES	(target_flags & MASK_CALL_PROLOGUES)
! #define TARGET_TINY_STACK	(target_flags & MASK_TINY_STACK)
! #define TARGET_PACK_ARGS	(target_flags & MASK_PACK_ARGS)
! #define TARGET_ENHANCED		(target_flags & MASK_ENHANCED)
  
  /* Dump each assembler insn's rtl into the output file.
     This is for debugging the compiler itself.  */
  
! #define TARGET_RTL_DUMP		(target_flags & MASK_RTL_DUMP)
! #define TARGET_ALL_DEBUG 	(target_flags & MASK_ALL_DEBUG)
  
  /* `TARGET_...'
     This series of macros is to allow compiler command arguments to
*************** extern int target_flags;
*** 83,99 ****
  
  
  #define TARGET_SWITCHES {						\
!   {"order1",0x1000, NULL},						\
!   {"order2",0x4000, NULL},						\
!   {"int8",0x10000,"Assume int to be 8 bit integer"},			\
!   {"no-interrupts",0x20000,"Don't output interrupt compatible code"},	\
!   {"call-prologues",0x40000,						\
!    "Use subroutines for functions prologue/epilogue"},			\
!   {"tiny-stack", 0x80000, "Change only low 8 bits of stack pointer"},	\
!   {"rtl",0x10, NULL},							\
!   {"size",0x2000,"Output instruction size's to the asm file"},		\
!   {"deb",0xfe0, NULL},							\
!   {"",0, NULL}}
  /* This macro defines names of command options to set and clear bits
     in `target_flags'.  Its definition is an initializer with a
     subgrouping for each command option.
--- 97,120 ----
  
  
  #define TARGET_SWITCHES {						\
!   { "order1", MASK_ORDER_1, NULL },					\
!   { "order2", MASK_ORDER_2, NULL },					\
!   { "int8", MASK_INT8, N_("Assume int to be 8 bit integer") },		\
!   { "no-interrupts", MASK_NO_INTERRUPTS,				\
!     N_("Change the stack pointer without disabling interrupts") },	\
!   { "call-prologues", MASK_CALL_PROLOGUES,				\
!     N_("Use subroutines for function prologue/epilogue") },		\
!   { "tiny-stack", MASK_TINY_STACK,					\
!     N_("Change only the low 8 bits of the stack pointer") },		\
!   { "pack-args", MASK_PACK_ARGS,					\
!     N_("Do not align function arguments on even numbered registers") },	\
!   { "enhanced", MASK_ENHANCED,						\
!     N_("Generate code for the enhanced AVR core") },			\
!   { "rtl", MASK_RTL_DUMP, NULL },					\
!   { "size", MASK_INSN_SIZE_DUMP,					\
!     N_("Output instruction sizes to the asm file") },			\
!   { "deb", MASK_ALL_DEBUG, NULL },					\
!   { "", 0, NULL } }
  /* This macro defines names of command options to set and clear bits
     in `target_flags'.  Its definition is an initializer with a
     subgrouping for each command option.
*************** extern struct mcu_type_s *avr_mcu_type;
*** 129,137 ****
  #define AVR_MEGA (avr_mcu_type->mega)
  
  #define TARGET_OPTIONS {						      \
!  {"init-stack=",&avr_ram_end,"Specify the initial stack address" },	      \
!  {"mcu=", &avr_mcu_name,						      \
!   "Specify the MCU name (at90s23xx,attiny22,at90s44xx,at90s85xx,atmega603,atmega103)"}}
  /* This macro is similar to `TARGET_SWITCHES' but defines names of
     command options that have values.  Its definition is an
     initializer with a subgrouping for each command option.
--- 150,157 ----
  #define AVR_MEGA (avr_mcu_type->mega)
  
  #define TARGET_OPTIONS {						      \
!  { "init-stack=", &avr_ram_end, N_("Specify the initial stack address") },    \
!  { "mcu=", &avr_mcu_name, N_("Specify the MCU name") } }
  /* This macro is similar to `TARGET_SWITCHES' but defines names of
     command options that have values.  Its definition is an
     initializer with a subgrouping for each command option.
*************** progmem_section (void)							      \
*** 1984,1990 ****
  {									      \
    if (in_section != in_progmem)						      \
      {									      \
!       fprintf (asm_out_file, ".section .progmem.gcc_sw_table\n");	      \
        in_section = in_progmem;						      \
      }									      \
  }
--- 2004,2011 ----
  {									      \
    if (in_section != in_progmem)						      \
      {									      \
!       fprintf (asm_out_file,						      \
! 	       ".section .progmem.gcc_sw_table, \"a\", @progbits\n");	      \
        in_section = in_progmem;						      \
      }									      \
  }
diff -Nrc3p orig/egcs/gcc/config/avr/avr.md egcs/gcc/config/avr/avr.md
*** orig/egcs/gcc/config/avr/avr.md	Sat Jun 24 20:33:48 2000
--- egcs/gcc/config/avr/avr.md	Sat Jul  1 14:42:38 2000
***************
*** 249,254 ****
--- 249,257 ----
    switch (which_alternative)
      {
      case 0: /* mov r,r */
+       if (TARGET_ENHANCED)
+ 	return (AS2 (movw,%0,%1));  /* FIXME: length = 2 -> 1 */
+ 
        if (true_regnum (operands[0]) > true_regnum (operands[1]))
          return (AS2 (mov,%B0,%B1) CR_TAB
  	        AS2 (mov,%A0,%A1));
***************
*** 653,658 ****
--- 656,712 ----
    [(set_attr "length" "4,4")
     (set_attr "cc" "set_czn,set_czn")])
  
+ ;******************************************************************************
+ ; mul
+ 
+ (define_insn "mulqi3"
+   [(set (match_operand:QI 0 "register_operand" "=r")
+ 	(mult:QI (match_operand:QI 1 "register_operand" "r")
+ 		 (match_operand:QI 2 "register_operand" "r")))]
+   "TARGET_ENHANCED"
+   "mul %1,%2
+ 	mov %0,r0
+ 	clr r1"
+   [(set_attr "length" "3")
+    (set_attr "cc" "clobber")])
+ 
+ (define_insn "mulqihi3"
+   [(set (match_operand:HI 0 "register_operand" "=r")
+ 	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
+ 		 (sign_extend:HI (match_operand:QI 2 "register_operand" "d"))))]
+   "TARGET_ENHANCED"
+   "muls %1,%2
+ 	movw %0,r0
+ 	clr r1"
+   [(set_attr "length" "3")
+    (set_attr "cc" "clobber")])
+ 
+ (define_insn "umulqihi3"
+   [(set (match_operand:HI 0 "register_operand" "=r")
+ 	(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+ 		 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
+   "TARGET_ENHANCED"
+   "mul %1,%2
+ 	movw %0,r0
+ 	clr r1"
+   [(set_attr "length" "3")
+    (set_attr "cc" "clobber")])
+ 
+ (define_insn "mulhi3"
+   [(set (match_operand:HI 0 "register_operand" "=&r")
+ 	(mult:HI (match_operand:HI 1 "register_operand" "r")
+ 		 (match_operand:HI 2 "register_operand" "r")))]
+   "TARGET_ENHANCED"
+   "mul %A1,%A2
+ 	movw %0,r0
+ 	mul %A1,%B2
+ 	add %B0,r0
+ 	mul %B1,%A2
+ 	add %B0,r0
+ 	clr r1"
+   [(set_attr "length" "7")
+    (set_attr "cc" "clobber")])
+ 
  ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
  ; and
  
***************
*** 1604,1612 ****
    if (which_alternative==0)
       return \"icall\";
    else if (which_alternative==1)
!      return (AS2 (mov, r30,%A0) CR_TAB
! 	     AS2 (mov, r31,%B0) CR_TAB
! 	     \"icall\");
    else if (!AVR_MEGA)
       return AS1(rcall,%c0);   
    return AS1(call,%c0);
--- 1658,1672 ----
    if (which_alternative==0)
       return \"icall\";
    else if (which_alternative==1)
!     {
!       if (TARGET_ENHANCED)
! 	return (AS2 (movw, r30, %0) CR_TAB
! 		\"icall\");
!       else
! 	return (AS2 (mov, r30, %A0) CR_TAB
! 		AS2 (mov, r31, %B0) CR_TAB
! 		\"icall\");
!     }
    else if (!AVR_MEGA)
       return AS1(rcall,%c0);   
    return AS1(call,%c0);
***************
*** 1634,1642 ****
    if (which_alternative==0)
       return \"icall\";
    else if (which_alternative==1)
!      return (AS2 (mov, r30,%A1) CR_TAB
! 	     AS2 (mov, r31,%B1) CR_TAB
! 	     \"icall\");
    else if (!AVR_MEGA)
       return AS1(rcall,%c1);   
    return AS1(call,%c1);
--- 1694,1708 ----
    if (which_alternative==0)
       return \"icall\";
    else if (which_alternative==1)
!     {
!       if (TARGET_ENHANCED)
! 	return (AS2 (movw, r30, %1) CR_TAB
! 		\"icall\");
!       else
! 	return (AS2 (mov, r30, %A1) CR_TAB
! 		AS2 (mov, r31, %B1) CR_TAB
! 		\"icall\");
!     }
    else if (!AVR_MEGA)
       return AS1(rcall,%c1);   
    return AS1(call,%c1);
***************
*** 1676,1681 ****
--- 1742,1762 ----
    "optimize"
    "")
  
+ (define_insn "*tablejump_enh"
+    [(set (pc) (mem:HI
+ 	       (plus:HI (match_operand:HI 0 "register_operand" "=&z")
+ 			(label_ref (match_operand 2 "" "")))))
+     (use (label_ref (match_operand 1 "" "")))]
+   "TARGET_ENHANCED"
+   "subi r30,lo8(-(%2))
+ 	sbci r31,hi8(-(%2))
+ 	lpm __tmp_reg__,Z+
+ 	lpm r31,Z
+ 	mov r30,__tmp_reg__
+ 	ijmp"
+   [(set_attr "length" "6")
+    (set_attr "cc" "clobber")])
+ 
  (define_insn "*tablejump"
     [(set (pc) (mem:HI
  	       (plus:HI (match_operand:HI 0 "register_operand" "=&z")
***************
*** 1686,1695 ****
  	sbci r31,hi8(-(%2))
  	lpm
  	push r0
!         adiw r30,1
  	lpm
  	push r0
!         ret"
    [(set_attr "length" "8")
     (set_attr "cc" "clobber")])
  
--- 1767,1776 ----
  	sbci r31,hi8(-(%2))
  	lpm
  	push r0
! 	adiw r30,1
  	lpm
  	push r0
! 	ret"
    [(set_attr "length" "8")
     (set_attr "cc" "clobber")])
  
diff -Nrc3p orig/egcs/gcc/config/avr/libgcc.S egcs/gcc/config/avr/libgcc.S
*** orig/egcs/gcc/config/avr/libgcc.S	Sat Jun 24 20:33:49 2000
--- egcs/gcc/config/avr/libgcc.S	Sat Jul  1 14:42:38 2000
*************** Boston, MA 02111-1307, USA.  */
*** 39,45 ****
  *******************************************************/
  #if defined (Lmulqi3)
  
! #define	r_arg2	r25		/* multiplicand */
  #define	r_arg1 	r24		/* multiplier */
  #define r_res	__tmp_reg__	/* result */
  
--- 39,45 ----
  *******************************************************/
  #if defined (Lmulqi3)
  
! #define	r_arg2	r22		/* multiplicand */
  #define	r_arg1 	r24		/* multiplier */
  #define r_res	__tmp_reg__	/* result */
  
*************** __mulsi3_exit:
*** 201,208 ****
         Division 8 / 8 => (result + remainder)
  *******************************************************/
  #define	r_rem	r26	/* remainder */
! #define	r_arg1	r25	/* dividend */
! #define	r_arg2	r24	/* divisor */
  #define	r_cnt	r27	/* loop count */
  
  #if defined (Lumodqi3)
--- 201,208 ----
         Division 8 / 8 => (result + remainder)
  *******************************************************/
  #define	r_rem	r26	/* remainder */
! #define	r_arg1	r24	/* dividend */
! #define	r_arg2	r22	/* divisor */
  #define	r_cnt	r27	/* loop count */
  
  #if defined (Lumodqi3)
*************** __divqi3_1:
*** 272,279 ****
  	sbrc	__tmp_reg__,7
  	neg	r_arg1		; correct result sign
  __divqi3_exit:
! 	mov	r24,r_arg1	; put result to return register
! 	ret
  .endfunc
  #endif /* defined (Ldivqi3) */
  
--- 272,278 ----
  	sbrc	__tmp_reg__,7
  	neg	r_arg1		; correct result sign
  __divqi3_exit:
! 	ret			; result already in r24 (r_arg1)
  .endfunc
  #endif /* defined (Ldivqi3) */
  
*************** _umodsi3_ret:
*** 434,441 ****
  	mov	r24,r_remHL
  	mov	r23,r_remH
  	mov	r22,r_remL
- 	.global	_cleanup
- _cleanup:
  	ret
  .endfunc
  #endif /* defined (Lumodsi3) */
--- 433,438 ----
*************** __epilogue_restores__:
*** 630,638 ****
  #endif /* defined (Lepilogue) */
  
  #ifdef L__exit
! 	.global	_exit
  	.func	_exit
  _exit:
  	rjmp	_exit
  .endfunc
  #endif
--- 627,638 ----
  #endif /* defined (Lepilogue) */
  
  #ifdef L__exit
! 	.weak	_exit
  	.func	_exit
  _exit:
  	rjmp	_exit
+ 	.weak	_cleanup
+ _cleanup:
+ 	ret
  .endfunc
  #endif


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]