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

📄 intr386.c

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

#define KWINTRINSHASH 33

extern int prm_cmangle, prm_intrinsic;
extern int regs[3];
extern long nextlabel;

static HASHREC **hashtable = 0;
static AMODE edxreg[] = 
{
    {
        am_dreg, EDX, 0, 0, 0, 4
    }
};
static AMODE alreg[] = 
{
    {
        am_dreg, EAX, 0, 0, 0, 1
    }
};
static AMODE clreg[] = 
{
    {
        am_dreg, ECX, 0, 0, 0, 1
    }
};
static AMODE axreg[] = 
{
    {
        am_dreg, EAX, 0, 0, 0, 2
    }
};
static AMODE dxreg[] = 
{
    {
        am_dreg, EDX, 0, 0, 0, 2
    }
};
static int pushedax, pushedcx;

static INTRINSICS intrinsic_table[] = 
{
    {
        0, "abs", 1
    }
    , 
    {
        0, "div", 2
    }
    , 
    {
        0, "ldiv", 3
    }
    , 
    {
        0, "_rotl", 4
    }
    , 
    {
        0, "_rotr", 5
    }
    , 
    {
        0, "memcmp", 6
    }
    , 
    {
        0, "memcpy", 7
    }
    , 
    {
        0, "memmove", 8
    }
    , 
    {
        0, "memset", 9
    }
    , 
    {
        0, "strcat", 10
    }
    , 
    {
        0, "strcmp", 11
    }
    , 
    {
        0, "strcpy", 12
    }
    , 
    {
        0, "strlen", 13
    }
    , 
    {
        0, "strncat", 14
    }
    , 
    {
        0, "strncmp", 15
    }
    , 
    {
        0, "strncpy", 16
    }
    , 
    {
        0, "memchr", 17
    }
    , 
    {
        0, "strchr", 18
    }
    , 
    {
        0, "strrchr", 19
    }
    , 
    {
        0, "inportb", 20
    }
    , 
    {
        0, "inport", 21
    }
    , 
    {
        0, "inp", 22
    }
    , 
    {
        0, "inpw", 23
    }
    , 
    {
        0, "outportb", 24
    }
    , 
    {
        0, "outport", 25
    }
    , 
    {
        0, "outp", 26
    }
    , 
    {
        0, "outpw", 27
    }
    , 
    {
        0, "_crotl", 28
    }
    , 
    {
        0, "_crotr", 29
    }
    , 
    {
        0, "__disable", 30
    }
    , 
    {
        0, "__enable", 31
    }
    , 
    {
        0, "inportd", 32
    }
    , 
    {
        0, "outportd", 33
    }
    , 
    {
        0, "labs", 1
    }
    ,  // same as abs()
    {
        0, 0, 0
    }
    , 
};
void IntrinsIni(void)
{
    INTRINSICS *q = intrinsic_table;
    if (!hashtable)
    {
        hashtable = (INTRINSICS **)malloc(KWINTRINSHASH *sizeof(INTRINSICS*));
        memset(hashtable, 0, KWINTRINSHASH *sizeof(INTRINSICS*));
        if (!hashtable)
            fatal("Out of memory");
        while (q->word)
        {
            AddHash(q, hashtable, KWINTRINSHASH);
            q++;
        }
    }
}

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

void SearchIntrins(SYM *sp)
{
    HASHREC **q;
    char *p = sp->name;
    if (!prm_intrinsic)
    {
        sp->tp->cflags &= ~DF_INTRINS;
        return ;
    }
    if (prm_cmangle)
        p++;
    q = LookupHash(p, hashtable, KWINTRINSHASH);
    if (!q)
    {
        gensymerror(ERR_NOINTRINSFOUND, sp->name);
        sp->tp->cflags &= ~DF_INTRINS;
        return ;
    }
    sp->value.i = ((INTRINSICS*)(*q))->val;
}

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

static int oneparm(ENODE *parms)
{
    if (!parms)
        return 0;
    return 1;
}

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

