/********************************************************************/
/* AnalizadorOperandos16bits.c */
/* */
/* Copyright (c) 1997-2006 Rafael Rico (rafael.rico@uah.es) */
/* */
/* This file is part of ADD version 5.10. */
/* */
/* ADD is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as */
/* published by the Free Software Foundation; either version 2 of */
/* the License, or (at your option) any later version. */
/* */
/* ADD is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with ADD; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
/* 02111-1307 USA */
/* */
/* --------------------------- History --------------------------- */
/* */
/* Revision 1.2. 01/2006 */
/* Added GPL License and JavaDoc style documentation */
/* */
/* Revision 1.1. 09/2005 */
/* Initial Revision */
/* */
/********************************************************************/
/******************************************************************************/
/** 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 */
/******************************************************************************/
/**@file AnalizadorOperandos16bits.c
Este módulo contiene las funciones que permiten analizar dependencias
de datos entre instrucciones
*/
/**@author Sergio Alvarez Moreno
*/
#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;
/**
@brief Esta función convierte una cadena de operandos a una cadena normalizada
de posibles ubicaciones (sin desplazamientos ni valores inmediatos)
@param *cadena: Cadena de caracteres que contienen operandos.
*/
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;
}
}
/**
@brief 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)
@param *operando: Operando el cual se va a clasificar
@param modo: Modo de funcionamiento del operando (LEIDOYESCRITO,LEIDO,NO_EXISTE)
@param *tarjetaoperandos: Puntero a una estructura del tipo fichainstruccion
*/
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;
}
}
}
/**
@brief 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)
@param *cadena: Cadena de caracteres que contiene los operandos que se van a clasificar
@param tipo: tipo de operación que se va a realizar (SALTO_CONDICIONAL,CONTROL)
@param *tarjetaoperandos: Puntero a una estructura del tipo fichainstruccion
*/
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;
}
}
/**
@brief 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)
@param *cadena: Cadena de caracteres que contiene los operandos que se van a clasificar
@param tipo: tipo de operación que se va a realizar (SALTO_CONDICIONAL,CONTROL)
@param *tarjetaoperandos: Puntero a una estructura del tipo fichainstruccion
*/
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;
}
}
/**
@brief 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
@param secuencia: Array con 2 posibles ormatos de instrucción: la que hay que desensamblar. ¡OJO! En realidad cada formato debería tener 7 bytes para prevenir el uso de prefijos
@param *tarjetaoperandos: Puntero a una estructura del tipo fichainstruccion
*/
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>