diff options
author | Frank Ch. Eigler <fche@redhat.com> | 2001-07-12 02:32:25 +0000 |
---|---|---|
committer | Frank Ch. Eigler <fche@redhat.com> | 2001-07-12 02:32:25 +0000 |
commit | 81f6038f98bd3ca48651c22779ffe6231d0873a0 (patch) | |
tree | b0b00e86933a62418f03d1de98982df853161f80 /opcodes/cgen-opc.c | |
parent | 3bbfbb92b3cf687215142bcd8dfe720cf9cdc6b0 (diff) | |
download | gdb-81f6038f98bd3ca48651c22779ffe6231d0873a0.zip gdb-81f6038f98bd3ca48651c22779ffe6231d0873a0.tar.gz gdb-81f6038f98bd3ca48651c22779ffe6231d0873a0.tar.bz2 |
* some support for funny-endian 16/32-bit insn sets
[cgen/ChangeLog]
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/ChangeLog]
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/opcode/ChangeLog]
2001-07-11 Frank Ch. Eigler <fche@redhat.com>
* cgen.h (CGEN_MACH): Add insn_chunk_bitsize field.
(cgen_cpu_desc): Ditto.
Diffstat (limited to 'opcodes/cgen-opc.c')
-rw-r--r-- | opcodes/cgen-opc.c | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/opcodes/cgen-opc.c b/opcodes/cgen-opc.c index 188a157..9dfc16e 100644 --- a/opcodes/cgen-opc.c +++ b/opcodes/cgen-opc.c @@ -391,7 +391,35 @@ cgen_get_insn_value (cd, buf, length) unsigned char *buf; int length; { - return bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG); + 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,8 +431,31 @@ cgen_put_insn_value (cd, buf, length, value) int length; CGEN_INSN_INT value; { - bfd_put_bits ((bfd_vma) value, buf, length, - cd->insn_endian == CGEN_ENDIAN_BIG); + 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. |