File:  [Repository ATC2] / ADD_ver_10 / Source Code / Source Files / AnalizadorOperandos16bits.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Feb 28 14:54:21 2006 UTC (18 years, 6 months ago) by rico
Branches: MAIN
CVS tags: HEAD
*** empty log message ***

/********************************************************************/
/*  AnalizadorOperandos16bits.c                                     */
/*                                                                  */
/*                                                                  */
/*  Copyright (c) 1997-2006 Rafael Rico      (rafael.rico@uah.es)   */
/*                                                                  */
/*  Este fichero forma parte de ADD                                 */
/*  (Analizador de Dependencias de Datos)                           */
/*  Version 5.10.                                                   */
/*                                                                  */
/*                                                                  */
/*  ADD es software libre. Puede redistribuirlo y/o modificarlo     */
/*  bajo los términos de la Licencia Pública General de GNU         */
/*  según es publicada por la Free Software Foundation, bien bajo   */
/*  la versión 2 de dicha Licencia o bien (según su elección)       */
/*  bajo cualquier versión posterior.                               */
/*                                                                  */
/*  ADD se distribuye con la esperanza de que sea útil,             */
/*  pero SIN NINGUNA GARANTÍA, incluso sin la garantía MERCANTIL    */
/*  implícita y sin garantizar la CONVENIENCIA PARA UN PROPÓSITO    */
/*  PARTICULAR. Véase la Licencia Pública General de GNU para       */
/*  más detalles.                                                   */
/*                                                                  */
/*  Debería haber recibido una copia de la Licencia Pública General */
/*  junto con ADD. Si no ha sido así, escriba a la Free Software    */
/*  Foundation, Inc., 51 Franklin St, Fifth Floor,                  */
/*  Boston, MA  02110-1301  EEUU.                                   */
/*                                                                  */
/*  -------------------------- Historia --------------------------- */
/*                                                                  */
/*  $Id: AnalizadorOperandos16bits.c,v 1.2 2006/02/28 14:54:21 rico Exp $                                                            */
/*                                                                  */
/*  Revisión 1.2. 01/2006                                           */
/*  Se añade la licencia GPL y documentación en estilo Javadoc      */
/*                                                                  */
/*  Revisión 1.1. 09/2005                                           */
/*  Versión inicial                                                 */
/*                                                                  */
/********************************************************************/

/******************************************************************************/
/* MÓDULO: AnalizadorOperandos16bits.c                                        */
/*                                                                            */
/* Este módulo analiza el uso de los operandos y construye una ficha de la    */
/* instrucción clasificando los operandos por su uso.                         */
/* También calcula el número total de ciclos.                                 */
/******************************************************************************/
/* Fecha: 13 de junio de 2005                                                 */
/******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "defines.h"
#include "tipos.h"
#include "analizadoroperandos16bits.h"

/* bases de datos */
extern unsigned int num_nemonicos;
extern operacion *nemonicos;
extern unsigned int num_simbolos;
extern operando *simbolos;



/* esta función convierte una cadena de operandos a una cadena normalizada */
/* de posibles ubicaciones (sin desplazamientos ni valores inmediatos) */

void NormalizarUbicacion(char *cadena)
{
    switch(cadena[0])
    {
        case '\0':    /* sin operando; aquí se supone que no debería entrar */
        break;

        case '[':    /* operando memoria */
        if(isxdigit(cadena[2])) strcpy(cadena, "[XXXX]");    /* es un desplazamiento absoluto */
        else
        {
            if(cadena[3]==']') cadena[4]='\0';    /* termino la cadena justo después aunque */
            else cadena[6]='\0';                /* pueda haber desplazamiento adicional */
        }
        break;

        default:    /* registros o valores (inmediatos o direcciones físicas) */
        if(isxdigit(cadena[1]))    /* es un número hexadecimal */
        {
            switch(strlen(cadena))
            {
                case 2:    /* inmediato de 1 byte */
                strcpy(cadena, "INM8");
                break;

                case 4:    /* inmediato de 2 bytes */
                strcpy(cadena, "INM16");
                break;

                case 9:    /* dirección física */
                strcpy(cadena, "B:D");
                break;
            }
        }
        break;
    }
}


