📄 fbvm.c
字号:
/* * FBCC - A simple C compiler. * * Copyright (c) 1996 Fabrice Bellard * * Contact addresses: * mail: Fabrice Bellard, 451 chemin du mas de Matour, 34790 Grabels, France * email: bellard@email.enst.fr * url: http://www.enst.fr/~bellard * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <stdio.h>#include "fbvmspec.h"#include "fbvminstr.h"/* #define DEBUG */typedef unsigned char VMCodeData;typedef unsigned char VMData;typedef int VMStackData;#if VM_LITTLE_ENDIAN == 0static void mput_i(unsigned char *p,unsigned int a){ p[0]=a >> 24; p[1]=a >> 16; p[2]=a >> 8; p[3]=a;}static int mget_i(unsigned char *p){ return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + (p[3]);}#else static void mput_i(unsigned char *p,unsigned int a){ p[3]=a >> 24; p[2]=a >> 16; p[1]=a >> 8; p[0]=a;}static int mget_i(unsigned char *p){ return (p[3]<<24) + (p[2]<<16) + (p[1]<<8) + (p[0]);}#endifint vm_argc;char **vm_argv;void VMLibCall(int *sp,int *bp,int c){ int a; int *p; switch(c) { case 0: /* getvars */ p=(void *)bp[-3]; p[0]=(int)stdin; p[1]=(int)stdout; p[2]=(int)stderr; p[3]=vm_argc; p[4]=(int)vm_argv; sp[0]=0; break; case 1: /* malloc */ sp[0]=(int)malloc(bp[-3]); break; case 2: /* free */ free((void *)bp[-3]); sp[0]=0; break; case 3: /* exit */ exit(bp[-3]); break; case 4: /* realloc */ p=(void *)bp[-3]; a=bp[-4]; sp[0]=(int) realloc(p,a); break; case 5: /* fputc */ sp[0]=fputc(bp[-3],(FILE *)bp[-4]); break; case 6: /* fgetc */ sp[0]=fgetc((FILE *)bp[-3]); break; case 7: /* fread */ sp[0]=fread((void *)bp[-3],bp[-4],bp[-5],(FILE *)bp[-6]); break; case 8: /* fwrite */ sp[0]=fwrite((void *)bp[-3],bp[-4],bp[-5],(FILE *)bp[-6]); break; case 9: /* ferror */ sp[0]=ferror((FILE *)bp[-3]); break; case 10: /* fopen */ sp[0]=(int)fopen((char *)bp[-3],(char *)bp[-4]); break; case 11: /* fclose */ sp[0]=fclose((FILE *)bp[-3]); break; default: fprintf(stderr,"libcall %d non impl閙ent閈n",c); break; }}void VMExec(VMCodeData *init_ip,VMStackData *init_sp){ register VMCodeData *ip; register int *sp; int *bp; int op_code; VMCodeData *ip1; int a,b; ip=init_ip; sp=init_sp; bp=init_sp; while (1) { op_code=*ip++;#ifdef DEBUG fprintf(stderr,"debug: sp=%d bp=%d sp[0]=%d %s\n", sp-init_sp,bp-init_sp,sp[0],vm_instr_str[op_code]);#endif switch(op_code) { /* memory read */ case ld_b: sp[0]=*((char *)sp[0]); break; case ld_ub: sp[0]=*((unsigned char *)sp[0]); break; case ld_w: sp[0]=*((short *)sp[0]); break; case ld_uw: sp[0]=*((unsigned short *)sp[0]); break; case ld_i: sp[0]=*((int *)sp[0]); break; /* memory write */ case st_i: *((int *)sp[0])=sp[-1]; sp--; break; case st_w: *((short *)sp[0])=sp[-1]; sp--; break; case st_b: *((char *)sp[0])=sp[-1]; sp--; break; /* load immediate pointers */ case libp_i: sp++; sp[0]=(int)bp + mget_i(ip); ip+=4; break; /* load immediate data */ case li_i: sp++; sp[0]=mget_i(ip); ip+=4; break; /* arithm閠ique */ case add_i: sp[-1]+=sp[0]; sp--; break; case sub_i: sp[-1]-=sp[0]; sp--; break; case mul_i: sp[-1]*=sp[0]; sp--; break; case div_i: sp[-1]/=sp[0]; sp--; break; case mod_i: sp[-1]%=sp[0]; sp--; break; case mul_ui: (unsigned int)sp[-1]*=(unsigned int)sp[0]; sp--; break; case div_ui: (unsigned int)sp[-1]/=(unsigned int)sp[0]; sp--; break; case mod_ui: (unsigned int)sp[-1]%=(unsigned int)sp[0]; sp--; break; case neg_i: sp[0]=-sp[0]; break; /* op閞ations logiques */ case and_i: sp[-1]&=sp[0]; sp--; break; case or_i: sp[-1]|=sp[0]; sp--; break; case xor_i: sp[-1]^=sp[0]; sp--; break; case not_i: sp[0]=~sp[0]; break; case shl_i: sp[-1]<<=sp[0]; sp--; break; case shr_i: sp[-1]>>=sp[0]; sp--; break; case shr_ui: (unsigned int)sp[-1]>>=sp[0]; sp--; break; /* conversions */ case cvt_i_b: sp[0]=(char)sp[0]; break; case cvt_b_i: case cvt_i_ub: sp[0]=(unsigned char)sp[0]; break; case cvt_i_w: sp[0]=(short)sp[0]; break; case cvt_w_i: case cvt_i_uw: sp[0]=(unsigned short)sp[0]; break; /* tests */ case cmplt_i: sp[-1]=sp[-1] < sp[0]; sp--; break; case cmple_i: sp[-1]=sp[-1] <= sp[0]; sp--; break; case cmpgt_i: sp[-1]=sp[-1] > sp[0]; sp--; break; case cmpge_i: sp[-1]=sp[-1] >= sp[0]; sp--; break; case cmplt_ui: sp[-1]=(unsigned int)sp[-1] < (unsigned int)sp[0]; sp--; break; case cmple_ui: sp[-1]=(unsigned int)sp[-1] <= (unsigned int)sp[0]; sp--; break; case cmpgt_ui: sp[-1]=(unsigned int)sp[-1] > (unsigned int)sp[0]; sp--; break; case cmpge_ui: sp[-1]=(unsigned int)sp[-1] >= (unsigned int)sp[0]; sp--; break; case cmpeq_i: sp[-1]=sp[-1] == sp[0]; sp--; break; case cmpne_i: sp[-1]=sp[-1] != sp[0]; sp--; break; /* subroutines */ case jsr: a=mget_i(ip); ip+=4; ip1=(void *)sp[0]; sp[0]=(int)ip; sp[1]=(int)bp; sp[2]=a; sp+=2; ip=ip1; bp=sp; break; case rts: a=sp[0]; /* valeur retourn閑 */ sp=bp; ip=(void *)sp[-2]; bp=(void *)sp[-1]; b=sp[0]; (int)sp=(int)sp-(b+8); sp[0]=a; break; /* jumps */ case jmp: ip1=(void *)mget_i(ip); ip=ip1; break; case jeq_i: ip1=(void *)mget_i(ip); ip+=4; if (sp[0]==0) ip=ip1; sp--; break; case jne_i: ip1=(void *)mget_i(ip); ip+=4; if (sp[0]!=0) ip=ip1; sp--; break; /* gestion de la pile */ case addsp: a=mget_i(ip); ip+=4; sp=(void *)((int)sp + a); break; case dup: sp++; sp[0]=sp[-1]; break; case pop: sp--; break; /* appels systeme */ case libcall: a=mget_i(ip); ip+=4; sp++; VMLibCall(sp,bp,a); break; /* gestion des switchs : inspir
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -