Autor Tema: PIC32MZ - Estrenando micro y bugs en el silicio/compilador  (Leído 46710 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2980
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #60 en: 17 de Mayo de 2015, 15:00:14 »
Pues si lo probaré en cuanto pueda pero no sera hoy ni mañana, pero lo hare ,

Por cierto esto antes funcionaba, instalate el virtual box he instalate un linux o window o lo que quieras instala mplabx y xc32 y activa la versión de evaluación, congela la maquina,  todo lo que guardes he instales a partir de ahora se te borrara cuando lo vuelvas a encender, pero las versiones de evaluación no te caducan en mi uní hacían eso, puedes programar en tu OS host y cuando lo tengas terminado compilarlo con la optimización a tope, no se si esto sigue funcionando pero merece la pena intentarlo si lo necesitas.

Un saludo


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #61 en: 17 de Mayo de 2015, 15:05:36 »
No tuve tiempo de mirarlo, pero si no mal recuerdo el nop esta por el tema del pipeline.

Una de las cosas que supe ver cuando miraba el ASM de MIPS

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #62 en: 17 de Mayo de 2015, 15:24:16 »
jeje sí, hay muchas maneras de truquear el compilador, pero no lo necesito.  :mrgreen:

Ah OK Killer, pues cosas raras de ASM que al menos están ahí para que funcione el micro.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #63 en: 17 de Mayo de 2015, 23:21:58 »
Bueno estuve mirando un poco el codigo y por lo que parece las optimizaciones hacen que utilize menos instrucciones para llegar al punto deseado. Registros propios de la CPU, Lo feo es que por ahi usa demasiadas instrucciones para cosas demasiados simples.
Para que me entiendan un poco
Una CPU MIPS32 posee 32 registros generales + 3 especiales, el tema es que de los registros generales tienen sus "funciones" en realidad es una convencion, en ASM puedo usar los que quiera y como quiera. Pero siguiendo la linea de C, deberia respetarlos

Los Registros son:

R0...R31    --- Registros generales, Particularidades
R0               es siempre 0, util para desechar resultados o poner a 0 algo.
R2/R3       para valores de retorno tambien llamados V0/V1
R4-R7      Para valores de argumento, primeros 4 sino lo demas al stack, tambien llamado A0 - A3
R8-R15 /R24/R25 Registros "temporales" . Tambien llamados T0-T9
R16-R23    "Saved Registers" S0-S7
R26/R27    "Kernel Reserved Registers" K0/K1
R28        "Global Pointer" Usado para direccionar variables globales estaticas o GP
R29        Stack Pointer o SP
R30        Frame Pointer o FP
R31        Return Address o RA

Registros especiales
HI, LO      --- Registros especiales, para resultados de multiplicacion/division , no confundir con %hi del codigo de juaperser
PC          --- Program Counter

Ahora voy a analizar el codigo de cada uno que me pasaron:

Código: [Seleccionar]
addiu $sp,$sp,-8 -------- SP = SP - 8 , Modifica el stack pointer para hacer lugar y guardar los Frame Pointer, 8 bytes
.LCFI0:
sw $fp,4($sp) -------- Store Word Frame pointer -> SP , FP -> (SP + 4) , Guarda el Frame Pointer es los primeros 4 bytes que ya habiamos reservados
.LCFI1:
move $fp,$sp    -------- FP -> SP , Guarda nuevamente el Frame Pointer en los otros 4 bytes y completamos los 8 reservados, ni idea por que 2 veces.
.LCFI2:
.loc 1 43 0
lui $2,%hi(ANSELB) ---- R2 = HI<<16 , guarda los 2 bytes de la direccion superior de ANSELB en R2
sw $0,%lo(ANSELB)($2)   [LO + R2] = R0  , Pone 0 en ANSELB, Direccion de arriba(2 bytes) + direccion de abajo(2 bytes)
.L2:
.loc 1 47 0
lui $2,%hi(LATB)            R2 = &LATB AND 0xFFFF.0000  , es decir la parte superior de la direccion se guarda en R2 quedando 0xaaaa.0000
lw $2,%lo(LATB)($2)        R2 = [R2 + LO] , conteniedo en R2 + offset apuntando a LATB y termina almacenando el Word(32bits) en R2
ext $2,$2,0,1 Extract bit field, Extrae los bits desde el bit 0, con una longitud de 1 y almacena eso nuevamente en R2, quedando solo el bit LATB0
andi $2,$2,0x00ff R2 = R2 & 0xFF
nor $2,$0,$2 R2 = ~ (R0|R2) , R2 ( que contenia LATB0 ) se realiza una OR y luego se nega con R0 ( que siempre es 0), Lo mismo que negar el bit LATB0 y todos los demas tambien
andi $2,$2,0x00ff R2 = R2 & 0xFF Nuevamente lo ajusta a 8 bits (pero de la NOR quedaron muchos 1 ademas del bit de interes)
andi $2,$2,0x1               R2 = R2 & 0x1  Finalmente solo deja LATB0
andi $4,$2,0x00ff R4 = R2 & 0xFF Vuelve a limitarlo a 8 bits y guarda en R4
lui $3,%hi(LATB) R3 = Upper 2 byte address LATB << 16
lw $2,%lo(LATB)($3) R2 = [LO + R3] Carga nuevamente lo que esta en la direccion de LATB
ins $2,$4,0,1 R2 = (R2 & 0xFFFF.FFFE )+ LATB0 (desde R4), la instruccion copia la seccion desde la posicion 0, longitud 1 de R4 a R2 dejando R2 con sus demas bits intactos
sw $2,%lo(LATB)($3)        [LO + R3] = R2  Finalmente guardo mi LATB modificado
.loc 1 48 0
j .L2 Salto a L2, por el pipeline si hay otra instruccion puede que se ejecute a pesra que se produjo el salto, asi que se pone un NOP
nop

Se puede observar que hace uso de los registros 2 , 3 y 4, cada instruccion esta explicada.
El frame pointer es para ordenar las subrutinas en las pilas, con cada llamado a subrutina se guarda el puntero de Frame, este Frame contiene algunos registros+espacio para las variables nuevas, etc, luego cuando se vuelve , se vuelve al anterior FP
En fin, ese programa hace desastres, es impresionante la cantidad de AND que hace y un NOR, cuando podria hacer un XOR. Otra cosa lee 2 veces el la memoria para obtener ese valor.

Algo parecido es lo que paso con el codigo de migsantiago sin optimizacion:

Código: [Seleccionar]
9d003e64: 3c02bf86 lui v0,0xbf86 ; Utiliza un registro nomas para almacenar la direccion de memoria
9d003e68: 8c420120 lw v0,288(v0)    
9d003e6c: 7c4200c0 ext v0,v0,0x3,0x1
9d003e70: 304200ff andi v0,v0,0xff       ; Multiples AND sin sentido
9d003e74: 24420001 addiu v0,v0,1
9d003e78: 30420001 andi v0,v0,0x1
9d003e7c: 304400ff andi a0,v0,0xff
9d003e80: 3c03bf86 lui v1,0xbf86        ; Lo cual lo hace cargarlo de nuevo
9d003e84: 8c620120 lw v0,288(v1)
9d003e88: 7c8218c4 ins v0,a0,0x3,0x1
9d003e8c: ac620120 sw v0,288(v1)
9d003e90: 0b400f99 j 9d003e64
9d003e94: 00000000 nop

Es identico al anterior (por eso no lo explico), nomas que aqui se puede ver realmente la direccion de los registros. si observan el %hi(LATx) y %lo(LATx) se transforma en 0xBF86.0120
Esto por que aceptan solo 16bits esa instruccion
Por ultimo con optimizacion 1:

Código: [Seleccionar]
9d002428: 3c02bf86 lui v0,0xbf86 V0 = 0xbf86.0000
9d00242c: 8c440120 lw a0,288(v0)      A0 = [V0 + 288] = [0xBF86.0120]
9d002430: 7c8400c0 ext a0,a0,0x3,0x1   Extrae el bit 4 de A0 y solo eso guarda en el bit0 en A0. (A0 & 0x00 + A0.bit0) = A0.bit4
9d002434: 38840001 xori a0,a0,0x1 A0 = A0 XOR 0x1 , Negar bit0
9d002438: 8c430120 lw v1,288(v0)      V1 = [V0 + 288] = [0xBF86.0120] , Vuelvo a cargar el valor del registro
9d00243c: 7c8318c4 ins v1,a0,0x3,0x1 Inserto el bot. V1.bit4 = A0.bit0
9d002440: ac430120 sw v1,288(v0) [V0 + 288] = [0xBF86.0120] = V1  Guardo mi registro
9d002444: 0b40090b j 9d00242c        Salto
9d002448: 00000000 nop

Muy parecido al anterior pero aun asi vuelve a hacer cosas sin sentido, como extraer el bit, insertarlo, etc. Ademas de cargar 2 veces lo que esta en memoria.
Si tuviera que hacer algo similar bastaria con 6 intrucciones.

Código: [Seleccionar]
loop:
lui v0,0xBF86    ; Direccion
lw a0,288(v0)   ; Cargo valor de registro en A0
xori a0,a0,0x1     ; A0 = A0 XOR 0x1
sw a0,288(v0)   ; Guardo A0 en el registro que sea
j loop
nop

Y el loop se puede hacer mas corto si el lui y el lw fuera de este loop. Algo asi:

Código: [Seleccionar]
start
lui v0,0xBF86    ; Direccion
lw a0,288(v0)   ; Cargo valor de registro en A0
loop
xori a0,a0,0x1     ; A0 = A0 XOR 0x1
sw a0,288(v0)   ; Guardo A0 en el registro que sea
j loop
nop
« Última modificación: 17 de Mayo de 2015, 23:41:57 por KILLERJC »

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #64 en: 17 de Mayo de 2015, 23:29:14 »
Muy interesante el análisis ASM que hiciste Killer.

Sería bueno poder ver lo que la optimización máxima logra. Seguro esas AND ADD de más desaparecen... o usan algo mejor... como el registro toggle atómico que trae el micro por sí solo jeje.

Gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #65 en: 18 de Mayo de 2015, 00:01:06 »
No encontre nada sobre el registro atomico, lo que si hay 2 instrucciones atomicas, aunque no permiten el cambio de 1 bit, sino es otra funcion. Las funciones son LL y SC, se usan juntos

Permiten compartir variables entre procesos y que siempre este actualizado. Al intentar guardarlo si nadie lo modifico entonces en el registro queda un 1.

L1:
LL T1, (T0) # load counter
ADDI T2, T1, 1 # increment
SC T2, (T0) # try to store, checking for atomicity
BEQ T2, 0, L1 # if not atomic (0), try again
NOP # branch-delay slot


Por otro lado, para que no quede en el aire, aqui esta la explicacion del por que se necesita un NOP luego de un salto
http://people.ece.cornell.edu/land/courses/ece4760/PIC32/Microchip_stuff/MIPS-M4K-Core.pdf
Bajo el titulo de Branch Delay

Y aca un ejemplo de como funciona:
http://en.wikipedia.org/wiki/Delay_slot

A pesar que vi un poco de ASM del SHARK DSP no recordaba que tuviera 2 branch delay :/.
En fin, es malo y tampoco TAN malo, ya que podrias ejecutar una instruccion que de otra forma tirarias.

Se podra mejorar el codigo haciendo esto?:

Código: [Seleccionar]
start
lui v0,0xBF86    ; Direccion
lw a0,288(v0)   ; Cargo valor de registro en A0
loop
xori a0,a0,0x1     ; A0 = A0 XOR 0x1
j loop
sw a0,288(v0)   ; Guardo A0 en el registro que sea
« Última modificación: 18 de Mayo de 2015, 00:18:09 por KILLERJC »

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #66 en: 18 de Mayo de 2015, 07:18:40 »
Yo en otros micros y versiones (xc16 y xc8) lo que hacia la optimizacion era lo siguiente:

Sin optimizacion creaba mucho codigo basura tipo:

PORTA=0x0000;
Se traducia en codigo asm como
-Copiar 0x0000 a una variable temporal
-Copiar de esa variable a PORTA

Luego en codigo optimizado al maximo lo hacia asi:
-Copia 0x0000 a PORTA

Y eso es solo un ejemplo, para cosas mas complicadas como sumas, if, y cosas por el estilo creaba mucho mas codigo, no es que la optimizacion te cree un supercodigo, mas bien seria que sin optimizar te crea codigo inservible o mas bien para hacer 1 paso simple te crea 3 pasos mas.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #67 en: 18 de Mayo de 2015, 08:50:40 »
no es que la optimizacion te cree un supercodigo, mas bien seria que sin optimizar te crea codigo inservible o mas bien para hacer 1 paso simple te crea 3 pasos mas.

No será tan inservible cuando el Debug no funciona correctamente sin ese código.


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #68 en: 18 de Mayo de 2015, 10:19:37 »
Si la diferencia desde C a ASM puede ser grande, yo hace un tiempo hice una comparacion de XC8 versus ASM, con un caso particular que era una formula y lo habia realizado en ASM.
El Problema principal que luego de hacer muchas formulas rebuscandolas, logre terminar casi con mi mismo codigo en ASM. Pero tuve que rebuscarmelas.

Por ejemplo, esto:

LATBbits.LATB0=~LATBbits.LATB0;

Se podria escribir como

LATB ^= 0x1;
LATB ^= (1 << 0);

Por supuesto, es rebuscarselas y puede que logres un mejor codigo.

El thread en cuestion aunque es XC8:
http://www.todopic.com.ar/foros/index.php?topic=44247.msg367049

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2980
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #69 en: 18 de Mayo de 2015, 11:23:08 »
Buenas killer, luego dices que no sabes ensamblador  :D :D

Bueno pues siguiendo tu explicacion, coincido contigo, es malo, pero me lo esperaba peor con nop a mala leche para bajarle velocidad.

No obstante, algo malo se esta cociendo en microchip  :(. Hoy he vuelto a meterle mano al bootloader msd AN1388, para empezar los ejemplos están hechos con la máxima optimización y mips16 activado, para que si tienes la versión gratuita te den bien por culo, si lo dejas así tal como, al compilarlo el bootloader msd(fat32 y USB) ocupan 16k, esto quiere decir que los micros pic32 de 16k se quedan sin bootloader msd y los de 32kb pierden la mitad de memoria solo con esto.

Como ya he denunciado en otros post desde hace un tiempo los compiladores de microchip cada vez comen mas memoria.

Bueno pues he adaptado el bootloader msd quitando las mips16 y la optimización y toda la morralla de las placas de evaluación para un pic32mx250 con 128kb, y me he quedado a cuadros cuando he visto que se ha comido el 47% de la memoria¡¡¡¡¡¡¡¡¡ 64 kb de memoria en bootloader¡¡¡¡¡ los micros de 64kb para abajo no sirven.

Increible, donde están los tiempos donde ni te preocupabas de la memoria del pic salvo para aplicaciones un poco mas especiales? La están cagando, a nadie le gusta este tipo de cosas y no están como para ir perdiendo confianza, en un mercado donde cada día mas fabricantes ofrecen herramientas gratuitas ellos se permiten el lujo de ir al revés y cada vez mas caro, desde cuando un ANxxxx te pide versión pro para usarlo? O es que les daba vergüenza que vean que su bootloader msd sin optimizacion ocupe 64k por sus cada vez peores compiladores?


También hice la prueba de ver que entraba en un pic32 16kb sin optimización con las harmony, sin ningúna librería ni nada, bueno pues entraron 8 funciones¡¡¡¡ y pequeñitas emm. 8 funciones no entra ni en la categoría de chiste por dios.

muchas gracias killer por tu exposición de asm y la explicación de los nop finales.

Posdata: he probado en una maquina virtual a pedir otra vez la versión de evaluación y se puede, por lo tanto se puede seguir congelando o rwinstalando maquinas virtuales y tener la versión pro siempre.

Un saludo

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #70 en: 18 de Mayo de 2015, 15:59:17 »
no es que la optimizacion te cree un supercodigo, mas bien seria que sin optimizar te crea codigo inservible o mas bien para hacer 1 paso simple te crea 3 pasos mas.

No será tan inservible cuando el Debug no funciona correctamente sin ese código.



si funciona, el problema es que la optimizacion elimina y/o ordena el codigo de una manera distinta por lo cual puede que al eliminar partes el debug se quede "loco" sin saber donde tener que dirigirse. Por ejemplo si hacemos:

var=4;
var=3;

la optimizacion elimina el var=4; y deja solo el 3, entonces si hacemos debug habra desaparecido esa linea y no sabra donde acudir, sin embargo sin optimizacion haria todo tal y como lo escribas, aunque hagas cosas del estilo.

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #71 en: 18 de Mayo de 2015, 19:49:09 »
No encontre nada sobre el registro atomico, lo que si hay 2 instrucciones atomicas, aunque no permiten el cambio de 1 bit, sino es otra funcion. Las funciones son LL y SC, se usan juntos

Son los SET, CLR e INV registers.



Sirven para levantar, bajar o invertir bits en los registros. Sólo los registros I/O tienen ese modo. Es curioso notar que prefieren meter registros con esas funcionalidades especiales a meter códigos de operación MIPS que hagan lo mismo (BSF, BCF en ASM de PIC sencillo, por ejemplo).

Con el INV, fácilmente en una sola instrucción se llevaría a cabo mi instrucción en C.

++APP_DEBUG_PIN;

Pero bueno, sólo el modo pro lo ha de soportar... espero.

OK, gracias por el link del NOP intruso.

Sobre tu pregunta de si se puede mejorar el ciclo, ¿qué te parece si usas el INV? Sobre ensamblador MIPS estoy en ceros jejej.

Gracias.
« Última modificación: 18 de Mayo de 2015, 19:55:54 por migsantiago »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #72 en: 18 de Mayo de 2015, 20:22:58 »
Esta bueno, no lo vi por que yo busque exclusivamente del MIPS32 M4K, te permite ahorrarte la XOR:


Código: [Seleccionar]
start
lui v0,%hi(LATxINV)    ; Direccion del registro INV
        adi    a0,R0,0x1              ; Cargo el valor 0x0000.0001 para invertir el bit0
loop
j loop
sw a0,%lo(LATxINV)(v0)   ; Guardo A0 en el registro que sea

La instruccion que cambiaria el pin seria ese SW (Store Word), es el que hace el cambio. Graba el valor al registro y permite el cambio del pin. Y cambia la direccion a la del LATxINV (ya que no la se cual es)

Citar
Es curioso notar que prefieren meter registros con esas funcionalidades especiales a meter códigos de operación MIPS que hagan lo mismo (BSF, BCF en ASM de PIC sencillo, por ejemplo).

Es que el nucleo es de MIPS, microchip compra los derechos para usarlos en sus chips, pero la arquitectura es de ellos. Es lo mismo que ocurre con ARM, que estan en micros de NXP,ST,TI,FREESCALE, etc.
Lo bueno que un Cortex-M3 en un ST funciona igual que un Cortex-M3 de un NXP. Lo que si cambian son los perifericos.
Asi que no  pueden modificar a libre voluntad el nucleo.

Esto lleva a usar el registro ese en C, para que sea mas corto el programa. Aun sin optimizacion, si se carga directo al registro imagino que debe ser bastante corto.
En ves de hacer:

LATBbits.LATB0=~LATBbits.LATB0;

hacer:

LATBINV = 0x1;

Con lo cual el loop completo en su peor estado ocuparia 6 instrucciones
« Última modificación: 18 de Mayo de 2015, 20:29:40 por KILLERJC »

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #73 en: 23 de Mayo de 2015, 19:58:48 »
Killer, me gustaría pedirte tu opinión...

Tengo este código súper sencillo en una interrupción de SPI2 TX...

Código: [Seleccionar]
         if(sent_bytes_per_submatrix < submatrix_total_bytes[4])
         {
            SPI2BUFFER = simulated_spi_bit[4];
         }
         else
         {
            SPI2BUFFER = 0;

            /* Set the RPE5 output as GPIO temporarily to avoid writing glitches */
            RPE5R = OUTPUT_FUNC_NO_CONNECT;
         }

¡Pero rarísimamente el compilador genera código duplicado!  :shock:

Código: [Seleccionar]
         if(sent_bytes_per_submatrix < submatrix_total_bytes[4])
9d0005b8: 11e00005 beqz t7,9d0005d0 <_Int_SPI_TX_2+0x318>
9d0005bc: 00000000 nop
         {
            SPI2BUFFER = simulated_spi_bit[4];
9d0005c0: 95820008 lhu v0,8(t4)
9d0005c4: ad621220 sw v0,4640(t3)
         else
         {
            SPI2BUFFER = 0;

            /* Set the RPE5 output as GPIO temporarily to avoid writing glitches */
            RPE5R = OUTPUT_FUNC_NO_CONNECT;
9d0005c8: 0b400177 j 9d0005dc <_Int_SPI_TX_2+0x324>
9d0005cc: 25c50001 addiu a1,t6,1
         {
            SPI2BUFFER = simulated_spi_bit[4];
         }
         else
         {
            SPI2BUFFER = 0;
9d0005d0: ad601220 sw zero,4640(t3)

            /* Set the RPE5 output as GPIO temporarily to avoid writing glitches */
            RPE5R = OUTPUT_FUNC_NO_CONNECT;
9d0005d4: ae801614 sw zero,5652(s4)
9d0005d8: 25c50001 addiu a1,t6,1
9d0005dc: 30a500ff andi a1,a1,0xff
   }

   /* Only read the buffer if it's ready to be read */
   if(1 == SD_Buffer_Can_Be_Read[Sys_Current_Buffer])
   {
      for(bit_count = 0; bit_count < SPI_FIFO_SIZE_16_BITS; ++bit_count)
9d0005e0: 2ca20008 sltiu v0,a1,8
9d0005e4: 1440ffc7 bnez v0,9d000504 <_Int_SPI_TX_2+0x24c>
9d0005e8: 00a07021 move t6,a1
9d0005ec: 24020005 li v0,5
9d0005f0: a3828040 sb v0,-32704(gp)
9d0005f4: a3858041 sb a1,-32703(gp)
            RPE5R = OUTPUT_FUNC_NO_CONNECT;
         }
      }

Es una optimización tremendamente rara... código duplicado... ¿cómo para qué?

Voy a probar con la VM e instalar la versión PRO.

Tengo problemas con la escritura del SDO2. Los demás SPIs que escribo también están duplicados en ASM... no me lo explico.

¿Por qué crees que el compilador haga eso?

Gracias.  :(

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: PIC32MZ - Estrenando micro y bugs en el silicio/compilador
« Respuesta #74 en: 23 de Mayo de 2015, 20:13:53 »
Ahi lo veo....

Estoy intentado buscar las direcciones xD, de todas formas parece que hay algo mas en ese codigo :/, como un for y seguro debe haber algo mas antes ya que no esta la parte donde carga las primeras direcciones de memoria.

Listo, no veo que lo haga 2 veces, a pesar que sale muchas veces en el disassembler la parte de C. Segun la parte del codigo que me diste(aunque parece que es mas extenso):

Código: [Seleccionar]
9d0005b8: 11e00005 beqz t7,9d0005d0 <_Int_SPI_TX_2+0x318>            ;Si t7==0 salta a 9d005d0 (no es correcta la instruccion ya que acepta solo 18bits, pero se entiende), seguro hay una instruccion de comparacion y que almacena el resultado en t7 antes
9d0005bc: 00000000 nop                                                ; nop por el salto

; No se cumplio el if:
    ; T3 = 0xBF82.0000 , T4 puede ser bank0 o bank1, 0xA000 a 0xA0007 o 0x8000 a 0x8007, no se bien el dispositivo
9d0005c0: 95820008 lhu v0,8(t4)     ; SPI2BUFFER = simulated_spi_bit[4]; Load HalfWord Unsigned V0 = [T4+8] ; T4 apunta a la base del vector simulated_spi_bit[], 8 de offset por ser de 16bits ( 4 * 2 = 8), HalfWord=16bits
9d0005c4: ad621220 sw v0,4640(t3)     ; [t3+4640] = [t3 + 0x1220] = v0 , es decir la formula de arriba (Proceso: cargar el simulated_spi_bit y guardarlo en SPI2BUFFER).
9d0005c8: 0b400177 j 9d0005dc <_Int_SPI_TX_2+0x324>     ; Salto a 9d0005dc, o PC = PC31:PC28 :: 0xd0005dc  (acepta solo 28bits)
9d0005cc: 25c50001 addiu a1,t6,1     ; Para aprovechar el salto, A1 = T6+1; Esto es del for siguiente que tiene un preincremento (bit_count)

Se cumplio el if:

    ; S4 = 0xBF80.0000
9d0005d0: ad601220 sw zero,4640(t3)     ; [t3+4640] = [t3 +0x1220] =0 , SPI2BUFFER
9d0005d4: ae801614 sw zero,5652(s4)     ; [s4+5652] = [s4 + 0x1614]=0 , RPE5R
9d0005d8: 25c50001 addiu a1,t6,1     ; A1 = t6 + 1;      Pre incremento del for, si se toma el camino que se cumple el if, no habia incremento como cuando no se cumplia

Fin del IF
    ; Tome o no el if ocurre A1 = T6+1;
9d0005dc: 30a500ff andi a1,a1,0xff     ; A1 = A1 & 0xFF    Pero lo tengo que limitar a 8bits por que asi esta definida como de 8bits (bit_count) imagino ya que luego usa un Store Byte


Comienzo de un if + un for (etc, ni idea )

9d0005e0: 2ca20008 sltiu v0,a1,8 ; V0 igual a 1 si A1 < 8, sino 0, parece ser que T6 es igual a bit_count y por ser pre,decrementado lo vemos antes
9d0005e4: 1440ffc7 bnez v0,9d000504 <_Int_SPI_TX_2+0x24c>       ; Si es 1 va a la direccion 0x9d000504 y ademas hace T6 = A1, A1 registro temporal solo para incrementarlo?, y aca actualiza si o si.
9d0005e8: 00a07021 move t6,a1
9d0005ec: 24020005 li v0,5 ; V0 = 5;
9d0005f0: a3828040 sb v0,-32704(gp) ; Guarda el byte de menor peso de V0 en [GP - 0x7FC0], es decir guarda el 5 en ese lugar, supongo una RAM, Usa R28 o Global Pointer. Variables estaticas.
9d0005f4: a3858041 sb a1,-32703(gp)                           ; Guarda el valor del bit_count, tambien en una posicion cercana al otro. [GP - 0x7FBF]


En fin podes tomar 2 caminos, que te llevan a donde puse "Comienzo de un if + un for", Si se cumple el if anterior o no, toma los dos caminos que separe, cada camino hace lo que puse ahi, que es exactametne lo que tenes en C.
Hay una instruccion repetida que es el del pre incremento de bit_count del for que le sigue al codigo C que pusiste. Fue su forma de resolverlo, podria haber puesto un nop y utilizar solo una ves esa instruccion, pero no ganaba nada de velocidad.

Por lo demas hay un salto a otra direccion y puede que continue el codigo. Pero ahi esta masomenos explicado e intente descifrar las direcciones de algunos registros que no aparece cuando se cargan.
Lo que si no veo es el equivalente de esto:

if(1 == SD_Buffer_Can_Be_Read[Sys_Current_Buffer])

Por lo que parece es como si arrancara con el for antes de revisar eso. O tal ves una optimizacion lo saco.
« Última modificación: 24 de Mayo de 2015, 12:19:25 por KILLERJC »