/* esta función clasifica un operando explícito según su funcionalidad */
/* las funciones de los operandos se dan en la base de datos de símbolos */
/* se consideran independientes de la operación (lo cual no es cierto siempre) */

void ClasificarOperandoExplicito(char *operando, char modo, fichainstruccion *tarjetaoperandos)
{
    int id_simb;
    char cadena[MAX_LINE];
    char mensaje[MAX_LINE];

    strcpy(cadena, operando);

    if(cadena[0]!= '\0')
    {
        NormalizarUbicacion(cadena);
        id_simb = BDBuscarCadena(TABLA_SIMBOLOS, CAMPO_SIMBOLO, cadena);

        if(id_simb == -1)
        {
            /* emito un error al fichero de log */ 
            sprintf(mensaje, "[ClasificarOperandoExplicito] La cadena '%s' no se ha encontrado en Tabla Símbolos", cadena);
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
        }

        /* relleno la tarjeta de operandos explícitos para el operando (cadena) */
        /* según la funcionalidad dada por el campo tipo */

        switch(simbolos[id_simb].tipo)
        {
            case DATOS:
            switch(modo)
            {
                case LEIDOYESCRITO:    /* leido y escrito */
                AgregarElementoLista(tarjetaoperandos->leidoexpldatos, simbolos[id_simb].simbolo);
                AgregarElementoLista(tarjetaoperandos->leidoexpldatos, simbolos[id_simb].dependencias);
                case ESCRITO:    /* escrito */
                AgregarElementoLista(tarjetaoperandos->escritoexpldatos, simbolos[id_simb].simbolo);
                AgregarElementoLista(tarjetaoperandos->escritoexpldatos, simbolos[id_simb].dependencias);
                break;

                case LEIDO:    /* leido */
                AgregarElementoLista(tarjetaoperandos->leidoexpldatos, simbolos[id_simb].simbolo);
                AgregarElementoLista(tarjetaoperandos->leidoexpldatos, simbolos[id_simb].dependencias);
                break;

                case NO_EXISTE:    /* no existe: emitir un error al fichero de log */
                sprintf(mensaje, "[ClasificarOperandoExplicito] El operando no existe");
                Notificar(mensaje, ERROR_SALIR, ECO_NO);
                break;
            }
            break;

            case PTR_MEM:
            switch(modo)
            {
                case LEIDOYESCRITO:    /* leido y escrito */
                AgregarElementoLista(tarjetaoperandos->leidoexpldir, simbolos[id_simb].simbolo);
                case ESCRITO:    /* escrito */
                AgregarElementoLista(tarjetaoperandos->escritoexpldir, simbolos[id_simb].simbolo);
                break;

                case LEIDO:    /* leido */
                AgregarElementoLista(tarjetaoperandos->leidoexpldir, simbolos[id_simb].simbolo);
                break;

                case NO_EXISTE:    /* no existe: emitir un error al fichero de log */
                sprintf(mensaje, "[ClasificarOperandoExplicito] El operando no existe");
                Notificar(mensaje, ERROR_SALIR, ECO_NO);
                break;
            }
            break;

            case PTR_PILA:
            switch(modo)
            {
                case LEIDOYESCRITO:    /* leido y escrito */
                AgregarElementoLista(tarjetaoperandos->leidoexplpila, simbolos[id_simb].simbolo);
                case ESCRITO:    /* escrito */
                AgregarElementoLista(tarjetaoperandos->escritoexplpila, simbolos[id_simb].simbolo);
                break;

                case LEIDO:    /* leido */
                AgregarElementoLista(tarjetaoperandos->leidoexplpila, simbolos[id_simb].simbolo);
                break;

                case NO_EXISTE:    /* no existe: emitir un error al fichero de log */
                sprintf(mensaje, "[ClasificarOperandoExplicito] El operando no existe");
                Notificar(mensaje, ERROR_SALIR, ECO_NO);
                break;
            }
            break;

            case BANDERAS:
            /* nunca se dan explícitamente pero pueden ser considerados explícitos a través del nemónico */
            /* así se hará en la clasificación de implícitos */
            break;

            /* los 2 siguientes no representan realmente funciones */

            case ACCESOS_MEM:    /* accesos a memoria */
            /* CÓMPUTO DE DIRECCIONES */
            /* BASE: registro de segmento */
            /* si hay prefijo de registro de segmento (longitud 2), ese es el leído */
            if(strlen(tarjetaoperandos->prefijo)==2)
            {
                if(strcmp(tarjetaoperandos->prefijo, "SS") == 0) AgregarElementoLista(tarjetaoperandos->leidoexplpila, tarjetaoperandos->prefijo);
                else AgregarElementoLista(tarjetaoperandos->leidoexpldir, tarjetaoperandos->prefijo);
            }
            /* si no lo hay, agrego el indicado por defecto */
            else
            {
                switch (simbolos[id_simb].segmento)
                {
                    case CS:
                    AgregarElementoLista(tarjetaoperandos->leidoimpldir, "CS");
                    break;

                    case SS:
                    AgregarElementoLista(tarjetaoperandos->leidoimplpila, "SS");
                    break;

                    case DS:
                    AgregarElementoLista(tarjetaoperandos->leidoimpldir, "DS");
                    break;

                    case ES:
                    AgregarElementoLista(tarjetaoperandos->leidoimpldir, "ES");
                    break;
                }
            }

            /* OFFSET: los registros involucrados en el cómputo de direcciones */
            /* siempre son leídos; la función depende de la BASE */
            if(strcmp(tarjetaoperandos->prefijo, "SS") == 0 ||
                simbolos[id_simb].segmento == SS)
                AgregarElementoLista(tarjetaoperandos->leidoexplpila, simbolos[id_simb].dependencias);
            else AgregarElementoLista(tarjetaoperandos->leidoexpldir, simbolos[id_simb].dependencias);

            /* DATO */
            if(strcmp(tarjetaoperandos->prefijo, "SS") == 0 || simbolos[id_simb].segmento == SS)
            {
                switch(modo)
                {
                    case LEIDOYESCRITO:    /* leido y escrito */
                    AgregarElementoLista(tarjetaoperandos->leidoexplpila, "PILA");
                    case ESCRITO:    /* escrito */
                    AgregarElementoLista(tarjetaoperandos->escritoexplpila, "PILA");
                    break;

                    case LEIDO:    /* leido */
                    AgregarElementoLista(tarjetaoperandos->leidoexplpila, "PILA");
                    break;

                    case NO_EXISTE:    /* no existe: emitir un error al fichero de log */
                    sprintf(mensaje, "[ClasificarOperandoExplicito] El operando no existe");
                    Notificar(mensaje, ERROR_SALIR, ECO_NO);
                    break;
                }
            }
            else
            {
                switch(modo)
                {
                    case LEIDOYESCRITO:    /* leido y escrito */
                    AgregarElementoLista(tarjetaoperandos->leidoexpldatos, "MEM");
                    case ESCRITO:    /* escrito */
                    AgregarElementoLista(tarjetaoperandos->escritoexpldatos, "MEM");
                    break;

                    case LEIDO:    /* leido */
                    AgregarElementoLista(tarjetaoperandos->leidoexpldatos, "MEM");
                    break;

                    case NO_EXISTE:    /* no existe: emitir un error al fichero de log */
                    sprintf(mensaje, "[ClasificarOperandoExplicito] El operando no existe");
                    Notificar(mensaje, ERROR_SALIR, ECO_NO);
                    break;
                }
                break;
            }
            break;

            case OTROS:
            AgregarElementoLista(tarjetaoperandos->leidoexpldir, simbolos[id_simb].dependencias);
            break;

            default:
            /* emitir un error al fichero de log */
            sprintf(mensaje, "[ClasificarOperandoExplicito] El tipo de símbolo no existe");
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
            break;
        }
    }
}


