Micro Motorola MC68000

//

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 Electrónica Digital. Voy a intentar enfocarlo para que cualquiera pueda empezar en este tema. No obstante, daré 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.

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)
Esquema 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.

MOVE $23345,CCR

Direccionamiento Inmediato

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

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.

ADDQ #6,A0

Direccionamiento Absoluto Largo

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

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.

EORI.B #$FF,$8000

Direccionamiento directo a registro

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

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.

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*)+

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.

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.

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)

DIVU 8(A3,D7.L),D5

Direccionamiento Relativo con Desplazamiento

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

LEA $200(PC),A3

Direccionamiento Relativo con Indice y Desplazamiento

Igual que el de indice y desplazamiento pero con el PC

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

6. El juego de instrucciones de MC68000

Aquí va un extracto del juego de instrucciones. Es 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.

[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)

Directiva Uso Descripción
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.

ORG $25000
END   Debe aparecer al final del programa. El código escrito a continuación se ignorará.
DC

DC

DC.L expr, expr,...

DC.B expr, expr,...

Inicializa espacio en memoria.

DC.W $2500
DC.L 'HOLA',$00
DS DS.B|W|L expresión

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

DS.W 2 -> DC.W 0,0
EQU etiqueta EQU expresión

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

NUMERO EQU $400

Existen más, pero las omito.


Instrucciones de transferencia de datos

Instrucción Uso Descripción
MOVE MOVE.B|W|L origen, destino

Transfiere datos del origen al destino.

MOVE #$12,D3
MOVEA MOVEA origen,A*

Transfiere una dirección.

MOVEA $27,A2
MOVEM

MOVEM.W|L lista_reg,destino

MOVEM.W|L origen,lista_reg

Transfiere múltiples 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*

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

Transferencia a perifericos.

Instrucciones de intercambio

Instrucción Uso Descripción
EXG (Exchange) EXG expresión, expresión Permite intercambiar dos registros (de direcciones, de datos o uno con otro)
SWAP SWAP D* registro de datos. Intercambia las dos mitades de un

Instrucciones de manejo de direcciones efectivas

Instrucción Uso Descripción
LEA (Load Effective Address) LEA fuente,A* Carga en un registro de direcciones la direccion efectiva del operando.
PEA (Push Effective Address) PEA fuente,A* Igual que el anterior, pero guarda la direccion efectiva en la pila.

Instrucciones de suma

Instrucción Uso Descripción
ADD ADD.B|W|L origen,destino

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

ADD #$4F,D3
ADDA ADDA.B|W|L fuente,A*

Suma de dirección.

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

Instrucción Uso Descripción
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

Instrucción Uso Descripción
NEG NEG.B|W|L operando Niega el operando.
NEGX NEGX.B|W|L operando Negacion con extensión.

Instrucciones de multiplicación

Instrucción Uso Descripción
MULS MULS.W operando,D*

Multplicación 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

Instrucción Uso Descripció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

Instrucción Uso Descripció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

Instrucción Uso Descripción
EXT EXT.W|L D* Extiende el bit de signo del operando.

Instrucción de puesta a cero

Instrucción Uso Descripción
CLR CLR.B|W|L operando Pone a 0 el operando.

Testeo de operandos

Instrucción Uso Descripción
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

Instrucción Uso Descripción
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

Instrucción Uso Descripción
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

Instrucción Uso Descripción
BTST

BTST #n,destino

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

BCLR D*,destino

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

BSET #n,destino

BSET D*,destino

Comprueba, actualiza Z y pone a 1 el bit.
BCHG

BCHG #n,destino

BCHG D*,destino

Comprueba, actualiza Z e invierte el valor del bit.

Instrucciones de desplazamiento y rotación

Instrucción Uso Descripció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 aritmetico 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 aritmetico 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

Instrucción Uso Descripción
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 dirección 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
Instrucción Uso Descripción
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

Instrucción Uso Descripció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:

Instrucción Uso Descripción
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
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 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 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

Nº vector Dirección 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 Violación 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 interrupción

[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.

**** 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