/* Supports instruction memory.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
James Bowman, Scott Dattalo
This file is part of gputils.
gputils 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, or (at your option)
any later version.
gputils 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 gputils; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "stdhdr.h"
#include "libgputils.h"
/************************************************************************
gpmemory.c
This file provides the functions used to manipulate the instruction
memory.
The instruction memory is stored in 'memory blocks' which are implemented
with the 'MemBlock' structure:
typedef struct MemBlock {
unsigned int base;
unsigned int *memory;
struct MemBlock *next;
} MemBlock;
Each MemBlock can hold up to `MAX_I_MEM' (32k currently) words. The `base'
is the base address of the memory block. If the instruction memory spans
more than 32k, then additional memory blocks can be allocated and linked
together in a singly linked list (`next'). The last memory block in a
linked list of blocks has its next ptr set to NULL. 32k was chose because
it corresponds to 64K bytes which is the upper limit on inhx8m files.
************************************************************************/
MemBlock *i_memory_create(void)
{
MemBlock *m;
m = (MemBlock *)malloc(sizeof(MemBlock));
m->base = 0;
m->memory = (unsigned int *)calloc(MAX_I_MEM, sizeof(unsigned int));
m->next = NULL;
return m;
}
void i_memory_free(MemBlock *m)
{
MemBlock *n;
do {
if(m->memory)
free(m->memory);
n = m->next;
free(m);
m = n;
} while(m);
}
/************************************************************************
* i_memory_new
*
* Create memory for a new memory block.
*
* Inputs:
* m - start of the instruction memory
* mpb - pointer to the memory block structure (MemBlock)
* base_address - where this new block of memory is based
*
************************************************************************/
MemBlock * i_memory_new(MemBlock *m, MemBlock *mbp, int base_address)
{
int base;
base = base_address >> I_MEM_BITS;
mbp->memory = (unsigned int *)calloc(MAX_I_MEM, sizeof(unsigned int));
mbp->base = base;
do {
if((m->next == NULL) || (m->next->base > base)) {
/* Insert after this block */
mbp->next = m->next;
m->next = mbp;
return mbp;
}
m = m->next;
} while(m);
assert(0);
return NULL;
}
/************************************************************************
* i_memory_get
*
* Fetch a word from the pic memory. This function will traverse through
* the linked list of memory blocks searching for the address from the
* word will be fetched. If the address is not found, then `0' will be
* returned.
*
* Inputs:
* address -
* m - start of the instruction memory
* Returns
* the word from that address
*
************************************************************************/
int i_memory_get(MemBlock *m, unsigned int address)
{
do {
assert(m->memory != NULL);
if( (address >> I_MEM_BITS) == m->base )
return m->memory[address & I_MEM_MASK];
m = m->next;
} while(m);
return 0;
}
/************************************************************************
* i_memory_put
*
* This function will write one word to a pic memory address. If the
* destination memory block is non-existant, a new one will be created.
*
* inputs:
* i_memory - start of the instruction memory
* address - destination address of the write
* value - the value to be written at that address
* returns:
* none
*
************************************************************************/
void i_memory_put(MemBlock *i_memory, unsigned int address, unsigned int value)
{
MemBlock *m = NULL;
do {
if(m)
m = m->next;
else
m = i_memory;
if(m->memory == NULL) {
i_memory_new(i_memory, m, address);
}
if( (address >> I_MEM_BITS) == m->base ) {
m->memory[address & I_MEM_MASK] = value;
return;
}
} while (m->next);
/* Couldn't find an address to write this value. This must be
the first time we've tried to write to high memory some place. */
m = i_memory_new(i_memory, (MemBlock *) malloc(sizeof(MemBlock)), address);
m->memory[address & I_MEM_MASK] = value;
}
int i_memory_used(MemBlock *m)
{
int words=0;
int i;
int maximum;
while(m) {
i = m->base << I_MEM_BITS;
maximum = i + MAX_I_MEM;
while (i < maximum) {
if ((i_memory_get(m, i) & MEM_USED_MASK)) {
words++;
}
i++;
}
m = m->next;
}
return words;
}
/************************************************************************
*
*
* These two functions are used to read and write instruction memory.
*
*
************************************************************************/
void print_i_memory(MemBlock *m, int byte_addr)
{
int base,i,j,row_used;
char c;
#define WORDS_IN_ROW 8
do {
assert(m->memory != NULL);
base = (m->base << I_MEM_BITS);
for(i = 0; i<MAX_I_MEM; i+=WORDS_IN_ROW) {
row_used = 0;
for(j = 0; j<WORDS_IN_ROW; j++)
if( m->memory[i+j] )
row_used = 1;
if(row_used) {
printf("%08X ",(base+i) << byte_addr );
for(j = 0; j<WORDS_IN_ROW; j++)
printf("%04X ", m->memory[i+j] & 0xffff );
for(j = 0; j<WORDS_IN_ROW; j++) {
c = m->memory[i+j] & 0xff;
putchar( (isprint(c)) ? c : '.');
c = (m->memory[i+j]>>8) & 0xff;
putchar( (isprint(c)) ? c : '.');
}
putchar('\n');
}
}
m = m->next;
} while(m);
}
syntax highlighted by Code2HTML, v. 0.9.1