2010-06-22 8 views

Respuesta

18

Antes de ARMv4, ARM no tenía soporte nativo para cargar halfwords y bytes con signo. Para cargar un byte con signo debe tener LDRB y luego firmar extender el valor (LSL arriba y luego ASR hacia abajo). Esto es doloroso así que char es unsigned por defecto.

En ARMv4 se han agregado las instrucciones para manejar halfwords y valores con signo. Estas nuevas instrucciones tuvieron que ser exprimidas en el espacio de instrucción disponible. Los límites en el espacio disponible significaban que no podían ser tan flexibles como las instrucciones originales, que pueden hacer varios cálculos de direcciones al cargar el valor.

Por lo tanto, es posible que LDRSB, por ejemplo, no pueda combinar una recuperación de memoria con un cálculo de dirección mientras que LDRB podría. Esto puede costar ciclos. A veces podemos volver a trabajar short-código pesado para operar en pares de ints para evitar esto.

Hay más información en mi sitio aquí: http://www.davespace.co.uk/arm/efficient-c-for-arm/memaccess.html

+1

wow He oído que 'signness de char' es definida por la implementación, pero esta es la primera vez que veo una aplicación real que utiliza char sin signo por defecto –

2

Creo que es solo que el conjunto de instrucciones para las CPU ARM está optimizado para unsigned. Algunas operaciones pueden realizarse con una instrucción para tipos sin firmar, pero necesitarán varias instrucciones si están firmadas. Es por eso que creo que si se compila para ARM en la mayoría (¿todos?) De los compiladores C y C++, el valor predeterminado es char sin signo más que el carácter más común firmado.

2

Las únicas ventajas de los tipos sin firmar que puedo pensar son que las implementaciones de división y módulo pueden ser ligeramente más rápidas, y puede hacer pruebas como if (unsigned_value < limit) en lugar de if (signed_value >= 0 && signed_value < limit).

Sospecho que su manual puede estar desactualizado. Cualquier ARM en uso hoy tendrá v4 o posterior del conjunto de instrucciones, y estoy bastante seguro de que las instrucciones no son más rápidas o más lentas, dependiendo de la firma.

En los ARM antiguos, creo que la multiplicación con signo podría ser más lenta; Creo que la terminación anticipada solo buscaba todos los ceros en los bits superiores, no en todos, por lo que las multiplicaciones que implican números negativos siempre tomarían el tiempo máximo. Aunque esto dependía del valor, no de si el tipo estaba firmado o no. Al menos ARMv4 y posterior, la terminación anticipada funciona para valores negativos.

Además, creo que los primeros ARM no podían cargar un solo byte, solo una palabra. Así que había necesidad de dos instrucciones para cargar un byte sin signo, y tres a uno carga una firmado:

ldr r0, [r1] 
and r0, r0, #0xff 

frente

ldr r0, [r1] 
mov r0, r0, asl #24 
mov r0, r0, asr #24 ; but this could maybe be combined with later instructions 

frente (en estos días) ldrb r0, [r1] o ldrsb r0, [r1] para hacer un solo byte carga.

En un procesador moderno, es muy poco probable que el uso de tipos sin signo tenga un impacto mensurable en el rendimiento. Utilice el tipo que tenga más sentido, luego mire el código en detalle una vez que haya identificado los cuellos de botella de rendimiento.

Cuestiones relacionadas