Инструкция add x1, sp, x2, lsl #1
должна быть «Добавить (сдвинутый регистр)», но у меня проблемы с кодировкой, чтобы различать, когда используется SP и XZR. Я поражен результатами.
Это кодировка для «ADD (сдвинутый регистр)»:
31:1, 30:0, 29:0, 28:0, 27:1, 26:0, 25:1, 24:1, 23..22:shift, 21:0, 20..16:Rm, 15..10:imm6, 9..5:Rn, 4..0:Rd
Если я соберу add x1, xzr, x2, lsl #1
, он будет соответствовать приведенной выше кодировке. Просто отметить важные моменты:
E1 07 02 8B add x1, xzr, x2, lsl #1
bit 21 = 0;
shift = 0 (lsl);
imm6 = 1
Но если собрать add x1, sp, x2, lsl #1
, то в кодировке странные изменения. Изменения:
E1 67 22 8B add x1, sp, x2, lsl #1
bit 21 = 1;
shift = 0;
imm6 = 011001 (lsl 25)
Итак, я предполагаю, что бит 21 означает SP вместо XZR. Но почему imm6 = 25? Это "LSL 25"!
Я смотрю на неправильную кодировку инструкций?
Закодированная инструкция изменяется с «ADD (сдвинутый регистр)» (§ C6.2.5) на «ADD (расширенный регистр)» (§ C6.2.3), если вы используете SP
в операнде. Это необходимо, так как только последний поддерживает использование SP
или WSP
в своем первом или втором операнде.
У меня проблемы с кодировкой, чтобы различать, когда используется SP и XZR.
В инструкции написано какой из двух используется. Если используется SP
, в поле будет написано что-то вроде <Xn|SP>
, а в тексте будет написано «регистр общего назначения или указатель стека». Когда используется XZR
, в поле отображается что-то вроде <Xn>
, а в тексте просто написано «регистр общего назначения». Вам нужно знать, какую инструкцию вы декодируете, чтобы знать, следует ли декодировать XZR
или SP
. И обратите внимание, что иногда несколько инструкций используют одну и ту же мнемонику. Например, мнемоника ADD
используется ими (без учета разных размеров операндов, доступных для одной и той же инструкции):
ADD <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}
ADD <Xd|SP>, <Xn|SP>, #imm{, <shift>}
ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
ADD <V><d>, <V><n>, <V><m>
Большое спасибо! Теперь все ясно. Я также пропустил ту важную часть описания, где SP также указывается в кодировке инструкции (например, <Xd|SP>
Что может сбивать с толку, так это то, что определены две формы, которые называются «ADD (сдвинутый регистр)» и «ADD (расширенный регистр)». Однако версия с «расширенным регистром» также может сдвигать свой операнд, только не такими гибкими способами (только сдвиг влево и только на 0-4 бита). И это не обязательно должно делать знаковое или нулевое расширение. Таким образом, несмотря на то, что
add x1, sp, x2, lsl #1
применяет сдвиг и не применяет никакого расширения, это все еще допустимый экземпляр инструкции «ДОБАВИТЬ (расширенный регистр)». Но я понимаю, почему вы не додумались туда заглянуть!