Micro Motorola MC68000

lunes 2 de julio, 2001
 

Nota preliminar: Este artículo fue publicado en el número 6 de NetSearch Ezine, en 2001.

 

Esto pretende ser el primero de una serie de artículos (si es que veo interés y tengo tiempo) sobre Eleectronica Digital. Voy a intentar enfocarlo para que cualquiera pueda empezar en este tema. No obstante, dare por hecho ciertos conocimientos básicos sobre informática (numeración hexadecimal, binaria,…).

La electronica digital es un tema muy amplio, por tanto esto será algo así como una guía básica a partir de la cual podreis investigar vosotros mismos y profundizar. Existen multitud de microprocesadores; yo voy a escribir sobre el MC68000 de Motorola, ya que es el que conozco y es un buen micro con el que aprender. Esta claro que despues utilizareis otros, pero sabiendo uno no tendreis problemas en aprender otros.

Estoy hablando de micros, ya que en este artículo voy a empezar con la estructura y la programación del micro. Decidí empezar por aquí porque creo que es lo más interesante para empezar en electrónica, ademas será una buena guía de iniciación a lenguaje ensamblador para la gente que no sabe utilizarlo. Si veo que interesa, en otros artículos escribiré sobre mapeo de memorias, circuiteria de selección,…

En la web podreis encontrar un simulador del MC68000 y un manual de funcionamiento con el que podreis compilar y simular los programas que hagais.

Puede que os esteis preguntando cual es la aplicación de todo el royo que vais a leer, sobre todo aplicado a los temas que os interesan. Programando un micro (en la práctica, lo más seguro es que programeis un PIC, que es un poco más limitado que un micro, pero os llegará de sobra) y creando un circuito digital controlado por el, podeis hacer desde una calculadora hasta un selector entre multiples tarjetas SIM segun el PIN introducido, cerraduras controladas por una tarjeta EPROM, emuladores de… cualquier circuito que conozcais.

Bueno, sin más preambulos empiezo.

1. Indice

  1. Indice
  2. Propiedades hardware
  3. Modelo de programación
  4. La Memoria
  5. Modos de Direccionamiento
  6. Juego de instrucciones
  7. Subrutinas
  8. Excepciones
  9. Interrupciones
  10. Ejemplo práctico

 

2. Propiedades hardware

  • Bus interno: 16 bits
  • Unidad Aritmetico Lógica (ALU) puede operar sobre 16 bits directamente
  • Registros internos de 32 bits (Datos y Direcciones)
  • La Entrada/Salida esta mapeada en memoria (Intel utiliza buses diferentes para entrada/salida)
  • Bus de datos: 16 bits
  • Bus de direcciones: 32 bits (pero solo utiliza las 24 líneas menos significativas)

Micro Motorola MC68000     

* Físicamente solo hay 23 lineas de dirección. A0 se sustituye por UDS y LDS de una forma especial.

[Nota:] Las líneas negadas (con una línea por encima) quieren decir que esa línea se activa con un “0″ lógico, en lugar de un “1″.

  • GND (Ground):  Masa.
  • CLK (Clock):  Señal de reloj.
  • D0-D13 (Data): Bus de datos.
  • A1-A23 (Address): Bus de direcciones.
  • AS# (Address Strobe): Validación de dirección.
  • R/W# (Read/Write): Control Lectura/Escritura.
  • UDS# (Upper Data Strobe): Transferencia por los 8 bits altos del bus de datos.
  • LDS# (Lower Data Strobe): Transferencia por los 8 bits bajos del bus de datos.
  • DTACK# (Data Transfer Acknowledge): Indicador de transferencia completa.  (la recibe del subsistema de memoria)
  • IPL*# (Interrupt Priority Level): Entradas de peticion de interrupción. Codifican un número de 3 bits con el nivel de interrupción.
  • BERR# (Bus Error): Error en el subsistema de memoria o en E/S.
  • RESET#: Es una linea bidireccional: De forma entrante inicializa el micro.    De forma saliente fuerza la inicializacion del entorno.
  • HALT#: Es bidireccional: Como entrada detiene la CPU. Como salida indica al subsistema que la CPU se ha detenido.
  • BR# (Bus Request): Peticion de bus para DMA.
  • BG# (Bus Grant): Concesion de bus.
  • BGACK# (Bus Acknowledge): Reconocimiento de concesión.
  • E: Salida de reloj para perifericos de la familia 68000.  Frecuencia de 1/10 CLK
  • VMA# (Valid Memory Address): Indica que el bus de direcciones contiene una  direccion válida.
  • VPA# (Valid Peripherial Address): Indica que la dirección pertenece a un periférico síncrono.
  • FC* (Function Codes): Señales de status.

 