/* esta función clasifica un operando implícito leído según su funcionalidad */
/* las funciones de los operandos se dan en la base de datos de símbolos */
/* se consideran independientes de la operación (lo cual no es cierto siempre) */

void ClasificarOperandoImplicitoLeido(char *cadena, char tipo, fichainstruccion *tarjetaoperandos)
{
    int id_simb;
    char mensaje[MAX_LINE];

    id_simb = BDBuscarCadena(TABLA_SIMBOLOS, CAMPO_SIMBOLO, cadena);

    if(id_simb == -1)
    {
        /* emito un error al fichero de log */ 
        sprintf(mensaje, "[ClasificarOperandoImplicitoLeido] La cadena '%s' no se ha encontrado en Tabla Símbolos", cadena);
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
    }

    switch(simbolos[id_simb].tipo)
    {
        case DATOS:
        AgregarElementoLista(tarjetaoperandos->leidoimpldatos, simbolos[id_simb].simbolo);
        AgregarElementoLista(tarjetaoperandos->leidoimpldatos, simbolos[id_simb].dependencias);
        break;

        case PTR_MEM:
        AgregarElementoLista(tarjetaoperandos->leidoimpldir, simbolos[id_simb].simbolo);
        break;

        case PTR_PILA:
        AgregarElementoLista(tarjetaoperandos->leidoimplpila, simbolos[id_simb].simbolo);
        break;

        case BANDERAS:
        if(tipo == SALTO_CONDICIONAL || tipo == CONTROL)
            /* los saltos condicionales y las operaciones sobre banderas */
            /* pueden ser considerados explícitos a través del nemónico */
            AgregarElementoLista(tarjetaoperandos->leidoexplestado, simbolos[id_simb].simbolo);
        else AgregarElementoLista(tarjetaoperandos->leidoimplestado, simbolos[id_simb].simbolo);
        break;

        default:    /* emitir un error al fichero de log */
        sprintf(mensaje, "[ClasificarOperandoImplicitoLeido] El tipo de símbolo no existe");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        break;
    }
}


