¿Cómo escribir códigos de ensamblaje en línea sobre LOOP en Xcode LLVM?

Estoy estudiando sobre assembly en línea. Quiero escribir una rutina simple en iPhone bajo Xcode 4 LLVM 3.0 Compiler. Logro escribir códigos de ensamblaje en línea básicos.

ejemplo:

int sub(int a, int b) { int c; asm ("sub %0, %1, %2" : "=r" (c) : "r" (a), "r" (b)); return c; } 

Lo encontré en stackoverflow.com y funciona muy bien. Pero, no sé cómo escribir código sobre LOOP.

Necesito ensamblar códigos como

 void brighten(unsigned char* src, unsigned char* dst, int numPixels, int intensity) { for(int i=0; i<numPixels; i++) { dst[i] = src[i] + intensity; } } 

Eche un vistazo aquí en la sección de bucles – http://en.wikipedia.org/wiki/ARM_architecture

Básicamente querrás algo como:

 void brighten(unsigned char* src, unsigned char* dst, int numPixels, int intensity) { asm volatile ( "\t mov r3, #0\n" "Lloop:\n" "\t cmp r3, %2\n" "\t bge Lend\n" "\t ldrb r4, [%0, r3]\n" "\t add r4, r4, %3\n" "\t strb r4, [%1, r3]\n" "\t add r3, r3, #1\n" "\tb Lloop\n" "Lend:\n" : "=r"(src), "=r"(dst), "=r"(numPixels), "=r"(intensity) : "0"(src), "1"(dst), "2"(numPixels), "3"(intensity) : "cc", "r3", "r4"); } 

Actualizar:

Y aquí está esa versión de NEON:

 void brighten_neon(unsigned char* src, unsigned char* dst, int numPixels, int intensity) { asm volatile ( "\t mov r4, #0\n" "\t vdup.8 d1, %3\n" "Lloop2:\n" "\t cmp r4, %2\n" "\t bge Lend2\n" "\t vld1.8 d0, [%0]!\n" "\t vqadd.s8 d0, d0, d1\n" "\t vst1.8 d0, [%1]!\n" "\t add r4, r4, #8\n" "\tb Lloop2\n" "Lend2:\n" : "=r"(src), "=r"(dst), "=r"(numPixels), "=r"(intensity) : "0"(src), "1"(dst), "2"(numPixels), "3"(intensity) : "cc", "r4", "d1", "d0"); } 

Así que esta versión de NEON hará 8 a la vez. Sin embargo, no comprueba que numPixels sea ​​divisible por 8, por lo que definitivamente querrías hacer eso, ¡de lo contrario las cosas saldrán mal! De todos modos, es solo el comienzo para mostrarle lo que se puede hacer. Observe el mismo número de instrucciones, pero la acción en ocho píxeles de datos a la vez. Ah, y también tiene la saturación que supongo que querrías.

Aunque esta respuesta no es directamente una respuesta a su pregunta, es más un consejo general con respecto al uso de comstackdores de ensamblador en comparación con los comstackdores modernos.

Por lo general, le será difícil vencer al comstackdor con respecto a la optimización de su código C. Por supuesto, mediante el uso inteligente de ciertos conocimientos sobre el comportamiento de sus datos, es posible que pueda modificarlos solo unos pocos porcentajes.

Una de las razones de esto es que los comstackdores modernos utilizan una serie de técnicas cuando manejan códigos como el que usted describe, por ejemplo, el desenrollado de bucles, el reordenamiento de instrucciones para evitar atascos y burbujas en la tubería, etc.

Si realmente desea hacer que el algoritmo grite, debería considerar rediseñar el algoritmo en lugar de C para evitar los peores retrasos. Por ejemplo, leer y escribir en la memoria es costoso en comparación con el acceso al registro.

Una forma de lograr esto podría ser que su código cargue 4 bytes a la vez usando un unsigned long y luego haciendo los cálculos matemáticos en los registros antes de volver a escribir estos 4 bytes en una sola operación.

Así que para recapitular, haga que su algoritmo trabaje de manera más inteligente, no más difícil.

    Intereting Posts