3. El Modelo de Programación

   El MC68000 tiene dos modos de funcionamiento:

   - Modo Usuario: No se pueden ejecutar ciertas instrucciones y solo se accede al byte bajo del registro de estado.

  • 8 registros de Datos de 32 bits (D0-D7)
  • 7 registros de direcciones de 32 bits (A0-A6)
  • PC (Contador de programa) de 32 bits
  • SP (Stack Pointer o Puntero de Pila de Usuario) de 32 bits (A7)
  • SR (Registro de estado) 8 bits

   - Modo Supervisor: Se accede a todo el juego de instrucciones y a todos los registros.

  • 8 registros de Datos de 32 bits (D0-D7)
  • 7 registros de direcciones de 32 bits (A0-A6)
  • PC (Contador de programa) de 32 bits
  • SSP (Stack Pointer o Puntero de Pila de Usuario) de 32 bits (A7)
  • SR (Registro de estado) 16 bits

[Nota:] Los registros de datos, direcciones y contador de programa son físicamente los mismos para los dos modos.

Los punteros de pila hay uno físicamente para cada modo.

El Registro de estado es físicamente el mismo: El usuario solo utiliza el byte menos significativo, y el supervisor el registro entero.

[Nota:] Los registros que almacenan direcciones (A*, Sp, CP) son de 32 bits pero solo utilizan los 24 bits menos significativos.

[Nota:] Cuando vallamos a utilizar la pila en un programa (ya sea de usuario, para las subrutinas, o de supervisor para las interrupciones) es necesario inicializarla, sino el micro generará un error.

La de usuario la podemos inicializar así:

   MOVE #$40000,A7

La de supervisor:

   ORG $00000

   DC.L $40000

  • Registro de Estados (SR):

bit        15 14 13 12 11 10  9  8 | 7  6  5  4  3  2  1  0

flag        T  #  S  #  # I2 I1 I0 | #  #  #  X  N  Z  V  C

[Nota:] El byte más significativo no es accesible por el modo usuario

  •   T (Trace): Si está a “1″ el micro funciona en modo traza (Paso a paso)
  •   S (Status): Si está a “1″ estamos en modo Supervisor  Si esta a “0″ estamos en modo Usuario
  •   I2 I1 I0 (Máscara de interrupción): Si un periférico solicita una interrupción, el nivel de prioridad debe ser superior al codificado por la máscara.
  •   X (Bit de Extension): Indica el acarreo en operaciones BCD
  •   N (Flag de Signo): Nos indica si la ultima operacion genero un numero negativo.
  •   Z (Flag de Zero): Indica que en la ultima operacion se obtuvo un 0.
  •   V (Flag de Overflow): Cuando esta a “1″ indica que la ultima operacion genero un desbordamiento.
  •    C (Flag de Carry): Indica ke en la ultima operacion se genero un acarreo

 

4. La Memoria

   El 68000 utiliza el formato Big Endian para el almacenamiento de datos superiores al byte en memoria. Esto quiere decir que el byte más significativo se almacena en posiciones de memoria bajas (cercanas al $00000).

              $00000

                 .

                 .

             byte alto

             byte bajo

                 .

                 .

              $FFFFF

La señal R/W# nos indica si vamos a leer o a escribir en memoria:

   

  •   R/W#   Acción

            0    Escribir

            1    Leer

 

La señal AS# se envia al sistema de memoria para decir si la dirección que se ha puesto en el bus de direcciones es válida.

  •    AS#     Indicación

             0    Dirección válida

             1    Dirección no válida

 

  • UDS# y LDS#:

  UDS#    LDS#      Acceso

   0       0        Tamaño palabra (16 bits)

   0       1        Byte bajo

   1       0        Byte alto

   1       1        No hay acceso a memoria

 

  • La señal DTACK# viene del sistema de memoria, e indica si se ha conseguido acceder con exito:

  DTACK#    Indicación

    0       Se ha accedido

    1       No se ha accedido

 

 

