Last active
December 27, 2015 06:19
-
-
Save SuperDoxin/7280607 to your computer and use it in GitHub Desktop.
Universal Machine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;temp: F | |
| write A >data | |
| write F >exit | |
| write C >loop ;constant | |
| write D 1 ;constant | |
| write E 0 ;constant | |
| loop: index F E A | |
| out F | |
| add A A D | |
| write G >exit | |
| CMOV G C F | |
| load E G | |
| exit: halt | |
| data: raw 72 | |
| raw 101 | |
| raw 108 | |
| raw 108 | |
| raw 111 | |
| raw 32 | |
| raw 87 | |
| raw 111 | |
| raw 114 | |
| raw 108 | |
| raw 100 | |
| raw 33 | |
| raw 10 | |
| raw 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| """ | |
| UASM | |
| Usage: | |
| uasm.py <input> <output> | |
| uasm.py (-h|--help|--version) | |
| Options: | |
| -h --help show this screen | |
| --version show version | |
| """ | |
| from docopt import docopt | |
| import re | |
| import json | |
| import struct | |
| registers=['a','b','c','d','e','f','g','h'] | |
| ops=["cmov","index","set","add","mult","div","nand","halt","new","del","out","input","load","write","raw"] | |
| class Pointer(object): | |
| def __init__(self,name=None): | |
| self.name=name | |
| def __repr__(self): | |
| return "J-{}".format(self.name) | |
| class Opcode(object): | |
| def __init__(self,data): | |
| self.pointers=[] | |
| for item in ["reg_a","reg_b","reg_c","value","op","label"]: | |
| try: | |
| setattr(self,item,data.group(item)) | |
| except IndexError: | |
| setattr(self,item,None) | |
| pass | |
| if self.op not in ops: | |
| raise SyntaxError("invalid op {!r}".format(self.op)) | |
| self.op=ops.index(self.op) | |
| if self.value!=None: | |
| if self.value.startswith(">"): | |
| self.value=Pointer(self.value[1:]) | |
| self.pointers.append(self.value) | |
| elif self.value.startswith("0x"): | |
| self.value=int(self.value[2:],16) | |
| else: | |
| self.value=int(self.value) | |
| if self.label!=None: | |
| self.label=self.label[:-1] | |
| #print "LABEL {!r}".format(self.label) | |
| if self.reg_a!=None: | |
| self.reg_a=registers.index(self.reg_a) | |
| if self.reg_b!=None: | |
| self.reg_b=registers.index(self.reg_b) | |
| if self.reg_c!=None: | |
| self.reg_c=registers.index(self.reg_c) | |
| if self.op==12: | |
| self.reg_c=self.reg_b | |
| self.reg_b=self.reg_a | |
| self.reg_a=None | |
| elif self.op==10 or self.op==9: | |
| self.reg_c=self.reg_a | |
| self.reg_a=None | |
| def write(self): | |
| val=self.op<<28 | |
| if self.op==13: | |
| try: | |
| val|=self.value&0x1FFFFFF | |
| except TypeError: | |
| val|=self.value.value | |
| val|=self.reg_a<<25 | |
| elif self.op==14: | |
| val=self.value | |
| else: | |
| if self.reg_a!=None: | |
| val|=self.reg_a<<6 | |
| if self.reg_b!=None: | |
| val|=self.reg_b<<3 | |
| if self.reg_c!=None: | |
| val|=self.reg_c | |
| return struct.pack(">L",val) | |
| def __repr__(self): | |
| dct={} | |
| for item in ["reg_a","reg_b","reg_c","value","op","label"]: | |
| v=getattr(self,item) | |
| if v!=None: | |
| dct[item]=v | |
| return "<Opcode {}>".format(dct) | |
| def main(infname,outfname): | |
| outp=[] | |
| labels={} | |
| with open(infname,"r") as fid: | |
| ops=[] | |
| opno=0 | |
| for lineno,line in enumerate(fid): | |
| if ";" in line: | |
| line,_,_=line.partition(";") | |
| line=line.lower().strip() | |
| if len(line)==0: | |
| continue | |
| m=None | |
| for i in xrange(1): | |
| #raw data | |
| m=re.match(r"(?P<label>[a-z]+[a-z0-9]*:)?\s*(?P<op>raw)\s+(?P<value>\d+|0x[0-9a-f]+)$",line) | |
| if m: | |
| break | |
| #3 register op | |
| m=re.match(r"(?P<label>[a-z]+[a-z0-9]*:)?\s*(?P<op>[a-z]+)\s+(?P<reg_a>[a-h])\s+(?P<reg_b>[a-h])\s+(?P<reg_c>[a-h])$",line) | |
| if m: | |
| break | |
| #2 register op | |
| m=re.match(r"(?P<label>[a-z]+[a-z0-9]*:)?\s*(?P<op>[a-z]+)\s+(?P<reg_a>[a-h])\s+(?P<reg_b>[a-h])$",line) | |
| if m: | |
| break | |
| #1 reg op | |
| m=re.match(r"(?P<label>[a-z]+[a-z0-9]*:)?\s*(?P<op>[a-z]+)\s+(?P<reg_a>[a-h])$",line) | |
| if m: | |
| break | |
| #0 register op | |
| m=re.match(r"(?P<label>[a-z]+[a-z0-9]*:)?\s*(?P<op>[a-z]+)$",line) | |
| if m: | |
| break | |
| #special op | |
| m=re.match(r"(?P<label>[a-z]+[a-z0-9]*:)?\s*(?P<op>[a-z]+)\s+(?P<reg_a>[a-h])\s+(?P<value>\d+|0x[0-9a-f]+|>[a-z]+[a-z0-9]*)$",line) | |
| if m: | |
| break | |
| if m==None: | |
| raise SystemExit("invalid syntax in line {}".format(lineno+1)) | |
| o=Opcode(m) | |
| #print repr(o) | |
| #outp.append(o.write()) | |
| o.pos=opno | |
| if o.label!=None: | |
| if o.label in labels: | |
| raise SystemExit("duplicate label {!r}.format(o.label)") | |
| labels[o.label]=o.pos | |
| outp.append(o) | |
| #print repr(o) | |
| opno+=1 | |
| for op in outp: | |
| for pointer in op.pointers: | |
| if pointer.name not in labels: | |
| raise SystemExit("undefined label {!r}".format(pointer.name)) | |
| pointer.value=labels[pointer.name] | |
| outp=map(lambda x:x.write(),outp) | |
| with open(outfname,"w") as fid: | |
| fid.write(''.join(outp)) | |
| print "wrote {} instructions".format(len(outp)) | |
| if __name__ == '__main__': | |
| arguments = docopt(__doc__, version='UASM 0.1') | |
| main(arguments["<input>"],arguments["<output>"]) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| int main(int argc, char *argv[]) | |
| { | |
| FILE *fp; | |
| FILE *wfp; | |
| unsigned int opcount; | |
| unsigned int *array0; | |
| unsigned int pointer=1; | |
| unsigned int op; | |
| unsigned int reg_a; | |
| unsigned int reg_b; | |
| unsigned int reg_c; | |
| unsigned int value; | |
| unsigned int registers[8]={0}; | |
| unsigned int data; | |
| unsigned int size; | |
| unsigned char ch; | |
| //printf("argc: %i\n",argc); | |
| if(argc!=3 && argc!=2) | |
| { | |
| printf("Usage:\n um <input> <listing>\n um <input>\n"); | |
| } | |
| fp=fopen(argv[1],"r"); | |
| if(fp==NULL) | |
| { | |
| perror("Error while opening file."); | |
| return 1; | |
| } | |
| fseek(fp, 0L, SEEK_END); | |
| opcount=ftell(fp)/4; | |
| fseek(fp, 0L, SEEK_SET); | |
| printf("%i ops to read\n",opcount); | |
| array0=(unsigned int*)calloc(opcount+1,sizeof(int)); | |
| array0[0]=opcount; | |
| if(argc==3) | |
| wfp=fopen(argv[2],"w"); | |
| //fprintf(wfp,"\n") | |
| for(int i=1;i<opcount;i++) | |
| { | |
| array0[i]=(fgetc(fp)<<24)|(fgetc(fp)<<16)|(fgetc(fp)<<8)|(fgetc(fp)); | |
| if(argc==3) | |
| { | |
| data=array0[i]; | |
| op=data>>28; | |
| if(op==13) | |
| { | |
| reg_a=(data>>25)&0x7; | |
| reg_b=0; | |
| reg_c=0; | |
| value=data&0x1FFFFFF; | |
| } | |
| else | |
| { | |
| reg_c=(data)&0x7; | |
| reg_b=(data>>3)&0x7; | |
| reg_a=(data>>6)&0x7; | |
| value=0; | |
| } | |
| fprintf(wfp,"%8x: ",i); | |
| switch(op) | |
| { | |
| case 0: fprintf(wfp,"CMOV %c==0 ? %c=%c",reg_c+65,reg_a+65,reg_b+65); break; | |
| case 1: fprintf(wfp,"INDEX %c=%c[%c]",reg_a+65,reg_b+65,reg_c+65); break; | |
| case 2: fprintf(wfp,"DIV %c[%c]=%c",reg_a+65,reg_b+65,reg_c+65); break; | |
| case 3: fprintf(wfp,"ADD %c=%c+%c",reg_a+65,reg_b+65,reg_c+65); break; | |
| case 4: fprintf(wfp,"MULT %c=%c*%c",reg_a+65,reg_b+65,reg_c+65); break; | |
| case 5: fprintf(wfp,"DIV %c=%c/%c",reg_a+65,reg_b+65,reg_c+65); break; | |
| case 6: fprintf(wfp,"NAND %c=%cV%c",reg_a+65,reg_b+65,reg_c+65); break; | |
| case 7: fprintf(wfp,"HALT"); break; | |
| case 8: fprintf(wfp,"NEW %c=new[%c]",reg_b+65,reg_c+65); break; | |
| case 9: fprintf(wfp,"DEL %c",reg_c+65); break; | |
| case 10: fprintf(wfp,"OUT %c",reg_c+65); break; | |
| case 11: fprintf(wfp,"INPUT %c=input",reg_c+65); break; | |
| case 12: fprintf(wfp,"LOAD %c\n JMP %c",reg_b+65,reg_c+65); break; | |
| case 13: | |
| if(value>=32 && value<=126) | |
| fprintf(wfp,"WRITE %c=%08x ;%c",reg_a+65,value,value); | |
| else | |
| fprintf(wfp,"WRITE %c=%08x",reg_a+65,value); | |
| break; | |
| default: fprintf(wfp,"DAT %08x",data); break; | |
| } | |
| fprintf(wfp,"\n"); | |
| } | |
| } | |
| printf("%i ops read\n---\n",opcount); | |
| if(argc==3) | |
| return 0; | |
| while(1) | |
| { | |
| if(pointer>array0[0]) | |
| { | |
| printf("\n=== END OF CODE ===\n"); | |
| return 0; | |
| } | |
| data=array0[pointer]; | |
| //printf("%u\n",data); | |
| //return 0; | |
| pointer++; | |
| op=data>>28; | |
| if(op==13) | |
| { | |
| reg_a=(data>>25)&0x7; | |
| reg_b=0; | |
| reg_c=0; | |
| value=data&0x1FFFFFF; | |
| } | |
| else | |
| { | |
| reg_c=(data)&0x7; | |
| reg_b=(data>>3)&0x7; | |
| reg_a=(data>>6)&0x7; | |
| value=0; | |
| } | |
| switch(op) | |
| { | |
| case 0: | |
| if(registers[reg_c]!=0) | |
| registers[reg_a]=registers[reg_b]; | |
| break; | |
| case 1: | |
| if(registers[reg_b]==0) | |
| registers[reg_a]=array0[registers[reg_c]+1]; | |
| else | |
| registers[reg_a]=((int*)registers[reg_b])[registers[reg_c]+1]; | |
| break; | |
| case 2: | |
| if(registers[reg_a]==0) | |
| array0[registers[reg_b]+1]=registers[reg_c]; | |
| else | |
| ((int*)registers[reg_a])[registers[reg_b]+1]=registers[reg_c]; | |
| break; | |
| case 3: | |
| registers[reg_a]=registers[reg_b]+registers[reg_c]; | |
| break; | |
| case 4: | |
| registers[reg_a]=registers[reg_b]*registers[reg_c]; | |
| break; | |
| case 5: | |
| registers[reg_a]=registers[reg_b]/registers[reg_c]; | |
| break; | |
| case 6: | |
| registers[reg_a]=~(registers[reg_b]®isters[reg_c]); | |
| break; | |
| case 7: | |
| printf("\n=== HALT ===\nhalted at %08x\n",pointer); | |
| return 0; | |
| case 8: | |
| //printf("[MEM] allocating %08x plates",registers[reg_c]); | |
| size=registers[reg_c]; | |
| registers[reg_b]=(unsigned int)calloc(size+1,sizeof(int)); //(int) | |
| //printf(" to %08x\n",registers[reg_b]); | |
| ((int*)registers[reg_b])[0]=size; | |
| break; | |
| case 9: | |
| //printf("[MEM] freeing %08x\n",registers[reg_c]); | |
| free((unsigned int*)registers[reg_c]); | |
| break; | |
| case 10: | |
| printf("%c",registers[reg_c]); | |
| break; | |
| case 11: | |
| fflush(stdout); | |
| ch=getchar(); | |
| //read(0, &ch, 1); | |
| if(ch=='\n') | |
| registers[reg_c]=255; | |
| else | |
| registers[reg_c]=ch; | |
| break; | |
| case 12: | |
| if(registers[reg_b]!=0) | |
| { | |
| size=((unsigned int*)registers[reg_b])[0]; | |
| array0=(unsigned int*)malloc((size+1)*sizeof(int)); | |
| memcpy(array0,(unsigned int*)registers[reg_b],(size+1)*sizeof(int)); | |
| } | |
| pointer=registers[reg_c]+1; | |
| break; | |
| case 13: | |
| registers[reg_a]=value; | |
| break; | |
| default: printf("Illegal op %i\n",op); return 1; | |
| } | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment