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