5.  Modos de direccionamiento

   Los modos de direccionamiento son los formas de indicar al micro donde encontrar un dato determinado, es decir, cual es su dirección efectiva (direccion física del dato).  En el 68000 tenemos 13 modos de direccionamiento:

  •  Direccionamiento Implícito:

       No se necesita operando. Se refiere a un registro definido en la operación.

       Ej: MOVE $23345,CCR

  • Direccionamiento Inmediato:

       Se expresa la dirección explicitamente en la operación.  Se utiliza el caracter # antes de la dirección.

       Ej: MOVE #$9F,D5

  • Direccionamiento Inmediato Rápido:

       Igual que antes, pero el valor es:

       Número entre 1 y 8 para suma y resta.

       Número entre -128 y 127 en instrucciones de movimiento de datos.

       Se añade el caracter Q al mnemónico y el # antes del número.

       Ej: ADDQ #6,A0

  • Direccionamiento Absoluto Largo:

     El argumento es la dirección efectiva a la que se accede.

   Ej: MULS $25022,D2

  • Direccionamiento Absoluto Corto:

     El argumento es una dirección de tamaño palabra (Word, 2 bytes)

     Si el valor está entre $0000-$7FFF accedemos a los 32k mas bajos de memoria.

     Si el valor está entre $8000-$FFFF accedemos a los 32k mas altos de memoria.

     Ej: EORI.B #$FF,$8000

  • Direccionamiento directo a registro:

    El operando es un registro interno, D* o A*

    Ej: SUB  D1,A2

  •  Direccionamiento Indirecto:

    El operando es una dirección de memoria intermedia, donde está contenida la dirección efectiva.

    Esta dirección de memoria esta contenida en un registro de dirección.

    Ej: ASL.W (A3)

  • Direccionamiento Indirecto con Postincremento:

   Igual que el anterior, pero despues de obtener el argumento el registro de direcciones se incrementa en un valor, segun el tamaño:

   .B (Byte): Se incrementa en 1

   .W (Word): Se incrementa en 2

   .L (LongWord): Se incrementa en 4

   Se utiliza la representacion (A*)+

  Ej: CMPM (A0)+,(A4)+

  Esto es muy útil para recorrer arrays y para actualizar el puntero de pila al sacar datos (El 68000 no tiene instrucción para eso)

  • Direccionamiento Indirecto con Predecremento:

    Primero se decrementa el valor del registro de direcciones y luego se accede al dato.

    Ej: OR.B D3,-(A0)

    Se utiliza para introducir datos en pila.

  • Direccionamiento Indirecto con Desplazamiento:

   La dirección efectiva se obtiene sumando un valor al contenido del registro de direcciones.

   El desplazamiento es un numero con signo de 16 bits.

   Ej:  CHR $24(A4),D3

  • Direccionamiento Indirecto con Indice y Desplazamiento:

    La dirección efectiva se halla sumando 3 valores:

    - El contenido de un registro de direcciones.

    - Un desplazamiento de 8 bits.

    - Un registro de datos.

    Formato:  desplazamiento(A*,D*.B|W|L)

   Ej: DIVU 8(A3,D7.L),D5

  • Direccionamiento Relativo con Desplazamiento:

    Igual que el de desplazamiento pero con el contador de programa.

    Ej: LEA $200(PC),A3

  • Direccionamiento Relativo con Indice y Desplazamiento

    Igual que el de indice y desplazamiento pero con el PC

    Ej: MOVE $B(PC,D1.L),D5

 

6. El juego de instrucciones

  Aquí va un extracto del juego de instrucciones. Es un juego sencillo, pero suficiente.

[Nota:] Omitiré ciertas instrucciones, puesto que este artículo está pensado para aprender a programar un micro, no para profundizar en el 68000. Si estás interesado puedes buscar en la web el juego completo.

 

                        JUEGO DE INSTRUCCIONES DEL MC68000

[Nota:] Este juego esta escrito resumidamente, y tiene el único fin de aprender un poco a programar el micro. Si se quiere utilizar con fines mas complejos, recomiendo que se busque las especificaciones completas de este código, ya que vendrán más extensamente comentadas.

  • Comentarios

  Los comentarios comienzan por * o por ‘ y el ensamblador los ignora al generar el código.

  • Representacion de datos:

Dato             Prefijo         Ejemplo

Decimal         Sin prefijo        63

Binario             %           %111111

Hexadecimal    $                   $3F

ASCII             ‘  ‘         ‘NETSEARCH’

 

  • Operaciones

  Estas operaciones pueden realizarse entre registros dentro de una instrucción.

  Por ejemplo:

  NETSEARCH EQU 20

  EZINE EQU 30

   MOVE #(NETSEARCH + EZINE / 2),D2

    sería lo mismo que

         MOVE #25,D2

 

  • |    OR lógico
  • ^    OR Exclusivo (aka XOR)
  • &    AND lógico
  • +    Suma de enteros
  • -    Resta de enteros
  • *    Multiplicación de enteros
  • /    División entera de enteros
  • >    Desplazamiento lógico hacia la derecha
  • <    Desplazamiento lógico hacia la izquierda
  • + (prefijo)    Signo positivo
  • - (prefijo)    Signo negativo
  • !    Negacion lógica
  • ( )   Parentesis sin límite de nivel
  • Etiquetas: Se utilizan para demarcar determinada posicion, y se emplean sobretodo para las subrutinas.
  • Extensiones: Se colocan en ciertas instrucciones.

     En instrucciones de manejo de datos:

          .B  El operando es un byte

         .W  El operando es una palabra (Por defecto para datos)

         .L  El operando es una palabra larga (Por defecto para direcciones)

     En instrucciones de tipo branch (ramificación):

         .S  Desplazamiento corto (8 bits)

         .L  Desplazamiento largo (16 bits)

  • Directivas o pseudoinstrucciones (Se ponen en el código fuente, pero solo los emplea el compilador, no generan código)

