📄 bitdcods.s
字号:
;/*
; * Bit decode assembler
; * Copyright (C) ARM Limited 1998-1999. All rights reserved.
; */
INCLUDE intworkm.h ; include interworking macros
AREA |C$$code|, CODE, READONLY $interwork
; load and store of halfword operations is required which has specific instructions defined in architecture 4 or later
; if architecture 4 or later is not available other instructions must be used to simulate the halfword instructions
;
; define, therefore, a flag which sets the instructions as appropriate for the architecture supported
GBLL ARCHITECTURE_4
ARCHITECTURE_4 SETL :LNOT:( {ARCHITECTURE} = "3" :LOR: {ARCHITECTURE} = "3M" )
TABLEBITS * 10 ; length of codeword in bits in the decoding tables that can be decoded directly
; all remaining codeword lengths over this being decoded by decoding trees
; this must be the same value used to construct the decoding tables/trees that are passed
; define the local register names used for the functions
fin_stream RN 0
streamstr RN 0
n RN 1
dest RN 2
lentable RN 3
symtable RN 4
source RN 0
lenwalk RN 5
symwalk RN 6
bits RN 7
srcword RN 8
word RN 9
dstword RN 10
symbol RN 11
codebits RN 12
t RN codebits
byte RN codebits
INCLUDE datam.h ; include the load and store operations
INCLUDE regchekm.h ; include distinct register checking macro
GENBITDECODE EQU 1 ; 1 = support general bit decoding function, 0 do not support
; if this is given as 1, byte, halfword and word data bit decoding are supported
; regardless of the condition of their flags that follow
BYTEBITDECODE EQU 1 ; 1 = support bit decoding function for byte data, 0 do not support
HWORDBITDECODE EQU 1 ; 1 = support bit decoding function for halfword data, 0 do not support
WORDBITDECODE EQU 1 ; 1 = support bit decoding function for word data, 0 do not support
;---------------------------------------------------------------
; initialise bit decoding
;
; saves registers, gets bit stream and bit position and loads
; next two words of data for decoding (if they exist)
;
; $streamstr register: pointer to a structure that must contain
; an unsigned character array as first entry that is
; the bitstream to use and an
; unsigned integer as second entry that is the
; bit position in this array to start from
; $lentable register: pointer to decoding length table
; $symtable register: pointer to decoding symbol table
; $lenwalk register: to hold pointer to decoding length tree
; $symwalk register: to hold pointer to decoding symbol tree
; $bits register: to hold bit position in the stream
; $source register: to hold address of bit stream
; $srcword register: to hold current word for decoding
; $word register: to hold top-up word for decoding
; $t register: temporary
; $datasize the size of the symbols
;
; $streamstr, $symtable, $lenwalk, $symwalk and $t must be distinct
; $lentable, $symtable, $lenwalk, $symwalk, $bits, $source, $srcword
; and $word must be distinct
; $t and $bits must be distinct
;
;---------------------------------------------------------------
MACRO
INITIALISEBITDECODING $streamstr, $lentable, $symtable, $lenwalk, $symwalk, $bits, $source, $srcword, $word, $t, $datasize
ASSERT ( $datasize = 8 :LOR: $datasize = 16 :LOR: $datasize = 32 ) ; ensure that $datasize is valid
; check registers are distinct
DISTINCT $streamstr, $symtable, $lenwalk, $symwalk, $t
DISTINCT $lentable, $symtable, $lenwalk, $symwalk, $bits, $source, $srcword, $word
DISTINCT $t, $bits
MOV $t, sp ; save the stack register on entry
STMFD sp!, { $streamstr, R4 - R11, lr } ; save registers including the state structure pointer
LDR $symtable, [ $t ] ; get the fifth parameter, the symbol table, which is on the stack
ADD $lenwalk, $lentable, #1 << TABLEBITS ; set the start of tree for lengths, $lentable being bytes
; set the start of tree for symbols which is dependent on the size of the data
IF $datasize = 8 ; $symtable is array of bytes
ADD $symwalk, $symtable, #1 << TABLEBITS
ELSE
IF $datasize = 16 ; $symtable is array of halfwords
ADD $symwalk, $symtable, #1 << ( TABLEBITS + 1 )
ELSE ; $symtable is array of words
ADD $symwalk, $symtable, #1 << ( TABLEBITS + 2 )
ENDIF
ENDIF
LDMIA $streamstr, { $source, $bits } ; load bit stream to decode and the bit position to start from in the stream
LDMIA $source!, { $srcword, $word } ; load in two words of bits from the source stream and increment
; the pointer to next un-read position
; the first word is the first 32-bits for decoding, the second is the
; refill word used to keep the word being decoded topped up with bits
IF {ENDIAN} = "little" ; the main decoding function operates in big endian mode so if the data is little
BYTEREV $srcword, $srcword, $t ; endian the bytes need reversing into big endian mode
BYTEREV $word, $word, $t
ENDIF
CMP $bits, #32 ; check if bit position is part way through a word (4 bytes = 32 bits)
RSBNE $t, $bits, #32 ; if $bits != 32, set $t = 32 - $bits
; $bits gives the number of bits free in word that keeps decoding word topped up and
; thus $t gives the number of bits in word for decoding that have previously been
; decoded and therefore need clearing
MOVNE $srcword, $srcword, LSL $t ; re-pack the word being decoded by clearing out the previously decoded bits
; so that actual next bits for decoding are contained from top bit down
; through word
ORRNE $srcword, $srcword, $word, LSR bits ; refill word for decoding so that all free bits are now filled with next
; bits for decoding read from top up word
; these bits are contained in the top $bits of the top-up word and required
; in the bottom $bits of the word for decoding hence the shift right
MEND
;---------------------------------------------------------------
; load data
;
; load next codeword length and symbol for given codeword
;
; the data read might reference a tree to traverse
;
; $lentable register: memory address of length table
; $symtable register: memory address of bytes,
; halfwords or words symbol table
; $srcword register: codeword index into the tables
; $codebits register: to hold length table data read
; $symbol register: to hold symbol data read
; $datasize the size of the data items in the array - 8, 16 or 32 bits
; $indexposinword the position codeword in $srcword to use as index
;
; $symtable must be distinct from $symbol
; $srcword and $codebits must be distinct
;
;---------------------------------------------------------------
MACRO
LOADSYMBOLANDLENGTH $lentable, $symtable, $srcword, $codebits, $symbol, $datasize, $indexposinword
; check registers are distinct
DISTINCT $srcword, $codebits
; load the next length information from byte length table
; 255 is returned if symbol to be read describes tree internal node else gives decoded codeword length
IF $indexposinword = 0 ; index given directly in bottom 8 bits
LDRB $codebits, [ $lentable, $srcword ]
ELSE ; index needs shifting into bottom 8 bits first
LDRB $codebits, [ $lentable, $srcword, LSR #$indexposinword ]
ENDIF
; load the next symbol information
; this references an internal tree node is length is 255 else symbol to decode to
; this checks the value in datasize
LOADDATA $symtable, $srcword, $symbol, $symbol, $datasize, $indexposinword
MEND
; decode the next codeword to a symbol and length of codeword that has been decoded
;---------------------------------------------------------------
; load data
;
; load next codeword length and symbol for given codeword
;
; the data read might reference a tree to traverse
;
; $lentable register: memory address of length table
; $symtable register: memory address of bytes,
; halfwords or words symbol table
; $srcword register: word of current data to decode
; $word register: top-up word for $srcword
; $bits register: number of bits left before $word exhausted
; $codebits register: to hold length table data read
; $symbol register: to hold symbol data read
; $datasize the size of the data items in the array - 8, 16 or 32 bits
;
; $symtable must be distinct from $symbol
; $srcword, $codebits, $bits and $word must be distinct
;
;---------------------------------------------------------------
MACRO
DECODECODEWORD $lentable, $symtable, $srcword, $word, $bits, $codebits, $symbol, $datasize
; check registers are distinct
DISTINCT $bits, $codebits, $srcword, $word
; load next length and symbol information using only bottom TABLEBITS of $srcword as codeword lookup index
LOADSYMBOLANDLENGTH $lentable, $symtable, $srcword, $codebits, $symbol, $datasize, 32-TABLEBITS
SUBS $bits, $bits, $codebits ; calculate the number of bits that will remain in the top-up word before it is
; after the current codeword is decoded, removed from decoding word and the top-up
; word used to top-up the decoding word
; $codebits may at this point be 255 however and thus this may not be true at this point
MOVGE $srcword, $srcword, LSL $codebits ; if $bits >= 0, remove the codeword that is being decoded from the decoding
; word and shift all remaining bits into the top freeing the bottom
; datasize is known to be correct here since it was checked by LOADSYMBOLANDLENGTH
; set up branch for tree or refilling decoding word based on data size
IF $datasize = 8 ; byte data
BLLT tree_or_refill_byte ; if $bits < 0, escape to either perform a tree walk ($codebits = 255) or to
; refill the top-up word from memory since there are not enough bits left in it
; to refill the decoding word after the codeword has been decoded
; (this will happen less often than a straight drop through in either case and thus
; the code is written so that most cases require minimum number of cycles with
; special cases requiring more work)
ELSE
IF $datasize = 16 ; halfword data
BLLT tree_or_refill_hword
ELSE
BLLT tree_or_refill_word ; word data
ENDIF
ENDIF
ORR $srcword, $srcword, $word, LSR $bits ; refill the bottom bits of the word being decoded with the
; next bits from the top-up word which are at the top of the word and need
; shifting down
MEND
;---------------------------------------------------------------
; end bit decoding process
;
; save the last bit stream and position reached in the stream
; to the structure, restore registers and return
;
; $bits register: number of bits free in $dstword
; $source register: bit stream data is decoded from
; $finaldeststreamaddress
; register: to hold final stream structure returned
; $t register: temporary
;
; $bits, $source, and $t must all be distinct
;
;---------------------------------------------------------------
MACRO
ENDBITDECODING $bits, $source, $finalstreamaddress, $t
; check registers are distinct
DISTINCT $bits, $source, $t
CMP $bits, #0 ; check if top-up word has been completely exhausted
ADDEQ $source, $source, #4 ; if the top-up word has been exhausted, move to the next memory location to read
; the next top-up word in else leave the location so that top-up word can be read
; back in again with current data
SUB $source, $source, #8 ; subtract two words from pointer so that if the decoder is called again
; the word for decoding will be read back with the data that is contains now
; and the top-up word will be the next set of data to read in
LDMFD sp!, { $t } ; read the state structure parameter from the stack that was saved at initialisation
; the structure is read into $t since $finalstreamaddress could easily be one of
; $source or $bits which are still required
STMIA $t, { $source, $bits } ; store the bit stream pointer reached and number of bits free in top-up word
MOV $finalstreamaddress, $t ; set up the return register with the returned structure
RETURN "R4 - R11","","","" ; decoding complete, restore registers and return (rlist, sp, lr, no condition)
MEND
;---------------------------------------------------------------
; decode to an array of bytes
;
; decode variable length codewords to byte symbols
;
; $nbytes register: number of bytes to decode
; $bytedest register: an array to store bytes decoded
; $dstword register: to hold decoded bytes before saving
; $lentable register: decoding length table
; $symtable register: decoding symbol table
; $srcword register: current word being decoded
; $word register: top-up for $srcword
; $bits register: number of bits before $word is exhausted
; $codebits register: to hold each length of codeword being decoded
; $symbol register: to hold each decoded symbol
; $t register: temporary
;
; $nbytes, $bytedest, $dstword, $lentable, $symtable, $srcword, $word,
; $bits, $codebits and $symbol must all be distinct
;
; $t must be distinct from all registers except $codebits and $symbol
;
;---------------------------------------------------------------
MACRO
DECODETOBYTES $nbytes, $bytedest, $dstword, $lentable, $symtable, $srcword, $word, $bits, $codebits, $symbol, $t
; check registers are distinct
DISTINCT $nbytes, $bytedest, $dstword, $lentable, $symtable, $srcword, $word, $bits, $codebits, $symbol
DISTINCT $t, $nbytes, $bytedest, $dstword, $lentable, $symtable, $srcword, $word, $bits
SUBS $nbytes, $nbytes, #4 ; check that there are at least 4 bytes (1 word)...
BLT %FT7 ; decode_bytes ; ...if <4 bytes, cannot operate on words so process as bytes
ANDS $t, $bytedest, #3 ; check that pointer is word-aligned (low 2-bits clear)...
BEQ %FT0 ; get_4_decoded_bytes ; ...if word aligned begin processing over words
LDR $dstword, [$bytedest, -$t]! ; ...else get initial (incomplete) destination word
; adjusting the pointer to make it word-aligned and leave the
; pointer in its adjusted state
ADD $nbytes, $nbytes, $t ; 4 has already been subtracted for word operations, however the
; byte offset for pointer indicates how many bytes have already been
; decoded into the destination and thus how many less will be
; decoded for the first word
CMP $t, #2 ; comparison used for branch to operate on bytes obtained
IF {ENDIAN} = "little"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -