! (Intel, AMD, etc) 8051 family assembler ! (c) May 1989 RWT - all rights reserved ! The user source file should be structured as follows: ! ! %begin ! %include "" ! program name = "" {optional but recommended} !
! %end {of DO PASS routine which begins at the end of this file} ! %end {matching the %begin} ! ! The contents of PROGRAM NAME are used to name the listing and code files. %option "-nons" %ownstring(31)program name = "8051" %externalroutinespec phex4(%integer x) %externalroutinespec phex2(%integer x) %constinteger blank = 255 {0 for on-chip rom, 255 for separate eprom} %constinteger - eprom2732=4096, eprom2764=8192, eprom27128=16384, eprom27256=32768, eprom27512=65536, promsize=eprom2764 %ownbytearray codebuffer(0:promsize-1) %owninteger pass,maxpc,pc,errors,orgno,labelno,instno %ownintegername orglab ! Operand codes: ! Literals in the signed/unsigned byte range stand for themselves. ! Other operands are represented by values greater than 1023. %constinteger - minnum=-128,maxnum=255, r7=-257,r6=-258,r5=-259,r4=-260, r3=-261,r2=-262,r1=-263,r0=-264, xr1=-265,xr0=-266, a=-267,c=-268,dptr=-269, xdptr=-270,xadptr=-271,xapc=-272, byte0=-1024,byte255=255-1024, bit0=-1536,bit255=255-1536, p0=byte0+16_80, p1=byte0+16_90, p2=byte0+16_a0, p3=byte0+16_b0, sp=byte0+16_81, pcon=byte0+16_87, dpl=byte0+16_82, dph=byte0+16_83, tcon=byte0+16_88, tmod=byte0+16_89, tl0=byte0+16_8a, tl1=byte0+16_8b, th0=byte0+16_8c, th1=byte0+16_8d, scon=byte0+16_98, sbuf=byte0+16+99, ie=byte0+16_a8, ip=byte0+16_b8, psw=byte0+16_d0, acc=byte0+16_e0, b=byte0+16_f0 %routine error(%string(255)s) ! Print error message (NL deferred to allow for error details) %routine report phex4(pc) %unless orglab==nil %start space %if orglab==orgno %then printsymbol('O') %else printsymbol('L') write(orglab,0) %finish printstring(" I"); write(instno,0) %if s="" %start write(errors,1); printstring(" error") printsymbol('s') %unless errors=1 %else printstring(" ***** ") printstring(s) %finish %end %returnif pass=1 selectoutput(0); report; newline selectoutput(1); newline; report errors = errors+1 %end %routine put(%integer x) codebuffer(pc) = x&255 %unless pc>=promsize pc = pc+1; maxpc = pc %if pc>maxpc %end %routine dump(%integer x) put(x); instno = instno+1 %end %routine dump2(%integer x,y) put(x); put(y); instno = instno+1 %end %routine dump3(%integer x,y,z) put(x); put(y); put(z); instno = instno+1 %end ! Checkers %predicate r(%integer n); %trueif n!7=r7; %false; %end %predicate xr(%integer n); %trueif n!1=xr1; %false; %end %predicate bit(%integer n); %trueif n!255=bit255; %false; %end %predicate byte(%integer n); %trueif n!255=byte255; %false; %end %predicate literal(%integer n); %trueif minnum<=n<=maxnum; %false; %end %routine must be r(%integer n); %returnif r(n) error("Operand R0-R7 expected"); %end %routine must be xr(%integer n); %returnif xr(n) error("Operand XR0-XR1 expected"); %end %routine must be bit(%integer n); %returnif bit(n) error("Bit variable expected"); %end %routine must be byte(%integer n); %returnif byte(n) error("Byte variable expected"); %end %routine must be literal(%integer n); %returnif literal(n) error("Literal operand expected"); %end %routine rel(%integer label) %unless pass=1 %start error("Label not declared") %if label=0; label = label-pc-1 error("Label too far for relative jump") %unless -128<=label<=127 %finish dump(label) %end %predicate reachable(%integer x) %trueif (x-pc-2)&(-16_800) = 0; %false %end %routine reach(%integer x) error("Label not declared") %if x=0 error("Label out of reach") %unless reachable(x) %end ! Declarators %owninteger bitloc=0,byteloc=0 %routine bitvar(%integername var, %integer bits) var = bitloc; bitloc = bitloc+bits %end %routine bytevar(%integername var, %integer bytes) var = byteloc; byteloc = byteloc+bytes %end %integerfn bytebit(%integer base,bit) mustbebyte(base); error("Invalid bit number") %unless bit>>3=0 %result = base-byte0+bit0+bit&7 %end %routine bytevarbit(%integername var, %integer base,bit) must be byte(base) error("Byte variable not bit-addressable") %unless base&7=0 var = bytebit(base,bit) %end %routine label(%integername x) orglab == labelno; labelno = labelno+1; instno = 1 %if pass=1 %start x = pc %else %unless x=pc %start error("Duplicate label "); phex4(x) %finish %finish %end ! Instructions %routine nop; dump(16_00); %end %routine swap a; dump(16_c4); %end %routine rl a; dump(16_23); %end %routine rlc a; dump(16_33); %end %routine rr a; dump(16_03); %end %routine rrc a; dump(16_13); %end %routine ret; dump(16_22); %end %routine reti; dump(16_32); %end %routine mul ab; dump(16_a4); %end %routine div ab; dump(16_84); %end %routine daa; dump(16_d4); %end %routine jmp xad; dump(16_73); %end %routine xchd(%integer p) must be xr(p); dump(16_d4+p&1) %end %routine clr(%integer x) %if x=a %then dump(16_e4) %else- %if x=c %then dump(16_c3) %elsestart must be bit(x); dump2(16_c2,x) %finish %end %routine cpl(%integer x) %if x=a %then dump(16_f4) %else- %if x=c %then dump(16_b3) %elsestart must be bit(x); dump2(16_b2,x) %finish %end %routine inc(%integer x) %if x=dptr %then dump(16_a3) %else- %if x=a %then dump(16_04) %else- %if r(x) %then dump(16_08+x&7) %else- %if xr(x) %then dump(16_06+x&1) %elsestart must be byte(x); dump2(16_05,x) %finish %end %routine dec(%integer x) %if x=a %then dump(16_14) %else- %if r(x) %then dump(16_18+x&7) %else- %if xr(x) %then dump(16_16+x&1) %elsestart must be byte(x); dump2(16_15,x) %finish %end %routine binary(%integer o,p) %if literal(p) %start dump2(o+4,p) %elseif r(p) dump(o+8+p&7) %elseif xr(p) dump(o+6+p&1) %else must be byte(p); dump2(p+5,p) %finish %end %routine add(%integer x); binary(16_20,x); %end %routine addc(%integer x); binary(16_30,x); %end %routine subb(%integer x); binary(16_90,x); %end %routine xch(%integer x) %if literal(x) %start x = byte0; error("No literal allowed") %finish binary(16_c0,x) %end %routine aox(%integer o,d,s) %if d=a %then binary(o,s) %else- %if d=c %start %if bit(\s) %start s = s!!255; o = o+16_60-16_32 %elseunless bit(s) s = bit0 error("Invalid source for destination C") %finish dump2(o+16_32,s) %else error("Invalid destination") %unless byte(d) %if s=a %then dump2(o+2,d) %elsestart must be literal(s); dump3(o+3,d,s) %finish %finish %end %routine anl(%integer d,s); aox(16_50,d,s); %end %routine orl(%integer d,s); aox(16_40,d,s); %end %routine xrl(%integer d,s) error("Invalid destination") %if d=c aox(16_60,d,s) %end %routine acall(%integer x) reach(x); dump2(x>>8<<5+17,x) %end %routine ajmp(%integer x) reach(x); dump2(x>>8<<5+1,x) %end %routine sjmp(%integer x) put(16_80); rel(x) %end %routine lcall(%integer x) dump3(18,x>>8,x) %end %routine ljmp(%integer x) dump3(2,x>>8,x) %end %routine call(%integer x) %if reachable(x) %then acall(x) %else lcall(x) %end %routine jmp(%integer x) dump(16_73) %andreturnif x=xadptr %if -128<=x-pc-2<=127 %then sjmp(x) %else- %if reachable(x) %then ajmp(x) %else ljmp(x) %end %routine djnz(%integer x,l) %if r(x) %then put(16_d8+x&7) %elsestart must be byte(x); put(16_d5); put(x) %finish rel(l) %end %routine cjne(%integer ra,x,l) %if ra=a %start %if byte(x) %then put(16_b5) %elsestart must be literal(x); put(16_b4) %finish put(x); rel(l) %else error("Invalid operands") %unless r(ra) must be literal(x); put(16_b8+ra&7); put(x); rel(l) %finish %end %routine jb(%integer b,l); must be bit(b); put(16_20); put(b); rel(l); %end %routine jnb(%integer b,l); must be bit(b); put(16_30); put(b); rel(l); %end %routine jbc(%integer b,l); must be bit(b); put(16_10); put(b); rel(l); %end %routine jc(%integer l); put(16_40); rel(l); %end %routine jnc(%integer l); put(16_50); rel(l); %end %routine jz(%integer l); put(16_60); rel(l); %end %routine jnz(%integer l); put(16_70); rel(l); %end %routine mov(%integer d,s) %if xr(d) %start %if s=a %then dump(16_f6+d&1) %else- %if byte(s) %then dump2(16_a6+d&1,s) %elsestart must be literal(s); dump2(16_76+d&1,s) %finish %elseif d=a %if r(s) %then dump(16_e8+s&7) %else- %if xr(s) %then dump(16_e6+s&1) %else- %if byte(s) %and s#acc %then dump2(16_e5,s) %elsestart must be literal(s); dump2(16_74,s) %finish %elseif s=c must be byte(d); dump2(16_92,d) %elseif d=c must be byte(s); dump2(16_a2,s) %elseif d=dptr dump3(16_90,s>>8,s) %elseif r(d) %if s=a %then dump(16_f8+d&7) %else- %if byte(s) %then dump2(16_a8+d&7,s) %elsestart must be literal(s); dump2(16_78+d&7,s) %finish %elseif byte(d) %if s=a %then dump2(16_f5,d) %else- %if r(s) %then dump2(16_88+s&7,d) %else- %if xr(s) %then dump2(16_86+s&1,d) %else- %if byte(s) %then dump3(16_85,s,d) %elsestart must be literal(s); dump3(16_75,d,s) %finish %else error("Invalid operands for MOV"); nop %finish %end %routine movc(%integer x) %if x=xapc %then dump(16_83) %elseif x=xadptr %then dump(16_93)- %else error("Invalid operand for MOVC") %and nop %end %routine movx(%integer d,s) %if s=a %start %if xr(d) %then dump(16_f2+d&1) %else- %if d=xdptr %then dump(16_f0) %else- error("Invalid MOVX destination") %and nop %elseif d=a %if xr(s) %then dump(16_e2+s&1) %else- %if s=xdptr %then dump(16_e0) %else- error("Invalid MOVX source") %and nop %else error("Invalid MOVX operands"); nop %finish %end %routine push(%integer x); must be byte(x); dump2(16_c0,x); %end %routine pop(%integer x); must be byte(x); dump2(16_d0,x); %end %routine setb(%integer x) %if b=c %then dump(16_d3) %elsestart must be bit(x); dump2(16_d2,x) %finish %end ! Directives %routine org(%integer x) ! Set location counter to X error("ORG backwards?") %if xpromsize newline; error("") newline; closeoutput openoutput(1,program name.".obj"); selectoutput(1) maxpc = promsize %if maxpc>promsize printsymbol(codebuffer(pc)) %for pc = 0,1,maxpc-1 closeoutput %routine do pass errors = 0; maxpc = 0; pc = 0; labelno=0; orgno=0; orglab == nil; instno=1 {END of include file}