ABSOLUTE

  Indica que el código que se generará es absoluto (las referencias a posiciones de memoria). El código absoluto solo se ejecutará correctamente si se encuentra en las posiciones de memoria para las que ha sido ensamblado.

RELATIVE

  Modo por defecto.

  Las referencias a posiciones de memoria seran relativas al Contador de programa (PC)

ORG (ORIGIN)

  ORG expresión

  Indica la posición de memoria a partir de la cual se coloca el código que se genere a continuación.

  En código absoluto puede aparecer 20 veces, y en relativo solo 1.

  Ej: ORG $25000

END

  Debe aparecer al final del programa. El código escrito a continuación se ignorará.

DC

  DC.B  expresión,expresóon,…

  DC.W  expresión,expresión,…

  DC.L  expresión,expresión,…

  Inicializa espacio en memoria.

  Ej: DC.W $25000

      DC.L ‘HOLA’,$00

DS

  DS.B|W|L expresión

  Reserva tantos bytes|words|longword como se ponga en expresión.

  Ej: DS.W 2   —->  DC.W  0,0

EQU

  etiqueta  EQU  expresión

  Asigna el valor de la expresión a una etiqueta.

  Ej: NUMERO  EQU  $400

Existen más, pero las omito.

 

  • Instrucciones de transferencia de datos

MOVE

  MOVE.B|W|L  origen, destino

  Transfiere datos del origen al destino.

  Ej: MOVE #$12,D3

MOVEA

  MOVEA  origen,A*

  Transfiere una dirección.

  Ej: MOVEA $27,A2

MOVEM

  MOVEM.W|L lista de registros,destino

               o

  MOVEM.W|L origen,lista de registros

  Transfiere multiples registros.

MOVEQ

  MOVEQ #n,D*

  Transferencia rapida a registro de datos.

  n es un numero de 8 bits en complemento a 2.

MOVEP

   MOVEP.W|L O(A2),D*

          o

  MOVEP.W|L D*,O(A2)

  Transferencia a periféricos.

 

  • Instrucciones de intercamibo

EXG (Exchange)

  EXG expresión, expresión

  Permite intercambiar dos registros (de direcciones, de datos o uno con otro)

SWAP

  SWAP D*

  Intercambia las dos mitades de un registro de datos.

 

  • Instrucciones de manejo de direcciones efectivas

LEA (Load Effective Address)

   LEA fuente,A*

  Carga en un registro de direcciones la direccion efectiva del operando.

PEA (Push Effective Address)

  Igual que el anterior, pero guarda la direccion efectiva en la pila.

 

  • Instrucciones de suma

ADD

  ADD.B|W|L origen,destino

  Suma binaria. Uno de los dos operandos ha de ser un registro de datos.

  Ej: ADD #$4F,D3

ADDA

  ADDA.B|W|L fuente,A*

  Suma de dirección.

  Ej: ADDA.W #$5,A2

ADDI

  ADDI.B|W|L #n,destino

  Suma inmediata.

ADDQ

  ADDQ.B|W|L #n,destino

  Suma rápida.  1 <= n <= 8

ADDX

  ADDX.B|W|L origen,destino

  Suma extendida. origen + destino + X = destino

  X es el flag extendido del registro de estados

 

  •  Instrucciones de Resta

SUB

  SUB.B|W|L origen,destino

  Resta binaria.

SUBA

  SUB.B|W|L origen,A*

  Resta de direcciones.

SUBI

  SUBI.B|W|L #n,destino

  Resta inmediata.

SUBQ

   SUBQ.B|W|L #n,destino

  Resta rapida.

SUBX

   SUBX.B|W|L origen,destino

  Resta extendida.

 

  • Instrucciones de negación

NEG

  NEG.B|W|L operando

  Niega el operando.

NEGX

   NEGX.B|W|L operando

  Negacion con extensión.

 

  • Instrucciones de multiplicación

MULS

   MULS.W operando,D*

  Multiplicacion con signo.

  Los operandos son de 16 bits y el resultado de 32 bits.

MULU

  MULU.W operando,D*

  Multiplicación sin signo. El resultado es de 32 bits.

 

  •  Instrucciones de división

