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, ¤tSection); 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; }
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; }
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; }
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; }
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; }