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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers forth_machine.cpp Source File

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 }