Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ARMマイコンで作るシンセサイザー

Fadis
May 09, 2015

 ARMマイコンで作るシンセサイザー

超低消費電力のARMマイコンLPC812を使ってFMシンセサイザーを作る方法と、その実装に用いられる乗算の最適化について解説します

Fadis

May 09, 2015
Tweet

More Decks by Fadis

Other Decks in Programming

Transcript

  1. ARM໋ྩʹ͸ରԠ͍ͯ͠ͳ͍ 5IVNC '16 ͷΈ 5IVNC '16 ͷΈ 5IVNCͷΈ 5IVNCͷҰ෦͚ͩ 5IVNCͷҰ෦͚ͩ

    5IVNCͷҰ෦͚ͩ Cortex-M7 Cortex-M4 Cortex-M3 Cortex-M1 Cortex-M0+ CortexM0 5IVNCͱ͸"3.ϓϩηοαͷ΋͏ͭͷ໋ྩηοτɻ ໋ྩ͕Մม௕Ͱ"3.໋ྩηοτΑΓϚγϯޠ͕খ͘͞ͳΔɻ
  2. ύΠϓϥΠϯ͕୹͍ Cortex-M7 Cortex-M4 Cortex-M3 Cortex-M1 Cortex-M0+ CortexM0 ஈ౤ػత࣮ߦ ஈ౤ػత࣮ߦ ஈ

    ஈ ஈ ஈ ౤ػత࣮ߦͱ͸ॲཧ͕ඞཁ͔Ͳ͏͔֬ఆ͢Δલ͔Β ࣮ߦΛ࢝Ί͓ͯ͘ࣄɻඞཁͳ͔ͬͨΒ࣮ߦ݁ՌΛࣺͯΔɻ
  3. MEMORY {! flash (rx) : ORIGIN = 0x00000000, LENGTH =

    16K! ram (rwx) : ORIGIN = 0x10000000, LENGTH = 4K! }! ENTRY(Reset_Handler)! SECTIONS {! .text : {! KEEP(*(.isr_vector))! *(.text*)! KEEP(*(.init))! KEEP(*(.fini))! *crtbegin.o(.ctors)! *crtbegin?.o(.ctors)! *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)! *(SORT(.ctors.*))! *(.ctors)! *crtbegin.o(.dtors)! *crtbegin?.o(.dtors)! *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)! *(SORT(.dtors.*))! *(.dtors)! *(.rodata*)! KEEP(*(.eh_frame*))! } > flash! .ARM.extab : {! *(.ARM.extab* .gnu.linkonce.armextab.*)! } > flash! __exidx_start = .;! .ARM.exidx : {! *(.ARM.exidx* .gnu.linkonce.armexidx.*)! } > flash! __exidx_end = .;! __etext__ = .;! .data : AT(__etext__) {! __data_values__ = LOADADDR(.data);! __data_begin__ = .;! *(vtable)! *(.data*)! 3".ͱϑϥογϡϝϞϦͷ ։࢝ΞυϨεͱαΠζ͸ ී௨σʔλγʔτʹॻ͍ͯ͋Δ ! ࠓճ࢖͏-1$ͷ৘ใ͸ ҎԼͷ63-͔ΒḷΕΔ IUUQXXXOYQMQDDPNMQD@NJDPODPSUFYN MQD ldscript
  4. MEMORY {! flash (rx) : ORIGIN = 0x00000000, LENGTH =

    16K! ram (rwx) : ORIGIN = 0x10000000, LENGTH = 4K! }! ENTRY(Reset_Handler)! SECTIONS {! .text : {! KEEP(*(.isr_vector))! *(.text*)! KEEP(*(.init))! KEEP(*(.fini))! *crtbegin.o(.ctors)! *crtbegin?.o(.ctors)! *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)! *(SORT(.ctors.*))! *(.ctors)! *crtbegin.o(.dtors)! *crtbegin?.o(.dtors)! *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)! *(SORT(.dtors.*))! *(.dtors)! *(.rodata*)! KEEP(*(.eh_frame*))! } > flash! .ARM.extab : {! *(.ARM.extab* .gnu.linkonce.armextab.*)! } > flash! __exidx_start = .;! .ARM.exidx : {! *(.ARM.exidx* .gnu.linkonce.armexidx.*)! } > flash! __exidx_end = .;! __etext__ = .;! .data : AT(__etext__) {! __data_values__ = LOADADDR(.data);! __data_begin__ = .;! *(vtable)! *(.data*)! . = ALIGN(4);! ϑϥογϡϝϞϦʹ͸ ! ׂΓࠐΈϕΫλ Ϛγϯޠ ॻ͖มΘΒͳ͍σʔλ ! Λஔ͘ ldscript
  5. .ARM.exidx : {! *(.ARM.exidx* .gnu.linkonce.armexidx.*)! } > flash! __exidx_end =

    .;! __etext__ = .;! .data : AT(__etext__) {! __data_values__ = LOADADDR(.data);! __data_begin__ = .;! *(vtable)! *(.data*)! . = ALIGN(4);! PROVIDE_HIDDEN (__preinit_array_start = .);! KEEP(*(.preinit_array))! PROVIDE_HIDDEN (__preinit_array_end = .);! . = ALIGN(4);! PROVIDE_HIDDEN (__init_array_start = .);! KEEP(*(SORT(.init_array.*)))! KEEP(*(.init_array))! PROVIDE_HIDDEN (__init_array_end = .);! . = ALIGN(4);! PROVIDE_HIDDEN (__fini_array_start = .);! KEEP(*(SORT(.fini_array.*)))! KEEP(*(.fini_array))! PROVIDE_HIDDEN (__fini_array_end = .);! . = ALIGN(4);! __data_end__ = .;! } > ram! .bss : {! __bss_begin__ = .;! *(.bss*)! *(COMMON)! __bss_end__ = .;! } > ram! __stack_begin__ = .;! .stack_dummy : {! *(.stack)! } > ram! __stack_end__ = .;! } 3".ʹ͸ ! WUBCMF ॻ͖มΘΔσʔλ ελοΫ ! Λஔ͘ ldscript
  6. ελʔτΞοϓϧʔνϯ Reset_Handler:! ldr r1, =__etext__! ldr r2, =__data_begin__! ldr r3,

    =__data_end__! ldr r0, =init_data! blx r0! ldr r0, =init_bss! blx r0! ldr r0, =run_preinit! blx r0! ldr r0, =run_init! blx r0! ldr r0, =SystemInit! blx r0! ldr r0, =main! blx r0! .pool ! .size Reset_Handler, . - Reset_Handler
  7. ελʔτΞοϓϧʔνϯ Reset_Handler:! ldr r1, =__etext__! ldr r2, =__data_begin__! ldr r3,

    =__data_end__! ldr r0, =init_data! blx r0! ldr r0, =init_bss! blx r0! ldr r0, =run_preinit! blx r0! ldr r0, =run_init! blx r0! ldr r0, =SystemInit! blx r0! ldr r0, =main! blx r0! .pool ! .size Reset_Handler, . - Reset_Handler ΞηϯϒϦͰ֨ಆͨ͘͠ͳ͍ͷͰ $Ͱ࣮૷ͨ͠ॳظԽίʔυʹඈͿ
  8. ελʔτΞοϓϧʔνϯ Reset_Handler:! ldr r1, =__etext__! ldr r2, =__data_begin__! ldr r3,

    =__data_end__! ldr r0, =init_data! blx r0! ldr r0, =init_bss! blx r0! ldr r0, =run_preinit! blx r0! ldr r0, =run_init! blx r0! ldr r0, =SystemInit! blx r0! ldr r0, =main! blx r0! .pool ! .size Reset_Handler, . - Reset_Handler σόΠεͷॳظԽ͸ CMSISʹ͓·͔ͤ
  9. void run_preinit(void) {! int *cur = &__preinit_array_start;! for( ; cur

    < &__preinit_array_end; cur++ ) {! void (*f)(void) = (void *)*cur;! (*f)();! }! }! void run_init(void) {! int *cur = &__init_array_start;! for( ; cur < &__init_array_end; cur++ ) {! void (*f)(void) = (void *)*cur;! (*f)();! }! }! void init_data(void) {! unsigned char *src = &__data_values__;! unsigned char *dest = &__data_begin__;! unsigned int len = &__data_end__ - &__data_begin__;! while( len-- ) *dest++ = *src++;! }! void init_bss(void) {! unsigned char *dest = &__bss_begin__;! unsigned int len = &__bss_end__ - &__bss_begin__;! while( len-- ) *dest++ = 0;! }
  10. void run_preinit(void) {! int *cur = &__preinit_array_start;! for( ; cur

    < &__preinit_array_end; cur++ ) {! void (*f)(void) = (void *)*cur;! (*f)();! }! }! void run_init(void) {! int *cur = &__init_array_start;! for( ; cur < &__init_array_end; cur++ ) {! void (*f)(void) = (void *)*cur;! (*f)();! }! }! void init_data(void) {! unsigned char *src = &__data_values__;! unsigned char *dest = &__data_begin__;! unsigned int len = &__data_end__ - &__data_begin__;! while( len-- ) *dest++ = *src++;! }! void init_bss(void) {! unsigned char *dest = &__bss_begin__;! unsigned int len = &__bss_end__ - &__bss_begin__;! while( len-- ) *dest++ = 0;! } RAMʹஔ͍͓ͯ͘σʔλΛ ϑϥογϡϝϞϦ͔Βίϐʔ
  11. void run_preinit(void) {! int *cur = &__preinit_array_start;! for( ; cur

    < &__preinit_array_end; cur++ ) {! void (*f)(void) = (void *)*cur;! (*f)();! }! }! void run_init(void) {! int *cur = &__init_array_start;! for( ; cur < &__init_array_end; cur++ ) {! void (*f)(void) = (void *)*cur;! (*f)();! }! }! void init_data(void) {! unsigned char *src = &__data_values__;! unsigned char *dest = &__data_begin__;! unsigned int len = &__data_end__ - &__data_begin__;! while( len-- ) *dest++ = *src++;! }! void init_bss(void) {! unsigned char *dest = &__bss_begin__;! unsigned int len = &__bss_end__ - &__bss_begin__;! while( len-- ) *dest++ = 0;! } άϩʔόϧΦϒδΣΫτͷ ίϯετϥΫλͱ͔Λ࣮ߦ
  12. #include "LPC8xx.h"! extern "C"! __attribute__((interrupt("IRQ")))! void SysTick_Handler(void) {! LPC_GPIO_PORT->NOT0 =

    ( 1 << 16 );! }! int main() {! LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 6);! LPC_GPIO_PORT->DIR0 |= ( 1 << 16 );! SysTick_Config( 6000000 );! while( 1 );! }
  13. #include "LPC8xx.h"! extern "C"! __attribute__((interrupt("IRQ")))! void SysTick_Handler(void) {! LPC_GPIO_PORT->NOT0 =

    ( 1 << 16 );! }! int main() {! LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 6);! LPC_GPIO_PORT->DIR0 |= ( 1 << 16 );! SysTick_Config( 6000000 );! while( 1 );! } SysTickλΠϚʔͷׂΓࠐΈ͕ൃੜͨ͠Β ൪໨ͷGPIOͷ஋Λ൓స @@BUUSJCVUF@@ JOUFSSVQU l*32z ͱ͸͜ΕΛࢦఆͯ͠ ͓͘ͱHDDׂ͕ΓࠐΈΤϯτϦϧʔνϯΛ෇͚ͯ͘ΕΔ
  14. #include "LPC8xx.h"! extern "C"! __attribute__((interrupt("IRQ")))! void SysTick_Handler(void) {! LPC_GPIO_PORT->NOT0 =

    ( 1 << 16 );! }! int main() {! LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 6);! LPC_GPIO_PORT->DIR0 |= ( 1 << 16 );! SysTick_Config( 6000000 );! while( 1 );! } GPIO΁ͷΫϩοΫΛ༗ޮʹͯ͠ ൪໨Λग़ྗϞʔυʹ੾Γସ͑ SysTick͕6,000,000Χ΢ϯτ͢Δ౓ʹ SysTickׂΓࠐΈΛൃੜͤ͞ΔΑ͏ʹ͢Δ
  15. ϚΠίϯʹ%"$͕ແ͍ͷͰ 41*ʹ%"$ΛͿΒԼ͛Δ 7 "3.ϚΠίϯ -1$ 41*%"$ .$1 Ξϯϓ*$ )57 1*0@

    1*0@ 1*0@ 7%% 744 7%% "744 $4 4$-, 4%* 73&' 7065" 744 LЊ Ж' Ж' Ж' 7%% 744 73&' "6%*/ 065/ 0651
  16. void init_dac() {! NVIC_DisableIRQ( (IRQn_Type)( SPI0_IRQn ) );! NVIC_SetPriority(SPI0_IRQn, 0);

    ! do {! NVIC_ClearPendingIRQ(SPI0_IRQn); ! } while(NVIC_GetPendingIRQ(SPI0_IRQn) != 0);! LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 11);! LPC_SPI0->DLY = 4;! LPC_SPI0->DIV = 2;! LPC_SPI0->TXCTRL = (16-1)<<24 | 1<<22 | ( 1 << 20 );! LPC_SPI0->CFG = (1<<5)|(1<<4)|(1<<2);! switch_matrix::bind_SPI0_SSEL_IO( 8 ); ! switch_matrix::bind_SPI0_SCK_IO( 9 );! switch_matrix::bind_SPI0_MOSI_IO( 1 );! LPC_SPI0->INTENSET = 0x0;! NVIC_EnableIRQ( (IRQn_Type)( SPI0_IRQn ) );! LPC_SPI0->TXDAT = 2048 | ( 1 << 13 )|( 1 << 12 );! }! void set_dac( uint16_t value ) {! value &= 4095;! LPC_SPI0->TXDAT = value | ( 1 << 13 )|( 1 << 12 );! }
  17. void init_dac() {! NVIC_DisableIRQ( (IRQn_Type)( SPI0_IRQn ) );! NVIC_SetPriority(SPI0_IRQn, 0);

    ! do {! NVIC_ClearPendingIRQ(SPI0_IRQn); ! } while(NVIC_GetPendingIRQ(SPI0_IRQn) != 0);! LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 11);! LPC_SPI0->DLY = 4;! LPC_SPI0->DIV = 2;! LPC_SPI0->TXCTRL = (16-1)<<24 | 1<<22 | ( 1 << 20 );! LPC_SPI0->CFG = (1<<5)|(1<<4)|(1<<2);! switch_matrix::bind_SPI0_SSEL_IO( 8 ); ! switch_matrix::bind_SPI0_SCK_IO( 9 );! switch_matrix::bind_SPI0_MOSI_IO( 1 );! LPC_SPI0->INTENSET = 0x0;! NVIC_EnableIRQ( (IRQn_Type)( SPI0_IRQn ) );! LPC_SPI0->TXDAT = 2048 | ( 1 << 13 )|( 1 << 12 );! }! void set_dac( uint16_t value ) {! value &= 4095;! LPC_SPI0->TXDAT = value | ( 1 << 13 )|( 1 << 12 );! } LPC812ͷSPI͸ Ұ౓ʹ16bit·ͰૹΕΔ MCP4821 ࠓճ࢖ͬͨDAC ͸ 16bitૹΔຖʹग़ྗ͕ߋ৽͞ΕΔ ૹ৴׬ྃ࣌ͷׂΓࠐΈ͕ཁΒͳ͍ ૹ৴όοϑΝ΋ཁΒͳ͍ ΍ͬͨͶ
  18. void init_system_clock() {! LPC_SYSCON->SYSAHBCLKDIV = 2;! LPC_SYSCON->SYSPLLCTRL = 0x24;! }!

    int main() {! LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 6);! LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 18);! LPC_GPIO_PORT->DIR0 |= ( 1 << 8 );! LPC_GPIO_PORT->DIR0 |= ( 1 << 9 );! LPC_GPIO_PORT->DIR0 |= ( 1 << 1 );! init_system_clock();! init_dac();! SysTick_Config( 1875*2 );! while( 1 );! } $16ͷΫϩοΫΛ.)[ʹͯ͠ SysTickΛ8kHzʹઃఆ
  19. uint16_t step = 0;! ! extern "C"! __attribute__((interrupt("IRQ")))! void SysTick_Handler(void)

    {! set_dac( step << 5 );! ++step;! } SysTickׂΓࠐΈ͕ൃੜͨ͠Β Χ΢ϯλͷ஋ΛDACʹૹΔ ͜ΕͰϊίΪϦ೾͕ग़Δ͸ͣ
  20. inline constexpr self_type operator*(! const self_type &y! ) const {!

    return self_type(! (! static_cast< double_type >( base ) *! static_cast< double_type >( y.base )! ) >> Shift::value, raw()! );! } NVMM͕࢖ΘΕΔ͜ͱΛظ଴ͯ͠ ৐ࢉΛ͜Μͳ෩ʹ࣮૷͍ͯͨ͠
  21. …! 00001374 <__aeabi_lmul>:! 1374: 469c mov ip, r3! 1376: 0403

    lsls r3, r0, #16! 1378: b5f0 push {r4, r5, r6, r7, lr}! 137a: 0c1b lsrs r3, r3, #16! 137c: 0417 lsls r7, r2, #16! 137e: 0c3f lsrs r7, r7, #16! 1380: 0c15 lsrs r5, r2, #16! 1382: 1c1e adds r6, r3, #0! 1384: 1c04 adds r4, r0, #0! 1386: 0c00 lsrs r0, r0, #16! 1388: 437e muls r6, r7! 138a: 436b muls r3, r5! 138c: 4347 muls r7, r0! 138e: 4345 muls r5, r0! 1390: 18fb adds r3, r7, r3! 1392: 0c30 lsrs r0, r6, #16! 1394: 1818 adds r0, r3, r0! 1396: 4287 cmp r7, r0! 1398: d902 bls.n 13a0 <__aeabi_lmul+0x2c>! 139a: 2380 movs r3, #128 ; 0x80! ݱ࣮
  22. 1392: 0c30 lsrs r0, r6, #16! 1394: 1818 adds r0,

    r3, r0! 1396: 4287 cmp r7, r0! 1398: d902 bls.n 13a0 <__aeabi_lmul+0x2c>! 139a: 2380 movs r3, #128 ; 0x80! 139c: 025b lsls r3, r3, #9! 139e: 18ed adds r5, r5, r3! 13a0: 0c03 lsrs r3, r0, #16! 13a2: 18ed adds r5, r5, r3! 13a4: 4663 mov r3, ip! 13a6: 435c muls r4, r3! 13a8: 434a muls r2, r1! 13aa: 0436 lsls r6, r6, #16! 13ac: 0c36 lsrs r6, r6, #16! 13ae: 18a1 adds r1, r4, r2! 13b0: 0400 lsls r0, r0, #16! 13b2: 1980 adds r0, r0, r6! 13b4: 1949 adds r1, r1, r5! 13b6: bdf0 pop {r4, r5, r6, r7, pc}! … ݱ࣮ mull͸࢖ΘΕ͍ͯͳ͍
  23. ARM໋ྩʹ͸ରԠ͍ͯ͠ͳ͍ 5IVNC '16 ͷΈ 5IVNC '16 ͷΈ 5IVNCͷΈ 5IVNCͷҰ෦͚ͩ 5IVNCͷҰ෦͚ͩ

    5IVNCͷҰ෦͚ͩ Cortex-M7 Cortex-M4 Cortex-M3 Cortex-M1 Cortex-M0+ CortexM0 5IVNCͱ͸"3.ϓϩηοαͷ΋͏ͭͷ໋ྩηοτɻ ໋ྩ͕Մม௕Ͱ"3.໋ྩηοτΑΓϚγϯޠ͕খ͘͞ͳΔɻ
  24. ARM໋ྩʹ͸ରԠ͍ͯ͠ͳ͍ 5IVNC '16 ͷΈ 5IVNC '16 ͷΈ 5IVNCͷΈ 5IVNCͷҰ෦͚ͩ 5IVNCͷҰ෦͚ͩ

    5IVNCͷҰ෦͚ͩ Cortex-M7 Cortex-M4 Cortex-M3 Cortex-M1 Cortex-M0+ CortexM0 5IVNCͱ͸"3.ϓϩηοαͷ΋͏ͭͷ໋ྩηοτɻ ໋ྩ͕Մม௕Ͱ"3.໋ྩηοτΑΓϚγϯޠ͕খ͘͞ͳΔɻ Ұ෦ͱ͸
  25. NPWNPWXNPWU BEEBEDBES TVCTCDSTC NVMNMBNMTTNVMMVNVMMTNMBMVNMBM TEJWVEJW TTBUVTBU DNQDNO BOEFPSPSSPSOCJDNWOUTUUFR MTMMTSBTSSPSSSYDM[ MESMESIMESCMESTIMESTCMESUMESIUMESCUMESTIUMESTCUMESEMEN

    TUSTUSITUSCTUSTITUSTCTUSUTUSIUTUSCUTUSTIUTUSTCUTUSETUN QVTIQPQ MESFYMESFYIMESFYCTUSFYTUSFYITUSFYCDMSFY CCMCYCMYDC[DC[OUCCUCI TWDJUDQTJEDQTJFNSTNTSCLQU TYUITYUCVYUIVYUC VCGYTCGYCGDCGJ SFWSFWSFWTISCJU TFWXFGXGJOPQ JTCENCETC M7/M4/M3 Ҡಈ Ճࢉ ݮࢉ ৐ࢉ আࢉ ๞࿨ԋࢉ ൺֱ ࿦ཧԋࢉ γϑτ ϩʔυ ετΞ ελοΫૢ࡞ ηϚϑΥ ෼ذ ঢ়ଶมߋ ܕͷ֦ு ϏοτϑΟʔϧυ Ϗοτྻ൓స ώϯτ όϦΞ ARMv7m
  26. NPWNPWXNPWU BEEBEDBES TVCTCDSTC NVMNMBNMTTNVMMVNVMMTNMBMVNMBM TEJWVEJW TTBUVTBU DNQDNO BOEFPSPSSPSOCJDNWOUTUUFR MTMMTSBTSSPSSSYDM[ MESMESIMESCMESTIMESTCMESUMESIUMESCUMESTIUMESTCUMESEMEN

    TUSTUSITUSCTUSTITUSTCTUSUTUSIUTUSCUTUSTIUTUSTCUTUSETUN QVTIQPQ MESFYMESFYIMESFYCTUSFYTUSFYITUSFYCDMSFY CCMCYCMYDC[DC[OUCCUCI TWDJUDQTJEDQTJFNSTNTSCLQU TYUITYUCVYUIVYUC VCGYTCGYCGDCGJ SFWSFWSFWTISCJU TFWXFGXGJZFJMEOPQ JTCENCETC Ҡಈ Ճࢉ ݮࢉ ৐ࢉ আࢉ ๞࿨ԋࢉ ൺֱ ࿦ཧԋࢉ γϑτ ϩʔυ ετΞ ελοΫૢ࡞ ηϚϑΥ ෼ذ ঢ়ଶมߋ ܕͷ֦ு ϏοτϑΟʔϧυ Ϗοτྻ൓స ώϯτ όϦΞ M1/M0+/M0 ARMv6m
  27. M1/M0+/M0 NPWNPWXNPWU BEEBEDBES TVCTCDSTC NVMNMBNMTTNVMMVNVMMTNMBMVNMBM TEJWVEJW TTBUVTBU DNQDNO BOEFPSPSSPSOCJDNWOUTUUFR MTMMTSBTSSPSSSYDM[

    MESMESIMESCMESTIMESTCMESUMESIUMESCUMESTIUMESTCUMESEMEN TUSTUSITUSCTUSTITUSTCTUSUTUSIUTUSCUTUSTIUTUSTCUTUSETUN QVTIQPQ MESFYMESFYIMESFYCTUSFYTUSFYITUSFYCDMSFY CCMCYCMYDC[DC[OUCCUCI TWDJUDQTJEDQTJFNSTNTSCLQU TYUITYUCVYUIVYUC VCGYTCGYCGDCGJ SFWSFWSFWTISCJU TFWXFGXGJZFJMEOPQ JTCENCETC Ҡಈ Ճࢉ ݮࢉ ৐ࢉ আࢉ ๞࿨ԋࢉ ൺֱ ࿦ཧԋࢉ γϑτ ϩʔυ ετΞ ελοΫૢ࡞ ηϚϑΥ ෼ذ ঢ়ଶมߋ ܕͷ֦ு ϏοτϑΟʔϧυ Ϗοτྻ൓స ώϯτ όϦΞ ARMv6m NVMM͸٘ਜ਼ʹͳͬͨͷͩ NVMNMBNMTTNVMMVNVMMTNMBMVNMBM
  28. NVMMແ͠ͰͲ͏΍ͬͯ ݁Ռ͕CJUͷ৐ࢉΛ͢Δ͔ a b a*d b*d * c d a*c

    b*c ((a*c)<<32)+((a*d+b*c)<<16)+b*d BCDE͸ͦΕͧΕCJU චࢉͷཁྖͰCJUͮͭ ܭࢉ͍ͯ͘͠
  29. a b a*d b*d * c d a*c b*c ((a*c)<<32)+((a*d+b*c)<<16)+b*d

    αϯϓϧຖʹ͜ΜͳܭࢉΛ Կ౓΋͍ͯͨ͠Βؒʹ߹Θͳ͍
  30. ࣮͸'.ԻݯͷܭࢉதʹݱΕΔ ৐ࢉͷຆͲʹ͜Ε͕੒Γཱͭ ϛΩαʔ J M J M J M J

    M J J J J M M M M ೖྗ͸'.ΦϖϨʔλͷग़ྗͳͷͰ࠷େ ॏΈ͸શ෦͋Θͤͯ࠷େ ྆ลڞʹͷ৔߹ͷΈ஫ҙ͢Ε͹NVMͰ0, ݁Ռ͕໌Β͔ͳ৔߹