⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iexpr.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 4 页
字号:

//this needs en_cfp and en_fp_ref, en_csp, en_sp_ref 
/* 
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
 */
/*
 * iexpr.c 
 *
 * routies to take an enode list and generate icode
 */
#include <stdio.h>
#include <stdlib.h>
#include "utype.h"
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "iexpr.h"
#include "iopt.h"
#include "diag.h"

/*
 *      this module contains all of the code generation routines
 *      for evaluating expressions and conditions.
 */
extern int global_flag;
extern int retlab;
extern SYM *currentfunc;
extern long nextlabel;
extern long bittab[32];
extern IMODE rret;
extern int stdintsize, stdretblocksize;
extern SYM *declclass;

IMODE *structret_imode;

int chksize(int lsize, int rsize)
/*
 * compare two sizes, ignoring sign during comparison
 */
{
    int l, r;
    l = lsize;
    r = rsize;
    if (l < 0)
        l =  - l;
    if (r < 0)
        r =  - r;
    return (l > r);
}
//-------------------------------------------------------------------------
SYM *varsp(ENODE *node)
{
    if (!node)
        return 0;
    switch (node->nodetype)
    {
        case en_nalabcon:
        case en_nacon:
        case en_napccon:
        case en_absacon:
        case en_autocon:
        case en_autoreg:
        case en_tempref:
            return node->v.sp;
    }
    return 0;
}

//-------------------------------------------------------------------------

IMODE *make_imaddress(ENODE *node, int size)
{
    SYM *sp = node->v.sp;
    IMODE *ap2;
    if (sp && sp->imaddress)
        return sp->imaddress;
    if (sp && sp->storage_class != sc_auto && sp->storage_class != sc_autoreg)
        global_flag++;
    ap2 = xalloc(sizeof(IMODE));
    ap2->offset = copy_enode(node); /* use as constant node */
    ap2->mode = i_immed;
    ap2->size = size;
    if (sp && sp->storage_class != sc_auto && sp->storage_class != sc_autoreg)
        global_flag--;
    if (sp)
        sp->imaddress = ap2;
    return ap2;
}

//-------------------------------------------------------------------------

IMODE *make_bf(ENODE *node, IMODE *ap, int size)
/*
 *      construct a bit field reference for 68020 bit field instructions
 */
{
    if (node->startbit ==  - 1)
        DIAG("Illegal bit field");
    ap->startbit = node->startbit;
    ap->bits = node->bits;
    ap->size = size;
    return ap;
}

//-------------------------------------------------------------------------

IMODE *make_immed(long i)
/*
 *      make a node to reference an immediate value i.
 */

{
    IMODE *ap = xalloc(sizeof(IMODE));
    ap->mode = i_immed;
    ap->offset = makenode(en_icon, (char*)i, 0);
    ap->size = ISZ_NONE;
    return ap;
}

//-------------------------------------------------------------------------

IMODE *make_fimmed(long double f)
/*
 *      make a node to reference an immediate value i.
 */

{
    IMODE *ap = xalloc(sizeof(IMODE));
    ap->mode = i_immed;
    ap->offset = makenode(en_lrcon, 0, 0);
    ap->offset->v.f = f;
    ap->size = ISZ_NONE;
    return ap;
}

//-------------------------------------------------------------------------

IMODE *make_parmadj(long i)
/*
 *			make a direct immediate, e.g. for parmadj
 */
{
    ENODE *node = makenode(en_icon, (char*)i, 0);
    IMODE *ap = xalloc(sizeof(IMODE));
    ap->mode = i_immed;
    ap->offset = node;
    return ap;
}

//-------------------------------------------------------------------------


IMODE *make_offset(ENODE *node)
/*
 *      make a direct reference to a node.
 */
{
    IMODE *ap;
    SYM *sp = varsp(node);
    if (sp && sp->imvalue)
        return sp->imvalue;
    if (sp && sp->storage_class != sc_auto && sp->storage_class != sc_autoreg)
        global_flag++;
    ap = xalloc(sizeof(IMODE));
    ap->offset = copy_enode(node);
    if (sp && sp->storage_class != sc_auto && sp->storage_class != sc_autoreg)
        global_flag--;
    ap->mode = i_direct;
    ap->size = natural_size(node);
    if (sp)
        sp->imvalue = ap;
    return ap;
}

//-------------------------------------------------------------------------

IMODE *genasn(ENODE *node, int size)
/*
 * Find the targe of an assigment.  if node is 0 we need a temp reg,
 * otherwise we calculate the assignment target
 */
{
    if (!node)
        return tempreg(size, 0);
    return gen_expr(node, 0, size);
}

//-------------------------------------------------------------------------

