📄 inasm68.c
字号:
/*
Copyright 1994-2003 Free Software Foundation, Inc.
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.
This program is derived from the cc68k complier by
Matthew Brandt (mattb@walkingdog.net)
You may contact the author of this derivative at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
*/
/*
* inline assembler (68k) not implemented
*/
#include <stdio.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "ccerr.h"
#include "gen68.h"
extern long framedepth, stackdepth, lc_maxauto;
extern int prm_68020, prm_68010, prm_smalldata;
extern int asmline;
extern int lastch;
extern int prm_linkreg;
extern enum e_sym lastst;
extern short *lptr;
extern TABLE lsyms;
extern int nextlabel;
extern char lastid[];
extern int linkreg;
ASMREG *keyimage;
ASMREG *regimage;
static SYM *lastsym;
static enum e_op op;
static int theSize;
ASMREG reglst[] =
{
{
"d0", am_dreg, 0, 1
} ,
{
"d1", am_dreg, 1, 1
}
,
{
"d2", am_dreg, 2, 1
}
,
{
"d3", am_dreg, 3, 1
}
,
{
"d4", am_dreg, 4, 1
}
,
{
"d5", am_dreg, 5, 1
}
,
{
"d6", am_dreg, 6, 1
}
,
{
"d7", am_dreg, 7, 1
}
,
{
"a0", am_areg, 0, 2
}
,
{
"a1", am_areg, 1, 2
}
,
{
"a2", am_areg, 2, 2
}
,
{
"a3", am_areg, 3, 2
}
,
{
"a4", am_areg, 4, 2
}
,
{
"a5", am_areg, 5, 2
}
,
{
"a6", am_areg, 6, 2
}
,
{
"a7", am_areg, 7, 2
}
,
{
"sp", am_areg, 7, 2
}
,
{
"fp0", am_freg, 0, 3
}
,
{
"fp1", am_freg, 1, 3
}
,
{
"fp2", am_freg, 2, 3
}
,
{
"fp3", am_freg, 3, 3
}
,
{
"fp4", am_freg, 4, 3
}
,
{
"fp5", am_freg, 5, 3
}
,
{
"fp6", am_freg, 6, 3
}
,
{
"fp7", am_freg, 7, 3
}
,
{
"fpcr", am_fpcr, 0, 5
}
,
{
"fpsr", am_fpsr, 0, 5
}
,
{
"sfc", am_sfc, 0, 4
}
,
{
"dfc", am_dfc, 0, 4
}
,
{
"usp", am_usp, 0, 4
}
,
{
"vbr", am_vbr, 0, 4
}
,
{
"cacr", am_cacr, 0, 4
}
,
{
"caar", am_caar, 0, 4
}
,
{
"msp", am_msp, 0, 4
}
,
{
"isp", am_isp, 0, 4
}
,
{
"sr", am_sr, 0, 6
}
,
{
"ccr", am_ccr, 0, 6
}
,
{
"pc", am_pc, 0, 7
}
,
{
0, 0, 0
}
,
};
static AMODE *asm_amode(void);
static void asm_err(int errnum)
{
*lptr = 0;
lastch = ' ';
generror(errnum, 0, 0);
getsym();
}
//-------------------------------------------------------------------------
int need_010(void)
{
if (!prm_68010 && !prm_68020)
{
asm_err(ERR_AINVSELPROC);
}
return prm_68020 || prm_68010;
}
//-------------------------------------------------------------------------
int need_020(void)
{
if (!prm_68020)
{
asm_err(ERR_AINVSELPROC);
}
return prm_68020;
}
//-------------------------------------------------------------------------
static ENODE *asm_ident(void)
{
ENODE *node = 0;
char *nm;
int fn = FALSE;
if (lastst != id)
asm_err(ERR_IDEXPECT);
else
{
SYM *sp;
ENODE *qnode = 0;
nm = litlate(lastid);
getsym();
/* No such identifier */
/* label, put it in the symbol table */
if ((sp = gsearch(nm)) == 0)
{
sp = makesym(sc_ulabel);
sp->name = nm;
sp->tp = xalloc(sizeof(TYP));
sp->tp->type = bt_unsigned;
sp->tp->uflags = UF_USED;
sp->tp->bits = sp->tp->startbit = - 1;
sp->value.i = nextlabel++;
insert(sp, &lsyms);
node = xalloc(sizeof(ENODE));
node->nodetype = en_labcon;
node->v.i = sp->value.i;
}
else
{
/* If we get here the symbol was already in the table
*/
foundsp: sp->tp->uflags |= UF_USED;
switch (sp->storage_class)
{
case sc_static:
case sc_global:
case sc_external:
case sc_externalfunc:
case sc_abs:
sp->mainsym->extflag = TRUE;
if (sp->value.classdata.gdeclare)
sp->value.classdata.gdeclare->mainsym->extflag =
TRUE;
if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc)
{
/* make a function node */
node = makenode(en_napccon, sp, 0);
isfunc:
}
else
/* otherwise make a node for a regular variable */
if (sp->absflag)
node = makenode(en_absacon, sp, 0);
else
if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc)
{
fn = TRUE;
node = makenode(en_napccon, sp, 0);
}
else
if (sp->staticlabel)
node = makenode(en_nalabcon, sp, 0);
else
node = makenode(en_nacon, sp, 0);
break;
case sc_const:
/* constants and enums */
node = makeintnode(en_icon, sp->value.i);
break;
case sc_label:
case sc_ulabel:
node = xalloc(sizeof(ENODE));
node->nodetype = en_labcon;
node->v.i = sp->value.i;
break;
default:
/* auto and any errors */
if (sp->storage_class != sc_auto && sp->storage_class !=
sc_autoreg)
{
gensymerror(ERR_ILLCLASS2, sp->name);
}
else
{
/* auto variables */
if (sp->storage_class == sc_auto)
node = makenode(en_autocon, sp, 0);
else if (sp->storage_class == sc_autoreg)
node = makenode(en_autoreg, sp, 0);
if (fn)
goto isfunc;
}
break;
}
(node)->cflags = 0;
}
lastsym = sp;
}
return node;
}
//-------------------------------------------------------------------------
static ENODE *asm_label(void)
{
char *nm = litlate(lastid);
ENODE *node;
SYM *sp;
getsym();
/* No such identifier */
/* label, put it in the symbol table */
if ((sp = search(lastid, &lsyms)) == 0)
{
sp = makesym(sc_label);
sp->name = litlate(lastid);
sp->tp = xalloc(sizeof(TYP));
sp->tp->type = bt_unsigned;
sp->tp->uflags = 0;
sp->tp->bits = sp->tp->startbit = - 1;
sp->value.i = nextlabel++;
insert(sp, &lsyms);
}
else
{
if (sp->storage_class == sc_label)
{
asm_err(ERR_DUPLABEL);
return 0;
}
if (sp->storage_class != sc_ulabel)
{
asm_err(ERR_ALABEXPECT);
return 0;
}
sp->storage_class = sc_label;
}
if (lastst != colon)
{
asm_err(ERR_ALABEXPECT);
return 0;
}
getsym();
node = xalloc(sizeof(ENODE));
node->nodetype = en_labcon;
node->v.i = sp->value.i;
return node;
}
//-------------------------------------------------------------------------
static int asm_getsize(void)
{
int theSize = 0;
if (lastst == dot)
{
switch (lastch)
{
case 'b':
case 'B':
theSize = 1;
break;
case 'w':
case 'W':
theSize = 2;
break;
case 'l':
case 'L':
theSize = 4;
break;
case 's':
case 'S':
theSize = 7;
break;
case 'd':
case 'D':
theSize = 8;
break;
case 'x':
case 'X':
theSize = 10;
break;
default:
asm_err(ERR_AINVSIZE);
return 0;
}
}
else
return 0;
getch();
getsym();
return theSize;
}
//-------------------------------------------------------------------------
static int needsize(int size)
{
if (theSize != size && theSize != 0)
{
asm_err(ERR_AINVSIZE);
return 0;
}
return 1;
}
//-------------------------------------------------------------------------
static int intsize(void)
{
if (theSize > 4)
{
asm_err(ERR_AINVSIZE);
return 0;
}
return 1;
}
//-------------------------------------------------------------------------
static int wordsize(void)
{
if (theSize > 4 || theSize == 1)
{
asm_err(ERR_AINVSIZE);
return 0;
}
return 1;
}
//-------------------------------------------------------------------------
static int need_freg(AMODE **v)
{
*v = asm_amode();
if (! *v || (*v)->mode != am_freg)
{
asm_err(ERR_ANEEDFP);
return 0;
}
return 1;
}
//-------------------------------------------------------------------------
static int need_adreg(AMODE **v)
{
*v = asm_amode();
if (! *v || (*v)->mode != am_areg && (*v)->mode != am_dreg)
{
asm_err(ERR_ANEEDAD);
return 0;
}
return 1;
}
//-------------------------------------------------------------------------
static int need_dreg(AMODE **v)
{
*v = asm_amode();
if (! *v || (*v)->mode != am_dreg)
{
asm_err(ERR_AILLADDRESS);
return 0;
}
return 1;
}
//-------------------------------------------------------------------------
static int need_areg(AMODE **v)
{
*v = asm_amode();
if ((*v)->mode != am_areg)
{
asm_err(ERR_AILLADDRESS);
return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -