📄 isp8asm.c
字号:
/*
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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
//
// ====================================================================
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97124
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 408-826-6000 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// ====================================================================
// File Details
// ====================================================================
// Project : ISP 8 bit Microcontroller
// File : isp8asm.c
// Title : Assembler for Lattice 8 bit microcontroller
//
// Description : This program is the assembler for Lattice 8 bit
// Microcontroller. Input is an assembler file output
// EBR initialization file.
//
// Additional info. :
//
// ====================================================================
// Revision History
// ====================================================================
// Ver | Author(s) | Mod. Date| Changes Made
// --------------------------------------------------------------------
// 1.0 | Sandeep Dutta | 04/27/05 | Initial Creation
// $Revision: 1.2 $
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
/* ==================================================== */
/* defines */
/* ==================================================== */
#define COMMENT_CHAR '#'
#define MAX_LINE_SIZE 1024
#define MAX_TOKEN_SIZE 100
#define MAX_REG 32
#define GETC() (*lbp ? *lbp++ : *lbp)
#define UNGETC() lbp--
#define ABS(x) (x < 0 ? -x : x)
/* ==================================================== */
/* types & data structures */
/* ==================================================== */
typedef unsigned int uint32;
enum otype {
OHEX = 0,
OBIN,
OVER,
OVHD
};
enum optype {
OP_NONE, OP_REGD,
OP_REGB, OP_LABEL,
OP_CONST, OP_PORT
};
enum codeflags {
CODE_ISDATA = 1,
CODE_ISLDEF = CODE_ISDATA*2
};
typedef struct instr_tab {
char *opname;
int opcode;
int nops;
int optypes[2];
} itab ;
typedef enum dirs {
D_ORG, D_INCLUDE, D_EQU
} dirs;
typedef struct code {
itab *itabp;
uint32 opcode;
uint32 rd, rb, konst;
uint32 flags;
struct stab *label_ref;
struct stab *label_def;
struct code *next;
int loc_counter;
int line_no;
uint32 port;
} code;
typedef enum sym_types {
SYM_LABEL = 1,
SYM_EQU = SYM_LABEL*2
} stypes;
typedef struct stab {
char *name;
stypes stype;
int value;
int loc_counter;
code *codep;
struct stab *next;
} stab;
typedef struct directs {
char *dname;
void (*dparse_func)();
} directs;
/* ==================================================== */
/* function forward declarations */
/* ==================================================== */
static uint32 parse_const();
static void dparse_equ();
static void dparse_org();
static void dparse_data();
/* ==================================================== */
/* global variables */
/* ==================================================== */
static code *croot = NULL;
static code *ccurr = NULL;
static stab *sroot = NULL;
static uint32 loc_counter = 0;
static FILE *infile = NULL;
static FILE *ofile = NULL;
static FILE *lfile = NULL;
static FILE *eifile = NULL;
static FILE *eofile = NULL;
static char *ifilename = NULL;
static char *ofilename = NULL;
static char *lfilename = NULL;
static int line_no = 0;
static char line_buffer[MAX_LINE_SIZE];
static char *lbp;
static char token[MAX_TOKEN_SIZE];
static int omode = 0 ;
static int lgen = 0 ;
static int prom_size = 512;
static int *vmstack;
static int vmsp = 0;
static directs dirtab_array[] = {
{"org", dparse_org},
{"equ", dparse_equ},
{"data",dparse_data}
};
#define DIRTAB_SIZE sizeof(dirtab_array)/sizeof(directs)
static itab itab_array [] = {
{"sub", ((0x0 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"subi", ((0x0 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"subc", ((0x1 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"subic", ((0x1 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"add", ((0x2 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"addi", ((0x2 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"addc", ((0x3 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"addic", ((0x3 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"mov", ((0x4 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"movi", ((0x4 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"and", ((0x5 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"andi", ((0x5 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"or", ((0x6 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"ori", ((0x6 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"xor", ((0x7 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"xori", ((0x7 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"cmp", ((0x8 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"cmpi", ((0x8 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"test", ((0x9 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"testi", ((0x9 << 14)|(0 << 10)|0), 2, {OP_REGD, OP_CONST}},
{"ror", ((0xa << 14)|(0 << 10)|0), 2, {OP_REGD, OP_REGB}},
{"rorc", ((0xa << 14)|(0 << 10)|2), 2, {OP_REGD, OP_REGB}},
{"rol", ((0xa << 14)|(0 << 10)|1), 2, {OP_REGD, OP_REGB}},
{"rolc", ((0xa << 14)|(0 << 10)|3), 2, {OP_REGD, OP_REGB}},
{"clrc", ((0xb << 14)|(0 << 10)|0), 0, {OP_NONE, OP_NONE}},
{"setc", ((0xb << 14)|(0 << 10)|1), 0, {OP_NONE, OP_NONE}},
{"clrz", ((0xb << 14)|(0 << 10)|2), 0, {OP_NONE, OP_NONE}},
{"setz", ((0xb << 14)|(0 << 10)|3), 0, {OP_NONE, OP_NONE}},
{"clri", ((0xb << 14)|(0 << 10)|4), 0, {OP_NONE, OP_NONE}},
{"seti", ((0xb << 14)|(0 << 10)|5), 0, {OP_NONE, OP_NONE}},
{"bz", ((0xc << 14)|(0 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"bnz", ((0xc << 14)|(1 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"bc", ((0xc << 14)|(2 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"bnc", ((0xc << 14)|(3 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"b", ((0xc << 14)|(4 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"callz", ((0xd << 14)|(0 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"callnz", ((0xd << 14)|(1 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"callc", ((0xd << 14)|(2 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"callnc", ((0xd << 14)|(3 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"call", ((0xd << 14)|(4 << 10)|0), 1, {OP_LABEL,OP_NONE}},
{"ret", ((0xe << 14)|(0 << 10)|0), 0, {OP_NONE, OP_NONE}},
{"iret", ((0xe << 14)|(4 << 10)|0), 0, {OP_NONE, OP_NONE}},
{"importi", ((0xf << 14)|(0 << 10)|3), 2, {OP_REGD, OP_REGB}},
{"inpi", ((0xf << 14)|(0 << 10)|3), 2, {OP_REGD, OP_REGB}},
{"exporti", ((0xf << 14)|(0 << 10)|2), 2, {OP_REGD, OP_REGB}},
{"outpi", ((0xf << 14)|(0 << 10)|2), 2, {OP_REGD, OP_REGB}},
{"import", ((0xf << 14)|(0 << 10)|1), 2, {OP_REGD, OP_PORT}},
{"inp", ((0xf << 14)|(0 << 10)|1), 2, {OP_REGD, OP_PORT}},
{"export", ((0xf << 14)|(0 << 10)|0), 2, {OP_REGD, OP_PORT}},
{"outp", ((0xf << 14)|(0 << 10)|0), 2, {OP_REGD, OP_PORT}},
{"lspi", ((0xf << 14)|(0 << 10)|7), 2, {OP_REGD, OP_REGB}},
{"sspi", ((0xf << 14)|(0 << 10)|6), 2, {OP_REGD, OP_REGB}},
{"lsp", ((0xf << 14)|(0 << 10)|5), 2, {OP_REGD, OP_PORT}},
{"ssp", ((0xf << 14)|(0 << 10)|4), 2, {OP_REGD, OP_PORT}},
{"nop", ((0x4 << 14)|(0 << 10)|0), 0, {OP_NONE, OP_NONE}}
};
#define ITAB_SIZE sizeof(itab_array)/sizeof(itab)
#if !defined(stricmp)
/* case independent string compare */
int stricmp(const char *s1, const char *s2)
{
while (*s1 && *s2) {
if (toupper(*s1) != toupper(*s2)) break;
s1++; s2++;
}
return *s1 - *s2;
}
#endif
/* find a symbol a given type & name */
static stab *sym_find(char *name, stypes stype)
{
stab *curr = sroot;
while (curr) {
if (!strcmp(curr->name,name) &&
curr->stype == stype) {
return curr;
}
curr = curr->next;
}
return NULL;
}
/* add a symbol into the table */
static stab *sym_insert(char *name, int loc, stypes stype)
{
stab *snew = (stab *) malloc(sizeof(stab));
snew->name = (char *) strdup(name);
snew->loc_counter = loc;
snew->codep = NULL;
snew->stype = stype;
snew->next = NULL;
if (!sroot) {
sroot = snew;
} else {
snew->next = sroot;
sroot = snew;
}
return snew;
}
static code *code_insert(itab *itabp, uint32 opcode,
uint32 rd, uint32 rb,
uint32 konst,stab *label_r,
stab *label_d, int port, uint32 flags)
{
code *cnew = (code *) malloc(sizeof(code));
cnew->itabp = itabp;
cnew->opcode = opcode;
cnew->rd = rd;
cnew->rb = rb;
cnew->konst = konst;
cnew->label_ref = label_r;
cnew->label_def = label_d;
cnew->loc_counter= (flags & CODE_ISLDEF ? loc_counter : loc_counter++);
cnew->port = port;
cnew->line_no = line_no;
cnew->next = NULL;
cnew->flags = flags;
if (croot == NULL) {
croot = cnew;
ccurr = croot;
} else {
ccurr->next = cnew;
ccurr = cnew;
}
return cnew;
}
static itab *itab_find(char *iname)
{
int i = 0 ;
for (i = 0 ; i < ITAB_SIZE ; i++ ) {
if (!stricmp(iname,itab_array[i].opname))
return &itab_array[i];
}
return NULL;
}
void error_exit(char *err_txt,...)
{
va_list ap;
va_start(ap,err_txt);
fprintf(stderr,"%s (%d) ",ifilename,line_no);
vfprintf(stderr,err_txt,ap);
fprintf(stderr,"\n\n");
va_end(ap);
exit(0);
}
static int get_token(char *buff, char *delims)
{
char nc = GETC();
do {
*buff++ = nc;
nc = GETC();
} while (!isspace(nc) && !strchr(delims,nc) && nc);
*buff = '\0';
return nc;
}
static int skip_space()
{
char nc ;
do {
nc = GETC();
} while (isspace(nc) && nc && nc != '\n');
UNGETC();
return nc;
}
static char *get_line()
{
if (feof(infile)) return NULL;
lbp = line_buffer;
line_no++;
return fgets(line_buffer,MAX_LINE_SIZE,infile);
}
/* parse .data directive format is
.data <constant> */
static void dparse_data()
{
char nc = skip_space();
uint32 val;
code *codep;
val = parse_const();
if (val & ~0x3FFFF) {
error_exit(".data value cannot exceed 0x3ffff, value is 0x%X",val);
}
codep = code_insert( NULL, val, 0, 0, 0, NULL, NULL, 0, CODE_ISDATA);
}
/* parse .equ directive. the format is
.equ <name>,<value> */
static void dparse_equ()
{
char nc = skip_space();
int value ;
stab *sym;
nc = get_token(token,",");
UNGETC();
nc = skip_space();
if (nc != ',') {
error_exit("invalid syntax for equate. expecting ','");
}
GETC(); /* skip the , */
skip_space();
value = parse_const();
if ((sym = sym_find(token,SYM_EQU))) {
error_exit("redifinition of .equ symbol %s",token);
}
sym = sym_insert(token,-1,SYM_EQU);
sym->value = value;
}
/* parse .org directive : followed by a number */
static void dparse_org()
{
char nc = skip_space();
uint32 new_loc = parse_const();
if (new_loc < loc_counter) {
error_exit(".org overlays previous code; curr pc %d , new pc %d",
loc_counter, new_loc);
}
loc_counter = new_loc;
}
/* parse assembler directives */
static void parse_direct()
{
int i;
get_token(token,"\n,");
for (i = 0; i < DIRTAB_SIZE; i++) {
if (!stricmp(dirtab_array[i].dname,token)) {
(*dirtab_array[i].dparse_func)();
return ;
}
}
error_exit("unrecognized directive %s",token);
}
/* parse label definition */
static stab *parse_label_def(char *label)
{
stab *stabp;
if (!(stabp = sym_find(label,SYM_LABEL))) {
stabp = sym_insert(label, loc_counter, SYM_LABEL);
} else if (stabp->loc_counter != -1) {
error_exit("multiple definition of label %s",label);
}
stabp->loc_counter = loc_counter;
code_insert( NULL, 0, 0, 0, 0, NULL, stabp, 0, CODE_ISLDEF);
return stabp;
}
/* parse label reference */
static stab *parse_label_ref()
{
char nc = skip_space();
stab *stabp;
get_token(token,"\n");
/* if !already exists then insert it*/
if (!(stabp = sym_find(token, SYM_LABEL))) {
stabp = sym_insert(token, -1, SYM_LABEL);
}
return stabp;
}
/* parse a number */
static uint32 parse_num()
{
char nc = GETC();
int sign = 0;
int base = 10;
int rval = 0;
if (nc == '+') nc = GETC();
if (nc == '-') {
sign = 1;
nc = GETC();
}
if (nc == '0') {
/* octal */
base = 8;
nc = GETC();
if (toupper(nc) == 'X') {
/* nope .. hex */
base = 16;
nc = GETC();
}
}
while (isdigit(nc) || isxdigit(toupper(nc))) {
rval *= base;
switch (base) {
case 8:
case 10:
rval += (nc - '0');
break;
case 16:
if (toupper(nc) >= 'A') {
rval += (10 + (toupper(nc) - 'A'));
} else {
rval += nc - '0';
}
break;
}
nc = GETC();
} while (isdigit(nc) || isxdigit(nc));
if (nc != -1) {
UNGETC();
}
if (sign) rval = -rval;
return rval;
}
/* parse a character constant of the form '<char>' */
static uint32 parse_char()
{
char nc = GETC();
assert(nc == '\'');
nc = GETC();
/* escape character */
if (nc == '\\') {
nc = GETC();
switch (nc) {
case 'n':
nc = '\n';
break;
case 'r':
nc = '\r';
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -