take 2: cgen/gas: some support for funny-endian instruction sets
Frank Ch. Eigler
fche@redhat.com
Wed Jul 11 19:23:00 GMT 2001
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
More information about the Binutils
mailing list