/*
casm - Simple, portable assembler
Copyright (C) 2003-2015 Ian Cowburn (ianc@noddybox.demon.co.uk)
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see .
-------------------------------------------------------------------------
Stores assembly state.
*/
#include
#include
#include "global.h"
#include "state.h"
#include "util.h"
#include "expr.h"
/* ---------------------------------------- TYPES AND GLOBALS
*/
#define BANK_SIZE 0x10000u
static int pass = 1;
static int maxpass = 2;
static int pc = 0;
static unsigned currbank = 0;
static WordMode wmode = LSB_Word;
static MemoryBank *bank;
static MemoryBank *current;
/* ---------------------------------------- PRIVATE
*/
static void RemoveBanks(void)
{
while(bank)
{
MemoryBank *t = bank->next;
free(bank);
bank = t;
}
current = NULL;
currbank = 0;
}
static MemoryBank *FindBank(unsigned n)
{
MemoryBank *t = bank;
while(t)
{
if (t->number == n)
{
return t;
}
t = t->next;
}
return NULL;
}
static void ClearBankWriteMarkers(void)
{
MemoryBank *t = bank;
while(t)
{
t->min_address_used = BANK_SIZE;
t->max_address_used = -1;
t = t->next;
}
}
static MemoryBank *AddBank(unsigned n)
{
MemoryBank *t = Malloc(sizeof *t);
t->min_address_used = BANK_SIZE;
t->max_address_used = -1;
t->number = n;
t->next = bank;
bank = t;
return t;
}
static MemoryBank *GetOrAddBank(unsigned n)
{
MemoryBank *b = FindBank(n);
if (!b)
{
b = AddBank(n);
}
return b;
}
/* ---------------------------------------- INTERFACES
*/
void ClearState(void)
{
pass = 1;
pc = 0;
wmode = LSB_Word;
RemoveBanks();
SetAddressBank(0);
}
void NextPass(void)
{
if (pass < maxpass)
{
ClearBankWriteMarkers();
pass++;
}
}
int IsFinalPass(void)
{
return pass == maxpass;
}
int IsFirstPass(void)
{
return pass == 1;
}
int IsIntermediatePass(void)
{
return pass > 1 && pass < maxpass;
}
void SetNeededPasses(int n)
{
if (!IsFinalPass())
{
maxpass = n;
}
}
void SetAddressBank(unsigned b)
{
currbank = b;
}
void SetWordMode(WordMode mode)
{
wmode = mode;
}
void SetPC(int i)
{
pc = i;
}
int PC(void)
{
return pc;
}
void PCAdd(int i)
{
pc += i;
while(pc < 0)
{
pc += BANK_SIZE;
}
pc %= BANK_SIZE;
}
void PCWrite(int i)
{
if (!current)
{
current = GetOrAddBank(currbank);
}
if (pc < current->min_address_used)
{
current->min_address_used = pc;
}
if (pc > current->max_address_used)
{
current->max_address_used = pc;
}
current->memory[pc] = ExprConvert(8, i);
pc = (pc + 1) % BANK_SIZE;
}
void PCWriteWord(int i)
{
PCWriteWordMode(i, wmode);
}
void PCWriteWordMode(int i, WordMode mode)
{
int w;
int lsb;
int msb;
w = ExprConvert(16, i);
lsb = LOBYTE(w);
msb = HIBYTE(w);
switch(mode)
{
case MSB_Word:
PCWrite(msb);
PCWrite(lsb);
break;
case LSB_Word:
PCWrite(lsb);
PCWrite(msb);
break;
}
}
const MemoryBank *MemoryBanks(void)
{
return bank;
}
Byte ReadByte(int addr)
{
Byte b = 0;
if (addr > -1 && addr < BANK_SIZE && current)
{
b = current->memory[addr];
}
return b;
}
/*
vim: ai sw=4 ts=8 expandtab
*/