📄 inasm386.c
字号:
/*
* 68K/386 32-bit C compiler.
*
* copyright (c) 1997, David Lindauer
*
* This compiler is intended for educational use. It may not be used
* for profit without the express written consent of the author.
*
* It may be freely redistributed, as long as this notice remains intact
* and either the original sources or derived sources
* are distributed along with any executables derived from the originals.
*
* The author is not responsible for any damages that may arise from use
* of this software, either idirect or consequential.
*
* v1.35 March 1997
* David Lindauer, gclind01@starbase.spd.louisville.edu
*
* Credits to Mathew Brandt for original K&R C compiler
*
*/
/*
* inline assembler (386)
*/
#include <stdio.h>
#include "expr.h"
#include "c.h"
#include "errors.h"
#include "gen386.h"
extern long framedepth, stackdepth, lc_maxauto;
extern int asmline;
extern int lastch;
extern int prm_linkreg;
extern enum e_sym lastst;
extern long ival;
extern short *lptr ;
extern TABLE lsyms;
extern int nextlabel;
extern char lastid[];
ASMNAME *keyimage;
ASMREG *regimage;
static SYM *lastsym;
static enum e_op op;
ASMREG reglst[] = {
{ "cs",am_seg,1,2 },
{ "ds",am_seg,2,2 },
{ "es",am_seg,3,2 },
{ "fs",am_seg,4,2 },
{ "gs",am_seg,5,2 },
{ "ss",am_seg,6,2 },
{ "al",am_dreg,0,1 },
{ "cl",am_dreg,1,1 },
{ "dl",am_dreg,2,1 },
{ "bl",am_dreg,3,1 },
{ "ah",am_dreg,4,1 },
{ "ch",am_dreg,5,1 },
{ "dh",am_dreg,6,1 },
{ "bh",am_dreg,7,1 },
{ "ax",am_dreg,0,2 },
{ "cx",am_dreg,1,2 },
{ "dx",am_dreg,2,2 },
{ "bx",am_dreg,3,2 },
{ "sp",am_dreg,4,2 },
{ "bp",am_dreg,5,2 },
{ "si",am_dreg,6,2 },
{ "di",am_dreg,7,2 },
{ "eax",am_dreg,0,4 },
{ "ecx",am_dreg,1,4 },
{ "edx",am_dreg,2,4 },
{ "ebx",am_dreg,3,4 },
{ "esp",am_dreg,4,4 },
{ "ebp",am_dreg,5,4 },
{ "esi",am_dreg,6,4 },
{ "edi",am_dreg,7,4 },
{ "st",am_freg,0,10 },
{ "cr0",am_screg,0,4 },
{ "cr1",am_screg,2,4 },
{ "cr2",am_screg,3,4 },
{ "cr3",am_screg,4,4 },
{ "cr4",am_screg,5,4 },
{ "cr5",am_screg,6,4 },
{ "cr6",am_screg,7,4 },
{ "cr7",am_screg,8,4 },
{ "dr0",am_sdreg,0,4 },
{ "dr1",am_sdreg,2,4 },
{ "dr2",am_sdreg,3,4 },
{ "dr3",am_sdreg,4,4 },
{ "dr4",am_sdreg,5,4 },
{ "dr5",am_sdreg,6,4 },
{ "dr6",am_sdreg,7,4 },
{ "dr7",am_sdreg,8,4 },
{ "tr0",am_streg,0,4 },
{ "tr1",am_streg,2,4 },
{ "tr2",am_streg,3,4 },
{ "tr3",am_streg,4,4 },
{ "tr4",am_streg,5,4 },
{ "tr5",am_streg,6,4 },
{ "tr6",am_streg,7,4 },
{ "tr7",am_streg,8,4 },
{ "st",am_freg,0,4 },
{ "byte", am_ext,akw_byte,0 },
{ "word", am_ext,akw_word,0 },
{ "dword", am_ext,akw_dword,0 },
{ "fword", am_ext,akw_fword,0 },
{ "qword", am_ext,akw_qword,0 },
{ "tbyte", am_ext,akw_tbyte,0 },
{ "ptr", am_ext, akw_ptr,0 },
{ "offset", am_ext,akw_offset,0 },
{ 0 , 0 , 0 },
};
static int floating;
void inasmini(void)
{
}
static void asm_err(int errnum)
{
*lptr = 0;
lastch = ' ';
generror(errnum,0,0);
getsym();
}
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 = xalloc(sizeof(SYM));
sp->name = nm;
sp->storage_class = sc_ulabel;
sp->tp = xalloc(sizeof(TYP));
sp->tp->type = bt_unsigned;
sp->tp->uflags = UF_USED;
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->extflag = TRUE;
if (sp->tp->type == bt_ptrfunc || sp->tp->type == bt_func || sp->tp->type == bt_ifunc) {
/* make a function node */
if (sp->tp->type == bt_ptrfunc)
node = makenode(en_nacon,sp,0);
else
node = makenode(en_napccon,sp,0);
isfunc:
if (sp->tp->type != bt_ptrfunc && sp->tp->type != bt_func && sp->tp->type != bt_ifunc)
generror(ERR_MISMATCH,0,0);
}
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,(char *)sp->value.i,0);
else
node = makenode(en_nacon,sp,0);
break;
case sc_const:
/* constants and enums */
node = makenode(en_icon,(char *)sp->value.i,0);
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 = xalloc(sizeof(SYM));
sp->name = litlate(lastid);
sp->storage_class = sc_label;
sp->tp = xalloc(sizeof(TYP));
sp->tp->type = bt_unsigned;
sp->tp->uflags = 0;
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 sz=0;
switch (regimage->regnum) {
case akw_byte: sz = 1; break;
case akw_word: sz = 2; break;
case akw_dword: sz = floating ? 6 : 4; break;
case akw_fword: sz = 6; break;
case akw_qword: sz = 8; break;
case akw_tbyte: sz = 10; break;
case akw_offset: sz = 4; break;
};
getsym();
if (lastst == kw_asmreg) {
regimage = keyimage;
if (regimage->regtype == am_ext) {
if (regimage->regnum != akw_ptr) {
asm_err(ERR_AILLADDRESS);
return 0;
}
getsym();
}
}
if (lastst != kw_asmreg && lastst != openbr && lastst != id) {
asm_err(ERR_AMODEEXPECT);
return 0;
}
regimage=keyimage;
return sz;
}
static int getscale (int *scale)
{
if (lastst == star) {
getsym();
if (lastst == iconst && !*scale)
if (ival== 1 || ival==2 || ival==4 || ival==8) {
if (ival < 3)
ival--;
else
ival = ival/4+1;
*scale =ival;
getsym();
return 1;
}
asm_err(ERR_ASCALE);
*scale = -1;
return 1;
}
return 0;
}
int asm_enterauto(ENODE *node, int *reg1, int *reg2)
{
if (node && (node->nodetype == en_autocon || node->nodetype == en_autoreg)) {
int *vreg;
if (*reg1 >=0 && *reg2 >=0) {
asm_err(ERR_AINVINDXMODE);
return 0;
}
if (reg1 < 0)
vreg = reg1;
else
vreg = reg2 ;
*vreg = ESP;
if (prm_linkreg) {
*vreg = EBP;
}
return 1;
}
return 2;
}
static AMODE *asm_mem(void)
{
int reg1=-1, reg2=-1, scale=0, temp,sz=0;
ENODE *node=0;
AMODE *rv;
int gotident = FALSE,autonode = FALSE;
while (TRUE) {
int rg;
getsym();
regimage = keyimage;
rg = regimage->regnum;
switch(lastst) {
case kw_asmreg:
regimage = keyimage;
if (regimage->regtype != am_dreg || regimage->size != 4) {
asm_err(ERR_AINVINDXMODE);
return 0;
}
if (reg1 >= 0) {
if (reg2 >=0) {
asm_err(ERR_AINVINDXMODE);
return 0;
}
reg2 = rg;
getsym();
getscale(&scale);
if (scale == -1)
return 0;
}
else {
getsym();
if (getscale(&scale)) {
if (scale == -1)
return 0;
if (reg2 >= 0) {
reg1 = reg2;
}
reg2 = rg;
}
else {
reg1 = rg;
}
}
break;
case iconst:
if (node)
node = makenode(en_add,node,makenode(en_icon,(char *)intexpr(0),0));
else
node = makenode(en_icon,(char *)intexpr(0),0);
break;
case id:
if (gotident) {
asm_err(ERR_AINVINDXMODE);
return 0;
}
node = asm_ident();
gotident = TRUE;
sz = lastsym->tp->size;
switch(asm_enterauto(node,®1,®2)) {
case 0:
return 0;
case 1:
autonode = TRUE;
break;
case 2:
autonode = FALSE;
break;
}
break;
default:
asm_err(ERR_AILLADDRESS);
return 0;
}
if (lastst == closebr) {
getsym();
break;
}
if (lastst != plus) {
asm_err(ERR_AINVINDXMODE);
return 0;
}
}
if ((reg2 == 4 || reg2 == 5) && scale > 1) {
asm_err(ERR_AINVINDXMODE);
return 0;
}
rv = xalloc(sizeof(AMODE));
if (node) {
rv->offset = node;
}
if (reg1 >=0) {
rv->preg = reg1;
if (reg2 >=0) {
rv->sreg = reg2;
rv->scale = scale;
rv->mode = am_indispscale;
}
else {
rv->mode = am_indisp;
}
}
else
if (reg2 >=0) {
rv->preg = -1;
rv->sreg = reg2;
rv->scale = scale;
rv->mode = am_indispscale;
}
else
rv->mode = am_direct;
return rv;
}
static AMODE *asm_amode(int nosegreg)
{
AMODE *rv=xalloc(sizeof(AMODE));
int sz = 0,seg=0;
lastsym = 0;
switch (lastst) {
case iconst:
case iuconst:
case lconst:
case luconst:
case cconst:
case kw_asmreg:
case openbr:
case id:
break;
default:
asm_err(ERR_AMODEEXPECT);
return 0;
}
if (lastst== kw_asmreg) {
regimage = keyimage;
if (regimage->regtype == am_ext) {
sz = asm_getsize();
regimage = keyimage;
}
}
loop:
switch (lastst) {
case kw_asmreg:
if (regimage->regtype == am_ext) {
asm_err(ERR_ATOOMANYSPECS);
return 0;
}
if (regimage->regtype == am_freg) {
getsym();
if (lastst == openpa) {
getsym();
if (lastst != iconst || ival < 0 || ival > 7) {
asm_err(ERR_ANEEDFP);
return 0;
}
getsym();
needpunc(closepa,0);
}
else ival = 0;
rv->preg = ival;
rv->mode = am_freg;
sz = 10;
}
else if (regimage->regtype == am_seg) {
if (rv->seg) {
asm_err(ERR_ATOOMANYSEGS);
return 0;
}
rv->seg = seg = regimage->regnum;
getsym();
if (lastst == colon) {
getsym();
goto loop;
}
rv->mode = am_seg;
sz = regimage->size;
}
else {
rv->preg = regimage->regnum;
rv->mode = regimage->regtype;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -