This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


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

take 2: cgen/gas: some support for funny-endian instruction sets


Hi -

Here is a modified version of the patch from Monday that I am
planning to commit shortly.  It's different in that it uses a new
cgen parameter ("insn-chunk-bitsize") to control this funny-endianness
parameter instead of using "word-bitsize".  I would have preferred not
to make the current plethora of cgen parameters even larger, but had
no choice. :-(


[cgen]
+ 2001-07-11  Frank Ch. Eigler  <fche@redhat.com>
+ 
+ 	* desc-cpu.scm (-gen-mach-table-defns): Emit fourth field: the
+ 	mach->cpu insn-chunk-bitsize.
+ 	(-gen-cpu-open): In @arch@_cgen_rebuild_tables, process above new
+ 	field toward CGEN_CPU_TABLE->insn_chunk_bitsize.
+ 	* mach.scm (<cpu>): New field insn-chunk-bitsize.
+ 	(-cpu-parse, -cpu-read): Parse/initialize it.
+ 	* doc/rtl.texi (define-cpu): Document it.
[opcodes]
+ 2001-07-11  Frank Ch. Eigler  <fche@redhat.com>
+ 
+ 	* cgen-dis.in (print_insn): Use cgen_get_insn_value instead of
+ 	bfd_get_bits.
+ 	* cgen-opc.c (cgen_get_insn_value, cgen_put_insn_value): Respect
+ 	non-zero CGEN_CPU_DESC->insn_chunk_bitsize.
[include/opcodes]
+ 2001-07-11  Frank Ch. Eigler  <fche@redhat.com>
+ 
+ 	* cgen.h (CGEN_MACH): Add insn_chunk_bitsize field.
+ 	(cgen_cpu_desc): Ditto.




*** cgen/desc-cpu.scm	2001/03/20 18:20:06	1.27
--- cgen/desc-cpu.scm	2001/07/12 02:14:25
***************
*** 70,80 ****
  		       (string-append "  { "
  				      "\"" (obj:name mach) "\", "
  				      "\"" (mach-bfd-name mach) "\", "
! 				      (mach-enum mach)
  				      " },\n")))
  		    (current-mach-list))
     "\
!   { 0, 0, 0 }
  };
  \n"
     )
--- 70,81 ----
  		       (string-append "  { "
  				      "\"" (obj:name mach) "\", "
  				      "\"" (mach-bfd-name mach) "\", "
! 				      (mach-enum mach) ", "
! 				      (number->string (cpu-insn-chunk-bitsize (mach-cpu mach)))
  				      " },\n")))
  		    (current-mach-list))
     "\
!   { 0, 0, 0, 0 }
  };
  \n"
     )
***************
*** 635,645 ****
  @arch@_cgen_rebuild_tables (cd)
       CGEN_CPU_TABLE *cd;
  {
!   int i,n_isas;
    unsigned int isas = cd->isas;
- #if 0
    unsigned int machs = cd->machs;
- #endif
  
    cd->int_insn_p = CGEN_INT_INSN_P;
  
--- 636,644 ----
  @arch@_cgen_rebuild_tables (cd)
       CGEN_CPU_TABLE *cd;
  {
!   int i;
    unsigned int isas = cd->isas;
    unsigned int machs = cd->machs;
  
    cd->int_insn_p = CGEN_INT_INSN_P;
  
***************
*** 677,696 ****
  	  cd->min_insn_bitsize = isa->min_insn_bitsize;
  	if (isa->max_insn_bitsize > cd->max_insn_bitsize)
  	  cd->max_insn_bitsize = isa->max_insn_bitsize;
- 
- 	++n_isas;
        }
  
- #if 0 /* Does nothing?? */
    /* Data derived from the mach spec.  */
    for (i = 0; i < MAX_MACHS; ++i)
      if (((1 << i) & machs) != 0)
        {
  	const CGEN_MACH *mach = & @arch@_cgen_mach_table[i];
  
! 	++n_machs;
        }
- #endif
  
    /* Determine which hw elements are used by MACH.  */
    build_hw_table (cd);
--- 676,701 ----
  	  cd->min_insn_bitsize = isa->min_insn_bitsize;
  	if (isa->max_insn_bitsize > cd->max_insn_bitsize)
  	  cd->max_insn_bitsize = isa->max_insn_bitsize;
        }
  
    /* Data derived from the mach spec.  */
    for (i = 0; i < MAX_MACHS; ++i)
      if (((1 << i) & machs) != 0)
        {
  	const CGEN_MACH *mach = & @arch@_cgen_mach_table[i];
+ 
+ 	if (mach->insn_chunk_bitsize != 0)
+ 	{
+ 	  if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize)
+ 	    {
+ 	      fprintf (stderr, \"@arch@_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\\n\",
+ 		       cd->insn_chunk_bitsize, mach->insn_chunk_bitsize);
+ 	      abort ();
+ 	    }
  
!  	  cd->insn_chunk_bitsize = mach->insn_chunk_bitsize;
! 	}
        }
  
    /* Determine which hw elements are used by MACH.  */
    build_hw_table (cd);


