La forma más rápida de alternar un poco en ASM

¿Cuál es la forma más rápida de alternar un bit 1 en MPASM para el conjunto de instrucciones mejoradas de 14 bits? (Estoy trabajando con un PIC16F1829)

El código debe ser independiente; quiero decir que se puede llamar en cualquier momento, sin saber el valor del bit en ese momento.

El criterio clave aquí es la velocidad : un programa con menos ciclos de instrucción es mejor. El número de ciclos de instrucciones se calcula como el número cuando el bit es 0 + el número cuando el bit es 1, dividido por 2.

1: con alternar quiero decir que el código tiene que ser similar a pin=!pinC

¿Qué es un dispositivo PIC16? Mejor llámalo por el núcleo, ¿supongo que te refieres al núcleo de 14 bits (no mejorado)?
@WoutervanOoijen gracias, buena idea: por cierto, es el núcleo mejorado para este chip, pero, por supuesto, no puede saberlo.
Curiosamente, 'pin = !pin' en C puede explotar mal. XC16 para PIC24 convierte esto en instrucciones de ensamblaje 11-12, ya que no tiene en cuenta la instrucción BTG. (Los compiladores de GCC apuntan a la portabilidad sobre la optimización, de ahí la necesidad de cosas como __builtin_btg)
@Madmanguruman Quiero decir que tiene que hacer lo mismo, no es que tenga que ser tan rápido como eso :)
@CamilStaps, ¿no sería mejor descartar mi respuesta invalidándola (retrospectivamente) con algunas palabras editadas en la pregunta? Tal como está la pregunta, mi respuesta es la forma más rápida de lograr su objetivo y alguien que llegue tarde a esta pregunta puede preguntarse por qué no ha aceptado mi respuesta. Estoy bastante feliz de eliminar mi respuesta si puede evitarla de alguna manera.
@Andyaka, su código hace más que solo invertir el bit, es por eso que (con 10 votantes a favor) creo que su respuesta es mejor. Para evitar volver a entrar en una discusión larga, venga al chat para discutir esto más a fondo.
@CamilStaps Estoy feliz de dejarlo como está si lo estás.

Respuestas (4)

Podría intentar lo siguiente usando un XOR:

movlw 0x01 ; move 0x01 to W register
xorwf lat, F ; XOR W with port & store result in port latch

Una operación OR exclusiva conservará los valores en bits donde los bits en el registro de trabajo se establecen en cero e invertirá los valores donde se establece. Entonces, también podría usar la misma técnica para alternar múltiples bits.

PeterJ, ¿está al tanto del problema Read-Modify_write? - actualización: Camil aclaró las reglas: núcleo mejorado de 14 bits ==> ¡usa el registro LAT en lugar del PORT!
Creo que esto es lo más corto que obtendrá en dispositivos que no admiten una instrucción BTG (PIC18, PIC24, etc.)
@WoutervanOoijen, sí, buen punto, actualizaré la respuesta

Se me ocurrió esto:

;                                                           Cycles if 1 | Cycles if 0
btfss    port, pin  ; skip next instruction if 1            1           | 1
goto     $+3        ; pin=0, goto PC+3                      1           | 2
bcf      port, pin  ; pin=1, clear pin and...               1           | 
goto     $+2        ;   ...proceed program                  2           |
bsf      port, pin  ; pin=0, set pin and proceed program                | 1           +
; ...                                                       ---------------------------
;                                                           5             4

Esto toma 4 o 5 ciclos de instrucciones. ¿Es posible algo más rápido?

Creo que el XOR de PeterJ es el más fatídico. Pero cíñete a tu estilo: trata de omitir las instrucciones de configuración de pines en lugar de saltar alrededor de ellas. La configuración de pines no cambiará las banderas, por lo que puede omitir tanto la cláusula "entonces" como la cláusula "else" de esta manera.
@WoutervanOoijen quieres decir btfss; bsf; bcf? Luego, el bit se borraría independientemente del estado. ¿Qué quieres decir? :)
Si no se establece, entonces do_set luego do_clear; de lo contrario, do_clear. Esto también funciona para mí.
@Andyaka esto es un if not_set entonces do_clear else do_set
@CamilStaps Estaba comentando sobre su interpretación del comentario de Wouter. Estaba siendo un poco juguetón porque no creo que haya acertado con la pregunta. Creo que quiere que el "código" se invierta un poco y luego salga O invierta el bit, luego invertir de nuevo y luego salir.
@Camile tienes razón, malinterpreté tu código. Apéguese a la solución XOR.
@Andyaka no, eso no es lo que quiero. Quiero invertir el bit, luego salir. No quiero invertirlo dos veces, nunca.

¿Cuál es la forma más rápida de alternar un bit1 en MPASM para el conjunto de instrucciones mejoradas de 14 bits? (Estoy trabajando con un PIC16F1829)

El código debe ser independiente; quiero decir que se puede llamar en cualquier momento, sin saber el valor del bit en ese momento.

El criterio clave aquí es la velocidad: un programa con menos ciclos de instrucción es mejor. El número de ciclos de instrucciones se calcula como el número cuando el bit es 0 + el número cuando el bit es 1, dividido por 2.

1: con alternar quiero decir que el código tiene que ser similar a pin=!pin en C

Supuse que el bit que desea alternar es parte de un registro que tiene "no importa" en los otros bits y, por lo tanto, el intercambio de nibbles funcionaría. Nunca dijo que no podría funcionar así y si tiene tan pocos registros que necesita los otros bits, se recomienda reescribir el código o actualizar la MCU.

Necesitaría configurar 11110000 (cualquier patrón funcionaría siempre que bn no sea igual a bn + 4) inicialmente, pero después de eso, cada vez que desee invertir uno de los bits que usa: -

intercambiarf f,d

Es una operación de un ciclo y no necesita 1 en la configuración del registro w.

Por supuesto, en el resto del programa tendrías que adherirte a este método de cambiar el bit PERO, de nuevo, no has dicho que no puedas; en otras palabras, las instrucciones BCF o BSF están prohibidas.

Pensé en las rotaciones, pero rotan a través del acarreo y esto probablemente corrompería las cosas. No he escrito el código PIC en más de 20 años, ¡así que el perdón debería estar al frente de su mente cuando vote negativamente!

Si desea invertir un PIN, debe cargar el estado del PIN, por lo que primero deberá seleccionar el banco para PORTA. Así que aquí está el código en C:

// PORTAbits.RA5=~PORTAbits.RA5;
PORTA=PORTA ^ 0b00100000;

con el resultado en ASM:

 MOVLB 0x0
 MOVF PORTA, W
 XORLW 0x20
 MOVWF PORTA
Parece que la respuesta aceptada es más rápida en un ciclo, incluso si se incorpora el interruptor de banco (que no siempre es necesario si realiza un seguimiento de en qué banco se encuentra). Por supuesto, el compilador de C no siempre brinda el código compilado más rápido, especialmente los compiladores gratuitos de Microchip generan un código muy poco optimizado.