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]

RFA: m32r/x support



2001-11-07  Ben Elliston  <bje@redhat.com>
            Michael Meissner  <meissner@redhat.com>
            Andrew MacLeod  <amacleod@redhat.com>
            Richard Henderson  <rth@redhat.com>
            Nick Clifton  <nickc@redhat.com>
	    Catherine Moore  <clm@redhat.com>

	* rtl.def (GROUP_PARALLEL, GROUP_SEQUENCE): New.

	* m32r.c: Add support for m32rx processor.
	* m32r.h: Ditto.
	* m32r.md: Ditto.
	* t-m32r: Ditto.
	* m32r-protos.h: Add prototypes for m32rx functions.

Index: rtl.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.def,v
retrieving revision 1.50
diff -p -r1.50 rtl.def
*** rtl.def	2001/11/03 16:28:33	1.50
--- rtl.def	2001/11/06 15:34:12
*************** DEF_RTL_EXPR(SEQUENCE, "sequence", "E", 
*** 333,338 ****
--- 333,348 ----
  /* Refers to the address of its argument.  This is only used in alias.c.  */
  DEF_RTL_EXPR(ADDRESS, "address", "e", 'm')
  
+ /* Express a group of insns that are executed in parallel.
+    1st operand: Vector of insns.
+    2nd operand: Available for scheduler use.  */
+ DEF_RTL_EXPR(GROUP_PARALLEL, "group_parallel", "E0", 'g')
+ 
+ /* Express a group of insns that are executed in sequence.
+    1st operand: Vector of insns.
+    2nd operand: Available for scheduler use.  */
+ DEF_RTL_EXPR(GROUP_SEQUENCE, "group_sequence", "E0", 'g')
+ 
  /* ----------------------------------------------------------------------
     Expressions used for insn attributes.  These also do not appear in
     actual rtl code in the compiler.
Index: m32r-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m32r/m32r-protos.h,v
retrieving revision 1.7
diff -p -r1.7 m32r-protos.h
*** m32r-protos.h	2001/08/18 20:25:52	1.7
--- m32r-protos.h	2001/11/06 15:34:32
*************** extern int    m32r_block_immediate_opera
*** 90,95 ****
--- 90,97 ----
  extern int    extend_operand			PARAMS ((rtx, Mmode));
  extern int    reg_or_eq_int16_operand		PARAMS ((rtx, Mmode));
  extern int    int8_operand			PARAMS ((rtx, Mmode));
+ extern int    reg_or_zero_operand               PARAMS ((rtx, Mmode));
+ 
  #endif /* HAVE_MACHINE_MODES */
  
  #ifdef TREE_CODE
Index: m32r.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m32r/m32r.c,v
retrieving revision 1.34
diff -p -r1.34 m32r.c
*** m32r.c	2001/09/21 01:27:05	1.34
--- m32r.c	2001/11/06 15:34:33
*************** unsigned int m32r_hard_regno_mode_ok[FIR
*** 171,177 ****
  {
    T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
    T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, S_MODES, S_MODES, S_MODES,
!   S_MODES, C_MODES, A_MODES
  };
  
  unsigned int m32r_mode_class [NUM_MACHINE_MODES];
--- 171,177 ----
  {
    T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
    T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, S_MODES, S_MODES, S_MODES,
!   S_MODES, C_MODES, A_MODES, A_MODES
  };
  
  unsigned int m32r_mode_class [NUM_MACHINE_MODES];
*************** m32r_encode_section_info (decl)
*** 462,467 ****
--- 462,471 ----
  
        strcpy (newstr + 1, str);
        *newstr = prefix;
+       /* Note - we cannot leave the string in the ggc_alloc'ed space.
+          It must reside in the stringtable's domain.  */
+       newstr = (char *) ggc_alloc_string (newstr, len + 2);
+ 
        XSTR (XEXP (rtl, 0), 0) = newstr;
      }
  }
*************** reg_or_cmp_int16_operand (op, mode)
*** 732,737 ****
--- 736,757 ----
    if (GET_CODE (op) != CONST_INT)
      return 0;
    return CMP_INT16_P (INTVAL (op));
+ }
+ 
+ /* Return true if OP is a register or the constant 0.  */
+ 
+ int
+ reg_or_zero_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+ {
+   if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+     return register_operand (op, mode);
+ 
+   if (GET_CODE (op) != CONST_INT)
+     return 0;
+ 
+   return INTVAL (op) == 0;
  }
  
  /* Return true if OP is a const_int requiring two instructions to load.  */