DIVS

  DIVS.W operando,D*

  División con signo.

  El la palabra más significativa del resultado es el resto, y la menos significativa el cociente.

DIVU

  DIVU.W operando,D*

  División sin signo.

 

  • Instrucciones de comparación

CMP

  CMP.B|W|L operando,D*

  Compara registros de datos.

CMPA

  CMPA.B|W|L operando,D*

  Comparacion inmediata.

CMPM

  CMPM.B|W|L (A*)+,(A*)+

  Comparacion de posiciones de memoria.

 

  • Instrucciones de extensión de signo

EXT

  EXT.W|L D*

  Extiende el bit de signo del operando.

 

  • Instrucción de puesta a cero

CLR (Clear)

  CLR.B|W|L operando

  Pone a 0 el operando.

 

  •  Testeo de operandos

TST

  TST.B|W|L operando

  Compara 0 con el operando.

TAS

  TAS.B operando

  Comprueba operando y pone a 1 su bit de signo.

 

  • Instrucciones de aritmética BCD

ABCD

  ABCD.B|W|L fuente,destino

  Suma en código BCD con extensión.

SBCD

   SBCD.B|W|L fuente,destino

  Resta BCD con extensión.

NBCD

  NBCD.B|W|L operando

  Negacion en BCD con extensión.

 

  • Instrucciones lógicas

AND

  AND.B|W|L fuente,destino

  Realiza un Y lógico entre los operandos.

ANDI

    ANDI.B|W|L #n,operando

  Y logico inmediato.

  #n es un número decimal entre 1 y 8.

OR

  OR.B|W|L origen,destino

  Realiza un O lógico.

ORI

  ORI.B|W|L #n,destino

  O lógico inmediato.

NOT

  NOT.B|W|L operando

  Negación lógica.

EOR

  EOR.B|W|L D*,destino

  Realiza un O exclusivo (aka XOR)

EORI

  EORI.B|W|L #n,destino

  O exclusivo inmediato.

 

  • Instrucciones de chequeo de bits

BTST

  BTST #n,destino

        o

  BTST D*,destino

  Comprobamos un bit y reflejamos el estado de ese bit en el flag Z del registro de estados. #n es el bit a comprobar.

BCLR

  BCLR #n,destino

        o

  BCLR D*,destino

  Comprueba el bit indicado y refleja el contenido en Z. Despues pone a 0 ese bit.

BSET

  BSET #n,destino

        o

  BSET D*,destino

  Comprueba, actualiza Z y pone a 1 el bit.

BCHG

  BCHG #n,destino

        o

  BCHG D*,destino

  Comprueba, actualiza Z e invierte el valor del bit.

 

  • Instrucciones de desplazamiento y rotación

LSL

   LSL.B|W|L Di,Dj      desp = Di mod 64

   LSL.B|W|L #n,D*      desp = #n

   LSL destino          desp = 1

   Desplaza hacia la izquierda los bits tantas veces como desp.

   C <–  bit|bit|bit| … |bit|bit|bit   <– 0

       |

   X <–

LSR

   LSR.B|W|L Di,Dj      desp = Di mod 64

   LSR.B|W|L #n,D*      desp = #n

   LSR destino          desp = 1

   Desplaza hacia la derecha los bits tantas veces como desp.

   0 –>  bit|bit|bit| … |bit|bit|bit  –> C

                                         |

                                         –> X

ASL

   ASL.B|W|L Di,Dj      desp = Di mod 64

   ASL.B|W|L #n,D*      desp = #n

   ASL destino          desp = 1

   Desplazamiento aritmético hacia la izquierda.

   El flag V (overflow) se pone a 1 si el bit más significativo cambia en algún momento.

ASR

  ASR.B|W|L Di,Dj      desp = Di mod 64

  ASR.B|W|L #n,D*      desp = #n

  ASR destino          desp = 1

  Desplazamiento aritmético hacia la derecha.

  El flag V (overflow) se pone a 1 si el bit menos significativo cambia en  algún momento.

ROL

  ROL.B|W|L Di,Dj      desp = Di mod 64

  ROL.B|W|L #n,D*      desp = #n

  ROL destino          desp = 1

  Rotación hacia la izquierda.

        ________________________________

       |                                |

  C  <–  bit|bit|bit|…|bit|bit|bit <–

ROR

  ROR.B|W|L Di,Dj      desp = Di mod 64

  ROR.B|W|L #n,D*      desp = #n

  ROR destino          desp = 1

  Rotación hacia la derecha.

     ________________________________

    |                                |

    –>  bit|bit|bit|…|bit|bit|bit –> C