/* esta función clasifica un operando implícito escrito según su funcionalidad */
/* las funciones de los operandos se dan en la base de datos de símbolos */
/* se consideran independientes de la operación (lo cual no es cierto siempre) */

void ClasificarOperandoImplicitoEscrito(char *cadena, char tipo, fichainstruccion *tarjetaoperandos)
{
    int id_simb;
    char mensaje[MAX_LINE];

    id_simb = BDBuscarCadena(TABLA_SIMBOLOS, CAMPO_SIMBOLO, cadena);
        
    if(id_simb == -1)
    {  
        /* emito un error al fichero de log */ 
        sprintf(mensaje, "[ClasificarOperandoImplicitoEscrito] La cadena '%s' no se ha encontrado en Tabla Símbolos", cadena);
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
    }

    switch(simbolos[id_simb].tipo)
    {
        case DATOS:
        AgregarElementoLista(tarjetaoperandos->escritoimpldatos, simbolos[id_simb].simbolo);
        AgregarElementoLista(tarjetaoperandos->escritoimpldatos, simbolos[id_simb].dependencias);
        break;

        case PTR_MEM:
        AgregarElementoLista(tarjetaoperandos->escritoimpldir, simbolos[id_simb].simbolo);
        break;

        case PTR_PILA:
        AgregarElementoLista(tarjetaoperandos->escritoimplpila, simbolos[id_simb].simbolo);
        break;

        case BANDERAS:
        if(tipo == SALTO_CONDICIONAL || tipo == CONTROL)
            /* los saltos condicionales y las operaciones sobre banderas */
            /* pueden ser considerados explícitos a través del nemónico */
            AgregarElementoLista(tarjetaoperandos->escritoexplestado, simbolos[id_simb].simbolo);
        else AgregarElementoLista(tarjetaoperandos->escritoimplestado, simbolos[id_simb].simbolo);
        break;

        default:    /* emitir un error al fichero de log */
        sprintf(mensaje, "[ClasificarOperandoImplicitoEscrito] El tipo de símbolo no existe");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        break;
    }
}


