División en asm con divisor impar

Software para o relacionado con el core ZX Spectrum / Software for or related to the ZX Spectrum core
Responder
Avatar de Usuario
Haplo
Mensajes: 366
Registrado: 05 Oct 2015, 13:51
Ubicación: Ciudad Real

División en asm con divisor impar

Mensaje por Haplo » 15 Jul 2016, 22:04

Estoy limando cosillas y me he topado con una chorrada que me consume tiempo de proceso, durante la actualización de coordenadas de los sprites, hay un momento que tengo que dividir un entero (entre 0 y 60) entre 3. Lo hago decrementando con el típico bucle pero claro, hay veces que se repite 20 veces...
Imagino que se podría hacer una pirula con desplazamientos de bits pero llevo rato buscando y probando cosas y no doy con la tecla.

Avatar de Usuario
antoniovillena
Mensajes: 2611
Registrado: 27 Sep 2015, 20:41

Re: División en asm con divisor impar

Mensaje por antoniovillena » 15 Jul 2016, 23:07

Haplo escribió:Estoy limando cosillas y me he topado con una chorrada que me consume tiempo de proceso, durante la actualización de coordenadas de los sprites, hay un momento que tengo que dividir un entero (entre 0 y 60) entre 3. Lo hago decrementando con el típico bucle pero claro, hay veces que se repite 20 veces...
Imagino que se podría hacer una pirula con desplazamientos de bits pero llevo rato buscando y probando cosas y no doy con la tecla.
El inverso de la división es la multiplicación, así que tienes que multiplicar por 1/3. Tomando como 1 el valor 65536, 1/3 saldría (en hexadecimal queda más chulo) $5555. Por ponerte un ejemplo, intenta multiplicar 25 (en hexadecimal $19). Te sale $19*$5555= $8554D, de los 24 bits te quedas con los 8 bits superiores y tienes el resultado. Si no necesitas tanta precisión puedes hacer 8x8bits= 16bits. $19*$55= $84d y te quedas con la parte alta.

Avatar de Usuario
Uto
Mensajes: 1389
Registrado: 17 Dic 2015, 16:39

Re: División en asm con divisor impar

Mensaje por Uto » 15 Jul 2016, 23:45

Haplo escribió:Estoy limando cosillas y me he topado con una chorrada que me consume tiempo de proceso, durante la actualización de coordenadas de los sprites, hay un momento que tengo que dividir un entero (entre 0 y 60) entre 3. Lo hago decrementando con el típico bucle pero claro, hay veces que se repite 20 veces...
Imagino que se podría hacer una pirula con desplazamientos de bits pero llevo rato buscando y probando cosas y no doy con la tecla.
Otra opción, si tiene que ser muy rápido (si son sprites supongo que sí) y te sobran 61 bytes de memoria, es hacerte una tabla lookup.

Avatar de Usuario
Haplo
Mensajes: 366
Registrado: 05 Oct 2015, 13:51
Ubicación: Ciudad Real

Re: División en asm con divisor impar

Mensaje por Haplo » 15 Jul 2016, 23:49

Lo de la tabla ya lo había pensado pero me parecía algo en plan "tiro la toalla" ejejjeee

Si no doy con una solución "elegante" y más rápida que la que tengo, tiraré de tabla ciertamente.

Gracias por las ideas chicos.

Avatar de Usuario
Uto
Mensajes: 1389
Registrado: 17 Dic 2015, 16:39

Re: División en asm con divisor impar

Mensaje por Uto » 16 Jul 2016, 00:19

Haplo escribió:
Si no doy con una solución "elegante" y más rápida que la que tengo, tiraré de tabla ciertamente.
Bueno, muchas demos de los 90 para PC/VGA usaban tablas lookup. Es cierto que era para cosas más complicadas como senos, cosenos y cosas así, pero oye, también estabamos hablando de 486 a 33/66Mhz frente a Z80 a 3.5Mhz, yo creo que si la cosa es más rápida que el cálculo en sí, y hay sitio, no hay nada de malo en usar una tabla lookup. Yo cuando las descubrí me parecían cosa "de hackers" ("mira que listo este" pensaba) :rofl!:

Avatar de Usuario
mcleod_ideafix
Mensajes: 828
Registrado: 27 Sep 2015, 00:14
Ubicación: Jerez de la Frontera
Contactar:

Re: División en asm con divisor impar

Mensaje por mcleod_ideafix » 16 Jul 2016, 02:05

Si lo que necesitas es velocidad, no hay nada más rápido que una tabla de lookup. Si encima te puedes permitir el lujo de que dicha tabla pueda comenzar en una posición de memoria múltiplo de 256 entonces tu código para dividir, por ejemplo, el valor del acumulador entre 3 y que el resultado se guarde de nuevo en A, te queda así:

Código: Seleccionar todo

LD L,A
LD H,MSB de la direccion de la tabla
LD A,(HL)
Esto son: 4+7+7=21 ciclos de reloj. Si encima pudiera ser que el valor a dividir estuviera de antemano en L te ahorras 4 ciclos quedando la cosa en 14 ciclos.

Se puede hacer "trampa" pidiéndole al diseñador del core que te proporcione un puerto de E/S de la forma nnxx . Es decir, un puerto con dirección de 16 bits, donde la parte baja es fija (el valor xx) y que habría que escoger usando alguna combinación de bits que no se estuviera usando; y donde la parte alta, nn, correspondería al valor que quieres dividir entre tres. El periférico en ese puerto lo que haría sería coger los 8 bits altos de la dirección, dividirlos entre 3 por hardware, y el resultado darlo como resultado de la lectura del periférico. Así, para dividir el valor del acumulador entre 3 y retornarlo en el mismo acumulador quedaría así:

Código: Seleccionar todo

IN A,(xx)
O sea, 11 ciclos :D
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA

Avatar de Usuario
Uto
Mensajes: 1389
Registrado: 17 Dic 2015, 16:39

Re: División en asm con divisor impar

Mensaje por Uto » 16 Jul 2016, 03:02

mcleod_ideafix escribió:

Código: Seleccionar todo

IN A,(xx)
O sea, 11 ciclos :D
Un coprocesador matemático sería una cosa molona, aunque fuera uno ficticio con solo unas pocas funciones engorrosas (multiplicar por cosas que no son potencia de 2, dividir, elevar a, raiz cuadrada). Podría darse soporte a la parte de aritmética entera de 16 bits del AMD 9511 por ejemplo: http://www.hartetechnologies.com/manual ... %20FPU.pdf

Pero ya la estamos liando .. XD

Responder