ROXL

  ROXL.B|W|L Di,Dj      desp = Di mod 64

  ROXL.B|W|L #n,D*      desp = #n

  ROXL destino          desp = 1

  Rotación a izquierda con extensión.

        ______________________________________

       |                                      |

  C  <–  bit|bit|bit|…|bit|bit|bit <– X <–

ROXR

  ROXR.B|W|L Di,Dj      desp = Di mod 64

  ROXR.B|W|L #n,D*      desp = #n

  ROXR destino          desp = 1

  Rotación a derecha con extensión.

      _____________________________________

     |                                     |

     — X –>  bit|bit|bit|…|bit|bit|bit –> C

 

  • Instrucciones de control de programa (Saltos) incondicionales

BRA (Branch)

  BRA etiqueta

  Ramificación incondicional (Salto de 8 o 16 bits relativo a PC)

  El PC apunta ahora a la dirección de etiqueta.

BSR (Branch SubRoutine)

  BSR etiqueta

  Ramificación a subrutina. (Llamada a subrutina con esa etiqueta)

  Guarda el PC en la pila y cambia el PC a la dir. de etiqueta.

  8 o 16 bits relativo a PC.

JMP (Jump)

  JMP destino

  Salto. (Direccionamiento absoluto)

  El PC se pone la dir. de etiqueta.

JSR (Jump SubRoutine)

  JSR destino

  Salto a subrutina.

  Guarda el PC en pila y cambia PC por la dir. destino.

  Direccionamiento absoluto.

RTS (Return SubRoutine)

  RTS

  Retorno de subrutina.

  Recupera el PC de la pila (Volvemos al punto donde se llamo la subrutina)

RTR

  RTR

  Retorno de subrutina y reposición de los códigos de condición.

 

  • Saltos condicionales

cc: Condiciones base. Se colocan como sufijo a la instruccion condicional.

Aritmética con signo

  •   GT (Greater Than)     si >
  •   LS (Less Than)        si <
  •   GE (Greater or Equal) si >=
  •   LE (Less or Equal)    si =<
  •   VS (Overflow)         si overflow
  •   VC (No overflow)      si no overflow
  •   PL (Plus)             si positivo
  •   MI (Minus)            si negativo

Aritmetica sin signo

  •   HI (Higher)            si mayor
  •   CS (Carry Set)         si menor
  •   CC (Carry Clear)       si mayor o igual
  •   LS (Low or Same)       si menor o igual
  •   EQ (Equal)             si igual
  •   NE (Not Equal)         si distinto
  •   T  (True)              si cierto
  •   F  (False)             si falso

 

Bcc   (Branch if …)

  Bcc etiqueta

  Si se cumple cc salta a etiqueta (etiqueta –> PC)

  Dirección relativa a PC (8 o 16 bits)

DBcc

  DBcc D*,etiqueta

  Decrementar y ramificar. Mientras cc se cumple no se hace nada.

  Si cc no se cumple, se decrementa el registro D*.

  Mientras D* es distinto de -1, se salta a etiqueta.

Scc (Set)

  Scc destino

  Pone destino a 1 si la condicion se cumple o a 0 si no.

  El destino sera un byte.

 

  • Instrucción de no operación

NOP

  NOP

  No hace nada. Solo consume tiempo de reloj (4 ciclos).

  Es útil para generar retrasos, reservas de espacio para futuras instrucciones o para substituir instrucciones sobrantes sin tener que modificar el resto del programa.

 

  • INSTRUCCIONES PRIVILEGIADAS

  Las instrucciones privilegiadas solo son accesibles en modo supervisor.

  Estas instrucciones son muchas de las anteriores pero aplicadas a los registros SR (Registro de estado), CCR (Registro de Códigos de Condición) y USP (Puntero de Pila de Usuario).  Ademas, tenemos estas otras:

RESET

  RESET

  Activa la linea de reset o produce una excepción (el micro no se reinicializa).

RTE (Return of Exception)

  RTE

  Retorna de una interrupción, restaurando SR y PC

STOP

  STOP #n

  Se pone #n en SR y se para la ejecución. Para reanudar la ejecución es necesaria una interrupción.

CHK (Check)

  CHK origen,D*

  Compara un registro con unos limites.

  D* < 0   o  D* > origen

  Si fuera de esos limites, se genera una interrupción 6 (Tipo trampa)

TRAP (Trampa)

  TRAP #n

  Se genera una interrupción trampa. #n esta entre 0 y 15, segun la  prioridad.

TRAPV

  TRAPV

  Se genera una excepción de tipo trampa de orden 7 si el flag V (Overflow) esta a 1.

 

7. Subrutinas

   A veces hay operaciones que se repiten durante un programa, y habría que reescribir todo el código de nuevo, con el consiguiente gasto de memoria y el engorro de reescribirlo. Para evitar esto se crean subrutinas, que son pedazos de código que podemos llamar mediante instrucciones de salto o ramificación. Físicamente, en memoria solo está una vez, pero puede utilizarse cuantas veces sea necesario. El funcionamiento básico de una subrutina es el siguiente:

Al llegar a una llamada a subrutina, se guarda en la pila la dirección a la que apunta ese momento el PC (Contador de programa). Entonces actualizamos el PC con la dirección de comienzo de la subrutina. Una vez termina la subrutina (Con la instruccion RTS o RTR), se recupera de la pila la direccion del PC y continuaremos en la siguiente instrucción a la llamada de la subrutina.

8. Excepciones

   Las excepciones son acontecimientos, internos o externos al micro, que hacen que se interrumpa la ejecución para realizar una subrutina de atencion a esa excepción.  Estas excepciones pueden ser:

  •      Errores hardware
  •      Errores intenos
  •      Reset
  •      Ejecución paso a paso
  •      Interrupciones hardware
  •      Interrupciones software

   Cada excepcion tiene asociada una dirección de memoria donde se encuentra su vector de excepción. Ese vector contiene la dirección de comienzo de la rutina de excepción.

                TABLA DE LOS VECTORES DE EXCEPCION DEL MC68000

[Nota:] El reset ocupa 2 vectores de excepcion

  Numero vector    Direccion              Asignación

     0             $000       Reset: SSP (Punt. de pila supervisor) inicial.

     -             $004       Reset: PC inicial.

     2             $008       Error de bus.

     3             $00C       Error de dirección.

     4             $010       Instrucción ilegal.

     5             $014       División por cero.

     6             $018       Instrucción CHK.

     7             $01C       Instrucción TRAP.

     8             $020       Violacion de privilegio.

     9             $024       Traza.

    10             $028       Instrucción emulada 1010.

    11             $02C       Instrucción emulada 1111.

    12             $030       No asignado. Reservado.

    13             $034       No asignado. Reservado.

    14             $038       No asignado. Reservado.

    15             $03C       Vector de interrupción no inicializado.

   6-23          $044-$05C    No asignado. Reservado.

    24             $060       Interrupción espúrea (Especie de timeout).

    25             $064       Autovector de Interrupción de nivel 1 (IRQ1).

    26             $068       Autovector de Interrupción de nivel 2 (IRQ2).

    27             $06C       Autovector de Interrupción de nivel 3 (IRQ3).

    28             $070       Autovector de Interrupción de nivel 4 (IRQ4).

    29             $074       Autovector de Interrupción de nivel 5 (IRQ5).

    30             $078       Autovector de Interrupción de nivel 6 (IRQ6).

    31             $07C       Autovector de Interrupción de nivel 7 (IRQ7).

   32-47         $080-$0BC    Vectores de la instrucción TRAP (1-15).

   48-63         $0C0-$0FC    No asignado. Reservado.

   64-255        $100-$3FC    Vectores de interrupción de usuario.

   Dirección de excepción = Número de vector x 4

 