IMODE *indnode(IMODE *ap1, int size)
/*
 * copy the address mode and change it to an indirect type
 *
 */
{
    IMODE *ap;
    SYM *sp;
    int hassp = FALSE;
    if (ap1->mode == i_ind)
    {
        IMODE *ap2 = tempreg(ISZ_ADDR, 0),*ap3;
        ap2->bits = ap1->bits;
        ap2->startbit = ap1->startbit;
        gen_icode(i_assn, ap2, ap1, 0);
        ap3 = xalloc(sizeof(IMODE));
        *ap3 = *ap2;
        ap3->mode = i_ind;
        ap3->size = size;
        return ap3;
    }
    sp = varsp(ap1->offset);
    if (sp && sp->imind)
    {
        ap = sp->imind;
        ap->offset = ap1->offset;
    }
    else
    {
        if (sp)
        {
            if (sp && sp->storage_class != sc_auto && sp->storage_class !=
                sc_autoreg)
                global_flag++;
            ap = xalloc(sizeof(IMODE));
            *ap =  *ap1;
            ap->offset = copy_enode(ap->offset);
            if (sp && sp->storage_class != sc_auto && sp->storage_class !=
                sc_autoreg)
                global_flag--;
        }
        else
        {
            ap = xalloc(sizeof(IMODE));
            *ap =  *ap1;
        }
        ap1->size = ISZ_ADDR;
        ap->mode = i_ind;
        if (sp)
            sp->imind = ap;
    }
    return ap;
}

//-------------------------------------------------------------------------

IMODE *gen_deref(ENODE *node, int flags, int size)
/*
 *      return the addressing mode of a dereferenced node.
 */
{
    IMODE *ap1,  *ap2,  *ap3,  *ap4;
    int siz1, psize;
    SYM *sp;
    int nt = node->v.p[0]->nodetype;
    psize = size;
    if (psize < 0)
        psize =  - psize;
    /* get size */
    switch (node->nodetype) /* get load size */
    {
        case en_substack:
        case en_structret:
            siz1 = ISZ_ADDR;
            break;
        case en_bool_ref:
			siz1 = ISZ_BOOL;
			break;
        case en_ub_ref:
            siz1 = ISZ_UCHAR;
            break;
        case en_b_ref:
            siz1 =  - ISZ_UCHAR;
            break;
        case en_uw_ref:
            siz1 = ISZ_USHORT;
            break;
        case en_w_ref:
            siz1 =  - ISZ_USHORT;
            break;
		case en_i_ref:
            siz1 =  - ISZ_UINT;
            break;
		case en_a_ref:
            siz1 =  ISZ_ADDR;
            break;
        case en_l_ref:
            siz1 =  - ISZ_ULONG;
            break;
        case en_ptr_ref:
            siz1 = ISZ_ADDR;
            break;
        case en_add:
        case en_addstruc:
            siz1 = ISZ_ADDR;
            break;
		case en_ui_ref:
            siz1 = ISZ_UINT;
            break;
		case en_ua_ref:
            siz1 = ISZ_ADDR;
            break;
        case en_ul_ref:
            siz1 = ISZ_ULONG;
            break;
        case en_ll_ref:
            siz1 =  - ISZ_ULONGLONG;
            break;
        case en_ull_ref:
            siz1 = ISZ_ULONGLONG;
            break;
        case en_floatref:
            siz1 = ISZ_FLOAT;
            break;
        case en_doubleref:
            siz1 = ISZ_DOUBLE;
            break;
        case en_longdoubleref:
            siz1 = ISZ_LDOUBLE;
            break;
        case en_fimaginaryref:
            siz1 = ISZ_IFLOAT;
            break;
        case en_rimaginaryref:
            siz1 = ISZ_IDOUBLE;
            break;
        case en_lrimaginaryref:
            siz1 = ISZ_ILDOUBLE;
            break;
        case en_fcomplexref:
            siz1 = ISZ_CFLOAT;
            break;
        case en_rcomplexref:
            siz1 = ISZ_CDOUBLE;
            break;
        case en_lrcomplexref:
            siz1 = ISZ_CLDOUBLE;
            break;
        default:
            siz1 = ISZ_UINT;
    }
    /* deref for add nodes */
    if (node->v.p[0]->nodetype == en_add || node->v.p[0]->nodetype == en_addstruc)
    {
        ap1 = gen_expr(node->v.p[0], 0, size);
        ap1 = indnode(ap1, siz1);
        ap1->offset->cflags = node->v.p[0]->cflags;
        return ap1;
    }
    /* deref for auto variables */
    else if (node->v.p[0]->nodetype == en_imode)
    {
        ap1 = node->v.p[0]->v.p[1];
        return ap1;
    }
    /* deref for cpu registers */
    else if (node->v.p[0]->nodetype == en_regref)
    {
        ap1 = gen_expr(node->v.p[0], 0, ISZ_REG);
        ap1->offset->cflags = node->v.p[0]->cflags;
        return ap1;
    }
    /* other deref */
    switch (nt)
    {
        case en_labcon:
            ap1 = xalloc(sizeof(IMODE));
            ap1->mode = i_direct;
            ap1->offset = node->v.p[0];
            ap1->size = siz1;
            break;
        case en_nalabcon:
        case en_nacon:
        case en_napccon:
        case en_autocon:
        case en_autoreg:
        case en_absacon:
            sp = node->v.p[0]->v.sp;
            if (sp->imvalue)
                return sp->imvalue;
            if (sp && sp->storage_class != sc_auto && sp->storage_class !=
                sc_autoreg)
                global_flag++;
            ap1 = xalloc(sizeof(IMODE));
            sp->imvalue = ap1;
            ap1->mode = i_direct;
            ap1->offset = copy_enode(node->v.p[0]);
            ap1->size = siz1;
            if (sp)
                if (sp->storage_class != sc_auto && sp->storage_class != sc_autoreg)
                    global_flag--;
            break;
        default:
            ap1 = gen_expr( node->v.p[0], 0, siz1); /* generate address */
            ap1 = indnode(ap1, siz1);
            break;
    }
    ap1->offset->cflags = node->v.p[0]->cflags;
    return ap1;
}

