Exemple #1
0
sObject* int_new_on_stack(int value)
{
   sObject* self = stack_get_free_object(T_INT);
   
   SINT(self) = value;

   return self;
}
SINT SoundSourceOggVorbis::readSampleFrames(
        SINT numberOfFrames, CSAMPLE* sampleBuffer,
        SINT sampleBufferSize, bool readStereoSamples) {
    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    DEBUG_ASSERT(getSampleBufferSize(numberOfFrames, readStereoSamples) <= sampleBufferSize);

    const SINT numberOfFramesTotal = math_min(numberOfFrames,
            SINT(getFrameIndexMax() - m_curFrameIndex));

    CSAMPLE* pSampleBuffer = sampleBuffer;
    SINT numberOfFramesRemaining = numberOfFramesTotal;
    while (0 < numberOfFramesRemaining) {
        float** pcmChannels;
        int currentSection;
        // Use 'long' here, because ov_read_float() returns this type.
        // This is an exception from the rule not to any types with
        // differing sizes on different platforms.
        // https://bugs.launchpad.net/mixxx/+bug/1094143
        const long readResult = ov_read_float(&m_vf, &pcmChannels,
                numberOfFramesRemaining, &currentSection);
        if (0 < readResult) {
            m_curFrameIndex += readResult;
            if (isChannelCountMono()) {
                if (readStereoSamples) {
                    for (long i = 0; i < readResult; ++i) {
                        *pSampleBuffer++ = pcmChannels[0][i];
                        *pSampleBuffer++ = pcmChannels[0][i];
                    }
                } else {
                    for (long i = 0; i < readResult; ++i) {
                        *pSampleBuffer++ = pcmChannels[0][i];
                    }
                }
            } else if (isChannelCountStereo() || readStereoSamples) {
                for (long i = 0; i < readResult; ++i) {
                    *pSampleBuffer++ = pcmChannels[0][i];
                    *pSampleBuffer++ = pcmChannels[1][i];
                }
            } else {
                for (long i = 0; i < readResult; ++i) {
                    for (SINT j = 0; j < getChannelCount(); ++j) {
                        *pSampleBuffer++ = pcmChannels[j][i];
                    }
                }
            }
            numberOfFramesRemaining -= readResult;
        } else {
            qWarning() << "Failed to read from OggVorbis file:" << readResult;
            break; // abort
        }
    }

    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    DEBUG_ASSERT(numberOfFramesTotal >= numberOfFramesRemaining);
    return numberOfFramesTotal - numberOfFramesRemaining;
}
SINT SoundSourceMp3::findSeekFrameIndex(
        SINT frameIndex) const {
    // Check preconditions
    DEBUG_ASSERT(0 < m_avgSeekFrameCount);
    DEBUG_ASSERT(!m_seekFrameList.empty());
    DEBUG_ASSERT(getMinFrameIndex() == m_seekFrameList.front().frameIndex);
    DEBUG_ASSERT(getMaxFrameIndex() == m_seekFrameList.back().frameIndex);

    SINT lowerBound =
            0;
    SINT upperBound =
            m_seekFrameList.size();
    DEBUG_ASSERT(lowerBound < upperBound);

    // Initial guess based on average frame size
    SINT seekFrameIndex =
            frameIndex / m_avgSeekFrameCount;
    if (seekFrameIndex >= upperBound) {
        seekFrameIndex = upperBound - 1;
    }

    while ((upperBound - lowerBound) > 1) {
        DEBUG_ASSERT(seekFrameIndex >= lowerBound);
        DEBUG_ASSERT(seekFrameIndex < upperBound);
        DEBUG_ASSERT(m_seekFrameList[lowerBound].frameIndex <= frameIndex);
        if (m_seekFrameList[seekFrameIndex].frameIndex <= frameIndex) {
            lowerBound = seekFrameIndex;
        } else {
            upperBound = seekFrameIndex;
        }
        // Next guess halfway between lower and upper bound
        seekFrameIndex = lowerBound + (upperBound - lowerBound) / 2;
    }

    // Check postconditions
    DEBUG_ASSERT(seekFrameIndex == lowerBound);
    DEBUG_ASSERT(SINT(m_seekFrameList.size()) > seekFrameIndex);
    DEBUG_ASSERT(m_seekFrameList[seekFrameIndex].frameIndex <= frameIndex);
    DEBUG_ASSERT(((seekFrameIndex + 1) >= SINT(m_seekFrameList.size())) ||
            (m_seekFrameList[seekFrameIndex + 1].frameIndex > frameIndex));

    return seekFrameIndex;
}
SINT SoundSourceCoreAudio::seekSampleFrame(SINT frameIndex) {
    DEBUG_ASSERT(isValidFrameIndex(frameIndex));

    // See comments above on kMp3StabilizationFrames.
    const SINT stabilization_frames = m_bFileIsMp3 ? math_min(
            kMp3StabilizationFrames, SINT(frameIndex + m_headerFrames)) : 0;
    OSStatus err = ExtAudioFileSeek(
            m_audioFile, frameIndex + m_headerFrames - stabilization_frames);
    if (stabilization_frames > 0) {
        readSampleFrames(stabilization_frames,
                         &kMp3StabilizationScratchBuffer[0]);
    }

    //_ThrowExceptionIfErr(@"ExtAudioFileSeek", err);
    //qDebug() << "SSCA: Seeking to" << frameIndex;
    if (err != noErr) {
        qDebug() << "SSCA: Error seeking to" << frameIndex; // << GetMacOSStatusErrorString(err) << GetMacOSStatusCommentString(err);
    }
    return frameIndex;
}
Exemple #5
0
FLAC__StreamDecoderWriteStatus SoundSourceFLAC::flacWrite(
        const FLAC__Frame* frame, const FLAC__int32* const buffer[]) {
    const SINT numChannels = frame->header.channels;
    if (channelCount() > numChannels) {
        kLogger.warning()
                << "Corrupt or unsupported FLAC file:"
                << "Invalid number of channels in FLAC frame header"
                << frame->header.channels << "<>" << channelCount();
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
    }
    if (sampleRate() != SINT(frame->header.sample_rate)) {
        kLogger.warning()
                << "Corrupt or unsupported FLAC file:"
                << "Invalid sample rate in FLAC frame header"
                << frame->header.sample_rate << "<>" << sampleRate();
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
    }
    const SINT numReadableFrames = frame->header.blocksize;
    if (numReadableFrames > m_maxBlocksize) {
        kLogger.warning()
                << "Corrupt or unsupported FLAC file:"
                << "Block size in FLAC frame header exceeds the maximum block size"
                << frame->header.blocksize << ">" << m_maxBlocksize;
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
    }

    // According to the API docs the decoder will always report the current
    // position in "FLAC samples" (= "Mixxx frames") for convenience
    DEBUG_ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
    m_curFrameIndex = frame->header.number.sample_number;

    // Decode buffer should be empty before decoding the next frame
    DEBUG_ASSERT(m_sampleBuffer.empty());
    const SampleBuffer::WritableSlice writableSlice(
            m_sampleBuffer.growForWriting(frames2samples(numReadableFrames)));

    const SINT numWritableFrames = samples2frames(writableSlice.length());
    DEBUG_ASSERT(numWritableFrames <= numReadableFrames);
    if (numWritableFrames < numReadableFrames) {
        kLogger.warning()
                << "Sample buffer has not enough free space for all decoded FLAC samples:"
                << numWritableFrames << "<" << numReadableFrames;
    }

    CSAMPLE* pSampleBuffer = writableSlice.data();
    DEBUG_ASSERT(channelCount() <= numChannels);
    switch (channelCount()) {
    case 1: {
        // optimized code for 1 channel (mono)
        for (SINT i = 0; i < numWritableFrames; ++i) {
            *pSampleBuffer++ = convertDecodedSample(buffer[0][i], m_bitsPerSample);
        }
        break;
    }
    case 2: {
        // optimized code for 2 channels (stereo)
        for (SINT i = 0; i < numWritableFrames; ++i) {
            *pSampleBuffer++ = convertDecodedSample(buffer[0][i], m_bitsPerSample);
            *pSampleBuffer++ = convertDecodedSample(buffer[1][i], m_bitsPerSample);
        }
        break;
    }
    default: {
        // generic code for multiple channels
        for (SINT i = 0; i < numWritableFrames; ++i) {
            for (SINT j = 0; j < channelCount(); ++j) {
                *pSampleBuffer++ = convertDecodedSample(buffer[j][i], m_bitsPerSample);
            }
        }
    }
    }

    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
SINT SoundSourceMp3::seekSampleFrame(SINT frameIndex) {
    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    DEBUG_ASSERT(isValidFrameIndex(frameIndex));

    // Handle trivial case
    if (m_curFrameIndex == frameIndex) {
        // Nothing to do
        return m_curFrameIndex;
    }
    // Handle edge case
    if (getMaxFrameIndex() <= frameIndex) {
        // EOF reached
        m_curFrameIndex = getMaxFrameIndex();
        return m_curFrameIndex;
    }

    SINT seekFrameIndex = findSeekFrameIndex(
            frameIndex);
    DEBUG_ASSERT(SINT(m_seekFrameList.size()) > seekFrameIndex);
    const SINT curSeekFrameIndex = findSeekFrameIndex(
            m_curFrameIndex);
    DEBUG_ASSERT(SINT(m_seekFrameList.size()) > curSeekFrameIndex);
    // some consistency checks
    DEBUG_ASSERT((curSeekFrameIndex >= seekFrameIndex) || (m_curFrameIndex < frameIndex));
    DEBUG_ASSERT((curSeekFrameIndex <= seekFrameIndex) || (m_curFrameIndex > frameIndex));
    if ((getMaxFrameIndex() <= m_curFrameIndex) || // out of range
            (frameIndex < m_curFrameIndex) || // seek backward
            (seekFrameIndex > (curSeekFrameIndex + kMp3SeekFramePrefetchCount))) { // jump forward

        // Adjust the seek frame index for prefetching
        // Implementation note: The type SINT is unsigned so
        // need to be careful when subtracting!
        if (kMp3SeekFramePrefetchCount < seekFrameIndex) {
            // Restart decoding kMp3SeekFramePrefetchCount seek frames
            // before the expected sync position
            seekFrameIndex -= kMp3SeekFramePrefetchCount;
        } else {
            // Restart decoding at the beginning of the audio stream
            seekFrameIndex = 0;
        }

        m_curFrameIndex = restartDecoding(m_seekFrameList[seekFrameIndex]);
        if (getMaxFrameIndex() <= m_curFrameIndex) {
            // out of range -> abort
            return m_curFrameIndex;
        }
        DEBUG_ASSERT(findSeekFrameIndex(m_curFrameIndex) == seekFrameIndex);
    }

    // Decoding starts before the actual target position
    DEBUG_ASSERT(m_curFrameIndex <= frameIndex);

    // Skip (= decode and discard) all samples up to the target position
    const SINT prefetchFrameCount = frameIndex - m_curFrameIndex;
    const SINT skipFrameCount = skipSampleFrames(prefetchFrameCount);
    DEBUG_ASSERT(skipFrameCount <= prefetchFrameCount);
    if (skipFrameCount < prefetchFrameCount) {
        qWarning() << "Failed to prefetch sample data while seeking"
                << skipFrameCount << "<" << prefetchFrameCount;
    }

    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    return m_curFrameIndex;
}
Exemple #7
0
SINT SoundSourceM4A::readSampleFrames(
        SINT numberOfFrames, CSAMPLE* sampleBuffer) {
    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));

    const SINT numberOfFramesTotal = math_min(
            numberOfFrames, getMaxFrameIndex() - m_curFrameIndex);
    const SINT numberOfSamplesTotal = frames2samples(numberOfFramesTotal);

    CSAMPLE* pSampleBuffer = sampleBuffer;
    SINT numberOfSamplesRemaining = numberOfSamplesTotal;
    while (0 < numberOfSamplesRemaining) {

        if (!m_sampleBuffer.isEmpty()) {
            // Consume previously decoded sample data
            const SampleBuffer::ReadableChunk readableChunk(
                    m_sampleBuffer.readFromHead(numberOfSamplesRemaining));
            if (pSampleBuffer) {
                SampleUtil::copy(pSampleBuffer, readableChunk.data(), readableChunk.size());
                pSampleBuffer += readableChunk.size();
            }
            m_curFrameIndex += samples2frames(readableChunk.size());
            DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
            DEBUG_ASSERT(numberOfSamplesRemaining >= readableChunk.size());
            numberOfSamplesRemaining -= readableChunk.size();
            if (0 == numberOfSamplesRemaining) {
                break; // exit loop
            }
        }
        // All previously decoded sample data has been consumed now
        DEBUG_ASSERT(m_sampleBuffer.isEmpty());

        if (0 == m_inputBufferLength) {
            // Fill input buffer from file
            if (isValidSampleBlockId(m_curSampleBlockId)) {
                // Read data for next sample block into input buffer
                u_int8_t* pInputBuffer = &m_inputBuffer[0];
                u_int32_t inputBufferLength = m_inputBuffer.size(); // in/out parameter
                if (!MP4ReadSample(m_hFile, m_trackId, m_curSampleBlockId,
                        &pInputBuffer, &inputBufferLength,
                        NULL, NULL, NULL, NULL)) {
                    qWarning()
                            << "Failed to read MP4 input data for sample block"
                            << m_curSampleBlockId << "(" << "min ="
                            << kSampleBlockIdMin << "," << "max ="
                            << m_maxSampleBlockId << ")";
                    break; // abort
                }
                ++m_curSampleBlockId;
                m_inputBufferLength = inputBufferLength;
                m_inputBufferOffset = 0;
            }
        }
        DEBUG_ASSERT(0 <= m_inputBufferLength);
        if (0 == m_inputBufferLength) {
            break; // EOF
        }

        // NOTE(uklotzde): The sample buffer for NeAACDecDecode2 has to
        // be big enough for a whole block of decoded samples, which
        // contains up to kFramesPerSampleBlock frames. Otherwise
        // we need to use a temporary buffer.
        CSAMPLE* pDecodeBuffer; // in/out parameter
        SINT decodeBufferCapacity;
        const SINT decodeBufferCapacityMin = frames2samples(kFramesPerSampleBlock);
        if (pSampleBuffer && (decodeBufferCapacityMin <= numberOfSamplesRemaining)) {
            // Decode samples directly into sampleBuffer
            pDecodeBuffer = pSampleBuffer;
            decodeBufferCapacity = numberOfSamplesRemaining;
        } else {
            // Decode next sample block into temporary buffer
            const SINT writeToTailCount = math_max(
                    numberOfSamplesRemaining, decodeBufferCapacityMin);
            const SampleBuffer::WritableChunk writableChunk(
                    m_sampleBuffer.writeToTail(writeToTailCount));
            pDecodeBuffer = writableChunk.data();
            decodeBufferCapacity = writableChunk.size();
        }
        DEBUG_ASSERT(decodeBufferCapacityMin <= decodeBufferCapacity);

        NeAACDecFrameInfo decFrameInfo;
        void* pDecodeResult = NeAACDecDecode2(
                m_hDecoder, &decFrameInfo,
                &m_inputBuffer[m_inputBufferOffset],
                m_inputBufferLength,
                reinterpret_cast<void**>(&pDecodeBuffer),
                decodeBufferCapacity * sizeof(*pDecodeBuffer));
        // Verify the decoding result
        if (0 != decFrameInfo.error) {
            qWarning() << "AAC decoding error:"
                    << decFrameInfo.error
                    << NeAACDecGetErrorMessage(decFrameInfo.error)
                    << getUrlString();
            break; // abort
        }
        DEBUG_ASSERT(pDecodeResult == pDecodeBuffer); // verify the in/out parameter

        // Verify the decoded sample data for consistency
        if (getChannelCount() != decFrameInfo.channels) {
            qWarning() << "Corrupt or unsupported AAC file:"
                    << "Unexpected number of channels" << decFrameInfo.channels
                    << "<>" << getChannelCount();
            break; // abort
        }
        if (getFrameRate() != SINT(decFrameInfo.samplerate)) {
            qWarning() << "Corrupt or unsupported AAC file:"
                    << "Unexpected sample rate" << decFrameInfo.samplerate
                    << "<>" << getFrameRate();
            break; // abort
        }

        // Consume input data
        m_inputBufferLength -= decFrameInfo.bytesconsumed;
        m_inputBufferOffset += decFrameInfo.bytesconsumed;

        // Consume decoded output data
        const SINT numberOfSamplesDecoded = decFrameInfo.samples;
        DEBUG_ASSERT(numberOfSamplesDecoded <= decodeBufferCapacity);
        SINT numberOfSamplesRead;
        if (pDecodeBuffer == pSampleBuffer) {
            numberOfSamplesRead = math_min(numberOfSamplesDecoded, numberOfSamplesRemaining);
            pSampleBuffer += numberOfSamplesRead;
        } else {
            m_sampleBuffer.readFromTail(decodeBufferCapacity - numberOfSamplesDecoded);
            const SampleBuffer::ReadableChunk readableChunk(
                    m_sampleBuffer.readFromHead(numberOfSamplesRemaining));
            numberOfSamplesRead = readableChunk.size();
            if (pSampleBuffer) {
                SampleUtil::copy(pSampleBuffer, readableChunk.data(), numberOfSamplesRead);
                pSampleBuffer += numberOfSamplesRead;
            }
        }
        // The decoder might decode more samples than actually needed
        // at the end of the file! When the end of the file has been
        // reached decoding can be restarted by seeking to a new
        // position.
        DEBUG_ASSERT(numberOfSamplesDecoded >= numberOfSamplesRead);
        m_curFrameIndex += samples2frames(numberOfSamplesRead);
        DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
        DEBUG_ASSERT(numberOfSamplesRemaining >= numberOfSamplesRead);
        numberOfSamplesRemaining -= numberOfSamplesRead;
    }

    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    DEBUG_ASSERT(numberOfSamplesTotal >= numberOfSamplesRemaining);
    return samples2frames(numberOfSamplesTotal - numberOfSamplesRemaining);
}
SINT SoundSourceMediaFoundation::seekSampleFrame(
        SINT frameIndex) {
    DEBUG_ASSERT(isValidFrameIndex(m_currentFrameIndex));

    if (frameIndex >= getMaxFrameIndex()) {
        // EOF
        m_currentFrameIndex = getMaxFrameIndex();
        return m_currentFrameIndex;
    }

    if (frameIndex > m_currentFrameIndex) {
        // seeking forward
        SINT skipFramesCount = frameIndex - m_currentFrameIndex;
        // When to prefer skipping over seeking:
        // 1) The sample buffer would be discarded before seeking anyway and
        //    skipping those already decoded samples effectively costs nothing
        // 2) After seeking we need to decode at least kNumberOfPrefetchFrames
        //    before reaching the actual target position -> Only seek if we
        //    need to decode more than  2 * kNumberOfPrefetchFrames frames
        //    while skipping
        SINT skipFramesCountMax =
                samples2frames(m_sampleBuffer.getSize()) +
                2 * kNumberOfPrefetchFrames;
        if (skipFramesCount <= skipFramesCountMax) {
            skipSampleFrames(skipFramesCount);
        }
    }
    if (frameIndex == m_currentFrameIndex) {
        return m_currentFrameIndex;
    }

    // Discard decoded samples
    m_sampleBuffer.reset();

    // Invalidate current position (end of stream)
    m_currentFrameIndex = getMaxFrameIndex();

    if (m_pSourceReader == nullptr) {
        // reader is dead
        return m_currentFrameIndex;
    }

    // Jump to a position before the actual seeking position.
    // Prefetching a certain number of frames is necessary for
    // sample accurate decoding. The decoder needs to decode
    // some frames in advance to produce the same result at
    // each position in the stream.
    SINT seekIndex = std::max(SINT(frameIndex - kNumberOfPrefetchFrames), AudioSource::getMinFrameIndex());

    LONGLONG seekPos = m_streamUnitConverter.fromFrameIndex(seekIndex);
    DEBUG_ASSERT(seekPos >= 0);
    PROPVARIANT prop;
    HRESULT hrInitPropVariantFromInt64 =
            InitPropVariantFromInt64(seekPos, &prop);
    DEBUG_ASSERT(SUCCEEDED(hrInitPropVariantFromInt64)); // never fails
    HRESULT hrSetCurrentPosition =
            m_pSourceReader->SetCurrentPosition(GUID_NULL, prop);
    PropVariantClear(&prop);
    if (SUCCEEDED(hrSetCurrentPosition)) {
        // NOTE(uklotzde): After SetCurrentPosition() the actual position
        // of the stream is unknown until reading the next samples from
        // the reader. Please note that the first sample decoded after
        // SetCurrentPosition() may start BEFORE the actual target position.
        // See also: https://msdn.microsoft.com/en-us/library/windows/desktop/dd374668(v=vs.85).aspx
        //   "The SetCurrentPosition method does not guarantee exact seeking." ...
        //   "After seeking, the application should call IMFSourceReader::ReadSample
        //    and advance to the desired position.
        SINT skipFramesCount = frameIndex - seekIndex;
        if (skipFramesCount > 0) {
            // We need to fetch at least 1 sample from the reader to obtain the
            // current position!
            skipSampleFrames(skipFramesCount);
            // Now m_currentFrameIndex reflects the actual position of the reader
            if (m_currentFrameIndex < frameIndex) {
                // Skip more samples if frameIndex has not yet been reached
                skipSampleFrames(frameIndex - m_currentFrameIndex);
            }
            if (m_currentFrameIndex != frameIndex) {
                qWarning() << kLogPreamble
                        << "Seek to frame"
                        << frameIndex
                        << "failed";
                // Jump to end of stream (= invalidate current position)
                m_currentFrameIndex = getMaxFrameIndex();
            }
        } else {
            // We are at the beginning of the stream and don't need
            // to skip any frames. Calling IMFSourceReader::ReadSample
            // is not necessary in this special case.
            DEBUG_ASSERT(frameIndex == AudioSource::getMinFrameIndex());
            m_currentFrameIndex = frameIndex;
        }
    } else {
        qWarning() << kLogPreamble
                << "IMFSourceReader::SetCurrentPosition() failed"
                << hrSetCurrentPosition;
        safeRelease(&m_pSourceReader); // kill the reader
    }

    return m_currentFrameIndex;
}
Exemple #9
0
const struct mips_operand *
decode_mips16_operand (char type, bfd_boolean extended_p)
{
  switch (type)
    {
    case '0': MAPPED_REG (0, 0, GP, reg_0_map);

    case 'L': SPECIAL (6, 5, ENTRY_EXIT_LIST);
    case 'M': SPECIAL (7, 0, SAVE_RESTORE_LIST);
    case 'P': SPECIAL (0, 0, PC);
    case 'R': MAPPED_REG (0, 0, GP, reg_31_map);
    case 'S': MAPPED_REG (0, 0, GP, reg_29_map);
    case 'X': REG (5, 0, GP);
    case 'Y': MAPPED_REG (5, 3, GP, reg32r_map);
    case 'Z': MAPPED_REG (3, 0, GP, reg_m16_map);

    case 'a': JUMP (26, 0, 2);
    case 'e': UINT (11, 0);
    case 'i': JALX (26, 0, 2);
    case 'l': SPECIAL (6, 5, ENTRY_EXIT_LIST);
    case 'm': SPECIAL (7, 0, SAVE_RESTORE_LIST);
    case 'v': MAPPED_REG (3, 8, GP, reg_m16_map);
    case 'w': MAPPED_REG (3, 5, GP, reg_m16_map);
    case 'x': MAPPED_REG (3, 8, GP, reg_m16_map);
    case 'y': MAPPED_REG (3, 5, GP, reg_m16_map);
    case 'z': MAPPED_REG (3, 2, GP, reg_m16_map);
    }

  if (extended_p)
    switch (type)
      {
      case '<': UINT (5, 0);
      case '>': UINT (5, 0);
      case '[': UINT (6, 0);
      case ']': UINT (6, 0);

      case '4': SINT (15, 0);
      case '5': SINT (16, 0);
      case '6': SINT (16, 0);
      case '8': SINT (16, 0);

      case 'A': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE);
      case 'B': PCREL (16, 0, TRUE, 0, 3, FALSE, FALSE);
      case 'C': SINT (16, 0);
      case 'D': SINT (16, 0);
      case 'E': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE);
      case 'H': SINT (16, 0);
      case 'K': SINT (16, 0);
      case 'U': UINT (16, 0);
      case 'V': SINT (16, 0);
      case 'W': SINT (16, 0);

      case 'j': SINT (16, 0);
      case 'k': SINT (16, 0);
      case 'p': BRANCH (16, 0, 1);
      case 'q': BRANCH (16, 0, 1);
      }
  else
    switch (type)
      {
      case '<': INT_ADJ (3, 2, 8, 0, FALSE);
      case '>': INT_ADJ (3, 8, 8, 0, FALSE);
      case '[': INT_ADJ (3, 2, 8, 0, FALSE);
      case ']': INT_ADJ (3, 8, 8, 0, FALSE);

      case '4': SINT (4, 0);
      case '5': UINT (5, 0);
      case '6': UINT (6, 5);
      case '8': UINT (8, 0);

      case 'A': PCREL (8, 0, FALSE, 2, 2, FALSE, FALSE);
      case 'B': PCREL (5, 0, FALSE, 3, 3, FALSE, FALSE);
      case 'C': INT_ADJ (8, 0, 255, 3, FALSE);	/* (0 .. 255) << 3 */
      case 'D': INT_ADJ (5, 0, 31, 3, FALSE);	/* (0 .. 31) << 3 */
      case 'E': PCREL (5, 0, FALSE, 2, 2, FALSE, FALSE);
      case 'H': INT_ADJ (5, 0, 31, 1, FALSE);	/* (0 .. 31) << 1 */
      case 'K': INT_ADJ (8, 0, 127, 3, FALSE);	/* (-128 .. 127) << 3 */
      case 'U': UINT (8, 0);
      case 'V': INT_ADJ (8, 0, 255, 2, FALSE);	/* (0 .. 255) << 2 */
      case 'W': INT_ADJ (5, 0, 31, 2, FALSE);	/* (0 .. 31) << 2 */

      case 'j': SINT (5, 0);
      case 'k': SINT (8, 0);
      case 'p': BRANCH (8, 0, 1);
      case 'q': BRANCH (11, 0, 1);
      }
  return 0;
}
Exemple #10
0
const struct mips_operand *
decode_mips16_operand (char type, bfd_boolean extended_p)
{
  switch (type)
    {
    case '.': MAPPED_REG (0, 0, GP, reg_0_map);
    case '>': HINT (5, 22);

    case '0': HINT (5, 0);
    case '1': HINT (3, 5);
    case '2': HINT (3, 8);
    case '3': HINT (5, 16);
    case '4': HINT (3, 21);
    case '6': HINT (6, 5);
    case '9': SINT (9, 0);

    case 'G': SPECIAL (0, 0, REG28);
    case 'L': SPECIAL (6, 5, ENTRY_EXIT_LIST);
    case 'N': REG (5, 0, COPRO);
    case 'O': UINT (3, 21);
    case 'Q': REG (5, 16, HW);
    case 'P': SPECIAL (0, 0, PC);
    case 'R': MAPPED_REG (0, 0, GP, reg_31_map);
    case 'S': MAPPED_REG (0, 0, GP, reg_29_map);
    case 'T': HINT (5, 16);
    case 'X': REG (5, 0, GP);
    case 'Y': MAPPED_REG (5, 3, GP, reg32r_map);
    case 'Z': MAPPED_REG (3, 0, GP, reg_m16_map);

    case 'a': JUMP (26, 0, 2);
    case 'b': BIT (5, 22, 0);			/* (0 .. 31) */
    case 'c': MSB (5, 16, 1, TRUE, 32);		/* (1 .. 32) */
    case 'd': MSB (5, 16, 1, FALSE, 32);	/* (1 .. 32) */
    case 'e': HINT (11, 0);
    case 'i': JALX (26, 0, 2);
    case 'l': SPECIAL (6, 5, ENTRY_EXIT_LIST);
    case 'm': SPECIAL (7, 0, SAVE_RESTORE_LIST);
    case 'n': INT_BIAS (2, 0, 3, 1, 0, FALSE);	/* (1 .. 4) */
    case 'o': INT_ADJ (5, 16, 31, 4, FALSE);	/* (0 .. 31) << 4 */
    case 'r': MAPPED_REG (3, 16, GP, reg_m16_map);
    case 's': HINT (3, 24);
    case 'u': HINT (16, 0);
    case 'v': OPTIONAL_MAPPED_REG (3, 8, GP, reg_m16_map);
    case 'w': OPTIONAL_MAPPED_REG (3, 5, GP, reg_m16_map);
    case 'x': MAPPED_REG (3, 8, GP, reg_m16_map);
    case 'y': MAPPED_REG (3, 5, GP, reg_m16_map);
    case 'z': MAPPED_REG (3, 2, GP, reg_m16_map);
    }

  if (extended_p)
    switch (type)
      {
      case '<': UINT (5, 22);
      case '[': UINT (6, 0);
      case ']': UINT (6, 0);

      case '5': SINT (16, 0);
      case '8': SINT (16, 0);

      case 'A': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE);
      case 'B': PCREL (16, 0, TRUE, 0, 3, FALSE, FALSE);
      case 'C': SINT (16, 0);
      case 'D': SINT (16, 0);
      case 'E': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE);
      case 'F': SINT (15, 0);
      case 'H': SINT (16, 0);
      case 'K': SINT (16, 0);
      case 'U': UINT (16, 0);
      case 'V': SINT (16, 0);
      case 'W': SINT (16, 0);

      case 'j': SINT (16, 0);
      case 'k': SINT (16, 0);
      case 'p': BRANCH (16, 0, 1);
      case 'q': BRANCH (16, 0, 1);
      }
  else
    switch (type)
      {
      case '<': INT_ADJ (3, 2, 8, 0, FALSE);
      case '[': INT_ADJ (3, 2, 8, 0, FALSE);
      case ']': INT_ADJ (3, 8, 8, 0, FALSE);

      case '5': UINT (5, 0);
      case '8': UINT (8, 0);

      case 'A': PCREL (8, 0, FALSE, 2, 2, FALSE, FALSE);
      case 'B': PCREL (5, 0, FALSE, 3, 3, FALSE, FALSE);
      case 'C': INT_ADJ (8, 0, 255, 3, FALSE);	/* (0 .. 255) << 3 */
      case 'D': INT_ADJ (5, 0, 31, 3, FALSE);	/* (0 .. 31) << 3 */
      case 'E': PCREL (5, 0, FALSE, 2, 2, FALSE, FALSE);
      case 'F': SINT (4, 0);
      case 'H': INT_ADJ (5, 0, 31, 1, FALSE);	/* (0 .. 31) << 1 */
      case 'K': INT_ADJ (8, 0, 127, 3, FALSE);	/* (-128 .. 127) << 3 */
      case 'U': UINT (8, 0);
      case 'V': INT_ADJ (8, 0, 255, 2, FALSE);	/* (0 .. 255) << 2 */
      case 'W': INT_ADJ (5, 0, 31, 2, FALSE);	/* (0 .. 31) << 2 */

      case 'j': SINT (5, 0);
      case 'k': SINT (8, 0);
      case 'p': BRANCH (8, 0, 1);
      case 'q': BRANCH (11, 0, 1);
      }
  return 0;
}