📄 gexpr386.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
*/
#include <stdio.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "gen386.h"
#include "diag.h"
extern OCODE *peep_tail, *frame_ins;
extern SYM *currentfunc;
extern int retlab;
#define ABS(x) ( (x) < 0 ? -(x) : (x))
/*
* this module contains all of the code generation routines
* for evaluating expressions and conditions.
*/
extern int prm_optmult;
extern SYM *declclass;
extern int stdinttype, stdunstype, stdintsize, stdldoublesize;
extern int stdaddrsize;
extern int stackadd, stackmod;
extern int prm_largedata;
extern AMODE push[], pop[];
extern int prm_68020, prm_intrinsic;
extern int regs[3], sregs[3];
extern long nextlabel;
extern long lc_maxauto;
extern int prm_cmangle;
extern int prm_cplusplus;
extern int prm_farkeyword;
extern int floatstack_mode;
AMODE freg0[] =
{
{
am_freg, 0
}
};
AMODE sreg[] =
{
{
am_dreg, BESZ_DWORD
}
};
int genning_inline;
static int ldx[] =
{
op_mov, 0, op_lds, op_les, op_lfs, op_lgs, op_lss
};
/* little ditty to allocate stack space for floating point
* conversions and return a pointer to it
* it will be at the bottom for standard stack frames; top for
* using ESP for frames
* 0-7 used for fistp, 8-BESZ_IFLOAT used for long intermediate values
*/
AMODE *floatconvpos(void)
{
AMODE *ap1;
int constv = 16;
// if (prm_cplusplus)
// constv = 12;
if (!floatstack_mode)
{
if (!lc_maxauto)
{
OCODE *new = xalloc(sizeof(OCODE));
new->opcode = op_sub;
new->oper1 = makedreg(ESP);
new->oper2 = make_immed(constv);
new->back = frame_ins;
new->fwd = frame_ins->fwd;
frame_ins->fwd->back = new;
frame_ins->fwd = new;
}
else
{
frame_ins->oper2->offset->v.i += constv;
}
floatstack_mode += constv;
}
ap1 = xalloc(sizeof(AMODE));
ap1->mode = am_indisp;
ap1->preg = EBP;
if (prm_farkeyword)
ap1->seg = SS;
ap1->offset = makeintnode(en_icon, - lc_maxauto - constv);
ap1->length = BESZ_DWORD ;
return ap1;
}
//-------------------------------------------------------------------------
int defseg(ENODE *node)
{
int rv = 0; // default DS
if (!prm_farkeyword)
return rv;
while (castvalue(node))
node = node->v.p[0];
if (node->nodetype == en_napccon)
rv = CS;
if (node->nodetype == en_autocon)
rv = SS;
return rv;
}
//-------------------------------------------------------------------------
AMODE *truncateFloat(AMODE *ap1, int size)
{
AMODE *ap = floatconvpos();
do_extend(ap1, size, F_FREG);
gen_codefs(op_fstp, size, ap, 0);
gen_codefs(op_fld, size, ap, 0);
return ap1;
}
//-------------------------------------------------------------------------
int chksize(int lsize, int rsize)
{
int l, r;
l = lsize;
r = rsize;
if (l < 0)
l = - l;
if (r < 0)
r = - r;
if (rsize == BESZ_BOOL)
/* BESZ_BOOL is used for bools, which are the smallest type now */
if (lsize == BESZ_BOOL)
return FALSE;
else
return TRUE;
if (lsize == BESZ_BOOL)
return FALSE;
if (rsize == BESZ_FARPTR)
if (lsize == BESZ_FARPTR)
return FALSE;
else
return l >= BESZ_QWORD;
else
if (lsize == BESZ_FARPTR)
return r < BESZ_QWORD;
return (l > r);
}
//-------------------------------------------------------------------------
AMODE *fstack(void)
{
AMODE *ap = xalloc(sizeof(AMODE));
ap->mode = am_freg;
ap->length = BESZ_LDOUBLE;
ap->preg = 0;
ap->sreg = 0;
ap->offset = 0;
ap->tempflag = TRUE;
return (ap);
}
//-------------------------------------------------------------------------
AMODE *make_muldivval(AMODE *ap)
{
int temp;
AMODE *ap1 = make_label(queue_muldivval(ap->offset->v.i));
ap1->mode = am_direct;
return (ap1);
}
//-------------------------------------------------------------------------
void make_floatconst(AMODE *ap)
{
int size = ap->length;
if (isintconst(ap->offset->nodetype))
{
ap->offset->v.f = ap->offset->v.i;
ap->offset->nodetype = en_rcon;
size = BESZ_FLOAT;
}
else
{
switch (ap->offset->nodetype)
{
case en_fcon:
size = BESZ_FLOAT;
break;
case en_rcon:
size = BESZ_DOUBLE;
break;
case en_lrcon:
size = BESZ_LDOUBLE;
break;
case en_fimaginarycon:
size = BESZ_IFLOAT;
break;
case en_rimaginarycon:
size = BESZ_IDOUBLE;
break;
case en_lrimaginarycon:
size = BESZ_ILDOUBLE;
break;
case en_fcomplexcon:
size = BESZ_CFLOAT;
break;
case en_rcomplexcon:
size = BESZ_CDOUBLE;
break;
case en_lrcomplexcon:
size = BESZ_CLDOUBLE;
break;
}
}
if (ap->offset->v.f == 1.0)
{
ap->mode = am_fconst;
ap->preg = fcone;
}
else if (ap->offset->v.f == 0.0)
{
ap->mode = am_fconst;
ap->preg = fczero;
}
else if (size >= BESZ_CFLOAT)
{
AMODE *ap1;
int siz1 = size -13;
int o = prm_optmult ;
prm_optmult = FALSE;
if (siz1>BESZ_DOUBLE)
siz1++;
ap1 = make_label(queue_floatval(ap->offset->v.c.r, siz1));
queue_floatval(ap->offset->v.c.i, siz1);
ap->mode = am_direct;
ap->length = size;
ap->offset = ap1->offset;
prm_optmult = o ;
}
else
{
AMODE *ap1 = make_label(queue_floatval(ap->offset->v.f, size));
ap->mode = am_direct;
ap->length = size;
ap->offset = ap1->offset;
}
}
//-------------------------------------------------------------------------
AMODE *make_label(int lab)
/*
* construct a reference node for an internal label number.
*/
{
ENODE *lnode;
AMODE *ap;
lnode = xalloc(sizeof(ENODE));
lnode->nodetype = en_labcon;
lnode->v.i = lab;
ap = xalloc(sizeof(AMODE));
ap->mode = am_immed;
ap->offset = lnode;
return ap;
}
//-------------------------------------------------------------------------
AMODE *makesegreg(int seg)
{
AMODE *ap = xalloc(sizeof(AMODE));
ap->mode = am_seg;
ap->seg = seg;
return ap;
}
//-------------------------------------------------------------------------
AMODE *make_immed(long i)
/*
* make a node to reference an immediate value i.
*/
{
AMODE *ap;
ENODE *ep;
ep = xalloc(sizeof(ENODE));
ep->nodetype = en_icon;
ep->v.i = i;
ap = xalloc(sizeof(AMODE));
ap->mode = am_immed;
ap->offset = ep;
return ap;
}
//-------------------------------------------------------------------------
AMODE *make_immedt(long i, int size)
/*
* make a node to reference an immediate value i.
*/
{
switch (size)
{
case BESZ_BYTE:
case - 1: i &= 0xff;
break;
case BESZ_WORD:
case - BESZ_WORD: i &= 0xffff;
break;
case BESZ_DWORD :
case - BESZ_DWORD : i &= 0xffffffff;
break;
}
return make_immed(i);
}
//-------------------------------------------------------------------------
AMODE *make_offset(ENODE *node)
/*
* make a direct reference to a node.
*/
{
AMODE *ap;
ap = xalloc(sizeof(AMODE));
ap->mode = am_direct;
ap->offset = node;
ap->seg = 0;
return ap;
}
//-------------------------------------------------------------------------
AMODE *make_stack(int number)
{
AMODE *ap = xalloc(sizeof(AMODE));
ENODE *ep = xalloc(sizeof(ENODE));
ep->nodetype = en_icon;
ep->v.i = - number;
ap->mode = am_indisp;
ap->preg = ESP;
ap->offset = ep;
return (ap);
}
//-------------------------------------------------------------------------
void do_ftol(void)
{
if (prm_intrinsic)
{
AMODE *sp, vv, *e8, *e0, *ax;
gen_code(op_sub, sp = makedreg(ESP), make_immed(12));
memset(&vv, 0, sizeof(vv));
vv.mode = am_indisp;
vv.preg = ESP;
vv.offset = e8 = makeintnode(en_icon, 8);
gen_code(op_fnstcw, copy_addr(&vv), 0);
gen_codes(op_mov, BESZ_WORD, ax = makedreg(EAX), copy_addr(&vv));
gen_codes(op_or, 1, makedreg(4), make_immed(0xc));
vv.offset = makeintnode(en_icon, BESZ_LDOUBLE);
gen_codes(op_mov, BESZ_WORD, copy_addr(&vv), ax);
gen_code(op_fldcw, copy_addr(&vv), 0);
vv.offset = e0 = makeintnode(en_icon, 0);
gen_codes(op_fistp, BESZ_DOUBLE, copy_addr(&vv), 0);
vv.offset = e8;
gen_code(op_fldcw, copy_addr(&vv), 0);
vv.offset = e0;
gen_codes(op_mov, BESZ_DWORD , makedreg(EAX), copy_addr(&vv));
gen_code(op_add, sp, make_immed(12));
}
else
call_library("__ftol");
}
//-------------------------------------------------------------------------
AMODE *complexstore(ENODE *node, AMODE *apr, int novalue, int size)
{
AMODE *ap2 ;
int offs = 0, siz = BESZ_BYTE;
if (apr->mode == am_frfr)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -