Для Xmega на C делил переменные INT16 на два байта. Сначала 16-ти разрядные множители присваивал переменным с разрядностью INT32, затем умножал на младшие байты и складывал.
Затем 16-ти разрядный множители присваивал переменным с разрядностью INT32, умножал на старшие байты и складывал.
Потом сдвигал сумму "старших" и складывал с суммой "младших" произведений.
При сильной оптимизации по скорости IAR не использует вызовы функций, умножения и сложения выполняются в линейном коде:
\ 0000009A 01C0 MOVW R25:R24, R1:R0
\ 0000009C A8C2 LDD R12, Z+50
\ 0000009E 2766 CLR R22
\ 000000A0 9CC3 MUL R12, R3
\ 000000A2 2CF0 MOV R15, R0
\ 000000A4 9CC2 MUL R12, R2
\ 000000A6 2CE0 MOV R14, R0
\ 000000A8 0CF1 ADD R15, R1
\ 000000AA 9EC9 MUL R12, R25
\ 000000AC 2CD0 MOV R13, R0
\ 000000AE 0CE1 ADD R14, R1
\ 000000B0 1EF6 ADC R15, R22
\ 000000B2 9EC8 MUL R12, R24
\ 000000B4 2CC0 MOV R12, R0
\ 000000B6 0CD1 ADD R13, R1
\ 000000B8 1EE6 ADC R14, R22
\ 000000BA 1EF6 ADC R15, R22
\ 000000BC 8440 LDD R4, Z+8
\ 000000BE 8451 LDD R5, Z+9
\ 000000C0 8462 LDD R6, Z+10
\ 000000C2 8473 LDD R7, Z+11
\ 000000C4 A984 LDD R24, Z+52
\ 000000C6 9D87 MUL R24, R7
\ 000000C8 2DB0 MOV R27, R0
\ 000000CA 9D86 MUL R24, R6
\ 000000CC 2DA0 MOV R26, R0
\ 000000CE 0DB1 ADD R27, R1
\ 000000D0 9D85 MUL R24, R5
\ 000000D2 2D90 MOV R25, R0
\ 000000D4 0DA1 ADD R26, R1
\ 000000D6 1FB6 ADC R27, R22
\ 000000D8 9D84 MUL R24, R4
\ 000000DA 0D91 ADD R25, R1
\ 000000DC 1FA6 ADC R26, R22
\ 000000DE 1FB6 ADC R27, R22
\ 000000E0 18C0 SUB R12, R0
\ 000000E2 0AD9 SBC R13, R25
\ 000000E4 0AEA SBC R14, R26
\ 000000E6 0AFB SBC R15, R27
...
\ 000001EE REQUIRE ?Subroutine0
\ 000001EE ; // Fall through to label ?Subroutine0