Index: m32r.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m32r/m32r.h,v
retrieving revision 1.47
diff -p -r1.47 m32r.h
*** m32r.h	2001/10/19 22:27:30	1.47
--- m32r.h	2001/11/06 15:34:33
*************** Boston, MA 02111-1307, USA.  */
*** 40,45 ****
--- 40,97 ----
  #undef ENDFILE_SPEC
  #undef SUBTARGET_SWITCHES
  
+ 
+ /* M32R/X overrides.  */
+ /* Print subsidiary information on the compiler version in use.  */
+ #define TARGET_VERSION fprintf (stderr, " (m32r/x)");
+ 
+ /* Additional flags for the preprocessor.  */
+ #define CPP_CPU_SPEC "%{m32rx:-D__M32RX__} %{m32r:-U__M32RX__}"
+ 
+ /* Assembler switches.  */
+ #define ASM_CPU_SPEC \
+ "%{m32r} %{m32rx} %{!O0: %{O*: -O}} --no-warn-explicit-parallel-conflicts"
+ 
+ /* Use m32rx specific crt0/crtinit/crtfini files.  */
+ #define STARTFILE_CPU_SPEC "%{!shared:crt0.o%s} %{m32rx:m32rx/crtinit.o%s} %{!m32rx:crtinit.o%s}"
+ #define ENDFILE_CPU_SPEC "-lgloss %{m32rx:m32rx/crtfini.o%s} %{!m32rx:crtfini.o%s}"
+ 
+ /* Extra machine dependent switches.  */
+ #define SUBTARGET_SWITCHES							\
+     { "32rx",			TARGET_M32RX_MASK, "Compile for the m32rx" },	\
+     { "32r",			-TARGET_M32RX_MASK, "" },
+ 
+ /* Define this macro as a C expression for the initializer of an array of
+    strings to tell the driver program which options are defaults for this
+    target and thus do not need to be handled specially when using
+    `MULTILIB_OPTIONS'.  */
+ #define SUBTARGET_MULTILIB_DEFAULTS , "m32r"
+ 
+ /* Number of additional registers the subtarget defines.  */
+ #define SUBTARGET_NUM_REGISTERS 1
+ 
+ /* 1 for registers that cannot be allocated.  */
+ #define SUBTARGET_FIXED_REGISTERS , 1
+ 
+ /* 1 for registers that are not available across function calls.  */
+ #define SUBTARGET_CALL_USED_REGISTERS , 1
+ 
+ /* Order to allocate model specific registers.  */
+ #define SUBTARGET_REG_ALLOC_ORDER , 19
+ 
+ /* Registers which are accumulators.  */
+ #define SUBTARGET_REG_CLASS_ACCUM 0x80000
+ 
+ /* All registers added.  */
+ #define SUBTARGET_REG_CLASS_ALL SUBTARGET_REG_CLASS_ACCUM
+ 
+ /* Additional accumulator registers.  */
+ #define SUBTARGET_ACCUM_P(REGNO) ((REGNO) == 19)
+ 
+ /* Define additional register names.  */
+ #define SUBTARGET_REGISTER_NAMES , "a1"
+ /* end M32R/X overrides.  */
+ 
  /* Print subsidiary information on the compiler version in use.  */
  #ifndef	TARGET_VERSION
  #define TARGET_VERSION fprintf (stderr, " (m32r)")
*************** extern int target_flags;
*** 161,166 ****
--- 213,224 ----
  /* Target machine to compile for.  */
  #define TARGET_M32R 		1
  
+ /* Support extended instruction set.  */
+ #define TARGET_M32RX_MASK       (1 << 5)
+ #define TARGET_M32RX            (target_flags & TARGET_M32RX_MASK)
+ #undef  TARGET_M32R
+ #define TARGET_M32R             (! TARGET_M32RX)
+ 
  /* Macro to define tables used to set the flags.
     This is a list in braces of pairs in braces,
     each pair being { "NAME", VALUE }
*************** extern enum m32r_sdata m32r_sdata;
*** 513,519 ****
     16    - arg pointer
     17    - carry flag
     18	 - accumulator
! 
     By default, the extension registers are not available.  */
  
  #ifndef SUBTARGET_FIXED_REGISTERS
