-#if ! CGEN_INT_INSN_P
-
-/* Subroutine of extract_normal.
- Ensure sufficient bytes are cached in EX_INFO.
- OFFSET is the offset in bytes from the start of the insn of the value.
- BYTES is the length of the needed value.
- Returns 1 for success, 0 for failure. */
-
-static INLINE int
-fill_cache (od, ex_info, offset, bytes, pc)
- CGEN_OPCODE_DESC od;
- CGEN_EXTRACT_INFO *ex_info;
- int offset, bytes;
- bfd_vma pc;
-{
- /* It's doubtful that the middle part has already been fetched so
- we don't optimize that case. kiss. */
- int mask;
- disassemble_info *info = (disassemble_info *) ex_info->dis_info;
-
- /* First do a quick check. */
- mask = (1 << bytes) - 1;
- if (((ex_info->valid >> offset) & mask) == mask)
- return 1;
-
- /* Search for the first byte we need to read. */
- for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
- if (! (mask & ex_info->valid))
- break;
-
- if (bytes)
- {
- int status;
-
- pc += offset;
- status = (*info->read_memory_func)
- (pc, ex_info->insn_bytes + offset, bytes, info);
-
- if (status != 0)
- {
- (*info->memory_error_func) (status, pc, info);
- return 0;
- }
-
- ex_info->valid |= ((1 << bytes) - 1) << offset;
- }
-
- return 1;
-}
-
-/* Subroutine of extract_normal. */
-
-static INLINE long
-extract_1 (od, ex_info, start, length, word_length, bufp, pc)
- CGEN_OPCODE_DESC od;
- CGEN_EXTRACT_INFO *ex_info;
- int start,length,word_length;
- unsigned char *bufp;
- bfd_vma pc;
-{
- unsigned long x,mask;
- int shift;
- int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
-
- 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 = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
- else
- x = bfd_getl16 (bufp) | (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 + 1) - length;
- else
- shift = (word_length - (start + length));
- return (x >> shift) & mask;
-}
-
-#endif /* ! CGEN_INT_INSN_P */
-
-/* Default extraction routine.
-
- INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order,
- or sometimes less for cases like the m32r where the base insn size is 32
- but some insns are 16 bits.
- ATTRS is a mask of the boolean attributes. We only need `UNSIGNED',
- but for generality we take a bitmask of all of them.
- WORD_OFFSET is the offset in bits from the start of the insn of the value.
- WORD_LENGTH is the length of the word in bits in which the value resides.
- START is the starting bit number in the word, architecture origin.
- LENGTH is the length of VALUE in bits.
- TOTAL_LENGTH is the total length of the insn in bits.
-
- Returns 1 for success, 0 for failure. */
-
-/* ??? The return code isn't properly used. wip. */
-
-/* ??? This doesn't handle bfd_vma's. Create another function when
- necessary. */
-
-static int
-extract_normal (od, ex_info, insn_value, attrs, word_offset, start, length,
- word_length, total_length, pc, valuep)
- CGEN_OPCODE_DESC od;
- CGEN_EXTRACT_INFO *ex_info;
- CGEN_INSN_INT insn_value;
- unsigned int attrs;
- unsigned int word_offset, start, length, word_length, total_length;
- bfd_vma pc;
- long *valuep;
-{
- CGEN_INSN_INT 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
- && word_offset != 0)
- abort ();
-
- if (word_length > 32)
- abort ();
-
- /* For architectures with insns smaller than the insn-base-bitsize,
- word_length may be too big. */
-#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE
- if (word_offset == 0
- && word_length > total_length)
- word_length = total_length;
-#endif
-
- /* Does the value reside in INSN_VALUE? */
-
- if (word_offset == 0)
- {
- /* Written this way to avoid undefined behaviour. */
- CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
-
- if (CGEN_INSN_LSB0_P)
- value = insn_value >> ((start + 1) - length);
- else
- value = insn_value >> (word_length - (start + length));
- value &= mask;
- /* sign extend? */
- if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
- && (value & (1L << (length - 1))))
- value |= ~mask;
- }
-
-#if ! CGEN_INT_INSN_P
-
- else
- {
- unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
-
- if (word_length > 32)
- abort ();
-
- if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0)
- return 0;
-
- value = extract_1 (od, ex_info, start, length, word_length, bufp, pc);
- }
-
-#endif /* ! CGEN_INT_INSN_P */
-
- *valuep = value;
-
- return 1;
-}
-