/* esta función desensambla una instrucción a partir de una secuencia de bytes */
/* extrae información a partir del nemónico */
/* clasifica el uso de los operandos explícitos según su función */
/* clasifica el uso de los operandos implícitos según su función */

void AnalizarOperandosIA16(unsigned char secuencia[12], fichainstruccion *tarjetaoperandos)
{
    /* El argumento de la función es un array con 2 posibles */
    /* formatos de instrucción: la que hay que desensamblar  */
    /* y la siguiente para poder saber si se salta o no      */
    /* ¡OJO! En realidad cada formato debería tener 7 bytes  */
    /* para prevenir el uso de prefijos                      */

    unsigned char formato[6];
    int i, j;
    struct desensamblado instruccion;  /* reservo memoria para una estructura de tipo desensamblado */
    int id_nemo;
    char cadena[MAX_LINE];    /* esto es un array de caracteres; cadena[x] es un puntero */
    char *elemento;           /* es un puntero a char; no es igual a cadena[x] para la función strtok */
    char mensaje[MAX_LINE];

    /* inicio la tarjeta de operandos */
    IniciarTarjeta(tarjetaoperandos);

    /* cargo la primera instrucción desde la secuencia */

    for(i=0; i<6; i++) formato[i] = secuencia[i];

    /* desensamblo la instrucción */
    DecodificarInstruccion086(formato, &instruccion);

    /* analizo la estructura desensamblada */
    /* PRIMERO: busco el nemónico en la BD */

    id_nemo = BDBuscarCadena(TABLA_NEMONICOS, CAMPO_NEMONICO, instruccion.nemonico);

    if(id_nemo == -1)
    {
        /* emito un error al fichero de log */ 
        sprintf(mensaje, "[AnalizarOperandosIA16] La cadena '%s' no se ha encontrado en Tabla Nemónicos", instruccion.nemonico);
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
    }

    /* salvo la información en la estructura de la ficha de instrucción */
    strcpy(tarjetaoperandos->nemonico, instruccion.nemonico);
    strcpy(tarjetaoperandos->op1, instruccion.op1);
    strcpy(tarjetaoperandos->op2, instruccion.op2);
    for (i=0; i<instruccion.longitud; i++)
    {
        cadena[0] = '\0';   /* inicio la cadena auxiliar */
        sprintf (cadena, "%02X", (unsigned char) formato[i]);
        /* si no le digo 'unsigned char' lo toma de 4 bytes */
        strcat(tarjetaoperandos->hexadecimal, cadena);
    }
    tarjetaoperandos->longitud = instruccion.longitud;

    /* ya puedo reutilizar la estructura de desensamblado de instrucción */
    /* porque la he salvado en la tarjeta de operandos */

    switch(nemonicos[id_nemo].tipo)
    {
        case SALTO_CONDICIONAL:     /* salto condicional */
        /* hay que saber si el salto se ha tomado o no */
        /* si la siguiente instrucción en la traza coincide con la */
        /* que aparece de forma residual en la cadena formato */
        /* a partir del último byte decodificado del salto entonces */
        /* el salto no se ha tomado ya que lo residual es consecutivo */

        /* cargo la siguiente instrucción desde la secuencia */

        for(i=0; i<BYTES_POR_INSTRUCCION; i++) formato[i] = secuencia[i+BYTES_POR_INSTRUCCION];

        /* desensamblo la instrucción */
        DecodificarInstruccion086(formato, &instruccion);

        /* compruebo si las codificaciones binarias son iguales */
        for(i=tarjetaoperandos->longitud, j = 0; i<BYTES_POR_INSTRUCCION-tarjetaoperandos->longitud && j<instruccion.longitud; i++, j++)
        {
            if (secuencia[i] != secuencia[BYTES_POR_INSTRUCCION+j]) break;
        }
        /* si salgo del bucle sin break entonces son iguales y NO hay salto */
        if(i==BYTES_POR_INSTRUCCION-tarjetaoperandos->longitud || j==instruccion.longitud) tarjetaoperandos->salto = NOTOMADO;
        /* si salgo con break la siguiente instrucción en la traza no es la */
        /* siguiente en la secuencia: el salto SI se toma */
        else tarjetaoperandos->salto = TOMADO;
        break;

        
        case PREFIJO:     /* prefijo */
        case PREFIJO_SEG:     /* prefijo registro de segmento */
        tarjetaoperandos->salto = 1;    /* no es instrucción de salto */

        /* guardo el prefijo */
        strcpy(tarjetaoperandos->prefijo, instruccion.nemonico);

        /* decodifico lo que queda de instrucción */
        /* OJO, el 7º byte se ha tomado de la siguiente instrucción */
        for(i=0; i<6; i++) formato[i] = secuencia[i+1];

        /* desensamblo la instrucción */
        DecodificarInstruccion086(formato, &instruccion);


        /* salvo la información en la estructura de la ficha de instrucción */
        strcpy(tarjetaoperandos->nemonico, instruccion.nemonico);
        strcpy(tarjetaoperandos->op1, instruccion.op1);
        strcpy(tarjetaoperandos->op2, instruccion.op2);
        /* anexo el formato al prefijo -primer byte hexadecimal- */
        for (i=0; i<instruccion.longitud; i++)
        {
            cadena[0] = '\0';   /* inicio la cadena auxiliar */
            sprintf (cadena, "%02X", (unsigned char) formato[i]);
            /* si no le digo 'unsigned char' lo toma de 4 bytes */
            strcat(tarjetaoperandos->hexadecimal, cadena);
        }
        tarjetaoperandos->longitud += instruccion.longitud;

        /* extraigo el índice del registro de la base de datos */
        id_nemo = BDBuscarCadena(TABLA_NEMONICOS, CAMPO_NEMONICO, instruccion.nemonico);

        if(id_nemo == -1)
        {
            /* emito un error al fichero de log */ 
            sprintf(mensaje, "[AnalizarOperandosIA16] La cadena '%s' no se ha encontrado en Tabla Nemónicos", instruccion.nemonico);
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
        }
        break;

        case TRANSFERENCIA:     /* transferencia */
        case ARITMETICA:     /* aritmética */
        case LOGICA:     /* lógica */
        case CADENAS:     /* cadenas */
        case CONTROL:     /* control */
        case SIN_TIPO:   /* sin tipo */
        tarjetaoperandos->salto = NO_SALTO;    /* no es instrucción de salto */
        break;

        case SALTO_INCONDICIONAL:     /* salto incondicional */
        tarjetaoperandos->salto = INCONDICIONAL;    /* instrucción de salto */
        break;
    }

    /* SEGUNDO: operandos explícitos */
    /* operando fuente (op2) */
    ClasificarOperandoExplicito(tarjetaoperandos->op2, nemonicos[id_nemo].modo_op2, tarjetaoperandos);
    
    /* operando destino (op1) */
    ClasificarOperandoExplicito(tarjetaoperandos->op1, nemonicos[id_nemo].modo_op1, tarjetaoperandos);
    

    /* TERCERO: operandos implícitos */
    /* analizo la lista de implícitos leídos */
    /* copio la información de la BD para no modificarla */
    strcpy(cadena, nemonicos[id_nemo].implicitos_leidos);

    elemento = strtok(cadena, ":");   /* el separador de elementos de la lista es ':' */
    while(elemento != NULL)
    {
        ClasificarOperandoImplicitoLeido(elemento, nemonicos[id_nemo].tipo, tarjetaoperandos);
        
        /* capturo el siguiente campo */
        elemento = strtok(NULL, ":");
    }

    /* analizo la lista de implícitos escritos */
    /* copio la información de la BD para no modificarla */
    strcpy(cadena, nemonicos[id_nemo].implicitos_escritos);
    
    elemento = strtok(cadena, ":");    /* el separador de elementos de la lista es ':' */
    while(elemento != NULL)
    {
        ClasificarOperandoImplicitoEscrito(elemento, nemonicos[id_nemo].tipo, tarjetaoperandos);

        /* capturo el siguiente campo */
        elemento = strtok(NULL, ":");
    }
}



FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>