MinIPS*1のアセンブラっぽいなにか
D言語(しかもDMD2.007以降でしかコンパイルできない。それ以降でもコンパイルできるか保証は無い)で書いたMinIPS(電通大情報工学科にて使われてる教育用プロセッサ)のアセンブラとか、範囲限定され過ぎだろと思った。なのでlex/yacc使って書き直してみました。
とりあえずWindowsバイナリこの辺 http://konbu.s13.xrea.com/lib/minika.exe
なんかまあ標準入力で受けて標準出力に吐きます。出力は相変わらず16進数表現のマシン語列です。
% make yacc -d -y minika.y lex -I minika.l mv y.tab.c minika.c cc lex.yy.c minika.c optable.h -ll -o minika % cat hoge.s add $1, $2, $3 sub $1, $2, $3 nop bne $1, $0, 10h beq $1, $0, -2 % ./minika <hoge.s 00430820 00430822 00000000 14010010 1001FFFE
ねむい。以下コード。
TARGET = minika SOURCES = minika.l minika.y optable.h all: minika minika: lex.yy.c minika.c optable.h $(CC) $^ -ll -o $@ lex.yy.c: minika.l y.tab.h $(LEX) -I $< y.tab.h: minika.y $(YACC) -d -y $< y.tab.c: minika.y $(YACC) -d -y $< minika.c: y.tab.c mv $< $@
最近Makefile書いてなかったんで、微妙に手間取った。
/** * minika.l **/ %{ #include "y.tab.h" int hex2int(char *hval) { int ival = 0, i; for(;*hval;++hval){ if(*hval>='0' && *hval<='9'){ ival = ival*16 + *hval - '0'; } else if(*hval>='A' && *hval<='F'){ ival = ival*16 + *hval - 'A' + 10; } else if(*hval>='a' && *hval<='f'){ ival = ival*16 + *hval - 'a' + 10; } else{ return ival; } } return ival; } %} ALPHA [a-zA-Z] NUM [0-9] ALNUM [0-9a-zA-Z] HEX [0-9a-fA-F] ID [a-zA-Z_][0-9a-zA-Z_]* RET [\r\n]|\r\n SP [ \t] %state COMMENT %% <INITIAL>{ID} { yylval.sval = yytext; return(IDENT); } <INITIAL>[0-9]+ { yylval.ival = atoi(yytext); return(INTEGER); } <INITIAL>{HEX}+h { yylval.ival = hex2int(yytext); return(INTEGER); }; <INITIAL>\: return(COL); <INITIAL>\$ return(DOL); <INITIAL>\, return(CAMMA); <INITIAL>\- return(MINUS); <INITIAL>\; {BEGIN(COMMENT);} <INITIAL>{RET} return(EOL); <INITIAL>{SP} ; <INITIAL>\( return(LPAREN); <INITIAL>\) return(RPAREN); <INITIAL>. { yyerror("Illegal character"); return(EOL); } <COMMENT>{RET} {BEGIN(INITIAL);return(EOL);} <COMMENT>[^\r\n] ; %%
たぶんほとんど変わってないな。MINUS追加したくらい。
/** * asm.y **/ %{ #include <stdio.h> #include <string.h> #include "optable.h" #define MAXCHAR 1000 char strbuf[MAXCHAR]; #define PROGSIZE 60000 Field program[PROGSIZE]; int counter = 0; int assoc_search(IntTable *, char *); int printField(Field *); Field field_search(FieldTable *, char *); Field *field_copy(Field *, Field); %} %union { int ival; float fval; char *sval; } %token <sval> IDENT %token <ival> INTEGER %token COL DOL CAMMA MINUS LPAREN RPAREN %token EOL %type <ival> integer %type <sval> ident %% input : | input line ; line : EOL | rform EOL | iform EOL | jform EOL ; rform : ident DOL integer CAMMA DOL integer CAMMA DOL integer{ Field *field = &program[counter++]; field->type = RForm; field->op = 0; field->rs = $6; field->rt = $9; field->rd = $3; field->shamt = 0; field->fun = assoc_search(&funtable, $1); } | ident DOL integer { Field *field = &program[counter++]; field->type = RForm; field->op = 0; field->rs = $3; field->rt = 0; field->rd = 0; field->shamt = 0; field->fun = assoc_search(&funtable, $1); } | ident DOL integer CAMMA DOL IDENT { Field *field = &program[counter++]; field->type = RForm; field->op = assoc_search(&optable, $1); field->rs = 0; field->rt = 14; field->rd = $3; field->shamt = 0; field->fun = 0; } | ident DOL IDENT CAMMA DOL integer { Field *field = &program[counter++]; field->type = RForm; field->op = assoc_search(&optable, $1); field->rs = 4; field->rt = $6; field->rd = 12; field->shamt = 0; field->fun = 0; } | ident { Field *field = &program[counter++]; field_copy(field, field_search(&constTable, $1)); } ; iform : ident DOL integer CAMMA DOL integer CAMMA integer{ Field *field = &program[counter++]; int fun; if((fun = assoc_search(&funtable, $1))!=-1){ field->type = RForm; field->op = 0; field->rs = 0; field->rt = $6; field->rd = $3; field->shamt = $8; field->fun = fun; } else{ field->type = IForm; field->op = assoc_search(&optable, $1); field->rs = $6; field->rt = $3; field->imm = $8; } } | ident DOL integer CAMMA integer LPAREN DOL integer RPAREN{ Field *field = &program[counter++]; field->type = IForm; field->op = assoc_search(&optable, $1); field->rs = $8; field->rt = $3; field->imm = $5; } | ident DOL integer CAMMA integer{ Field *field = &program[counter++]; field->type = IForm; field->op = assoc_search(&optable, $1); field->rs = 0; field->rt = $3; field->imm = $5; } ; jform : ident integer { Field *field = &program[counter++]; field->type = JForm; field->op = assoc_search(&optable, $1); field->target = $2; } ; ident : IDENT { $$ = strncpy(strbuf, $1, MAXCHAR);} ; integer : INTEGER { $$ = $1;} | MINUS INTEGER { $$ = - $2;} ; %% int assoc_search(IntTable *assoc, char *key) { int val, i; for(i=0;i<assoc->len;++i){ if(strcmp(key, assoc->data[i].key)==0){ return assoc->data[i].val; } } return -1; } void printBin(unsigned int val, int len) { for(;len>0;--len){ int x = (val&((1<<len-1))) != 0; putchar('0'+x); } } int printFieldBin(Field *field) { switch(field->type){ default: case RForm: printBin(field->op, 6); printBin(field->rs, 5); printBin(field->rt, 5); printBin(field->rd, 5); printBin(field->shamt, 5); printBin(field->fun, 6); break; case IForm: printBin(field->op, 6); printBin(field->rs, 5); printBin(field->rt, 5); printBin(field->imm, 16); break; case JForm: printBin(field->op, 6); printBin(field->target, 26); break; } return 1; } unsigned long field2ulong(Field *field) { unsigned long result = 0; switch(field->type){ default: case RForm: result = field->op<<26; result |= field->rs<<21; result |= field->rt<<16; result |= field->rd<<11; result |= field->shamt<<6; result |= field->fun; return result; case IForm: result = field->op<<26; result |= field->rs<<21; result |= field->rt<<16; result |= (field->imm)&65535; return result; case JForm: result = field->op<<26; result |= field->target; return result; } } Field field_search(FieldTable *fassoc, char *key) { int val, i; for(i=0;i<fassoc->len;++i){ if(strcmp(key, fassoc->data[i].key)==0){ return fassoc->data[i].field; } } return fassoc->data[0].field; } Field *field_copy(Field *dest, Field src) { *dest = src; return dest; } int yyerror(const char *s) { fprintf(stderr, "%s\n", s); } int main() { int pc; yyparse(); for(pc=0;pc<counter;++pc){ printf("%08X", field2ulong(&program[pc])); putchar('\n'); } }
てきとうだなあ。