📄 intr386.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
*/
/*
* 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 + -