-#if ! CGEN_INT_INSN_P
-
-/* Subroutine of extract_normal. */
-
-static INLINE long
-extract_1 (od, ex_info, start, length, word_length, bufp)
- CGEN_OPCODE_DESC od;
- CGEN_EXTRACT_INFO *info;
- int start,length,word_length;
- unsigned char *bufp;
-{
- unsigned long x,mask;
- int shift;
- int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
-
- /* FIXME: Need to use ex_info to ensure bytes have been fetched. */
-
- switch (word_length)
- {
- case 8:
- x = *bufp;
- break;
- case 16:
- if (big_p)
- x = bfd_getb16 (bufp);
- else
- x = bfd_getl16 (bufp);
- break;
- case 24:
- /* ??? This may need reworking as these cases don't necessarily
- want the first byte and the last two bytes handled like this. */
- if (big_p)
- x = (bfd_getb8 (bufp) << 16) | bfd_getb16 (bufp + 1);
- else
- x = bfd_getl16 (bufp) | (bfd_getb8 (bufp + 2) << 16);
- break;
- case 32:
- if (big_p)
- x = bfd_getb32 (bufp);
- else
- x = bfd_getl32 (bufp);
- break;
- default :
- abort ();
- }
-
- /* Written this way to avoid undefined behaviour. */
- mask = (((1L << (length - 1)) - 1) << 1) | 1;
- if (CGEN_INSN_LSB0_P)
- shift = start;
- else
- shift = (word_length - (start + length));
- return (x >> shift) & mask;
-}
-
-#endif /* ! CGEN_INT_INSN_P */
-
-/* Default extraction routine.
-
- ATTRS is a mask of the boolean attributes. We only need `unsigned',
- but for generality we take a bitmask of all of them. */
-
-/* ??? This doesn't handle bfd_vma's. Create another function when
- necessary. */
-
-static int
-extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, valuep)
- CGEN_OPCODE_DESC od;
- CGEN_EXTRACT_INFO *ex_info;
- CGEN_INSN_BYTES insn_value;
- unsigned int attrs;
- int start, length, total_length;
- long *valuep;
-{
- unsigned long value;
-
- /* If LENGTH is zero, this operand doesn't contribute to the value
- so give it a standard value of zero. */
- if (length == 0)
- {
- *valuep = 0;
- return 1;
- }
-
-#if CGEN_INT_INSN_P
-
- {
- /* Written this way to avoid undefined behaviour. */
- unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
-
- if (CGEN_INSN_LSB0_P)
- value = insn_value >> start;
- else
- value = insn_value >> (total_length - (start + length));
- value &= mask;
- /* sign extend? */
- if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
- && (value & (1L << (length - 1))))
- value |= ~mask;
- }
-
-#else
-
- /* The hard case is probably too slow for the normal cases.
- It's certainly more difficult to understand than the normal case.
- Thus this is split into two. Keep it that way. The hard case is defined
- to be when a field straddles a (loosely defined) word boundary
- (??? which may require target specific help to determine). */
-
-#if 0 /*wip*/
-
-#define HARD_CASE_P 0 /* FIXME:wip */
-
- if (HARD_CASE_P)
- {
- }
-#endif
- else
- {
- unsigned char *bufp = (unsigned char *) insn_value;
-
- if (length > 32)
- abort ();
-
- /* Adjust start,total_length,bufp to point to the pseudo-word that holds
- the value. For example in a 48 bit insn where the value to insert
- (say an immediate value) is the last 16 bits then word_length here
- would be 16. To handle a 24 bit insn with an 18 bit immediate,
- extract_1 handles 24 bits (using a combination of bfd_get8,16). */
-
- if (total_length > 32)
- {
- int needed_width = start % 8 + length;
- int fetch_length = (needed_width <= 8 ? 8
- : needed_width <= 16 ? 16
- : 32);
-
- if (CGEN_INSN_LSB0_P)
- {
- if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
- {
- abort (); /* wip */
- }
- else
- {
- int offset = start & ~7;
-
- bufp += offset / 8;
- start -= offset;
- total_length -= offset;
- }
- }
- else
- {
- if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
- {
- int offset = start & ~7;
-
- bufp += offset / 8;
- start -= offset;
- total_length -= offset;
- }
- else
- {
- abort (); /* wip */
- }
- }
- }
-
- /* FIXME: which bytes are being extracted have been lost. */
- value = extract_1 (od, ex_info, start, length, total_length, bufp);
- }
-
-#endif /* ! CGEN_INT_INSN_P */
-
- *valuep = value;
-
- /* FIXME: for now */
- return 1;
-}
-