#====================================================================== # Rutina de tratamiento de excepciones y programa cargador #---------------------------------------------------------------------- # # La rutina de tratamiento de excepciones se ejecuta cuando ocurre # una excepción. Distingue entre excepciones que no son interrupciones # e interrupciones. # # El programa cargador se encarga de lanzar las aplicaciones cargadas # en el simulador # #====================================================================== #====================================================================== # Espacio para las variables utilizadas por la rutina que gestiona las # interrupciones, así como para almacenar temporalmente datos. #---------------------------------------------------------------------- .kdata # Mensajes que se imprimen en las distintas rutinas _exc_: .asciiz " * Se ha generado una excepción software *\n" _int_: .asciiz " * Se ha generado una interrupción *\n" _kbd_: .asciiz " * Se ha generado una interrupción de teclado *\n" # Espacio reservado para almacenar temporalmente registros .align 2 reserva: .space 40 #====================================================================== #====================================================================== # Código que gestiona las interrupciones y excepciones en MIPS #---------------------------------------------------------------------- .ktext 0x80000180 # Dirección de inicio de la # rutina de gestión de excepciones #---------------------------------------------------------------------- # Almacenamiento de los registros que se vayan a utilizar #---------------------------------------------------------------------- sw $k0,reserva sw $k1,reserva+4 sw $v0,reserva+8 sw $a0,reserva+12 sw $t0,reserva+16 # Se almacena el registro $at en $k1. Esto se tiene que hacer # obligatoriamente. .set noat move $k1, $at .set at #---------------------------------------------------------------------- # Determinación de la causa de la excepción #---------------------------------------------------------------------- mfc0 $k0, $13 # Registro Cause srl $a0, $k0, 2 # Extracción del Código de Excepción andi $a0, $a0, 0xf # Salto a la rutina específica según si es interrupción o excepción bne $a0, 0, exc_sw #---------------------------------------------------------------------- # Rutina de tratamiento de una interrupción #---------------------------------------------------------------------- int: #------------------------------------------------------------ # Comprobación de si la interrupción es de teclado #------------------------------------------------------------ andi $a0, $k0, 0x0800 bne $a0, $0, intkbd # Ir a intkbd si es de teclado #------------------------------------------------------------ # Es una interrupción, pero no de teclado #------------------------------------------------------------ li $v0, 4 # + la $a0, _int_ # | Impresión mensaje syscall # + mtc0 $0, $13 # Puesta a 0 del registro Cause j ret # Ir a recuperar estado #------------------------------------------------------------ # Es una interrupción de teclado #------------------------------------------------------------ intkbd: li $v0, 4 # + la $a0, _kbd_ # | Mensaje de interrupción de teclado syscall # + # Se pone a 0 el bit 11 del registro Cause para indicar que # se ha servido la interrupción de teclado mfc0 $t0, $13 andi $t0, $t0, 0xF7FF mtc0 $t0, $13 j ret # Ir a recuperar estado #---------------------------------------------------------------------- # Rutina de tratamiento de una excepción (no interrupción) #---------------------------------------------------------------------- # exc_sw: li $v0, 4 # + la $a0, _exc_ # | Impresión mensaje syscall # + # Se incrementa el EPC para que continue la ejecución en la # siguiente instrucción a la que provocó la excepción mfc0 $k0, $14 # + addiu $k0, $k0, 4 # | Excepción: EPC<-EPC+4 mtc0 $k0, $14 # + mtc0 $0, $13 # Puesta a 0 del registro Cause #---------------------------------------------------------------------- # Recuperar estado y retornar #---------------------------------------------------------------------- ret: # Restauración de los registros utilizados por la rutina lw $k0,reserva lw $v0,reserva+8 lw $a0,reserva+12 lw $t0,reserva+16 # Se recuperan los registros $at y $k1 .set noat move $at $k1 .set at lw $k1,reserva+4 # Recuperación del estado del procesador, PC y SR. Y retorno # de la rutina de tratamiento de excepciones eret #====================================================================== #====================================================================== # Programa cargador. Invoca la rutina «main» con los argumentos argc, # argv y envp. #---------------------------------------------------------------------- .text .globl __start __start: lw $a0, 0($sp) # argc addiu $a1, $sp, 4 # argv addiu $a2, $a1, 4 # envp sll $v0, $a0, 2 addu $a2, $a2, $v0 jal main li $v0, 10 syscall # syscall 10 (exit) .globl __eoth __eoth: #======================================================================