9. Interrupciones

   Las interrupciones son el mecanismo básico de sincronización del micro con dispositivos externos. Quizá sean una de las cosas mas importantes en un micro.

   Pueden ser generadas por hardware, a traves de las lineas IPL2 IPL1 e IPL0 o por software, mediante las instrucciones TRAP.

   Existe tambien una interrupción especial llamada Interrupción Espúrea, que sirve para evitar esperas infinitas cuando el micro lleva mucho tiempo esperando (por ejemplo, se activa una IRQ por ruido, pero realmente nadie pide la interrupción).

   Una interrupción funciona básicamente igual que una subrutina, con la diferencia de que se trabaja en modo supervisor (y por tanto, tambien utilizamos la pila de supervisor (SSP).

  • Mecanismo de solicitud

   En las líneas de interrupción se codifica el nivel de prioridad de la interrupción. Se utilizan los 7 Autovectores (ya que estamos hablando de una interrupción generada externamente, por un periférico, por ejemplo).

     IPL2   IPL1   IPL0       Nivel de prioridad

       0      0      0             7  (Máxima, no enmascarable)

       0      0      1             6

       0      1      0             5

       0      1      1             4

       1      0      0             3

       1      0      1             2

       1      1      0             1  (Mínima)

       1      1      1             No se solicita interrupcion

[Nota:] Como vemos, son lineas que se activan a nivel bajo (es decir, con un 0).

   Se suele utilizar un codificador para generar estos códigos a partir de las 7 IRQ, pero eso ya lo veremos en próximos artículos.

  • Enmascaramiento

   El enmascaramiento nos sirve para controlar si cuando se activa una interrupción y ya esta otra en ejecución se debe parar la primera o no. Esto se hace con la máscara de interrupción, codificada en el byte alto del registro de estado, como hemos visto anteriormente. Esta máscara se actualiza cuando se genera una interrupción, y si se genera otra, el nivel de prioridad de esta interrupción debe ser superior a la máscara, o se ignorará.

10. Ejemplo práctico

   Aquí os dejo un pequeño ejercicio práctico para que veais como funciona el 68000. Tendreis que utilizar el simulador.

   No voy a explicar como funciona, porque es bastante intuitivo. Simplemente, teneis que compilar y linkar el código y ejecutarlo en el simulador. Dentro del simulador, antes de ejecutar debereis configurar las posiciones de memoria de los puertos de entrada y de salida que necesiteis (aquí uso como entrada $60000 y como salida $60001) y configurar la ventana para que muestre esos puertos y ver su contenido durante la ejecución. Tambien podeis ejecutar en modo traza.

   Bien, el objetivo es el siguiente:

  Tenemos un sistema de 8 leds conectados a la posicion de memoria $60000 de un sistema digital con un micro MC68000. Cada uno de esos leds se enciende cuando recibe un “1″ lógico, y se apaga al recibir un “0″.  En el puerto de entrada, situado en la posicion $60001, si se pone un 1 los leds deben parpadear mientras ese 1 siga ahí. Si se pone un 2, los leds deben hacer un efecto estilo el coche fantástico Kit (bueno, los malotes si lo preferis le poneis leds verdes y ya esta :P). Si se pone cualquier otro dato, los leds continuarán apagados.

  Tambien tenemos un pulsador conectado a las lineas de interrupción, que genera una interrupción de nivel 2 (IRQ2). Si lo pulsamos, apagamos todos los leds.

[Nota:] Cada led esta conectado a un bit del primer byte del puerto de salida.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
**** SIMULACION CON LEDS
 
	ABSOLUTE
 
	ORG	$00000
        DC.L	$40000  * Inicializamos la SSP
	DC.L	$25000
 
        ORG	$68     * Inicializamos la IRQ2 (Su autovector
        DC.L    $26000  * es el $68) la direccion de comienzo
                        * de la rutina de interrupcion sera
                        * la $26000
 
 
 
	ORG	$25000
 
	MOVE.L	#$29000,A7   * Inicializacion de SP
INICIO
	CLR.L	D0        * Ponemos a 0 D0
	MOVE.B	$60000,D0 * Leer entrada
	CMPI.B	#1,D0     * Si es 1...
	BEQ	PARPADEO  * ...saltamos a parpadeo
	CMPI.B	#2,D0     * Si es 2...
	BEQ	COCHE	  * ...saltamos a COCHE
	JMP	INICIO    * Sino, reiniciamos
 
 
**** Bucle FOR de $F a $0
 
WAIT
	MOVE.W	#$F,D1
ITER
	DBF	D1,ITER *
	RTS
 
 
**** Subrutina 1: Parpadeo
 
PARPADEO
	MOVE.B	#$FF,$60001 * Escribir 1's en el byte de salida (8 LEDS)
	JSR	WAIT * Hacemos un retardo (Subrutina Bucle FOR)
	MOVE.B  #$00,$60001 * Escribir 0's en salida
	CMPI.B 	#1,D0
	BNE 	INICIO
	JSR 	WAIT
	JMP 	PARPADEO
 
 
*** Subrutina 2: Coche Fantastico
 
COCHE
	MOVE	#1,D2
IZQUIERDA
	MOVE.B	D2,$60001 * Poner 1 en salida
	JSR	WAIT 
	CMPI.B	#2,D0 * Comprobar que D0 sigue siendo 2...
	BNE	INICIO * ...sino volvemos al comienzo
	MULU	#$2,D2 * Multiplicamos por 2 D2, asi tenemos el siguiente LED
                       * que serian 1,2,4,8,16,32,64 y 128 en binario
 
        CMP     #128,D2 * Se para en el ultimo bit encendido y cambia de
                        * sentido
	BEQ	DERECHA
	JMP	IZQUIERDA
DERECHA
	MOVE.B	D2,$60001
	JSR	WAIT
	CMPI.B	#2,D0
	BNE	INICIO
	DIVU	#$2,D2
        CMP     #1,D2  * Se para en el primer bit encendido y cambia de
                       * sentido
 
	BEQ	IZQUIERDA
	JMP	DERECHA
 
 
 
	ORG	$26000  * Direccion del codigo a continuacion
 
PUESTACERO
	MOVE.W	#0,D0 * Poner 0 en D0
	RTE
 
	END

Deja un comentario