//------------------------------------------------------------------- unsigned int parse_branch_label ( unsigned int ra ) { unsigned int rb; unsigned int rc; is_const=0; is_label=0; for(;newline[ra];ra++) if(newline[ra]!=0x20) break; if(numchar[newline[ra]]) { ra=parse_immed(ra); if(ra==0) return(0); is_const=1; } else { //assume label, find space or eol. for(rb=ra;newline[rb];rb++) { if(newline[rb]==0x20) break; //no spaces in labels } //got a label rc=rb-ra; if(rc==0) { printf("<%u> Error: Invalid label\n",line); return(0); } rc--; if(rc>=LABLEN) { printf("<%u> Error: Label too long\n",line); return(0); } for(rb=0;rb<=rc;rb++) { lab_struct[nlabs].name[rb]=newline[ra++]; } lab_struct[nlabs].name[rb]=0; lab_struct[nlabs].addr=curradd; lab_struct[nlabs].line=line; lab_struct[nlabs].type=1; nlabs++; rx=0; is_label=1; } return(ra); }
//------------------------------------------------------------------- //------------------------------------------------------------------- int assemble ( void ) { unsigned int ra; unsigned int rb; unsigned int rc; curradd=0; nlabs=0; memset(mem,0x00,sizeof(mem)); memset(mark,0x00,sizeof(mark)); line=0; while(fgets(newline,sizeof(newline)-1,fpin)) { line++; //tabs to spaces and other things for(ra=0;newline[ra];ra++) { if(newline[ra]<0x20) newline[ra]=0x20; if(newline[ra]>=0x7F) newline[ra]=0; } //various ways to comment lines for(ra=0;newline[ra];ra++) { if(newline[ra]==';') newline[ra]=0; if(newline[ra]=='@') newline[ra]=0; if((newline[ra]=='/')&&(newline[ra+1]=='/')) newline[ra]=0; if(newline[ra]==0) break; } //skip spaces for(ra=0;newline[ra];ra++) if(newline[ra]!=0x20) break; if(newline[ra]==0) continue; //look for a label? for(rb=ra;newline[rb];rb++) { if(newline[rb]==0x20) break; //no spaces in labels if(newline[rb]==':') break; } if(newline[rb]==':') { //got a label rc=rb-ra; if(rc==0) { printf("<%u> Error: Invalid label\n",line); return(1); } rc--; if(rc>=LABLEN) { printf("<%u> Error: Label too long\n",line); return(1); } for(rb=0;rb<=rc;rb++) { lab_struct[nlabs].name[rb]=newline[ra++]; } lab_struct[nlabs].name[rb]=0; lab_struct[nlabs].addr=0x3000+curradd; lab_struct[nlabs].line=line; lab_struct[nlabs].type=0; ra++; for(lab=0;lab<nlabs;lab++) { if(lab_struct[lab].type) continue; if(strcmp(lab_struct[lab].name,lab_struct[nlabs].name)==0) break; } if(lab<nlabs) { printf("<%u> Error: label [%s] already defined on line %u\n",line,lab_struct[lab].name,lab_struct[lab].line); return(1); } nlabs++; //skip spaces for(;newline[ra];ra++) if(newline[ra]!=0x20) break; if(newline[ra]==0) continue; } // .word ----------------------------------------------------------- if(strncmp(&newline[ra],".word ",6)==0) { ra+=6; ra=parse_immed(ra); if(ra==0) return(1); mem[curradd]=rx; mark[curradd]|=0x80000000; curradd++; if(rest_of_line(ra)) return(1); continue; } // add ----------------------------------------------------------- if(strncmp(&newline[ra],"add ",4)==0) { ra+=4; //add rd,rs,rx //add rd,rs,#imm ra=parse_two_regs(ra); if(ra==0) return(1); ra=parse_comma(ra); if(ra==0) return(1); if(newline[ra]=='#') { ra=parse_immed(ra+1); if(ra==0) return(1); if(check_simmed5(rx)) return(1); mem[curradd]=0x1020|(rd<<9)|(rs<<6)|(rx&0x1F); mark[curradd]|=0x80000000; curradd++; } else { ra=parse_reg(ra); if(ra==0) return(1); mem[curradd]=0x1000|(rd<<9)|(rs<<6)|rx; mark[curradd]|=0x80000000; curradd++; } if(rest_of_line(ra)) return(1); continue; } // and ----------------------------------------------------------- if(strncmp(&newline[ra],"and ",4)==0) { ra+=4; //and rd,rs,rx //and rd,rs,#imm ra=parse_two_regs(ra); if(ra==0) return(1); ra=parse_comma(ra); if(ra==0) return(1); if(newline[ra]=='#') { ra=parse_immed(ra+1); if(ra==0) return(1); if(check_simmed5(rx)) return(1); mem[curradd]=0x5020|(rd<<9)|(rs<<6)|(rx&0x1F); mark[curradd]|=0x80000000; curradd++; } else { ra=parse_reg(ra); if(ra==0) return(1); mem[curradd]=0x5000|(rd<<9)|(rs<<6)|rx; mark[curradd]|=0x80000000; curradd++; } if(rest_of_line(ra)) return(1); continue; } // jmp ----------------------------------------------------------- if(strncmp(&newline[ra],"jmp ",4)==0) { ra+=4; //jmp rs ra=parse_reg(ra); if(ra==0) return(1); mem[curradd]=0xC000|(rx<<6); mark[curradd]|=0x80000000; curradd++; if(rest_of_line(ra)) return(1); continue; } // jsrr ----------------------------------------------------------- if(strncmp(&newline[ra],"jsrr ",5)==0) { ra+=5; //jsrr rs ra=parse_reg(ra); if(ra==0) return(1); mem[curradd]=0x4000|(rx<<6); mark[curradd]|=0x80000000; curradd++; if(rest_of_line(ra)) return(1); continue; } // not ----------------------------------------------------------- if(strncmp(&newline[ra],"not ",4)==0) { ra+=4; //not rd,rs ra=parse_two_regs(ra); if(ra==0) return(1); mem[curradd]=0x9000|(rd<<9)|(rs<<6); mark[curradd]|=0x80000000; curradd++; if(rest_of_line(ra)) return(1); continue; } // ret ----------------------------------------------------------- if(strncmp(&newline[ra],"ret",3)==0) { ra+=3; //ret mem[curradd]=0xC1C0; mark[curradd]|=0x80000000; curradd++; if(rest_of_line(ra)) return(1); continue; } // rti ----------------------------------------------------------- if(strncmp(&newline[ra],"rti",3)==0) { ra+=3; //rti mem[curradd]=0x8000; mark[curradd]|=0x80000000; curradd++; if(rest_of_line(ra)) return(1); continue; } // brn ----------------------------------------------------------- if(strncmp(&newline[ra],"brn ",4)==0) { ra+=4; //brn offset/label ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: branch too far\n",line); return(1); } mem[curradd]=0x0800|(rx&0x1FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x0800; mark[curradd]|=0x80000002; curradd++; } continue; } // brz ----------------------------------------------------------- if(strncmp(&newline[ra],"brz ",4)==0) { ra+=4; //brz offset/label ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: branch too far\n",line); return(1); } mem[curradd]=0x0400|(rx&0x1FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x0400; mark[curradd]|=0x80000002; curradd++; } continue; } // brp ----------------------------------------------------------- if(strncmp(&newline[ra],"brp ",4)==0) { ra+=4; //brp offset/label ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: branch too far\n",line); return(1); } mem[curradd]=0x0200|(rx&0x1FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x0200; mark[curradd]|=0x80000002; curradd++; } continue; } // brnz ----------------------------------------------------------- if(strncmp(&newline[ra],"brnz ",5)==0) { ra+=5; //brnzp offset/label ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: branch too far\n",line); return(1); } mem[curradd]=0x0C00|(rx&0x1FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x0C00; mark[curradd]|=0x80000002; curradd++; } continue; } // brnp ----------------------------------------------------------- if(strncmp(&newline[ra],"brnp ",5)==0) { ra+=5; //brnp offset/label ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: branch too far\n",line); return(1); } mem[curradd]=0x0A00|(rx&0x1FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x0A00; mark[curradd]|=0x80000002; curradd++; } continue; } // brzp ----------------------------------------------------------- if(strncmp(&newline[ra],"brzp ",5)==0) { ra+=5; //brzp offset/label ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: branch too far\n",line); return(1); } mem[curradd]=0x0600|(rx&0x1FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x0600; mark[curradd]|=0x80000002; curradd++; } continue; } // brnzp ----------------------------------------------------------- if(strncmp(&newline[ra],"brnzp ",6)==0) { ra+=6; //brnzp offset/label ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: branch too far\n",line); return(1); } mem[curradd]=0x0E00|(rx&0x1FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x0E00; mark[curradd]|=0x80000002; curradd++; } continue; } // jsr ----------------------------------------------------------- if(strncmp(&newline[ra],"jsr ",4)==0) { ra+=4; //jsr offset/label ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset11(rx)) { printf("<%u> Error: jsr too far\n",line); return(1); } mem[curradd]=0x4800|(rx&0x07FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x4800; mark[curradd]|=0x80000002; curradd++; } continue; } // ld ----------------------------------------------------------- if(strncmp(&newline[ra],"ld ",3)==0) { ra+=3; //ld rd,offset/label ra=parse_reg(ra); if(ra==0) return(1); rd=rx; ra=parse_comma(ra); if(ra==0) return(1); ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: ld too far\n",line); return(1); } mem[curradd]=0x2000|(rd<<9)|(rx&0x01FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x2000|(rd<<9); mark[curradd]|=0x80000002; curradd++; } continue; } // ldi ----------------------------------------------------------- if(strncmp(&newline[ra],"ldi ",4)==0) { ra+=4; //ldi rd,offset/label ra=parse_reg(ra); if(ra==0) return(1); rd=rx; ra=parse_comma(ra); if(ra==0) return(1); ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: ldi too far\n",line); return(1); } mem[curradd]=0xA000|(rd<<9)|(rx&0x01FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0xA000|(rd<<9); mark[curradd]|=0x80000002; curradd++; } continue; } // ldr ----------------------------------------------------------- if(strncmp(&newline[ra],"ldr ",4)==0) { ra+=4; //ldr rd,rs,#offset ra=parse_two_regs(ra); if(ra==0) return(1); ra=parse_comma(ra); if(ra==0) return(1); ra=parse_pound(ra); if(ra==0) return(1); ra=parse_immed(ra); if(ra==0) return(1); if(rest_of_line(ra)) return(1); if(check_simmed6(rx)) return(1); mem[curradd]=0x6000|(rd<<9)|(rs<<6)|(rx&0x003F); mark[curradd]|=0x80000000; curradd++; continue; } // lea ----------------------------------------------------------- if(strncmp(&newline[ra],"lea ",4)==0) { ra+=4; //ldi rd,offset/label ra=parse_reg(ra); if(ra==0) return(1); rd=rx; ra=parse_comma(ra); if(ra==0) return(1); ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: lea too far\n",line); return(1); } mem[curradd]=0xE000|(rd<<9)|(rx&0x01FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0xE000|(rd<<9); mark[curradd]|=0x80000002; curradd++; } continue; } // st ----------------------------------------------------------- if(strncmp(&newline[ra],"st ",3)==0) { ra+=3; //st rd,offset/label ra=parse_reg(ra); if(ra==0) return(1); rd=rx; ra=parse_comma(ra); if(ra==0) return(1); ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: st too far\n",line); return(1); } mem[curradd]=0x3000|(rd<<9)|(rx&0x01FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0x3000|(rd<<9); mark[curradd]|=0x80000002; curradd++; } continue; } // sti ----------------------------------------------------------- if(strncmp(&newline[ra],"sti ",4)==0) { ra+=4; //sti rd,offset/label ra=parse_reg(ra); if(ra==0) return(1); rd=rx; ra=parse_comma(ra); if(ra==0) return(1); ra=parse_branch_label(ra); if(ra==0) return(0); if(rest_of_line(ra)) return(1); if(is_const) { if(check_offset9(rx)) { printf("<%u> Error: sti too far\n",line); return(1); } mem[curradd]=0xB000|(rd<<9)|(rx&0x01FF); mark[curradd]|=0x80000000; curradd++; } else { mem[curradd]=0xB000|(rd<<9); mark[curradd]|=0x80000002; curradd++; } continue; } // str ----------------------------------------------------------- if(strncmp(&newline[ra],"str ",4)==0) { ra+=4; //str rd,rs,#offset ra=parse_two_regs(ra); if(ra==0) return(1); ra=parse_comma(ra); if(ra==0) return(1); ra=parse_pound(ra); if(ra==0) return(1); ra=parse_immed(ra); if(ra==0) return(1); if(rest_of_line(ra)) return(1); if(check_simmed6(rx)) return(1); mem[curradd]=0x7000|(rd<<9)|(rs<<6)|(rx&0x003F); mark[curradd]|=0x80000000; curradd++; continue; } // trap ----------------------------------------------------------- if(strncmp(&newline[ra],"trap ",5)==0) { ra+=5; //trap imm ra=parse_immed(ra); if(ra==0) return(1); if((rx&0xFF)!=rx) { printf("<%u> Error: invalid trap vector\n",line); return(1); } mem[curradd]=0xF000|(rx&0xFF); mark[curradd]|=0x80000000; curradd++; if(rest_of_line(ra)) return(1); continue; } // ----------------------------------------------------------- printf("<%u> Error: syntax error\n",line); return(1); } return(0); }
int parse_inst(char *label, char *inst, char args[][16]) { int i=0; int j; WORD a[3]; int len; /* find the instruction */ while( instructions[i].inst ) { if( !strcasecmp(instructions[i].inst,inst) ) break; i++; } /* check if we had a match */ if( !instructions[i].inst ) { /* didn't find the instruction */ pendvm_error("undefined instruction"); return -1; } /* we have a match. process each of the 3 args */ for(j=0;j<3;j++) { switch(instructions[i].args[j]) { case NIL: a[j]=0; break; case REG: { int reg=parse_reg(args[j]); if(reg==-1) { pendvm_error("expected register"); return -1; } else if(reg==-2) { pendvm_error("register out of range"); return -1; } else { a[j]=reg; } break; } case AMT: case IMM: { int *immed; if( instructions[i].args[j]==AMT ) len=16; else len=5; /* ??? */ immed=parse_immed(args[j],len); if( !immed ) { pendvm_error("bad immediate/amt"); return -1; } else { a[j]=*immed; } break; } case OFF: case LOFF: { int *absolute; if( instructions[i].args[j]==OFF ) len=16; else len=26; /* ??? */ absolute=parse_immed(args[j],len); if( !absolute ) { pendvm_error("bad offset"); return -1; } else { a[j]=*absolute - m->PC; } break; } } /* switch */ } /* for (step through 3 args) */ /* now do the right thing */ return (*instructions[i].func)(a[0],a[1],a[2]); }