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

📄 gstmt68.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 
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 <limits.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "gen68.h"
#include "diag.h"

extern int conscount;
extern int virtualfuncs;
extern SNODE *funcstmt,  *funcendstmt;
extern SYM *thissp;
extern long lc_maxauto;
extern int linkreg;
extern long framedepth;
extern TYP stdfunc;
extern struct amode push[], pop[], mvma7[], mvma7i[];
extern OCODE *peep_tail,  *peep_head,  *peep_insert;
extern long stackdepth;
extern SYM *currentfunc;
extern int prm_cplusplus, prm_linkreg, prm_phiform, prm_68020, prm_68010;
extern int prm_pcrel, prm_datarel, prm_smallcode, prm_profiler, prm_coldfire;
extern long firstlabel, nextlabel;
extern int global_flag;
extern int save_mask, fsave_mask;
extern TABLE *gsyms;
extern ENODE *thisenode;
extern ENODE *block_rundown;
extern char dregs[], aregs[], fregs[];
extern int funcfloat; /* unused, placeholder */
extern int rmaskcnt;
extern int prm_smartframes;
extern int xceptoffs;
extern int prm_xcept;
extern TRYBLOCK *try_block_list;
extern int prm_cplusplus, prm_xcept;
extern int genning_inline;

LIST *mpthunklist;

static int returndreg;
static int diddef;
static int breaklab;
static int contlab;
int retlab;
static long plabel;
static long retsize;

struct cases {
    LLONG_TYPE bottom;
    LLONG_TYPE top;
    int count;
    int deflab;
    int tablepos;
    int diddef : 1;
    struct caseptrs {
        int label;
        int binlabel;
        LLONG_TYPE id;
    } *ptrs;
} ;

void genstmtini(void){}
AMODE *makedreg(int r)
/*
 *      make an address reference to a data register.
 */
{
    AMODE *ap;
    ap = xalloc(sizeof(AMODE));
    ap->mode = am_dreg;
    ap->preg = r;
    return ap;
} 

AMODE *makeareg(int r)
/*
 *      make an address reference to an address register.
 */
{
    AMODE *ap;
    ap = xalloc(sizeof(AMODE));
    ap->mode = am_areg;
    ap->preg = r;
    return ap;
}

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

AMODE *makefreg(int r)
/*
 *      make an address reference to a data register.
 */
{
    AMODE *ap;
    ap = xalloc(sizeof(AMODE));
    ap->mode = am_freg;
    ap->preg = r;
    return ap;
}

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

AMODE *make_mask(int mask, int floatflag)
/*
 *      generate the mask address structure.
 */
{
    AMODE *ap;
    ap = xalloc(sizeof(AMODE));
    if (floatflag)
        ap->mode = am_fmask;
    else
        ap->mode = am_mask;
    ap->offset = (ENODE*)mask;
    return ap;
}

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

AMODE *make_direct(int i)
/*
 *      make a direct reference to an immediate value.
 */
{
    return make_offset(makeintnode(en_icon, i));
}

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

AMODE *make_strlab(char *s)
/*
 *      generate a direct reference to a string label.
 */
{
    AMODE *ap;
    ap = xalloc(sizeof(AMODE));
    ap->mode = am_direct;
    ap->offset = makenode(en_nacon, s, 0);
    return ap;
}

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

void genwhile(SNODE *stmt)
/*
 *      generate code to evaluate a while statement.
 */
{
    int lab1, lab2, lab3;
    initstack(); /* initialize temp registers */
    lab1 = contlab; /* save old continue label */
    contlab = nextlabel++; /* new continue label */
    if (stmt->s1 != 0)
     /* has block */
    {
        lab2 = breaklab; /* save old break label */
        breaklab = nextlabel++;
        gen_codes(op_bra, 0, make_label(contlab), 0);
        lab3 = nextlabel++;
        gen_label(lab3);
        genstmt(stmt->s1);
        gen_label(contlab);
        initstack();
        if (stmt->lst)
            gen_line(stmt->lst);
        truejp(stmt->exp, lab3);
        gen_label(breaklab);
        breaklab = lab2; /* restore old break label */
    }
    else
     /* no loop code */
    {
        if (stmt->lst)
            gen_line(stmt->lst);
        gen_label(contlab);
        initstack();
        truejp(stmt->exp, contlab);
    }
    contlab = lab1; /* restore old continue label */
}

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

void gen_for(SNODE *stmt)
/*
 *      generate code to evaluate a for loop
 */
{
    int old_break, old_cont, exit_label, loop_label, start_label;
    old_break = breaklab;
    old_cont = contlab;
    loop_label = nextlabel++;
    contlab = nextlabel++;
    start_label = nextlabel++;
    exit_label = nextlabel++;
    initstack();
    if (stmt->label != 0)
        gen_void(stmt->label);

    gen_codes(op_bra, 0, make_label(start_label), 0);
    gen_label(loop_label);
    if (stmt->s1 != 0)
    {
        breaklab = exit_label;
        genstmt(stmt->s1);
    }
    if (stmt->lst)
        gen_line(stmt->lst);
    gen_label(contlab);
    initstack();
    if (stmt->s2 != 0)
        gen_void(stmt->s2);
    gen_label(start_label);
    initstack();
    if (stmt->exp != 0)
        truejp(stmt->exp, loop_label);
    else
        gen_codes(op_bra, 0, make_label(loop_label), 0);
    gen_label(exit_label);
    breaklab = old_break;
    contlab = old_cont;
}

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

void genif(SNODE *stmt)
/*
 *      generate code to evaluate an if statement.
 */
{
    int lab1, lab2;
    lab1 = nextlabel++; /* else label */
    lab2 = nextlabel++; /* exit label */
    initstack(); /* clear temps */
    falsejp(stmt->exp, lab1);
    genstmt(stmt->s1);
    if (stmt->s2 != 0)
     /* else part exists */
    {
        gen_codes(op_bra, 0, make_label(lab2), 0);
        gen_label(lab1);
        genstmt(stmt->s2);
        gen_label(lab2);
    }
    else
     /* no else code */
        gen_label(lab1);
}

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

void gendo(SNODE *stmt)
/*
 *      generate code for a do - while loop.
 */
{
    int oldcont, oldbreak, looplab;
    oldcont = contlab;
    oldbreak = breaklab;
    looplab = nextlabel++;
    contlab = nextlabel++;
    breaklab = nextlabel++;
    gen_label(looplab);
    genstmt(stmt->s1); /* generate body */
    gen_label(contlab);
    initstack();
    truejp(stmt->exp, looplab);
    gen_label(breaklab);
    breaklab = oldbreak;
    contlab = oldcont;
}

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

void gen_genword(SNODE *stmt)
/*
 * Generate data in the code stream
 */
{
    gen_codes(op_genword, 2, make_immed((int)stmt->exp), 0);
}

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

AMODE *set_symbol(char *name, int isproc)
/*
 *      generate a call to a library routine.
 */
{
    SYM *sp;
    AMODE *result = xalloc(sizeof(AMODE));
    sp = gsearch(name);
    if (sp == 0)
    {
        ++global_flag;
        sp = makesym(isproc ? sc_externalfunc : sc_external);
        sp->tp = &stdfunc;
        sp->name = name;
        sp->mainsym->extflag = TRUE;
        insert(sp, gsyms);
        --global_flag;
    }
    if (prm_68020)
    {
        result->preg = 4;
    }
    else
    {
        result->preg = 2;
    }
    if (prm_pcrel)
        result->mode = am_pcindx;
    else
        result->mode = am_adirect;
    result->offset = makenode(en_napccon, (void*)sp, 0);
    return result;
}

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

static char xdregs[3], xaregs[3], xfregs[3];
AMODE *flush_for_libcall()
{
    int i;
    for (i = 0; i < 3; i++)
    {
        if (xdregs[i] = dregs[i])
            gen_push(i, am_dreg, 0);
    }
    for (i = 0; i < 3; i++)
    {
        if (xaregs[i] = aregs[i])
            gen_push(i, am_areg, 0);
    }
    for (i = 0; i < 3; i++)
    {
        if (xfregs[i] = fregs[i])
            gen_push(i, am_freg, 0);
    }
}

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

void call_library2(char *lib_name, int size)
{
    AMODE *ap1 = set_symbol(lib_name, 1);
    gen_codes(op_jsr, 0, ap1, 0);
    if (size)
        gen_codes(op_add, BESZ_DWORD, make_immed(size), makeareg(7));
}

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

AMODE *call_library(char *lib_name, int size)
/*
 *      generate a call to a library routine.
 */
{
    int i;
    AMODE *result;
    result = set_symbol(lib_name, 1);
    gen_codes(op_jsr, 0, result, 0);
    if (size)
        gen_codes(op_add, BESZ_DWORD, make_immed(size), makeareg(7));
    result = temp_data();
    if (result->preg != 0)
        gen_codes(op_move, BESZ_DWORD, makedreg(0), result);
    result->tempflag = TRUE;
    for (i = 2; i >= 0; i--)
    {
        if (xfregs[i])
            gen_pop(i, am_freg, 0);
    }
    for (i = 2; i >= 0; i--)
    {
        if (xaregs[i])
            gen_pop(i, am_areg, 0);
    }
    for (i = 2; i >= 0; i--)
    {
        if (xdregs[i])
            gen_pop(i, am_dreg, 0);
    }
    return result;
}
//-------------------------------------------------------------------------

void count_cases(SNODE *stmt, struct cases *cs)
{
    while (stmt)
    {
        switch(stmt->stype) {        
             case st_tryblock:
                break;
            case st_throw:
                break;
            case st_return:
            case st_expr:
                break;
            case st_while:
            case st_do:
                count_cases(stmt->s1,cs);
                break;
            case st_for:
                count_cases(stmt->s1,cs);
                break;
            case st_if:
                count_cases(stmt->s1,cs);
                count_cases(stmt->s2,cs);
                break;
            case st_switch:
                break;
            case st_block:
                count_cases(stmt->exp,cs);
                break;
            case st_asm:
                break;
            case st_case:
               if (!stmt->s2)
                {
                    cs->count++;
                    
                    if (stmt->switchid < cs->bottom)
                        cs->bottom = stmt->switchid;
                    if (stmt->switchid > cs->top)
                        cs->top = stmt->switchid;
                }
                break;
        }
        stmt = stmt->next;
    }
}
//-------------------------------------------------------------------------
void gather_cases(SNODE *stmt, struct cases *cs, int compact)
{
    if (!cs->ptrs) {
        global_flag++;

⌨️ 快捷键说明

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