По сути, у меня есть 8 частей данных, по 2 бита каждая (4 состояния), которые хранятся в 16 младших битах 32-разрядного целого числа.Я хочу изменить порядок частей данных, чтобы выполнить некоторое сопоставление с образцом.
Мне дано целое число и 8 кандидатов, и мне нужно сопоставить одного из кандидатов с ссылкой.Однако подходящий кандидат может быть преобразован некоторым предсказуемым образом.
Если контрольные данные имеют вид [0,1,2,3,4,5,6,7], то возможные совпадения могутбыть в одной из этих 8 форм:
[0,1,2,3,4,5,6,7], [0,7,6,5,4,3,2,1]
[6,7,0,1,2,3,4,5], [2,1,0,7,6,5,4,3]
[4,5,6,7,0,1,2,3], [4,3,2,1,0,7,6,5]
[2,3,4,5,6,7,0,1], [6,5,4,3,2,1,0,7]
Шаблон состоит в том, что данные всегда в порядке, но их можно перевернуть и повернуть.
Я реализую это в C и MIPS.У меня оба работают, но они кажутся громоздкими.Мой текущий подход состоит в том, чтобы замаскировать каждый фрагмент из оригинала, переместить его на новую позицию и ИЛИ с новой переменной (инициализированной на 0).
Я сделал более жесткое кодирование в C:
int ref = 4941; // reference value, original order [1,3,0,1,3,0,1,0], (encoded as 0b0001001101001101)
int rev = 0;
rev |= ((ref & 0x0003) << 14) | ((ref & 0x000C) << 10) | ((ref & 0x0030) << 6) | ((ref & 0x00C0) << 2); // move bottom 8 bits to top
rev |= ((ref & 0xC000) >> 14) | ((ref & 0x3000) >> 10) | ((ref & 0x0C00) >> 6) | ((ref & 0x0300) >> 2); // move top 8 bits to bottom
// rev = 29124 reversed order [0,1,0,3,1,0,3,1], (0b0111000111000100)
Я реализовал цикл в MIPS, чтобы попытаться уменьшить статические инструкции:
lw $01, Reference($00) # load reference value
addi $04, $00, 4 # initialize $04 as Loop counter
addi $05, $00, 14 # initialize $05 to hold shift value
addi $06, $00, 3 # initialize $06 to hold mask (one piece of data)
# Reverse the order of data in Reference and store it in $02
Loop: addi $04, $04, -1 # decrement Loop counter
and $03, $01, $06 # mask out one piece ($03 = Reference & $06)
sllv $03, $03, $05 # shift piece to new position ($03 <<= $05)
or $02, $02, $03 # put piece into $02 ($02 |= $03)
sllv $06, $06, $05 # shift mask for next piece
and $03, $01, $06 # mask out next piece (#03 = Reference & $06)
srlv $03, $03, $05 # shift piece to new position ($03 >>= $05)
or $02, $02, $03 # put new piece into $02 ($02 |= $03)
srlv $06, $06, $05 # shift mask back
addi $05, $05, -4 # decrease shift amount by 4
sll $06, $06, 2 # shift mask for next loop
bne $04, $00, Loop # keep looping while $04 != 0
Есть ли способ реализовать это, что проще или, по крайней мере, меньше инструкций?