//-------------------------------------------------------------------------

IMODE *gen_unary(ENODE *node, int flags, int size, int op)
/*
 *      generate code to evaluate a unary minus or complement.
 */
{
    IMODE *ap,  *ap1;
    ap = gen_expr(node->v.p[0], F_VOL, size);
    gen_icode(op, ap1 = genasn(0, size), ap, 0);
    return ap1;
}

//-------------------------------------------------------------------------

IMODE *gen_binary(ENODE *node, int flags, int size, int op)
/*
 *      generate code to evaluate a binary node and return 
 *      the addressing mode of the result.
 */
{
    IMODE *ap,  *ap1,  *ap2;
    ap1 = gen_expr(node->v.p[0], F_VOL, size);
    ap2 = gen_expr(node->v.p[1], 0, size);
    if (ap1->size >= ISZ_CFLOAT || ap2->size >= ISZ_CFLOAT)
        size = max(ap1->size,ap2->size);
    else
        if (ap1->size >= ISZ_IFLOAT && ap2->size < ISZ_IFLOAT)
            if (ap2->size < ISZ_FLOAT)
                size = ap1->size;
            else
                size = max(ap1->size - ISZ_IFLOAT, ap2->size - ISZ_FLOAT) + ISZ_CFLOAT;
        else
            if (ap2->size >= ISZ_IFLOAT && ap1->size < ISZ_IFLOAT)
                if (ap1->size < ISZ_FLOAT)
                    size = ap2->size;
                else
                    size = max(ap2->size - ISZ_IFLOAT, ap1->size - ISZ_FLOAT) + ISZ_CFLOAT;
    gen_icode(op, ap = genasn(0, size), ap1, ap2);
    return ap;
}

//-------------------------------------------------------------------------

IMODE *gen_pdiv( ENODE *node, int flags, int size)
/*
 *			generate code for an array/structure size compensation
 */
{
    IMODE *ap,  *ap1,  *ap2;
    ap1 = gen_expr( node->v.p[0], F_VOL, ISZ_UINT);
    ap2 = gen_expr( node->v.p[1], 0, ISZ_USHORT);
    gen_icode(i_udiv, ap = genasn(0, size), ap2, ap1);
    return ap;
}

//-------------------------------------------------------------------------

IMODE *gen_pmul( ENODE *node, int flags, int size)
/*
 *			generate code for an array/structure size compensation
 */
{
    IMODE *ap,  *ap1,  *ap2;
    ap1 = gen_expr( node->v.p[0], F_VOL, ISZ_UINT);
    ap2 = gen_expr( node->v.p[1], 0, ISZ_UINT);
    gen_icode(i_umul, ap = genasn(0, size), ap2, ap1);
    return ap;
}

//-------------------------------------------------------------------------

IMODE *gen_hook( ENODE *node, int flags, int size)
/*
 *      generate code to evaluate a condition operator node (?:)
 */
{
    IMODE *ap1,  *ap2;
    int false_label, end_label;
    false_label = nextlabel++;
    end_label = nextlabel++;
    flags = flags | F_VOL;
    falsejp(node->v.p[0], false_label);
    node = node->v.p[1];
    ap1 = tempreg(natural_size(node), 0);
    ap2 = gen_expr( node->v.p[0], flags, size);
    gen_icode(i_assn, ap1, ap2, 0);
    ap1->offset->v.sp->iglobal = TRUE;
    gen_igoto(end_label);
    gen_label(false_label);
    ap2 = gen_expr( node->v.p[1], flags, size);
    gen_icode(i_assn, ap1, ap2, 0);
    ap1->offset->v.sp->iglobal = TRUE;
    gen_label(end_label);
    return ap1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -