├── README.md ├── clean.sh ├── test.sh └── smallc.c /README.md: -------------------------------------------------------------------------------- 1 | # smallc 2 | Derivative of Ron Cain's Small C Compiler 3 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | rm -f smallc smallc2 4 | rm -f smallc.s smallc2.s 5 | rm -f smallc.i 6 | rm -f core.* 7 | 8 | exit 0 9 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | gcc -m32 -w -o smallc smallc.c || exit 1 4 | 5 | gcc -DSMALLC -E -P -o smallc.i smallc.c || exit 1 6 | 7 | ./smallc <<><> Small-C V1.2 DOS--CP/M Cross Compiler <><><>" 12 | 13 | #define VERSION "<><><><><> CP/M Large String Space Version <><><><><>" 14 | 15 | #define AUTHOR "<><><><><><><><><><> By Ron Cain <><><><><><><><><><>" 16 | 17 | #define LINE "<><><><><><><><><><><><><><>X<><><><><><><><><><><><><><>" 18 | 19 | 20 | /* Define system dependent parameters */ 21 | 22 | #define NULL 0 23 | #define eol 10 24 | 25 | /* Define the symbol table parameters */ 26 | 27 | #define symsiz 14 28 | #define symtbsz 5040 29 | #define numglbs 300 30 | #define startglb symtab 31 | #define endglb startglb+numglbs*symsiz 32 | #define startloc endglb+symsiz 33 | #define endloc symtab+symtbsz-symsiz 34 | 35 | /* Define symbol table entry format */ 36 | 37 | #define name 0 38 | #define ident 9 39 | #define type 10 40 | #define storage 11 41 | #define offset 12 42 | 43 | /* System wide name size (for symbols) */ 44 | 45 | #define namesize 9 46 | #define namemax 8 47 | 48 | /* Define possible entries for "ident" */ 49 | 50 | #define variable 1 51 | #define array 2 52 | #define pointer 3 53 | #define function 4 54 | 55 | /* Define possible entries for "type" */ 56 | 57 | #define cchar 1 58 | #define cint 2 59 | 60 | /* Define possible entries for "storage" */ 61 | 62 | #define statik 1 63 | #define stkloc 2 64 | 65 | /* Define the "while" statement queue */ 66 | 67 | #define wqtabsz 300 68 | #define wqsiz 4 69 | #define wqmax wq+wqtabsz-wqsiz 70 | 71 | /* Define entry offsets in while queue */ 72 | 73 | #define wqsym 0 74 | #define wqsp 1 75 | #define wqloop 2 76 | #define wqlab 3 77 | 78 | /* Define the literal pool */ 79 | 80 | #define litabsz 8000 81 | #define litmax litabsz-1 82 | 83 | /* Define the input line */ 84 | 85 | #define linesize 80 86 | #define linemax linesize-1 87 | #define mpmax linemax 88 | 89 | /* Define the macro (define) pool */ 90 | 91 | #define macqsize 3000 92 | #define macmax macqsize-1 93 | 94 | /* Define statement types (tokens) */ 95 | 96 | #define stif 1 97 | #define stwhile 2 98 | #define streturn 3 99 | #define stbreak 4 100 | #define stcont 5 101 | #define stasm 6 102 | #define stexp 7 103 | 104 | /* Define how to carve up a name too long for the assembler */ 105 | 106 | #define asmpref 7 107 | #define asmsuff 7 108 | 109 | /* Now reserve some storage words */ 110 | 111 | char symtab[symtbsz]; /* symbol table */ 112 | char *glbptr,*locptr; /* ptrs to next entries */ 113 | 114 | int wq[wqtabsz]; /* while queue */ 115 | int *wqptr; /* ptr to next entry */ 116 | 117 | char litq[litabsz]; /* literal pool */ 118 | int litptr; /* ptr to next entry */ 119 | 120 | char macq[macqsize]; /* macro string buffer */ 121 | int macptr; /* and its index */ 122 | 123 | char line[linesize]; /* parsing buffer */ 124 | char mline[linesize]; /* temp macro buffer */ 125 | int lptr,mptr; /* ptrs into each */ 126 | 127 | /* Misc storage */ 128 | 129 | int nxtlab, /* next avail label # */ 130 | litlab, /* label # assigned to literal pool */ 131 | Zsp, /* compiler relative stk ptr */ 132 | argstk, /* function arg sp */ 133 | ncmp, /* # open compound statements */ 134 | errcnt, /* # errors in compilation */ 135 | errstop, /* stop on error gtf 7/17/80 */ 136 | eof, /* set non-zero on final input eof */ 137 | input, /* iob # for input file */ 138 | output, /* iob # for output file (if any) */ 139 | input2, /* iob # for "include" file */ 140 | ctext, /* non-zero to intermix c-source */ 141 | cmode, /* non-zero while parsing c-code */ 142 | /* zero when passing assembly code */ 143 | lastst, /* last executed statement type */ 144 | saveout, /* holds output ptr when diverted to console */ 145 | /* gtf 7/16/80 */ 146 | fnstart, /* line# of start of current fn. gtf 7/2/80 */ 147 | lineno, /* line# in current file gtf 7/2/80 */ 148 | infunc, /* "inside function" flag gtf 7/2/80 */ 149 | savestart, /* copy of fnstart " " gtf 7/16/80 */ 150 | saveline, /* copy of lineno " " gtf 7/16/80 */ 151 | saveinfn; /* copy of infunc " " gtf 7/16/80 */ 152 | 153 | char *currfn, /* ptr to symtab entry for current fn. gtf 7/17/80 */ 154 | *savecurr; /* copy of currfn for #include gtf 7/17/80 */ 155 | char quote[2]; /* literal string for '"' */ 156 | char *cptr; /* work ptr to any char buffer */ 157 | 158 | /* */ 159 | /* Compiler begins execution here */ 160 | /* */ 161 | main() 162 | { 163 | glbptr=startglb; /* clear global symbols */ 164 | locptr=startloc; /* clear local symbols */ 165 | wqptr=wq; /* clear while queue */ 166 | macptr= /* clear the macro pool */ 167 | litptr= /* clear literal pool */ 168 | Zsp = /* stack ptr (relative) */ 169 | errcnt= /* no errors */ 170 | errstop= /* keep going after an error gtf 7/17/80 */ 171 | eof= /* not eof yet */ 172 | input= /* no input file */ 173 | input2= /* or include file */ 174 | output= /* no open units */ 175 | saveout= /* no diverted output */ 176 | ncmp= /* no open compound states */ 177 | lastst= /* no last statement yet */ 178 | fnstart= /* current "function" started at line 0 gtf 7/2/80 */ 179 | lineno= /* no lines read from file gtf 7/2/80 */ 180 | infunc= /* not in function now gtf 7/2/80 */ 181 | quote[1]= 182 | 0; /* ...all set to zero.... */ 183 | quote[0]='"'; /* fake a quote literal */ 184 | currfn=NULL; /* no function yet gtf 7/2/80 */ 185 | cmode=1; /* enable preprocessing */ 186 | /* */ 187 | /* compiler body */ 188 | /* */ 189 | ask(); /* get user options */ 190 | openin(); /* and initial input file */ 191 | openout(); /* get an output file */ 192 | header(); /* intro code */ 193 | parse(); /* process ALL input */ 194 | dumplits(); /* then dump literal pool */ 195 | dumpglbs(); /* and all static memory */ 196 | trailer(); /* follow-up code */ 197 | closeout(); /* close the output (if any) */ 198 | errorsummary(); /* summarize errors (on console!) */ 199 | return errcnt!=0; 200 | } 201 | 202 | /* */ 203 | /* Abort compilation */ 204 | /* gtf 7/17/80 */ 205 | zabort() 206 | { 207 | if(input2) 208 | endinclude(); 209 | if(input) 210 | fclose(input); 211 | closeout(); 212 | toconsole(); 213 | pl("Compilation aborted."); nl(); 214 | exit(1); 215 | /* end zabort */} 216 | 217 | /* */ 218 | /* Process all input text */ 219 | /* */ 220 | /* At this level, only static declarations, */ 221 | /* defines, includes, and function */ 222 | /* definitions are legal... */ 223 | parse() 224 | { 225 | while (eof==0) /* do until no more input */ 226 | { 227 | if(amatch("char",4)){declglb(cchar);ns();} 228 | else if(amatch("int",3)){declglb(cint);ns();} 229 | else if(match("#asm"))doasm(); 230 | else if(match("#include"))doinclude(); 231 | else if(match("#define"))addmac(); 232 | else newfunc(); 233 | blanks(); /* force eof if pending */ 234 | } 235 | } 236 | /* */ 237 | /* Dump the literal pool */ 238 | /* */ 239 | dumplits() 240 | {int j,k; 241 | if (litptr==0) return; /* if nothing there, exit...*/ 242 | printlabel(litlab);col(); /* print literal label */ 243 | k=0; /* init an index... */ 244 | while (k=litptr)) 250 | {nl(); /* need */ 251 | break; 252 | } 253 | outbyte(','); /* separate bytes */ 254 | } 255 | } 256 | } 257 | /* */ 258 | /* Dump all static variables */ 259 | /* */ 260 | dumpglbs() 261 | { 262 | int j; 263 | cptr=startglb; 264 | while (cptr>>>>> start of cc2 <<<<<<<< */ 508 | 509 | /* */ 510 | /* Get required array size */ 511 | /* */ 512 | /* invoked when declared variable is followed by "[" */ 513 | /* this routine makes subscript the absolute */ 514 | /* size of the array. */ 515 | needsub() 516 | { 517 | int num[1]; 518 | if(match("]"))return 0; /* null size */ 519 | if (number(num)==0) /* go after a number */ 520 | {error("must be constant"); /* it isn't */ 521 | num[0]=1; /* so force one */ 522 | } 523 | if (num[0]<0) 524 | {error("negative size illegal"); 525 | num[0]=(-num[0]); 526 | } 527 | needbrack("]"); /* force single dimension */ 528 | return num[0]; /* and return size */ 529 | } 530 | /* */ 531 | /* Begin a function */ 532 | /* */ 533 | /* Called from "parse" this routine tries to make a function */ 534 | /* out of what follows. */ 535 | newfunc() 536 | { 537 | char n[namesize]; /* ptr => currfn, gtf 7/16/80 */ 538 | if (symname(n)==0) 539 | {error("illegal function or declaration"); 540 | kill(); /* invalidate line */ 541 | return; 542 | } 543 | fnstart=lineno; /* remember where fn began gtf 7/2/80 */ 544 | infunc=1; /* note, in function now. gtf 7/16/80 */ 545 | if(currfn=findglb(n)) /* already in symbol table ? */ 546 | {if(currfn[ident]!=function)multidef(n); 547 | /* already variable by that name */ 548 | else if(currfn[offset]==function)multidef(n); 549 | /* already function by that name */ 550 | else currfn[offset]=function; 551 | /* otherwise we have what was earlier*/ 552 | /* assumed to be a function */ 553 | } 554 | /* if not in table, define as a function now */ 555 | else currfn=addglb(n,function,cint,function); 556 | 557 | toconsole(); /* gtf 7/16/80 */ 558 | outstr("====== "); outstr(currfn+name); outstr("()"); nl(); 559 | tofile(); 560 | 561 | ot(".global ");outname(n);nl(); 562 | outname(n);col();nl(); /* print function name */ 563 | 564 | /* we had better see open paren for args... */ 565 | if(match("(")==0)error("missing open paren"); 566 | argstk=0; /* init arg count */ 567 | while(match(")")==0) /* then count args */ 568 | /* any legal name bumps arg count */ 569 | {if(symname(n))argstk=argstk+4; 570 | else{error("illegal argument name");junk();} 571 | blanks(); 572 | /* if not closing paren, should be comma */ 573 | if(streq(line+lptr,")")==0) 574 | {if(match(",")==0) 575 | error("expected comma"); 576 | } 577 | if(endst())break; 578 | } 579 | locptr=startloc; /* "clear" local symbol table*/ 580 | Zsp=0; /* preset stack ptr */ 581 | while(argstk) 582 | /* now let user declare what types of things */ 583 | /* those arguments were */ 584 | {if(amatch("char",4)){getarg(cchar);ns();} 585 | else if(amatch("int",3)){getarg(cint);ns();} 586 | else{error("wrong number args");break;} 587 | } 588 | if(statement()!=streturn) /* do a statement, but if */ 589 | /* it's a return, skip */ 590 | /* cleaning up the stack */ 591 | {modstk(0); 592 | zret(); 593 | } 594 | Zsp=0; /* reset stack ptr again */ 595 | locptr=startloc; /* deallocate all locals */ 596 | infunc=0; /* not in fn. any more gtf 7/2/80 */ 597 | } 598 | /* */ 599 | /* Declare argument types */ 600 | /* */ 601 | /* called from "newfunc" this routine adds an entry in the */ 602 | /* local symbol table for each named argument */ 603 | getarg(t) /* t = cchar or cint */ 604 | int t; 605 | { 606 | char n[namesize],c;int j; 607 | while(1) 608 | {if(argstk==0)return; /* no more args */ 609 | if(match("*"))j=pointer; 610 | else j=variable; 611 | if(symname(n)==0) illname(); 612 | if(findloc(n))multidef(n); 613 | if(match("[")) /* pointer ? */ 614 | /* it is a pointer, so skip all */ 615 | /* stuff between "[]" */ 616 | {while(inbyte()!=']') 617 | if(endst())break; 618 | j=pointer; 619 | /* add entry as pointer */ 620 | } 621 | addloc(n,j,t,argstk); 622 | argstk=argstk-4; /* cnt down */ 623 | if(endst())return; 624 | if(match(",")==0)error("expected comma"); 625 | } 626 | } 627 | /* */ 628 | /* Statement parser */ 629 | /* */ 630 | /* called whenever syntax requires */ 631 | /* a statement. */ 632 | /* this routine performs that statement */ 633 | /* and returns a number telling which one */ 634 | statement() 635 | { 636 | if(amatch("char",4)) 637 | {declloc(cchar);ns();} 638 | else if(amatch("int",3)) 639 | {declloc(cint);ns();} 640 | else if(match("{"))compound(); 641 | else if(amatch("if",2)) 642 | {doif();lastst=stif;} 643 | else if(amatch("while",5)) 644 | {dowhile();lastst=stwhile;} 645 | else if(amatch("return",6)) 646 | {doreturn();ns();lastst=streturn;} 647 | else if(amatch("break",5)) 648 | {dobreak();ns();lastst=stbreak;} 649 | else if(amatch("continue",8)) 650 | {docont();ns();lastst=stcont;} 651 | else if(match(";")); 652 | else if(match("#asm")) 653 | {doasm();lastst=stasm;} 654 | /* if nothing else, assume it's an expression */ 655 | else{expression();ns();lastst=stexp;} 656 | return lastst; 657 | } 658 | /* */ 659 | /* Semicolon enforcer */ 660 | /* */ 661 | /* called whenever syntax requires a semicolon */ 662 | ns() {if(match(";")==0)error("missing semicolon");} 663 | /* */ 664 | /* Compound statement */ 665 | /* */ 666 | /* allow any number of statements to fall between "{}" */ 667 | compound() 668 | { 669 | ++ncmp; /* new level open */ 670 | while (match("}")==0) statement(); /* do one */ 671 | --ncmp; /* close current level */ 672 | } 673 | /* */ 674 | /* "if" statement */ 675 | /* */ 676 | doif() 677 | { 678 | int flev,fsp,flab1,flab2; 679 | flev=locptr; /* record current local level */ 680 | fsp=Zsp; /* record current stk ptr */ 681 | flab1=getlabel(); /* get label for false branch */ 682 | test(flab1); /* get expression, and branch false */ 683 | statement(); /* if true, do a statement */ 684 | Zsp=modstk(fsp); /* then clean up the stack */ 685 | locptr=flev; /* and deallocate any locals */ 686 | if (amatch("else",4)==0) /* if...else ? */ 687 | /* simple "if"...print false label */ 688 | {printlabel(flab1);col();nl(); 689 | return; /* and exit */ 690 | } 691 | /* an "if...else" statement. */ 692 | jump(flab2=getlabel()); /* jump around false code */ 693 | printlabel(flab1);col();nl(); /* print false label */ 694 | statement(); /* and do "else" clause */ 695 | Zsp=modstk(fsp); /* then clean up stk ptr */ 696 | locptr=flev; /* and deallocate locals */ 697 | printlabel(flab2);col();nl(); /* print true label */ 698 | } 699 | /* */ 700 | /* "while" statement */ 701 | /* */ 702 | dowhile() 703 | { 704 | int wq[4]; /* allocate local queue */ 705 | wq[wqsym]=locptr; /* record local level */ 706 | wq[wqsp]=Zsp; /* and stk ptr */ 707 | wq[wqloop]=getlabel(); /* and looping label */ 708 | wq[wqlab]=getlabel(); /* and exit label */ 709 | addwhile(wq); /* add entry to queue */ 710 | /* (for "break" statement) */ 711 | printlabel(wq[wqloop]);col();nl(); /* loop label */ 712 | test(wq[wqlab]); /* see if true */ 713 | statement(); /* if so, do a statement */ 714 | Zsp = modstk(wq[wqsp]); /* zap local vars: 9/25/80 gtf */ 715 | jump(wq[wqloop]); /* loop to label */ 716 | printlabel(wq[wqlab]);col();nl(); /* exit label */ 717 | locptr=wq[wqsym]; /* deallocate locals */ 718 | delwhile(); /* delete queue entry */ 719 | } 720 | /* */ 721 | /* "return" statement */ 722 | /* */ 723 | doreturn() 724 | { 725 | /* if not end of statement, get an expression */ 726 | if(endst()==0)expression(); 727 | modstk(0); /* clean up stk */ 728 | zret(); /* and exit function */ 729 | } 730 | /* */ 731 | /* "break" statement */ 732 | /* */ 733 | dobreak() 734 | { 735 | int *ptr; 736 | /* see if any "whiles" are open */ 737 | if ((ptr=readwhile())==0) return; /* no */ 738 | modstk((ptr[wqsp])); /* else clean up stk ptr */ 739 | jump(ptr[wqlab]); /* jump to exit label */ 740 | } 741 | /* */ 742 | /* "continue" statement */ 743 | /* */ 744 | docont() 745 | { 746 | int *ptr; 747 | /* see if any "whiles" are open */ 748 | if ((ptr=readwhile())==0) return; /* no */ 749 | modstk((ptr[wqsp])); /* else clean up stk ptr */ 750 | jump(ptr[wqloop]); /* jump to loop label */ 751 | } 752 | /* */ 753 | /* "asm" pseudo-statement */ 754 | /* */ 755 | /* enters mode where assembly language statement are */ 756 | /* passed intact through parser */ 757 | doasm() 758 | { 759 | cmode=0; /* mark mode as "asm" */ 760 | while (1) 761 | {readline(); /* get and print lines */ 762 | if (match("#endasm")) break; /* until... */ 763 | if(eof)break; 764 | outstr(line); 765 | nl(); 766 | } 767 | kill(); /* invalidate line */ 768 | cmode=1; /* then back to parse level */ 769 | } 770 | /* >>>>> start of cc3 <<<<<<<<< */ 771 | 772 | /* */ 773 | /* Perform a function call */ 774 | /* */ 775 | /* called from heir11, this routine will either call */ 776 | /* the named function, or if the supplied ptr is */ 777 | /* zero, will call the contents of HL */ 778 | callfunction(ptr) 779 | char *ptr; /* symbol table entry (or 0) */ 780 | { int nargs; 781 | nargs=0; 782 | blanks(); /* already saw open paren */ 783 | if(ptr==0)zpush(); /* calling HL */ 784 | while(streq(line+lptr,")")==0) 785 | {if(endst())break; 786 | expression(); /* get an argument */ 787 | if(ptr==0)swapstk(); /* don't push addr */ 788 | zpush(); /* push argument */ 789 | nargs=nargs+4; /* count args*2 */ 790 | if (match(",")==0) break; 791 | } 792 | needbrack(")"); 793 | if(ptr)zcall(ptr); 794 | else callstk(); 795 | Zsp=modstk(Zsp+nargs); /* clean up arguments */ 796 | } 797 | junk() 798 | { if(an(inbyte())) 799 | while(an(ch()))gch(); 800 | else while(an(ch())==0) 801 | {if(ch()==0)break; 802 | gch(); 803 | } 804 | blanks(); 805 | } 806 | endst() 807 | { blanks(); 808 | return ((streq(line+lptr,";")|(ch()==0))); 809 | } 810 | illname() 811 | { error("illegal symbol name");junk();} 812 | multidef(sname) 813 | char *sname; 814 | { error("already defined"); 815 | comment(); 816 | outstr(sname);nl(); 817 | } 818 | needbrack(str) 819 | char *str; 820 | { if (match(str)==0) 821 | {error("missing bracket"); 822 | comment();outstr(str);nl(); 823 | } 824 | } 825 | needlval() 826 | { error("must be lvalue"); 827 | } 828 | findglb(sname) 829 | char *sname; 830 | { char *ptr; 831 | ptr=startglb; 832 | while(ptr!=glbptr) 833 | {if(astreq(sname,ptr,namemax))return ptr; 834 | ptr=ptr+symsiz; 835 | } 836 | return 0; 837 | } 838 | findloc(sname) 839 | char *sname; 840 | { char *ptr; 841 | ptr=startloc; 842 | while(ptr!=locptr) 843 | {if(astreq(sname,ptr,namemax))return ptr; 844 | ptr=ptr+symsiz; 845 | } 846 | return 0; 847 | } 848 | addglb(sname,id,typ,value) 849 | char *sname,id,typ; 850 | int value; 851 | { char *ptr; 852 | if(cptr=findglb(sname))return cptr; 853 | if(glbptr>=endglb) 854 | {error("global symbol table overflow"); 855 | return 0; 856 | } 857 | cptr=ptr=glbptr; 858 | while(an(*ptr++ = *sname++)); /* copy name */ 859 | cptr[ident]=id; 860 | cptr[type]=typ; 861 | cptr[storage]=statik; 862 | cptr[offset]=value; 863 | cptr[offset+1]=value>>8; 864 | glbptr=glbptr+symsiz; 865 | return cptr; 866 | } 867 | addloc(sname,id,typ,value) 868 | char *sname,id,typ; 869 | int value; 870 | { char *ptr; 871 | if(cptr=findloc(sname))return cptr; 872 | if(locptr>=endloc) 873 | {error("local symbol table overflow"); 874 | return 0; 875 | } 876 | cptr=ptr=locptr; 877 | while(an(*ptr++ = *sname++)); /* copy name */ 878 | cptr[ident]=id; 879 | cptr[type]=typ; 880 | cptr[storage]=stkloc; 881 | cptr[offset]=value; 882 | cptr[offset+1]=value>>8; 883 | locptr=locptr+symsiz; 884 | return cptr; 885 | } 886 | /* Test if next input string is legal symbol name */ 887 | symname(sname) 888 | char *sname; 889 | { int k;char c; 890 | blanks(); 891 | if(alpha(ch())==0)return 0; 892 | k=0; 893 | while(an(ch()))sname[k++]=gch(); 894 | sname[k]=0; 895 | return 1; 896 | } 897 | /* Return next avail internal label number */ 898 | getlabel() 899 | { return(++nxtlab); 900 | } 901 | /* Print specified number as label */ 902 | printlabel(label) 903 | int label; 904 | { 905 | outstr(".L");outdec(label); 906 | } 907 | /* Test if given character is alpha */ 908 | alpha(c) 909 | int c; 910 | { 911 | return ((c>='a')&(c<='z'))| 912 | ((c>='A')&(c<='Z'))| 913 | (c=='_'); 914 | } 915 | /* Test if given character is numeric */ 916 | numeric(c) 917 | int c; 918 | { 919 | return (c>='0')&(c<='9'); 920 | } 921 | /* Test if given character is alphanumeric */ 922 | an(c) 923 | int c; 924 | { 925 | return alpha(c)|numeric(c); 926 | } 927 | /* Print a carriage return and a string only to console */ 928 | pl(str) 929 | char *str; 930 | { int k; 931 | k=0; 932 | putchar(eol); 933 | while(str[k])putchar(str[k++]); 934 | } 935 | addwhile(ptr) 936 | int ptr[]; 937 | { 938 | int k; 939 | if (wqptr==wqmax) 940 | {error("too many active whiles");return;} 941 | k=0; 942 | while (k0) 994 | {if((k==eol)|(lptr>=linemax))break; 995 | line[lptr++]=k; 996 | } 997 | line[lptr]=0; /* append null */ 998 | lineno++; /* read one more line gtf 7/2/80 */ 999 | if(k<=0) 1000 | {fclose(unit); 1001 | if(input2)endinclude(); /* gtf 7/16/80 */ 1002 | else input=0; 1003 | } 1004 | if(lptr) 1005 | {if((ctext)&(cmode)) 1006 | {comment(); 1007 | outstr(line); 1008 | nl(); 1009 | } 1010 | lptr=0; 1011 | return; 1012 | } 1013 | } 1014 | } 1015 | /* >>>>>> start of cc4 <<<<<<< */ 1016 | 1017 | keepch(c) 1018 | char c; 1019 | { mline[mptr]=c; 1020 | if(mptr=mpmax)error("line too long"); 1091 | lptr=mptr=0; 1092 | while(line[lptr++]=mline[mptr++]); 1093 | lptr=0; 1094 | } 1095 | addmac() 1096 | { char sname[namesize]; 1097 | int k; 1098 | if(symname(sname)==0) 1099 | {illname(); 1100 | kill(); 1101 | return; 1102 | } 1103 | k=0; 1104 | while(putmac(sname[k++])); 1105 | while(ch()==' ' | ch()==9) gch(); 1106 | while(putmac(gch())); 1107 | if(macptr>=macmax)error("macro table full"); 1108 | } 1109 | putmac(c) 1110 | char c; 1111 | { macq[macptr]=c; 1112 | if(macptr='a') & (c<='z')) 1318 | c = c - 'a' + 'A'; 1319 | return(c); 1320 | /* end raise */} 1321 | 1322 | /* ------------------------------------------------------------- */ 1323 | 1324 | /* >>>>>>> start of cc5 <<<<<<< */ 1325 | 1326 | /* as of 5/5/81 rj */ 1327 | 1328 | expression() 1329 | { 1330 | int lval[2]; 1331 | if(heir1(lval))rvalue(lval); 1332 | } 1333 | heir1(lval) 1334 | int lval[]; 1335 | { 1336 | int k,lval2[2]; 1337 | k=heir2(lval); 1338 | if (match("=")) 1339 | {if(k==0){needlval();return 0;} 1340 | if (lval[1])zpush(); 1341 | if(heir1(lval2))rvalue(lval2); 1342 | store(lval); 1343 | return 0; 1344 | } 1345 | else return k; 1346 | } 1347 | heir2(lval) 1348 | int lval[]; 1349 | { int k,lval2[2]; 1350 | k=heir3(lval); 1351 | blanks(); 1352 | if(ch()!='|')return k; 1353 | if(k)rvalue(lval); 1354 | while(1) 1355 | {if (match("|")) 1356 | {zpush(); 1357 | if(heir3(lval2)) rvalue(lval2); 1358 | zpop(); 1359 | zor(); 1360 | } 1361 | else return 0; 1362 | } 1363 | } 1364 | heir3(lval) 1365 | int lval[]; 1366 | { int k,lval2[2]; 1367 | k=heir4(lval); 1368 | blanks(); 1369 | if(ch()!='^')return k; 1370 | if(k)rvalue(lval); 1371 | while(1) 1372 | {if (match("^")) 1373 | {zpush(); 1374 | if(heir4(lval2))rvalue(lval2); 1375 | zpop(); 1376 | zxor(); 1377 | } 1378 | else return 0; 1379 | } 1380 | } 1381 | heir4(lval) 1382 | int lval[]; 1383 | { int k,lval2[2]; 1384 | k=heir5(lval); 1385 | blanks(); 1386 | if(ch()!='&')return k; 1387 | if(k)rvalue(lval); 1388 | while(1) 1389 | {if (match("&")) 1390 | {zpush(); 1391 | if(heir5(lval2))rvalue(lval2); 1392 | zpop(); 1393 | zand(); 1394 | } 1395 | else return 0; 1396 | } 1397 | } 1398 | heir5(lval) 1399 | int lval[]; 1400 | { 1401 | int k,lval2[2]; 1402 | k=heir6(lval); 1403 | blanks(); 1404 | if((streq(line+lptr,"==")==0)& 1405 | (streq(line+lptr,"!=")==0))return k; 1406 | if(k)rvalue(lval); 1407 | while(1) 1408 | {if (match("==")) 1409 | {zpush(); 1410 | if(heir6(lval2))rvalue(lval2); 1411 | zpop(); 1412 | zeq(); 1413 | } 1414 | else if (match("!=")) 1415 | {zpush(); 1416 | if(heir6(lval2))rvalue(lval2); 1417 | zpop(); 1418 | zne(); 1419 | } 1420 | else return 0; 1421 | } 1422 | } 1423 | heir6(lval) 1424 | int lval[]; 1425 | { 1426 | int k,lval2[2]; 1427 | k=heir7(lval); 1428 | blanks(); 1429 | if((streq(line+lptr,"<")==0)& 1430 | (streq(line+lptr,">")==0)& 1431 | (streq(line+lptr,"<=")==0)& 1432 | (streq(line+lptr,">=")==0))return k; 1433 | if(streq(line+lptr,">>"))return k; 1434 | if(streq(line+lptr,"<<"))return k; 1435 | if(k)rvalue(lval); 1436 | while(1) 1437 | {if (match("<=")) 1438 | {zpush(); 1439 | if(heir7(lval2))rvalue(lval2); 1440 | zpop(); 1441 | if(cptr=lval[0]) 1442 | if(cptr[ident]==pointer) 1443 | {ule(); 1444 | continue; 1445 | } 1446 | if(cptr=lval2[0]) 1447 | if(cptr[ident]==pointer) 1448 | {ule(); 1449 | continue; 1450 | } 1451 | zle(); 1452 | } 1453 | else if (match(">=")) 1454 | {zpush(); 1455 | if(heir7(lval2))rvalue(lval2); 1456 | zpop(); 1457 | if(cptr=lval[0]) 1458 | if(cptr[ident]==pointer) 1459 | {uge(); 1460 | continue; 1461 | } 1462 | if(cptr=lval2[0]) 1463 | if(cptr[ident]==pointer) 1464 | {uge(); 1465 | continue; 1466 | } 1467 | zge(); 1468 | } 1469 | else if((streq(line+lptr,"<"))& 1470 | (streq(line+lptr,"<<")==0)) 1471 | {inbyte(); 1472 | zpush(); 1473 | if(heir7(lval2))rvalue(lval2); 1474 | zpop(); 1475 | if(cptr=lval[0]) 1476 | if(cptr[ident]==pointer) 1477 | {ult(); 1478 | continue; 1479 | } 1480 | if(cptr=lval2[0]) 1481 | if(cptr[ident]==pointer) 1482 | {ult(); 1483 | continue; 1484 | } 1485 | zlt(); 1486 | } 1487 | else if((streq(line+lptr,">"))& 1488 | (streq(line+lptr,">>")==0)) 1489 | {inbyte(); 1490 | zpush(); 1491 | if(heir7(lval2))rvalue(lval2); 1492 | zpop(); 1493 | if(cptr=lval[0]) 1494 | if(cptr[ident]==pointer) 1495 | {ugt(); 1496 | continue; 1497 | } 1498 | if(cptr=lval2[0]) 1499 | if(cptr[ident]==pointer) 1500 | {ugt(); 1501 | continue; 1502 | } 1503 | zgt(); 1504 | } 1505 | else return 0; 1506 | } 1507 | } 1508 | /* >>>>>> start of cc6 <<<<<< */ 1509 | 1510 | heir7(lval) 1511 | int lval[]; 1512 | { 1513 | int k,lval2[2]; 1514 | k=heir8(lval); 1515 | blanks(); 1516 | if((streq(line+lptr,">>")==0)& 1517 | (streq(line+lptr,"<<")==0))return k; 1518 | if(k)rvalue(lval); 1519 | while(1) 1520 | {if (match(">>")) 1521 | {zpush(); 1522 | if(heir8(lval2))rvalue(lval2); 1523 | zpop(); 1524 | asr(); 1525 | } 1526 | else if (match("<<")) 1527 | {zpush(); 1528 | if(heir8(lval2))rvalue(lval2); 1529 | zpop(); 1530 | asl(); 1531 | } 1532 | else return 0; 1533 | } 1534 | } 1535 | heir8(lval) 1536 | int lval[]; 1537 | { 1538 | int k,lval2[2]; 1539 | k=heir9(lval); 1540 | blanks(); 1541 | if((ch()!='+')&(ch()!='-'))return k; 1542 | if(k)rvalue(lval); 1543 | while(1) 1544 | {if (match("+")) 1545 | {zpush(); 1546 | if(heir9(lval2))rvalue(lval2); 1547 | if(cptr=lval[0]) 1548 | if((cptr[ident]==pointer)& 1549 | (cptr[type]==cint)) 1550 | doublereg(); 1551 | zpop(); 1552 | zadd(); 1553 | } 1554 | else if (match("-")) 1555 | {zpush(); 1556 | if(heir9(lval2))rvalue(lval2); 1557 | if(cptr=lval[0]) 1558 | if((cptr[ident]==pointer)& 1559 | (cptr[type]==cint)) 1560 | doublereg(); 1561 | zpop(); 1562 | zsub(); 1563 | } 1564 | else return 0; 1565 | } 1566 | } 1567 | heir9(lval) 1568 | int lval[]; 1569 | { 1570 | int k,lval2[2]; 1571 | k=heir10(lval); 1572 | blanks(); 1573 | if((ch()!='*')&(ch()!='/')& 1574 | (ch()!='%'))return k; 1575 | if(k)rvalue(lval); 1576 | while(1) 1577 | {if (match("*")) 1578 | {zpush(); 1579 | if(heir9(lval2))rvalue(lval2); 1580 | zpop(); 1581 | mult(); 1582 | } 1583 | else if (match("/")) 1584 | {zpush(); 1585 | if(heir10(lval2))rvalue(lval2); 1586 | zpop(); 1587 | div(); 1588 | } 1589 | else if (match("%")) 1590 | {zpush(); 1591 | if(heir10(lval2))rvalue(lval2); 1592 | zpop(); 1593 | zmod(); 1594 | } 1595 | else return 0; 1596 | } 1597 | } 1598 | heir10(lval) 1599 | int lval[]; 1600 | { 1601 | int k; 1602 | char *ptr; 1603 | if(match("++")) 1604 | {if((k=heir10(lval))==0) 1605 | {needlval(); 1606 | return 0; 1607 | } 1608 | if(lval[1])zpush(); 1609 | rvalue(lval); 1610 | inc(); 1611 | ptr=lval[0]; 1612 | if ((ptr[ident]==pointer)&(ptr[type]==cint)) { 1613 | inc(); 1614 | inc(); 1615 | inc(); 1616 | } 1617 | store(lval); 1618 | return 0; 1619 | } 1620 | else if(match("--")) 1621 | {if((k=heir10(lval))==0) 1622 | {needlval(); 1623 | return 0; 1624 | } 1625 | if(lval[1])zpush(); 1626 | rvalue(lval); 1627 | dec(); 1628 | ptr=lval[0]; 1629 | if ((ptr[ident]==pointer)&(ptr[type]==cint)) { 1630 | dec(); 1631 | dec(); 1632 | dec(); 1633 | } 1634 | store(lval); 1635 | return 0; 1636 | } 1637 | else if (match("-")) 1638 | {k=heir10(lval); 1639 | if (k) rvalue(lval); 1640 | neg(); 1641 | return 0; 1642 | } 1643 | else if(match("*")) 1644 | {k=heir10(lval); 1645 | if(k)rvalue(lval); 1646 | lval[1]=cint; 1647 | if(ptr=lval[0])lval[1]=ptr[type]; 1648 | lval[0]=0; 1649 | return 1; 1650 | } 1651 | else if(match("&")) 1652 | {k=heir10(lval); 1653 | if(k==0) 1654 | {error("illegal address"); 1655 | return 0; 1656 | } 1657 | else if(lval[1])return 0; 1658 | else 1659 | {immed(); 1660 | outname(ptr=lval[0]); 1661 | nl(); 1662 | lval[1]=ptr[type]; 1663 | return 0; 1664 | } 1665 | } 1666 | else 1667 | {k=heir11(lval); 1668 | if(match("++")) 1669 | {if(k==0) 1670 | {needlval(); 1671 | return 0; 1672 | } 1673 | if(lval[1])zpush(); 1674 | rvalue(lval); 1675 | inc(); 1676 | ptr=lval[0]; 1677 | if ((ptr[ident]==pointer)&(ptr[type]==cint)) { 1678 | inc(); 1679 | inc(); 1680 | inc(); 1681 | } 1682 | store(lval); 1683 | dec(); 1684 | if ((ptr[ident]==pointer)&(ptr[type]==cint)) { 1685 | dec(); 1686 | dec(); 1687 | dec(); 1688 | } 1689 | return 0; 1690 | } 1691 | else if(match("--")) 1692 | {if(k==0) 1693 | {needlval(); 1694 | return 0; 1695 | } 1696 | if(lval[1])zpush(); 1697 | rvalue(lval); 1698 | dec(); 1699 | ptr=lval[0]; 1700 | if ((ptr[ident]==pointer)&(ptr[type]==cint)) { 1701 | dec(); 1702 | dec(); 1703 | dec(); 1704 | } 1705 | store(lval); 1706 | inc(); 1707 | if ((ptr[ident]==pointer)&(ptr[type]==cint)) { 1708 | inc(); 1709 | inc(); 1710 | inc(); 1711 | } 1712 | return 0; 1713 | } 1714 | else return k; 1715 | } 1716 | } 1717 | /* >>>>>> start of cc7 <<<<<< */ 1718 | 1719 | heir11(lval) 1720 | int *lval; 1721 | { int k;char *ptr; 1722 | k=primary(lval); 1723 | ptr=lval[0]; 1724 | blanks(); 1725 | if((ch()=='[')|(ch()=='(')) 1726 | while(1) 1727 | {if(match("[")) 1728 | {if(ptr==0) 1729 | {error("can't subscript"); 1730 | junk(); 1731 | needbrack("]"); 1732 | return 0; 1733 | } 1734 | else if(ptr[ident]==pointer)rvalue(lval); 1735 | else if(ptr[ident]!=array) 1736 | {error("can't subscript"); 1737 | k=0; 1738 | } 1739 | zpush(); 1740 | expression(); 1741 | needbrack("]"); 1742 | if(ptr[type]==cint)doublereg(); 1743 | zpop(); 1744 | zadd(); 1745 | lval[1]=ptr[type]; 1746 | /* 4/1/81 - after subscripting, not ptr anymore */ 1747 | lval[0]=0; 1748 | k=1; 1749 | } 1750 | else if(match("(")) 1751 | {if(ptr==0) 1752 | {callfunction(0); 1753 | } 1754 | else if(ptr[ident]!=function) 1755 | {rvalue(lval); 1756 | callfunction(0); 1757 | } 1758 | else callfunction(ptr); 1759 | k=lval[0]=0; 1760 | } 1761 | else return k; 1762 | } 1763 | if(ptr==0)return k; 1764 | if(ptr[ident]==function) { 1765 | ot("movl $");outname(ptr);outstr(",%eax");nl(); 1766 | return 0; 1767 | } 1768 | return k; 1769 | } 1770 | primary(lval) 1771 | int *lval; 1772 | { char *ptr,sname[namesize];int num[1]; 1773 | int k; 1774 | if(match("(")) 1775 | {k=heir1(lval); 1776 | needbrack(")"); 1777 | return k; 1778 | } 1779 | if(symname(sname)) 1780 | {if(ptr=findloc(sname)) 1781 | {getloc(ptr); 1782 | lval[0]=ptr; 1783 | lval[1]=ptr[type]; 1784 | if(ptr[ident]==pointer)lval[1]=cint; 1785 | if(ptr[ident]==array)return 0; 1786 | else return 1; 1787 | } 1788 | if(ptr=findglb(sname)) 1789 | if(ptr[ident]!=function) 1790 | {lval[0]=ptr; 1791 | lval[1]=0; 1792 | if(ptr[ident]!=array)return 1; 1793 | ot("movl $");outname(ptr);outstr(",%eax");nl(); 1794 | lval[1]=ptr[type]; 1795 | return 0; 1796 | } 1797 | ptr=addglb(sname,function,cint,0); 1798 | lval[0]=ptr; 1799 | lval[1]=0; 1800 | return 0; 1801 | } 1802 | if(constant(num)) 1803 | return(lval[0]=lval[1]=0); 1804 | else 1805 | {error("invalid expression"); 1806 | immed();outdec(0);nl(); 1807 | junk(); 1808 | return 0; 1809 | } 1810 | } 1811 | store(lval) 1812 | int *lval; 1813 | { if (lval[1]==0)putmem(lval[0]); 1814 | else putstk(lval[1]); 1815 | } 1816 | rvalue(lval) 1817 | int *lval; 1818 | { if((lval[0] != 0) & (lval[1] == 0)) 1819 | getmem(lval[0]); 1820 | else indirect(lval[1]); 1821 | } 1822 | test(label) 1823 | int label; 1824 | { 1825 | needbrack("("); 1826 | expression(); 1827 | needbrack(")"); 1828 | testjump(label); 1829 | } 1830 | constant(val) 1831 | int val[]; 1832 | { 1833 | if (number(val)) { 1834 | ot("movl $"); 1835 | } 1836 | else if (pstr(val)) { 1837 | ot("movl $"); 1838 | } 1839 | else if (qstr(val)) { 1840 | ot("movl $");printlabel(litlab);outbyte('+'); 1841 | } 1842 | else return 0; 1843 | outdec(val[0]);outstr(",%eax");nl(); 1844 | return 1; 1845 | } 1846 | number(val) 1847 | int val[]; 1848 | { 1849 | int k; 1850 | k=0; 1851 | if(numeric(ch())==0)return 0; 1852 | while (numeric(ch())) { 1853 | k=k*10+gch()-'0'; 1854 | } 1855 | val[0]=k; 1856 | return 1; 1857 | } 1858 | pstr(val) 1859 | int val[]; 1860 | { 1861 | int c,k; 1862 | k=0; 1863 | if (match("'")==0) return 0; 1864 | while((c=gch())!=39) 1865 | k=(k<<8)+c; 1866 | val[0]=k; 1867 | return 1; 1868 | } 1869 | qstr(val) 1870 | int val[]; 1871 | { 1872 | if (match(quote)==0) return 0; 1873 | val[0]=litptr; 1874 | while (ch()!='"') 1875 | {if(ch()==0)break; 1876 | if(litptr>=litmax) 1877 | {error("string space exhausted"); 1878 | zabort(); 1879 | } 1880 | litq[litptr++]=gch(); 1881 | } 1882 | gch(); 1883 | litq[litptr++]=0; 1884 | return 1; 1885 | } 1886 | 1887 | /* Begin a comment line for the assembler */ 1888 | comment() 1889 | { outbyte(';'); 1890 | } 1891 | 1892 | /* Put out assembler info before any code is generated */ 1893 | header() 1894 | { 1895 | } 1896 | /* Print any assembler stuff needed after all code */ 1897 | trailer() 1898 | { 1899 | } 1900 | 1901 | /* Print out a name such that it won't annoy the assembler */ 1902 | /* (by matching anything reserved, like opcodes.) */ 1903 | outname(sname) 1904 | char *sname; 1905 | { 1906 | outstr(sname); 1907 | } 1908 | /* Fetch a static memory cell into the primary register */ 1909 | getmem(sym) 1910 | char *sym; 1911 | { 1912 | if ((sym[ident]!=pointer)&(sym[type]==cchar)) { 1913 | ot("movsbl "); 1914 | } 1915 | else { 1916 | ot("movl "); 1917 | } 1918 | outname(sym+name);outstr(",%eax");nl(); 1919 | } 1920 | /* Fetch the address of the specified symbol */ 1921 | /* into the primary register */ 1922 | getloc(sym) 1923 | char *sym; 1924 | { 1925 | ot("leal "); 1926 | outdec((sym[offset]&255)+(sym[offset+1]<<8)-Zsp); 1927 | outstr("(%esp),%eax"); 1928 | nl(); 1929 | } 1930 | /* Store the primary register into the specified */ 1931 | /* static memory cell */ 1932 | putmem(sym) 1933 | char *sym; 1934 | { 1935 | if ((sym[ident]!=pointer)&(sym[type]==cchar)) { 1936 | ot("movb %al,"); 1937 | } 1938 | else { 1939 | ot("movl %eax,"); 1940 | } 1941 | outname(sym+name);nl(); 1942 | } 1943 | /* Store the specified object type in the primary register */ 1944 | /* at the address on the top of the stack */ 1945 | putstk(typeobj) 1946 | int typeobj; 1947 | { 1948 | zpop(); 1949 | if (typeobj==cchar) { 1950 | ol("movb %al,(%ecx)"); 1951 | } 1952 | else { 1953 | ol("movl %eax,(%ecx)"); 1954 | } 1955 | } 1956 | /* Fetch the specified object type indirect through the */ 1957 | /* primary register into the primary register */ 1958 | indirect(typeobj) 1959 | int typeobj; 1960 | { 1961 | if (typeobj==cchar) { 1962 | ol("movsbl (%eax),%eax"); 1963 | } 1964 | else { 1965 | ol("movl (%eax),%eax"); 1966 | } 1967 | } 1968 | /* Swap the primary and secondary registers */ 1969 | swap() 1970 | { 1971 | ol("xchgl %ecx,%eax"); 1972 | } 1973 | /* Print partial instruction to get an immediate value */ 1974 | /* into the primary register */ 1975 | immed() 1976 | { ot("LXI H,"); 1977 | } 1978 | /* Push the primary register onto the stack */ 1979 | zpush() 1980 | { 1981 | ol("pushl %eax"); 1982 | Zsp=Zsp-4; 1983 | } 1984 | /* Pop the top of the stack into the secondary register */ 1985 | zpop() 1986 | { 1987 | ol("popl %ecx"); 1988 | Zsp=Zsp+4; 1989 | } 1990 | /* Swap the primary register and the top of the stack */ 1991 | swapstk() 1992 | { ol("XTHL"); 1993 | } 1994 | /* Call the specified subroutine name */ 1995 | zcall(sname) 1996 | char *sname; 1997 | { 1998 | ot("call ");outname(sname);nl(); 1999 | } 2000 | /* Return from subroutine */ 2001 | zret() 2002 | { 2003 | ol("ret"); 2004 | } 2005 | /* Perform subroutine call to value on top of stack */ 2006 | callstk() 2007 | { immed(); 2008 | outstr("$+5"); 2009 | nl(); 2010 | swapstk(); 2011 | ol("PCHL"); 2012 | Zsp=Zsp+2; /* corrected 5 May 81 rj */ 2013 | } 2014 | /* Jump to specified internal label number */ 2015 | jump(label) 2016 | int label; 2017 | { 2018 | ot("jmp ");printlabel(label);nl(); 2019 | } 2020 | /* Test the primary register and jump if false to label */ 2021 | testjump(label) 2022 | int label; 2023 | { 2024 | ol("testl %eax,%eax"); 2025 | ot("jz ");printlabel(label);nl(); 2026 | } 2027 | /* Print pseudo-op to define a byte */ 2028 | defbyte() 2029 | { ot(".byte "); 2030 | } 2031 | /*Print pseudo-op to define storage */ 2032 | defstorage() 2033 | { ot(".comm "); 2034 | } 2035 | /* Print pseudo-op to define a word */ 2036 | defword() 2037 | { ot(".word "); 2038 | } 2039 | /* Modify the stack pointer to the new value indicated */ 2040 | modstk(newsp) 2041 | int newsp; 2042 | { 2043 | int k; 2044 | k=newsp-Zsp; 2045 | if (k) { 2046 | ot("addl $");outdec(k);outstr(",%esp");nl(); 2047 | } 2048 | return newsp; 2049 | } 2050 | /* Double the primary register */ 2051 | doublereg() 2052 | { 2053 | ol("sall $2,%eax"); 2054 | } 2055 | /* Add the primary and secondary registers */ 2056 | /* (results in primary) */ 2057 | zadd() 2058 | { 2059 | ol("addl %ecx,%eax"); 2060 | } 2061 | /* Subtract the primary register from the secondary */ 2062 | /* (results in primary) */ 2063 | zsub() 2064 | { 2065 | ol("subl %ecx,%eax"); 2066 | neg(); 2067 | } 2068 | /* Multiply the primary and secondary registers */ 2069 | /* (results in primary */ 2070 | mult() 2071 | { 2072 | ol("imull %ecx,%eax"); 2073 | } 2074 | /* Divide the secondary register by the primary */ 2075 | /* (quotient in primary, remainder in secondary) */ 2076 | div() 2077 | { 2078 | swap(); 2079 | ol("cltd"); 2080 | ol("idivl %ecx"); 2081 | } 2082 | /* Compute remainder (mod) of secondary register divided */ 2083 | /* by the primary */ 2084 | /* (remainder in primary, quotient in secondary) */ 2085 | zmod() 2086 | { 2087 | div(); 2088 | ol("movl %edx,%eax"); 2089 | } 2090 | /* Inclusive 'or' the primary and the secondary registers */ 2091 | /* (results in primary) */ 2092 | zor() 2093 | { 2094 | ol("orl %ecx,%eax"); 2095 | } 2096 | /* Exclusive 'or' the primary and seconday registers */ 2097 | /* (results in primary) */ 2098 | zxor() 2099 | { 2100 | ol("xorl %ecx,%eax"); 2101 | } 2102 | /* 'And' the primary and secondary registers */ 2103 | /* (results in primary) */ 2104 | zand() 2105 | { 2106 | ol("andl %ecx,%eax"); 2107 | } 2108 | /* Arithmetic shift right the secondary register number of */ 2109 | /* times in primary (results in primary) */ 2110 | asr() 2111 | { 2112 | swap(); 2113 | ol("sarl %cl,%eax"); 2114 | } 2115 | /* Arithmetic left shift the secondary register number of */ 2116 | /* times in primary (results in primary) */ 2117 | asl() 2118 | { 2119 | swap(); 2120 | ol("sall %cl,%eax"); 2121 | } 2122 | /* Form two's complement of primary register */ 2123 | neg() 2124 | { 2125 | ol("negl %eax"); 2126 | } 2127 | /* Increment the primary register by one */ 2128 | inc() 2129 | { 2130 | ol("incl %eax"); 2131 | } 2132 | /* Decrement the primary register by one */ 2133 | dec() 2134 | { 2135 | ol("decl %eax"); 2136 | } 2137 | 2138 | /* Following are the conditional operators */ 2139 | /* They compare the secondary register against the primary */ 2140 | /* and put a literal 1 in the primary if the condition is */ 2141 | /* true, otherwise they clear the primary register */ 2142 | 2143 | /* Test for equal */ 2144 | zeq() 2145 | { 2146 | ol("cmpl %eax,%ecx"); 2147 | ol("sete %al"); 2148 | ol("movzbl %al,%eax"); 2149 | } 2150 | /* Test for not equal */ 2151 | zne() 2152 | { 2153 | ol("cmpl %eax,%ecx"); 2154 | ol("setne %al"); 2155 | ol("movzbl %al,%eax"); 2156 | } 2157 | /* Test for less than (signed) */ 2158 | zlt() 2159 | { 2160 | ol("cmpl %eax,%ecx"); 2161 | ol("setl %al"); 2162 | ol("movzbl %al,%eax"); 2163 | } 2164 | /* Test for less than or equal to (signed) */ 2165 | zle() 2166 | { 2167 | ol("cmpl %eax,%ecx"); 2168 | ol("setle %al"); 2169 | ol("movzbl %al,%eax"); 2170 | } 2171 | /* Test for greater than (signed) */ 2172 | zgt() 2173 | { 2174 | ol("cmpl %eax,%ecx"); 2175 | ol("setg %al"); 2176 | ol("movzbl %al,%eax"); 2177 | } 2178 | /* Test for greater than or equal to (signed) */ 2179 | zge() 2180 | { 2181 | ol("cmpl %eax,%ecx"); 2182 | ol("setge %al"); 2183 | ol("movzbl %al,%eax"); 2184 | } 2185 | /* Test for less than (unsigned) */ 2186 | ult() 2187 | { 2188 | ol("cmpl %eax,%ecx"); 2189 | ol("setb %al"); 2190 | ol("movzbl %al,%eax"); 2191 | } 2192 | /* Test for less than or equal to (unsigned) */ 2193 | ule() 2194 | { 2195 | ol("cmpl %eax,%ecx"); 2196 | ol("setbe %al"); 2197 | ol("movzbl %al,%eax"); 2198 | } 2199 | /* Test for greater than (unsigned) */ 2200 | ugt() 2201 | { 2202 | ol("cmpl %eax,%ecx"); 2203 | ol("seta %al"); 2204 | ol("movzbl %al,%eax"); 2205 | } 2206 | /* Test for greater than or equal to (unsigned) */ 2207 | uge() 2208 | { 2209 | ol("cmpl %eax,%ecx"); 2210 | ol("setae %al"); 2211 | ol("movzbl %al,%eax"); 2212 | } 2213 | 2214 | --------------------------------------------------------------------------------