Просто попробуйте ...
so.s
.thumb
sub r0,#1
.syntax unified
subs r0,r0,#1
sub r0,#1
subs.n r0,#1
собрать и разобрать
arm-none-eabi-as so.s -o so.o
arm-none-eabi-objdump -D so.o
so.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <.text>:
0: 3801 subs r0, #1
2: 3801 subs r0, #1
4: f1a0 0001 sub.w r0, r0, #1
8: 3801 subs r0, #1
РЕДАКТИРОВАТЬ комментарий Олафа.
.thumb
sub r0,#1
sub r0,r0,#1
sub r1,r2,#1
.syntax unified
subs r0,r0,#1
sub r0,#1
subs.n r0,#1
subs.n r0,r0,#1
subs r1,r2,#1
00000000 <.text>:
0: 3801 subs r0, #1
2: 3801 subs r0, #1
4: 1e51 subs r1, r2, #1
6: 3801 subs r0, #1
8: f1a0 0001 sub.w r0, r0, #1
c: 3801 subs r0, #1
e: 3801 subs r0, #1
10: 1e51 subs r1, r2, #1
Я / вы / мы должны были бы покопаться в источнике ассемблера, чтобы посмотреть, есть ли способ обойти это. Фуз может иметь самый простой ответ. Вероятно, что ассемблер оптимизирован для того, чтобы с большей гибкостью сразу. Вы, безусловно, можете удалить эту оптимизацию / функцию (если флаг отсутствует).
EDIT2
Возможно, это так.
#define T_OPCODE_SUB_I8 0x3800
#define T_OPCODE_SUB_I3 0x1e00
else if (rs == rd)
{
if (value & ~0xff)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("immediate value out of range"));
newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
newval |= (rd << 8) | value;
}
else
{
if (value & ~0x7)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("immediate value out of range"));
newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
newval |= rd | (rs << 3) | (value << 6);
}
Если вы добавите это
else if (value & ~0x7)
{
newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
newval |= rd | (rs << 3) | (value << 6);
}
перед
else if (rs == rd)
тогда
.cpu cortex-m7
.thumb
sub r0,r0,#15
sub r0,r0,#1
.syntax unified
subs.n r0,r0,#1
subs.n r0,r0,#15
дает желаемый результат.
0: 1fc0 subs r0, r0, #7
2: 3801 subs r0, #1
4: 3801 subs r0, #1
6: 1fc0 subs r0, r0, #7
Так что я думаю, что rs == rd мешает вам генерировать требуемую инструкцию.
РЕДАКТИРОВАТЬ 3
binutils 2.7 не имеет этого определения T_OPCODE_SUB_I8, поэтому, возможно, не имеет поддержки большого пальца, не копал глубже, чем это. binutils 2.8 делает и включает эту оптимизацию. Так что еще в 1997 году это было там. Если вы хотите сгенерировать соответствующую инструкцию с помощью ассемблера gnu, похоже, вам нужно изменить ассемблер gnu ...