A project to implement a console using the Mbed using VGA for video output and a PS/2 keyboard for the input. The eventual goal is to also include tools for managing SD cards, and a semi-self-hosting programming environment.
Dependencies: PS2_MbedConsole fastlib SDFileSystem vga640x480g_mbedconsole lightvm mbed
forth_machine.cpp
00001 /* 00002 <Copyright Header> 00003 Copyright (c) 2012 Jordan "Earlz" Earls <http://lastyearswishes.com> 00004 All rights reserved. 00005 00006 Redistribution and use in source and binary forms, with or without 00007 modification, are permitted provided that the following conditions 00008 are met: 00009 00010 1. Redistributions of source code must retain the above copyright 00011 notice, this list of conditions and the following disclaimer. 00012 2. Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in the 00014 documentation and/or other materials provided with the distribution. 00015 3. The name of the author may not be used to endorse or promote products 00016 derived from this software without specific prior written permission. 00017 00018 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 00019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00020 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 00021 THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00022 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00023 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 00024 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00025 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00026 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 00027 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00028 00029 This file is part of the MbedConsole project 00030 */ 00031 00032 #include "mbedconsole.h" 00033 #include "plEarlz.h" 00034 #include <stdint.h> 00035 #include <stdarg.h> 00036 00037 00038 //An extremely simple virtual machine to make this implementation about 10 times easier and probably a bit faster 00039 00040 00041 00042 00043 00044 int pl_stackpos=0; 00045 int pl_stack[MAXSTACK]; 00046 00047 00048 00049 00050 int pl_dictionary_count=0; 00051 int pl_dictionary_size=0; 00052 WordKey *pl_dictionary; //todo: a hash table would be much faster 00053 00054 void pl_push(int val) 00055 { 00056 if(pl_stackpos>=MAXSTACK) 00057 { 00058 vputs("Stack overflow!"); 00059 pl_error=StackOverflow; 00060 return; 00061 } 00062 pl_stack[pl_stackpos]=val; 00063 pl_stackpos++; 00064 } 00065 int pl_pop() 00066 { 00067 if(pl_stackpos<=0) 00068 { 00069 vputs("Stack underflow!"); 00070 pl_error=StackUnderflow; 00071 return 0; 00072 } 00073 pl_stackpos--; 00074 return pl_stack[pl_stackpos]; 00075 } 00076 00077 WordKey *pl_lookup(char* name) 00078 { 00079 for(int i=0;i<pl_dictionary_count;i++) 00080 { 00081 if(strlcmp(name, pl_dictionary[i].name, 12)==0) 00082 { 00083 return &pl_dictionary[i]; 00084 } 00085 } 00086 return NULL; 00087 } 00088 00089 int pl_addword() 00090 { 00091 if(pl_dictionary_size==0){ 00092 pl_dictionary=(WordKey*)malloc(sizeof(WordKey)*12); 00093 pl_dictionary_size=12; 00094 return 0; 00095 } 00096 if(pl_dictionary_size<=pl_dictionary_count) 00097 { 00098 void* tmp=realloc(pl_dictionary, pl_dictionary_size+sizeof(WordKey)*DICTIONARYSTEP); 00099 if(tmp==NULL) 00100 { 00101 vputs("Out of memory!! Epic Fail!!"); 00102 return -1; 00103 } 00104 pl_dictionary=(WordKey*)tmp; 00105 pl_dictionary_size+=sizeof(WordKey)*DICTIONARYSTEP; 00106 } 00107 return pl_dictionary_count++; 00108 } 00109 00110 00111 typedef struct CallStateStruct 00112 { 00113 int lastcall; //the pl_temppos when this word was first called 00114 CallStateStruct* previous; 00115 } CallState; 00116 00117 int pl_tempstack[MAXTEMPSTACK]; 00118 int pl_temppos=0; 00119 CallState* callstate; 00120 void pl_temppush(int val) 00121 { 00122 if(pl_temppos>=MAXTEMPSTACK) 00123 { 00124 vputs("Temporary stack overflow\n"); 00125 return; 00126 } 00127 pl_tempstack[pl_temppos]=val; 00128 pl_temppos++; 00129 } 00130 int pl_temppop() 00131 { 00132 if(pl_temppos<=0) 00133 { 00134 vputs("Temporary stack underflow\n"); 00135 return 0; 00136 } 00137 return pl_tempstack[pl_temppos--]; 00138 } 00139 00140 int forth_execute(uint8_t* block, int length) 00141 { 00142 uint16_t pos=0; 00143 printf("block length: %x\r\n",length); 00144 while(pos<length) 00145 { 00146 //serial.getc(); 00147 Opcode op=(Opcode)block[pos]; 00148 printf("pos: %x -- opcode: %x\r\n",(int)pos, (int)op); 00149 switch(op) 00150 { 00151 case BranchTrue: 00152 if(pl_pop()){ 00153 pos++; 00154 pos=*((uint16_t*)&block[pos]); 00155 00156 }else{ 00157 pos+=3; 00158 } 00159 break; 00160 case BranchFalse: 00161 if(!pl_pop()){ 00162 pos++; 00163 serial.printf("branch false %x\r\n",(int)pos); 00164 pos=*((uint16_t*)&block[pos]); 00165 serial.printf("branch false %x\r\n",(int)pos); 00166 }else{ 00167 pos+=3; 00168 serial.printf("branch false skip %x\r\n", (int)pos); 00169 } 00170 break; 00171 case Branch: 00172 pos++; 00173 pos=*((uint16_t*)&block[pos]); 00174 break; 00175 case Push: 00176 pos++; 00177 pl_push(*(uint32_t*)&block[pos]); 00178 pos+=4; 00179 break; 00180 case Drop: 00181 pos++; 00182 pl_pop(); 00183 break; 00184 case Add: 00185 pos++; 00186 pl_push(pl_pop()+pl_pop()); 00187 break; 00188 case Sub: 00189 pos++; 00190 pl_push(pl_pop()-pl_pop()); 00191 break; 00192 case Mul: 00193 pos++; 00194 pl_push(pl_pop()*pl_pop()); 00195 break; 00196 case Div: 00197 pos++; 00198 pl_push(pl_pop()/pl_pop()); 00199 break; 00200 case Mod: 00201 pos++; 00202 pl_push(pl_pop()%pl_pop()); 00203 break; 00204 case Cgt: 00205 pos++; 00206 pl_push(pl_pop()>pl_pop()); 00207 break; 00208 case Clt: 00209 pos++; 00210 pl_push(pl_pop()<pl_pop()); 00211 break; 00212 case Cgte: 00213 pos++; 00214 pl_push(pl_pop()>=pl_pop()); 00215 break; 00216 case Clte: 00217 pos++; 00218 pl_push(pl_pop()<=pl_pop()); 00219 break; 00220 case Ceq: 00221 pos++; 00222 pl_push(pl_pop()==pl_pop()); 00223 break; 00224 case Cneq: 00225 pos++; 00226 pl_push(pl_pop()!=pl_pop()); 00227 break; 00228 case CallInt:{ 00229 pos++; 00230 uint32_t tmp=*(uint32_t*)&block[pos]; 00231 ((BuiltinFunction)tmp)(); 00232 pos+=4; 00233 break;} 00234 case Swap:{ 00235 pos++; 00236 int tmp=pl_pop(); 00237 int tmp2=pl_pop(); 00238 pl_push(tmp); 00239 pl_push(tmp2); 00240 break; 00241 } 00242 case PushTemp: 00243 pos++; 00244 pl_temppush(pl_pop()); 00245 break; 00246 case PopTemp: 00247 pos++; 00248 pl_push(pl_temppop()); 00249 case Pick:{ 00250 pos++; 00251 int tmp=pl_pop(); 00252 if(pl_stackpos-tmp>0){ 00253 pl_push(pl_stack[pl_stackpos-tmp]); 00254 00255 }else{ 00256 pl_push(0); 00257 vputs("Stack underflow on pick\n"); 00258 } 00259 break;} 00260 case Ret: 00261 return 0; 00262 00263 00264 default: 00265 vputs("Unknown opcode!!"); 00266 return; 00267 } 00268 } 00269 return 0; 00270 }
Generated on Sun Jul 17 2022 09:10:09 by 1.7.2