--- 571,577 ----
     16    - arg pointer
     17    - carry flag
     18	 - accumulator
!    19    - accumulator 1 in the m32r/x
     By default, the extension registers are not available.  */
  
  #ifndef SUBTARGET_FIXED_REGISTERS
*************** enum m32r_function_type
*** 2051,2056 ****
--- 2109,2115 ----
     matched by the predicate.  The list should have a trailing comma.  */
  
  #define PREDICATE_CODES							\
+ { "reg_or_zero_operand",        { REG, SUBREG, CONST_INT }},            \
  { "conditional_move_operand",	{ REG, SUBREG, CONST_INT }},		\
  { "carry_compare_operand",	{ EQ, NE }},				\
  { "eqne_comparison_operator",	{ EQ, NE }},				\
Index: m32r.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m32r/m32r.md,v
retrieving revision 1.20
diff -p -r1.20 m32r.md
*** m32r.md	2001/11/04 02:12:10	1.20
--- m32r.md	2001/11/06 15:34:34
***************
*** 69,74 ****
--- 69,94 ----
  (define_attr "m32r" "no,yes"
    (const (symbol_ref "(TARGET_M32R != 0)")))
  
+ (define_attr "m32rx" "no,yes"
+   (const (symbol_ref "(TARGET_M32RX != 0)")))
+ 
+ (define_attr "m32rx_pipeline" "either,s,o,long,m32r"
+   (cond [(eq_attr "m32rx" "no")
+          (const_string "m32r")
+ 
+          (eq_attr "insn_size" "!short")
+          (const_string "long")]
+ 
+         (cond [(eq_attr "type" "int2")
+                (const_string "either")
+ 
+                (eq_attr "type" "load2,store2,shift2,uncond_branch,branch,call")
+                (const_string "o")
+ 
+                (eq_attr "type" "mul2")
+                (const_string "s")]
+ 
+               (const_string "long"))))
  
  ;; ::::::::::::::::::::
  ;; ::
***************
*** 218,223 ****
--- 238,308 ----
    3 0
    [(eq_attr "insn_size" "short")])
  
+ (define_function_unit "left" 1 1
+   (and (eq_attr "m32rx_pipeline" "o,either")
+        (eq_attr "type" "!load2"))
+   1 0
+   [(eq_attr "insn_size" "long")])
+ 
+ (define_function_unit "left" 1 1	;; load delay of 1 clock for mem execution + 1 clock for WB
+   (and (eq_attr "m32rx_pipeline" "o,either")
+        (eq_attr "type" "load2"))
+   3 0
+   [(eq_attr "insn_size" "long")])
+ 
+ (define_function_unit "right" 1 1
+   (eq_attr "m32rx_pipeline" "s,either")
+   1 0
+   [(eq_attr "insn_size" "long")])
+ 
+ (define_function_unit "long" 1 1
+   (and (eq_attr "m32rx" "yes")
+        (and (eq_attr "insn_size" "long")
+ 	    (eq_attr "type" "!load4,load8")))
+   2 0
+   [(eq_attr "insn_size" "short")])
+ 
+ (define_function_unit "long" 1 1	;; load delay of 1 clock for mem execution + 1 clock for WB
+   (and (eq_attr "m32rx" "yes")
+        (and (eq_attr "insn_size" "long")
+ 	    (eq_attr "type" "load4,load8")))
+   3 0
+   [(eq_attr "insn_size" "short")])
+ 
+ ;; Instruction grouping
+ 
+ (define_insn "*small_sequence"
+   [(group_sequence [(match_insn 0 "small_insn_p")
+ 		    (match_insn 1 "small_insn_p")])]
+   ""
+   "*
+ {
+   abort ();
+ }"
+   [(set_attr "length" "4")
+    (set_attr "type" "multi")])
+ 
+ (define_insn "*small_parallel"
+   [(group_parallel [(match_insn 0 "small_insn_p")
+ 		    (match_insn 1 "small_insn_p")])]
+   "TARGET_M32RX"
+   "*
+ {
+   abort ();
+ }"
+   [(set_attr "length" "4")
+    (set_attr "type" "multi")])
+ 
+ (define_insn "*long_group"
+   [(group_sequence [(match_insn 0 "large_insn_p")])]
+   ""
+   "*
+ {
+   abort ();
+ }"
+   [(set_attr "length" "4")
+    (set_attr "type" "multi")])
+ 
  
  ;; Expand prologue as RTL
  (define_expand "prologue"
***************
*** 1126,1139 ****
    DONE;
  }")
  
  ;; The cmp_xxx_insn patterns set the condition bit to the result of the
  ;; comparison.  There isn't a "compare equal" instruction so cmp_eqsi_insn
  ;; is quite inefficient.  However, it is rarely used.
  
  (define_insn "cmp_eqsi_insn"
    [(set (reg:SI 17)
! 	(eq:SI (match_operand:SI 0 "register_operand" "r,r")
! 	       (match_operand:SI 1 "reg_or_cmp_int16_operand" "r,P")))
     (clobber (match_scratch:SI 2 "=&r,&r"))]
    ""
    "*
--- 1211,1235 ----
    DONE;
  }")
  
+ (define_insn "cmp_eqsi_zero_insn"
+   [(set (reg:SI 17)
+         (eq:SI (match_operand:SI 0 "register_operand" "r,r")
+                (match_operand:SI 1 "reg_or_zero_operand" "r,P")))]
+   "TARGET_M32RX"
+   "@
+    cmpeq %0, %1
+    cmpz  %0"
+   [(set_attr "type" "int4")
+    (set_attr "length" "4")])
+ 
  ;; The cmp_xxx_insn patterns set the condition bit to the result of the
  ;; comparison.  There isn't a "compare equal" instruction so cmp_eqsi_insn
  ;; is quite inefficient.  However, it is rarely used.
  
  (define_insn "cmp_eqsi_insn"
    [(set (reg:SI 17)
!         (eq:SI (match_operand:SI 0 "register_operand" "r,r")
!                (match_operand:SI 1 "reg_or_cmp_int16_operand" "r,P")))
     (clobber (match_scratch:SI 2 "=&r,&r"))]
    ""
    "*
***************
*** 1157,1164 ****
  
  (define_insn "cmp_ltsi_insn"
    [(set (reg:SI 17)
! 	(lt:SI (match_operand:SI 0 "register_operand" "r,r")
! 	       (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
    ""
    "@
     cmp %0,%1
--- 1253,1260 ----
  
  (define_insn "cmp_ltsi_insn"
    [(set (reg:SI 17)
!         (lt:SI (match_operand:SI 0 "register_operand" "r,r")
!                (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
    ""
    "@
     cmp %0,%1
***************
*** 1168,1175 ****
  
  (define_insn "cmp_ltusi_insn"
    [(set (reg:SI 17)
! 	(ltu:SI (match_operand:SI 0 "register_operand" "r,r")
! 	        (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
    ""
    "@
     cmpu %0,%1
--- 1264,1271 ----
  
  (define_insn "cmp_ltusi_insn"
    [(set (reg:SI 17)
!         (ltu:SI (match_operand:SI 0 "register_operand" "r,r")
!                 (match_operand:SI 1 "reg_or_int16_operand" "r,J")))]
    ""
    "@
     cmpu %0,%1
***************
*** 1177,1182 ****
--- 1273,1279 ----
    [(set_attr "type" "int2,int4")
     (set_attr "length" "2,4")])
  
+ 
  ;; reg == small constant comparisons are best handled by putting the result
  ;; of the comparison in a tmp reg and then using beqz/bnez.
  ;; ??? The result register doesn't contain 0/STORE_FLAG_VALUE,
***************
*** 1448,1454 ****
    ""
    "*
  {
!   const char *br,*invbr;
    char asmtext[40];
  
    switch (GET_CODE (operands[1]))
--- 1545,1551 ----
    ""
    "*
  {
!   char *br,*invbr;
    char asmtext[40];
  
    switch (GET_CODE (operands[1]))
***************
*** 1495,1501 ****
    ""
    "*
  {
!   const char *br,*invbr;
    char asmtext[40];
  
    switch (GET_CODE (operands[1]))
--- 1592,1598 ----
    ""
    "*
  {
!   char *br,*invbr;
    char asmtext[40];
  
    switch (GET_CODE (operands[1]))
***************
*** 1550,1555 ****
--- 1647,1660 ----
    if (! register_operand (op1, mode))
      op1 = force_reg (mode, op1);
  
+   if (TARGET_M32RX)
+     {
+       if (! reg_or_zero_operand (op2, mode))
+         op2 = force_reg (mode, op2);
+ 
+       emit_insn (gen_seq_insn_m32rx (op0, op1, op2));
+       DONE;
+     }
    if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0)
      {
        emit_insn (gen_seq_zero_insn (op0, op1));
***************
*** 1562,1567 ****
--- 1667,1695 ----
    emit_insn (gen_seq_insn (op0, op1, op2));
    DONE;
  }")
+ 
+ (define_insn "seq_insn_m32rx"
+   [(set (match_operand:SI 0 "register_operand" "=r")
+ 	(eq:SI (match_operand:SI 1 "register_operand" "%r")
+ 	       (match_operand:SI 2 "reg_or_zero_operand" "rP")))
+    (clobber (reg:SI 17))]
+   "TARGET_M32RX"
+   "#"
+   [(set_attr "type" "multi")
+    (set_attr "length" "6")])
+ 
+ (define_split
+   [(set (match_operand:SI 0 "register_operand" "")
+ 	(eq:SI (match_operand:SI 1 "register_operand" "")
+ 	       (match_operand:SI 2 "reg_or_zero_operand" "")))
+    (clobber (reg:SI 17))]
+   "TARGET_M32RX"
+   [(set (reg:SI 17)
+ 	(eq:SI (match_dup 1)
+ 	       (match_dup 2)))
+    (set (match_dup 0)
+ 	(reg:SI 17))]
+   "")
  
  (define_insn "seq_zero_insn"
    [(set (match_operand:SI 0 "register_operand" "=r")
Index: t-m32r
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m32r/t-m32r,v
retrieving revision 1.6
diff -p -r1.6 t-m32r
*** t-m32r	2001/05/17 03:16:00	1.6
--- t-m32r	2001/11/06 15:34:34
*************** crtfini.o: $(srcdir)/config/m32r/initfin
*** 36,51 ****
  	  -DCRT_FINI -finhibit-size-directive -fno-inline-functions \
  	  -g0 -mmodel=medium -c $(srcdir)/config/m32r/initfini.c -o crtfini.o
  
  
  # -mmodel={small,medium} requires separate libraries.
  # We don't build libraries for the large model, instead we use the medium
  # libraries.  The only difference is that the large model can handle jumps
  # more than 26 signed bits away.
  
! MULTILIB_OPTIONS = mmodel=small/mmodel=medium
! MULTILIB_DIRNAMES = small medium
  MULTILIB_MATCHES = mmodel?medium=mmodel?large
- 
  
  # Set MULTILIB_EXTRA_OPTS so shipped libraries have small data in .sdata and
  # SHN_M32R_SCOMMON.
--- 36,64 ----
  	  -DCRT_FINI -finhibit-size-directive -fno-inline-functions \
  	  -g0 -mmodel=medium -c $(srcdir)/config/m32r/initfini.c -o crtfini.o
  
+ m32rx:
+ 	mkdir $@
  
+ m32rx/crtinit.o: m32rx $(srcdir)/config/m32r/initfini.c $(GCC_PASSES) $(CONFIG_H)
+ 	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
+ 	-DCRT_INIT -finhibit-size-directive -fno-inline-functions \
+ 	-g0 -mmodel=medium -c $(srcdir)/config/m32r/initfini.c -m32rx \
+ 	-o m32rx/crtinit.o
+ 
+ m32rx/crtfini.o: m32rx $(srcdir)/config/m32r/initfini.c $(GCC_PASSES) $(CONFIG_H)
+ 	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
+ 	-DCRT_FINI -finhibit-size-directive -fno-inline-functions \
+ 	-g0 -mmodel=medium -c $(srcdir)/config/m32r/initfini.c -m32rx \
+ 	-o m32rx/crtfini.o
+ 
  # -mmodel={small,medium} requires separate libraries.
  # We don't build libraries for the large model, instead we use the medium
  # libraries.  The only difference is that the large model can handle jumps
  # more than 26 signed bits away.
  
! MULTILIB_OPTIONS = mmodel=small/mmodel=medium m32r/m32rx
! MULTILIB_DIRNAMES = small medium m32r m32rx
  MULTILIB_MATCHES = mmodel?medium=mmodel?large
  
  # Set MULTILIB_EXTRA_OPTS so shipped libraries have small data in .sdata and
  # SHN_M32R_SCOMMON.


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