static int twoparms(ENODE *parms)
{
    if (!parms || !parms->v.p[1])
        return 0;
    return 1;
}

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

static int threeparms(ENODE *parms)
{
    if (!parms || !parms->v.p[1] || !parms->v.p[1]->v.p[1])
        return 0;
    return 1;
}

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

static AMODE *roll(ENODE *parms, int size, int op)
{
    AMODE *ap1,  *ap2,  *ap3;
    int pushed = FALSE;
    if (!twoparms(parms))
        return 0;
    ap1 = gen_expr(parms->v.p[1]->v.p[0], 0, 0, 4);
    do_extend(ap1, size, F_DREG | F_VOL);
    ap2 = gen_expr(parms->v.p[0], 0, 0, 0);
    if (ap2->mode != am_immed)
    {
        do_extend(ap2, 4, 0);
        if (ap1->mode == am_dreg && ap1->preg == ECX)
        {
            ap3 = temp_data();
            gen_code(op_mov, ap3, ap1);
            freeop(ap1);
            ap1 = ap3;
        }
        if (ap2->mode != am_dreg || ap2->preg != ECX)
        {
            if (regs[2])
            {
                gen_push(ECX, am_dreg, 0);
                pushed = TRUE;
            }
            gen_code(op_mov, makedreg(ECX), ap2);
            ap2 = clreg;
        }
    }
    ap1->length = size;
    gen_code(op, ap1, ap2);
    if (pushed)
        gen_pop(ECX, am_dreg, 0);
    freeop(ap2);
    freeop(ap1);
    return ap1;
}

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

static void LoadCX(ENODE *parms)
{
    AMODE *ap1;
    regs[0]++;
    ap1 = gen_expr(parms, FALSE, FALSE, 4);
    do_extend(ap1, 4, F_DREG | F_VOL);
    regs[0]--;
    if (ap1->preg != ECX)
        gen_code(op_mov, makedreg(ECX), ap1);
}

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

static void LoadSIDI(ENODE *parms, int backwards, int savecx)
{
    AMODE *ap1,  *ap2,  *ap3;
    pushedax = pushedcx = FALSE;
    ap2 = gen_expr(parms->v.p[0], FALSE, FALSE, 0);
    noids(ap2);
    ap1 = gen_expr(parms->v.p[1]->v.p[0], FALSE, FALSE, 0);
    if (ap1->mode == am_indisp && ap1->preg == ESI || (ap1->mode ==
        am_indispscale && (ap1->preg == ESI || ap1->sreg == ESI)) || (ap1->mode
        == am_dreg && ap1->preg == ESI))
    {
        ap3 = temp_data();
        gen_code(op_mov, ap3, ap1);
        freeop(ap1);
        ap1 = ap3;
    }

    gen_codes(op_mov, 4, makedreg(ESI), ap2);
    gen_codes(op_mov, 4, makedreg(EDI), ap1);
    if (backwards)
        gen_code(op_xchg, makedreg(ESI), makedreg(EDI));
    freeop(ap2);
    freeop(ap1);
    gen_code(op_cld, 0, 0);
}

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

static void LoadDI(ENODE *parms, int savecx)
{
    AMODE *ap1;
    pushedax = pushedcx = FALSE;
    ap1 = gen_expr(parms->v.p[0], FALSE, FALSE, 4);
    noids(ap1);
    freeop(ap1);
    if (regs[1] && savecx)
    {
        gen_push(ECX, am_dreg, 0);
        pushedcx = TRUE;
    }
    if (regs[0])
    {
        gen_push(EAX, am_dreg, 0);
        pushedax = TRUE;
    }
    gen_codes(op_mov, 4, makedreg(EDI), ap1);
    gen_code(op_cld, 0, 0);
}

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

static AMODE *popDI(AMODE *ap, int tocx)
{
    AMODE *ap1 = ap;
    if (pushedax)
    {
        gen_pop(EAX, am_dreg, 0);
    }
    if (pushedcx)
        gen_pop(ECX, am_dreg, 0);

⌨️ 快捷键说明

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