/* * as81.c * Assemble a line. */ #include #include "as8.h" /* * Assemble a line. */ asmline() { register struct sym *sp; register int rs, rd; int a, c, opcode; char id[NCPS]; listaddr = dot->s_value; listmode = SLIST; loop: if((c=getnb())=='\0' || c=='/') return; if(!alpha(c)) { err('q'); return; } getid(c, id); /* * Direct assignment. */ if((c=getnb()) == '=') { sp = lookup(id, ust); if(sp->s_type!=S_UND && (sp->s_flag&SF_ASG)==0) err('m'); sp->s_type = S_ABS; sp->s_flag |= SF_ASG; sp->s_value = listaddr = expr(); listmode = ALIST; /* * Label. */ } else if(c == ':') { if((sp=lookup(id, ust)) == dot) err('.'); else if(pass==0) { if(sp->s_type!=S_UND && (sp->s_flag&SF_ASG)==0) sp->s_flag |= SF_MDF; sp->s_type = S_ABS; sp->s_value = dot->s_value; } else { if((sp->s_flag&SF_MDF)!=0) err('m'); if(sp->s_type!=S_ABS || sp->s_value!=dot->s_value) err('p'); } listmode = ALIST; goto loop; /* * Normal (keyword) line. */ } else { putback(c); listmode = CLIST; if((sp=lookup(id, pst)) == NULL) err('o'); else { opcode = sp->s_value; switch(sp->s_type) { case S_ENTRY: entaddr = expr(); break; case S_BYTE: do { a = expr(); byte(a); codeb(a); } while((c=getnb()) == ','); putback(c); break; case S_WORD: do { codew(expr()); } while((c=getnb()) == ','); putback(c); break; case S_ASCII: ascii(0); break; case S_ASCIZ: ascii(1); break; case S_BLKB: a = expr(); while(a--) codeb(0); listmode = ALIST; break; case S_OP1: codeb(opcode); break; case S_OP2: a = expr(); byte(a); codeb(opcode); codeb(a); break; case S_OP3: rd = getreg(S_REG); comma(); a = expr(); byte(a); code3(opcode, rd); codeb(a); break; case S_OP4: rd = getreg(S_REG); comma(); rs = getreg(S_REG); codeb(opcode | rd<<3 | rs); break; case S_OP5: if((rd=getreg(S_REGP))!=BC && rd!=DE) err('a'); code4(opcode, rd); break; case S_OP6: if((rd=getreg(S_REGP)) == PSW) err('a'); code4(opcode, rd); break; case S_OP7: if((rd=getreg(S_REGP)) == SP) err('a'); if(rd == PSW) rd = SP; code4(opcode, rd); break; case S_OP8: a = expr(); if(a<0 || a>7) err('t'); code3(opcode, a&07); break; case S_OP9: rs = getreg(S_REG); if(opcode==INR || opcode==DCR) code3(opcode, rs); else codeb(opcode | rs); break; case S_OP10: if((rd=getreg(S_REGP)) == PSW) err('a'); comma(); a = expr(); code4(opcode, rd); codew(a); break; case S_OP11: a = expr(); codeb(opcode); codew(a); break; default: err('o'); } } } if((c=getnb())!='\0' && c!='/') err('q'); } /* * Process the body of .ascii * and .asciz pseudo ops. * The z flag is true for a * .asciz */ ascii(z) { register int c, delim; if((delim=getnb()) == '\0') { err('q'); return; } while((c=getmap())!='\0' && c!=delim) codeb(c); if(c == '\0') err('q'); if(z) codeb(0); } /* * Get a register. * Type is either S_REG or S_REGP. */ getreg(type) { register struct sym *sp; register int c; char id[NCPS]; if(!alpha(c=getnb())) { err('a'); putback(c); return(0); } getid(c, id); if((sp=lookup(id, pst))==NULL || sp->s_type!=type) { err('a'); return(0); } return(sp->s_value); } /* * Insure that the value of * an expression is a legal * byte value. * Error if not. */ byte(b) { if((b&0200)!=0) b |= ~0377; if(b>127 || b<-128) err('t'); } /* * Check for `,'. */ comma() { if(getnb() != ',') err('a'); } /* * Build instructions of the * general form xxrrrxxx. */ code3(x, r) { codeb(x | r<<3); } /* * Build instructions of the * general form xxrrxxxx. */ code4(x, r) { codeb(x | r<<4); }