*** cgen/mach.scm	2001/06/22 15:41:12	1.46
--- cgen/mach.scm	2001/07/12 02:14:30
***************
*** 992,997 ****
--- 992,1001 ----
  		; number of bits in a word.
  		word-bitsize
  
+ 		; number of bits in a chunk of an instruction word, for
+ 		; endianness conversion purposes; 0 = no chunking
+ 		insn-chunk-bitsize
+ 
  		; Transformation to use in generated files should one be
  		; needed.  At present the only supported value is a string
  		; which is the file suffix.
***************
*** 1015,1021 ****
  
  ; Accessors.
  
! (define-getters <cpu> cpu (word-bitsize file-transform parallel-insns max-delay))
  (define-setters <cpu> cpu (max-delay))
  
  ; Return endianness of instructions.
--- 1019,1025 ----
  
  ; Accessors.
  
! (define-getters <cpu> cpu (word-bitsize insn-chunk-bitsize file-transform parallel-insns max-delay))
  (define-setters <cpu> cpu (max-delay))
  
  ; Return endianness of instructions.
***************
*** 1052,1058 ****
  
  (define (-cpu-parse name comment attrs
  		    endian insn-endian data-endian float-endian
! 		    word-bitsize file-transform parallel-insns)
    (logit 2 "Processing cpu family " name " ...\n")
    ; Pick out name first 'cus we need it as a string(/symbol).
    (let* ((name (parse-name name "cpu"))
--- 1056,1062 ----
  
  (define (-cpu-parse name comment attrs
  		    endian insn-endian data-endian float-endian
! 		    word-bitsize insn-chunk-bitsize file-transform parallel-insns)
    (logit 2 "Processing cpu family " name " ...\n")
    ; Pick out name first 'cus we need it as a string(/symbol).
    (let* ((name (parse-name name "cpu"))
***************
*** 1064,1069 ****
--- 1068,1074 ----
  	      (atlist-parse attrs "cpu" errtxt)
  	      endian insn-endian data-endian float-endian
  	      word-bitsize
+ 	      insn-chunk-bitsize
  	      file-transform
  	      parallel-insns
  	      0 ; default max-delay. will compute correct value
***************
*** 1090,1095 ****
--- 1095,1101 ----
  	  (data-endian #f)
  	  (float-endian #f)
  	  (word-bitsize nil)
+ 	  (insn-chunk-bitsize 0)
  	  (file-transform "")
  	  ; FIXME: Hobbit computes the wrong symbol for `parallel-insns'
  	  ; in the `case' expression below because there is a local var
***************
*** 1111,1116 ****
--- 1117,1123 ----
  		((data-endian) (set! data-endian (cadr arg)))
  		((float-endian) (set! float-endian (cadr arg)))
  		((word-bitsize) (set! word-bitsize (cadr arg)))
+ 		((insn-chunk-bitsize) (set! insn-chunk-bitsize (cadr arg)))
  		((file-transform) (set! file-transform (cadr arg)))
  		((parallel-insns) (set! parallel-insns- (cadr arg)))
  		(else (parse-error errtxt "invalid cpu arg" arg)))
***************
*** 1118,1124 ****
        ; Now that we've identified the elements, build the object.
        (-cpu-parse name comment attrs
  		  endian insn-endian data-endian float-endian
! 		  word-bitsize file-transform parallel-insns-)
        )
      )
  )
--- 1125,1131 ----
        ; Now that we've identified the elements, build the object.
        (-cpu-parse name comment attrs
  		  endian insn-endian data-endian float-endian
! 		  word-bitsize insn-chunk-bitsize file-transform parallel-insns-)
        )
      )
  )


*** cgen/doc/rtl.texi	2001/06/06 21:35:09	1.54
--- cgen/doc/rtl.texi	2001/07/12 02:14:31
***************
*** 556,561 ****
--- 556,562 ----
    (data-endian big|little|either)
    (float-endian big|little|either)
    (word-bitsize n)
+   (insn-chunk-bitsize n)
    (parallel-insns n)
    (file-transform transformation)
  )
***************
*** 586,591 ****
--- 587,598 ----
  @subsubsection word-bitsize
  
  The number of bits in a word.  In GCC, this is @code{BITS_PER_WORD}.
+ 
+ @subsubsection insn-chunk-bitsize
+ 
+ The number of bits in an instruction word chunk, for purposes of
+ per-chunk endianness conversion.  The default is zero, meaning
+ no chunking is required.
  
  @subsubsection parallel-insns
  

*** opcodes/cgen-dis.in	2001/05/15 18:08:19	1.37
--- opcodes/cgen-dis.in	2001/07/12 02:14:32
***************
*** 229,240 ****
       char *buf;
       int buflen;
  {
!   unsigned long insn_value;
    const CGEN_INSN_LIST *insn_list;
    CGEN_EXTRACT_INFO ex_info;
  
    /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
!   insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
  
    /* Fill in ex_info fields like read_insn would.  Don't actually call
       read_insn, since the incoming buffer is already read (and possibly
--- 229,240 ----
       char *buf;
       int buflen;
  {
!   CGEN_INSN_INT insn_value;
    const CGEN_INSN_LIST *insn_list;
    CGEN_EXTRACT_INFO ex_info;
  
    /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
!   insn_value = cgen_get_insn_value (cd, buf, buflen * 8);
  
    /* Fill in ex_info fields like read_insn would.  Don't actually call
       read_insn, since the incoming buffer is already read (and possibly





*** opcodes/cgen-opc.c	2001/06/29 00:10:04	1.29
--- opcodes/cgen-opc.c	2001/07/12 02:14:32
***************
*** 391,397 ****
       unsigned char *buf;
       int length;
  {
!   return bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG);
  }
  
  /* Cover function to store an insn value properly byteswapped.  */
--- 391,425 ----
       unsigned char *buf;
       int length;
  {
!   int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
!   int insn_chunk_bitsize = cd->insn_chunk_bitsize;
!   CGEN_INSN_INT value = 0;
! 
!   if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
!     {
!       /* We need to divide up the incoming value into insn_chunk_bitsize-length
! 	 segments, and endian-convert them, one at a time. */
!       int i;
! 
!       /* Enforce divisibility. */ 
!       if ((length % insn_chunk_bitsize) != 0)
! 	abort ();
! 
!       for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
! 	{
! 	  int index;
! 	  bfd_vma this_value;
! 	  index = i; /* NB: not dependent on endianness; opposite of cgen_put_insn_value! */
! 	  this_value = bfd_get_bits (& buf[index / 8], insn_chunk_bitsize, big_p);
! 	  value = (value << insn_chunk_bitsize) | this_value;
! 	}
!     }
!   else
!     {
!       value = bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG);
!     }
! 
!   return value;
  }
  
  /* Cover function to store an insn value properly byteswapped.  */
***************
*** 403,410 ****
       int length;
       CGEN_INSN_INT value;
  {
!   bfd_put_bits ((bfd_vma) value, buf, length,
! 		cd->insn_endian == CGEN_ENDIAN_BIG);
  }
  
  /* Look up instruction INSN_*_VALUE and extract its fields.
--- 431,461 ----
       int length;
       CGEN_INSN_INT value;
  {
!   int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
!   int insn_chunk_bitsize = cd->insn_chunk_bitsize;
! 
!   if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
!     {
!       /* We need to divide up the incoming value into insn_chunk_bitsize-length
! 	 segments, and endian-convert them, one at a time. */
!       int i;
! 
!       /* Enforce divisibility. */ 
!       if ((length % insn_chunk_bitsize) != 0)
! 	abort ();
! 
!       for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
! 	{
! 	  int index;
! 	  index = (length - insn_chunk_bitsize - i); /* NB: not dependent on endianness! */
! 	  bfd_put_bits ((bfd_vma) value, & buf[index / 8], insn_chunk_bitsize, big_p);
! 	  value >>= insn_chunk_bitsize;
! 	}
!     }
!   else
!     {
!       bfd_put_bits ((bfd_vma) value, buf, length, big_p);
!     }
  }
  
  /* Look up instruction INSN_*_VALUE and extract its fields.




*** include/opcode/cgen.h	2001/06/16 15:22:00	1.59
--- include/opcode/cgen.h	2001/07/12 02:14:34
***************
*** 199,204 ****
--- 199,206 ----
    const char *bfd_name;
    /* one of enum mach_attr */
    int num;
+   /* parameter from mach->cpu */
+   unsigned int insn_chunk_bitsize;
  } CGEN_MACH;
  
  /* Parse result (also extraction result).
***************
*** 1165,1170 ****
--- 1167,1176 ----
       ??? Another alternative is to create a table of selected machs and
       lazily fetch the data from there.  */
    unsigned int word_bitsize;
+ 
+   /* Instruction chunk size (in bits), for purposes of endianness
+      conversion.  */
+   unsigned int insn_chunk_bitsize;
  
    /* Indicator if sizes are unknown.
       This is used by default_insn_bitsize,base_insn_bitsize if there is a


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