crasm/0000700000175000017500000000000012235465054010243 5ustar cmbcmbcrasm/crasm.spec0000700000175000017500000000124210241007153012211 0ustar cmbcmbName: crasm Summary: Cross assembler for 6800/6801/6803/6502/65C02/Z80. Version: 1.4 Release: 1 License: GPL Group: Applications/Internet URL: http://crasm.sourceforge.net/ Source0: %{name}-%{version}.tar.gz Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root %description Crasm is a cross assembler for 6800/6801/6803/6502/65C02/Z80. It produces binaries in Intel HEX or Motorola S Code. %prep %setup -q %build make %install rm -fr %{buildroot} install -d %{buildroot}%{_bindir} install -d %{buildroot}%{_mandir}/man1 %makeinstall %clean rm -fr %{buildroot} %files %defattr(-,root,root) %{_bindir}/* %{_mandir}/* %doc crasm.html %doc test %changelog crasm/COPYING0000600000175000017500000004310510107144710011270 0ustar cmbcmb GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. crasm/Makefile0000600000175000017500000000044110107144710011671 0ustar cmbcmbSHELL=/bin/sh MAKE=make prefix=/usr bindir=${prefix}/bin mandir=${prefix}/share/man all: ( cd src; ${MAKE} all ) clean: ( cd src; ${MAKE} clean ) install: cp src/crasm ${bindir}/crasm chmod 0755 ${bindir}/crasm cp crasm.1 ${mandir}/man1/crasm.1 chmod 0644 ${mandir}/man1/crasm.1 crasm/test/0000700000175000017500000000000012235044616011217 5ustar cmbcmbcrasm/test/uchess2.65C020000600000175000017500000004767610107212457013236 0ustar cmbcmb;*********************************************************************** ; ; MicroChess (c) 1996-2002 Peter Jennings, ; mailto:peterj@benlo.com ; http://www.benlo.com/microchess.html ; ;*********************************************************************** ; I have been given permission to distribute this program ; by the author and copyright holder, Peter Jennings. ; Please get his permission if you wish to ; re-distribute by other channels. ; modified by Daryl Rictor to work over a ; serial terminal connection, August 2002. cpu 65c02 page 0,132 ; ; 6551 I/O Port Addresses ; ACIADat = $7F70 ACIASta = $7F71 ACIACmd = $7F72 ACIACtl = $7F73 ; ; page zero variables ; BOARD = $50 BK = $60 PIECE = $B0 SQUARE = $B1 SP2 = $B2 SP1 = $B3 INCHEK = $B4 STATE = $B5 MOVEN = $B6 REV = $B7 OMOVE = $DC WCAP0 = $DD COUNT = $DE BCAP2 = $DE WCAP2 = $DF BCAP1 = $E0 WCAP1 = $E1 BCAP0 = $E2 MOB = $E3 MAXC = $E4 CC = $E5 PCAP = $E6 BMOB = $E3 BMAXC = $E4 BMCC = $E5 ; was BCC (TASS doesn't like it as a label) BMAXP = $E6 XMAXC = $E8 WMOB = $EB WMAXC = $EC WCC = $ED WMAXP = $EE PMOB = $EF PMAXC = $F0 PCC = $F1 PCP = $F2 OLDKY = $F3 BESTP = $FB BESTV = $FA BESTM = $F9 DIS1 = $FB DIS2 = $FA DIS3 = $F9 temp = $FC ; ; ; *=$1000 ; load into RAM @ $1000-$15FF LDA #$00 ; REVERSE TOGGLE STA REV JSR Init_6551 CHESS CLD ; INITIALIZE LDX #$FF ; TWO STACKS TXS LDX #$C8 STX SP2 ; ; ROUTINES TO LIGHT LED ; DISPLAY AND GET KEY ; FROM KEYBOARD ; OUT JSR pout ; DISPLAY AND JSR KIN ; GET INPUT *** my routine waits for a keypress ; CMP OLDKY ; KEY IN ACC *** no need to debounce ; BEQ OUT ; (DEBOUNCE) ; STA OLDKY ; CMP #$43 ; [C] BNE NOSET ; SET UP LDX #$1F ; BOARD WHSET LDA SETW,X ; FROM STA BOARD,X ; SETW DEX BPL WHSET LDX #$1B ; *ADDED STX OMOVE ; INITS TO $FF LDA #$CC ; Display CCC BNE CLDSP ; NOSET CMP #$45 ; [E] BNE NOREV ; REVERSE JSR REVERSE ; BOARD IS SEC LDA #$01 SBC REV STA REV ; TOGGLE REV FLAG LDA #$EE ; IS BNE CLDSP ; NOREV CMP #$40 ; [P] BNE NOGO ; PLAY CHESS JSR GO CLDSP STA DIS1 ; DISPLAY STA DIS2 ; ACROSS STA DIS3 ; DISPLAY BNE CHESS ; NOGO CMP #$0D ; [Enter] BNE NOMV ; MOVE MAN JSR MOVE ; AS ENTERED JMP DISP NOMV CMP #$41 ; [Q] ***Added to allow game exit*** BEQ DONE ; quit the game, exit back to system. JMP INPUT ; process move DONE JMP $FF00 ; *** MUST set this to YOUR OS starting address ; ; THE ROUTINE JANUS DIRECTS THE ; ANALYSIS BY DETERMINING WHAT ; SHOULD OCCUR AFTER EACH MOVE ; GENERATED BY GNM ; ; ; JANUS LDX STATE BMI NOCOUNT ; ; THIS ROUTINE COUNTS OCCURRENCES ; IT DEPENDS UPON STATE TO INDEX ; THE CORRECT COUNTERS ; COUNTS LDA PIECE BEQ OVER ; IF STATE=8 CPX #$08 ; DO NOT COUNT BNE OVER ; BLK MAX CAP CMP BMAXP ; MOVES FOR BEQ XRT ; WHITE ; OVER INC MOB,X ; MOBILITY CMP #$01 ; + QUEEN BNE NOQ ; FOR TWO INC MOB,X ; NOQ BVC NOCAP LDY #$0F ; CALCULATE LDA SQUARE ; POINTS ELOOP CMP BK,Y ; CAPTURED BEQ FOUN ; BY THIS DEY ; MOVE BPL ELOOP FOUN LDA POINTS,Y CMP MAXC,X BCC LESS ; SAVE IF STY PCAP,X ; BEST THIS STA MAXC,X ; STATE ; LESS CLC PHP ; ADD TO ADC CC,X ; CAPTURE STA CC,X ; COUNTS PLP ; NOCAP CPX #$04 BEQ ON4 BMI TREE ;(=00 ONLY) XRT RTS ; ; GENERATE FURTHER MOVES FOR COUNT ; AND ANALYSIS ; ON4 LDA XMAXC ; SAVE ACTUAL STA WCAP0 ; CAPTURE LDA #$00 ; STATE=0 STA STATE JSR MOVE ; GENERATE JSR REVERSE ; IMMEDIATE JSR GNMZ ; REPLY MOVES JSR REVERSE ; LDA #$08 ; STATE=8 STA STATE ; GENERATE ; JSR OHM ; CONTINUATION JSR UMOVE ; MOVES ; JMP STRATGY ; FINAL EVALUATION NOCOUNT CPX #$F9 BNE TREE ; ; DETERMINE IF THE KING CAN BE ; TAKEN, USED BY CHKCHK ; LDA BK ; IS KING CMP SQUARE ; IN CHECK? BNE RETJ ; SET INCHEK=0 LDA #$00 ; IF IT IS STA INCHEK RETJ RTS ; ; IF A PIECE HAS BEEN CAPTURED BY ; A TRIAL MOVE, GENERATE REPLIES & ; EVALUATE THE EXCHANGE GAIN/LOSS ; TREE BVC RETJ ; NO CAP LDY #$07 ; (PIECES) LDA SQUARE LOOPX CMP BK,Y BEQ FOUNX DEY BEQ RETJ ; (KING) BPL LOOPX ; SAVE FOUNX LDA POINTS,Y ; BEST CAP CMP BCAP0,X ; AT THIS BCC NOMAX ; LEVEL STA BCAP0,X NOMAX DEC STATE LDA #$FB ; IF STATE=FB CMP STATE ; TIME TO TURN BEQ UPTREE ; AROUND JSR GENRM ; GENERATE FURTHER UPTREE INC STATE ; CAPTURES RTS ; ; THE PLAYER'S MOVE IS INPUT ; INPUT CMP #$08 ; NOT A LEGAL BCS ERROR ; SQUARE # JSR DISMV DISP LDX #$1F SEARCH LDA BOARD,X CMP DIS2 BEQ HERE ; DISPLAY DEX ; PIECE AT BPL SEARCH ; FROM HERE STX DIS1 ; SQUARE STX PIECE ERROR JMP CHESS ; ; GENERATE ALL MOVES FOR ONE ; SIDE, CALL JANUS AFTER EACH ; ONE FOR NEXT STE? ; ; GNMZ LDX #$10 ; CLEAR GNMX LDA #$00 ; COUNTERS CLEAR STA COUNT,X DEX BPL CLEAR ; GNM LDA #$10 ; SET UP STA PIECE ; PIECE NEWP DEC PIECE ; NEW PIECE BPL NEX ; ALL DONE? RTS ; #NAME? ; NEX JSR RESET ; READY LDY PIECE ; GET PIECE LDX #$08 STX MOVEN ; COMMON START CPY #$08 ; WHAT IS IT? BPL PAWN ; PAWN CPY #$06 BPL KNIGHT ; KNIGHT CPY #$04 BPL BISHOP ; BISHOP CPY #$01 BEQ QUEEN ; QUEEN BPL ROOK ; ROOK ; KING JSR SNGMV ; MUST BE KING! BNE KING ; MOVES BEQ NEWP ; 8 TO 1 QUEEN JSR LINE BNE QUEEN ; MOVES BEQ NEWP ; 8 TO 1 ; ROOK LDX #$04 STX MOVEN ; MOVES AGNR JSR LINE ; 4 TO 1 BNE AGNR BEQ NEWP ; BISHOP JSR LINE LDA MOVEN ; MOVES CMP #$04 ; 8 TO 5 BNE BISHOP BEQ NEWP ; KNIGHT LDX #$10 STX MOVEN ; MOVES AGNN JSR SNGMV ; 16 TO 9 LDA MOVEN CMP #$08 BNE AGNN BEQ NEWP ; PAWN LDX #$06 STX MOVEN P1 JSR CMOVE ; RIGHT CAP? BVC P2 BMI P2 JSR JANUS ; YES P2 JSR RESET DEC MOVEN ; LEFT CAP? LDA MOVEN CMP #$05 BEQ P1 P3 JSR CMOVE ; AHEAD BVS NEWP ; ILLEGAL BMI NEWP JSR JANUS LDA SQUARE ; GETS TO AND #$F0 ; 3RD RANK? CMP #$20 BEQ P3 ; DO DOUBLE JMP NEWP ; ; CALCULATE SINGLE STEP MOVES ; FOR K,N ; SNGMV JSR CMOVE ; CALC MOVE BMI ILL1 ; -IF LEGAL JSR JANUS ; -EVALUATE ILL1 JSR RESET DEC MOVEN RTS ; ; CALCULATE ALL MOVES DOWN A ; STRAIGHT LINE FOR Q,B,R ; LINE JSR CMOVE ; CALC MOVE BCC OVL ; NO CHK BVC LINE ; NOCAP OVL BMI ILL ; RETURN PHP JSR JANUS ; EVALUATE POSN PLP BVC LINE ; NOT A CAP ILL JSR RESET ; LINE STOPPED DEC MOVEN ; NEXT DIR RTS ; ; EXCHANGE SIDES FOR REPLY ; ANALYSIS ; REVERSE LDX #$0F ETC SEC LDY BK,X ; SUBTRACT LDA #$77 ; POSITION SBC BOARD,X ; FROM 77 STA BK,X STY BOARD,X ; AND SEC LDA #$77 ; EXCHANGE SBC BOARD,X ; PIECES STA BOARD,X DEX BPL ETC RTS ; ; CMOVE CALCULATES THE TO SQUARE ; USING SQUARE AND THE MOVE ; TABLE FLAGS SET AS FOLLOWS: ; N#NAME? MOVE ; V#NAME? (LEGAL UNLESS IN CR) ; C#NAME? BECAUSE OF CHECK ; [MY &THANKS TO JIM BUTTERFIELD ; WHO WROTE THIS MORE EFFICIENT ; VERSION OF CMOVE) ; CMOVE LDA SQUARE ; GET SQUARE LDX MOVEN ; MOVE POINTER CLC ADC MOVEX,X ; MOVE LIST STA SQUARE ; NEW POS'N AND #$88 BNE ILLEGAL ; OFF BOARD LDA SQUARE ; LDX #$20 LOOP DEX ; IS TO BMI NO ; SQUARE CMP BOARD,X ; OCCUPIED? BNE LOOP ; CPX #$10 ; BY SELF? BMI ILLEGAL ; LDA #$7F ; MUST BE CAP! ADC #$01 ; SET V FLAG BVS SPX ; (JMP) ; NO CLV ; NO CAPTURE ; SPX LDA STATE ; SHOULD WE BMI RETL ; DO THE CMP #$08 ; CHECK CHECK? BPL RETL ; ; CHKCHK REVERSES SIDES ; AND LOOKS FOR A KING ; CAPTURE TO INDICATE ; ILLEGAL MOVE BECAUSE OF ; CHECK SINCE THIS IS ; TIME CONSUMING, IT IS NOT ; ALWAYS DONE ; CHKCHK PHA ; STATE #392 PHP LDA #$F9 STA STATE ; GENERATE STA INCHEK ; ALL REPLY JSR MOVE ; MOVES TO JSR REVERSE ; SEE IF KING JSR GNM ; IS IN JSR RUM ; CHECK PLP PLA STA STATE LDA INCHEK BMI RETL ; NO - SAFE SEC ; YES - IN CHK LDA #$FF RTS ; RETL CLC ; LEGAL LDA #$00 ; RETURN RTS ; ILLEGAL LDA #$FF CLC ; ILLEGAL CLV ; RETURN RTS ; ; REPLACE PIECE ON CORRECT SQUARE ; RESET LDX PIECE ; GET LOGAT LDA BOARD,X ; FOR PIECE STA SQUARE ; FROM BOARD RTS ; ; ; GENRM JSR MOVE ; MAKE MOVE GENR2 JSR REVERSE ; REVERSE BOARD JSR GNM ; GENERATE MOVES RUM JSR REVERSE ; REVERSE BACK ; ; ROUTINE TO UNMAKE A MOVE MADE BY ; MOVE ; UMOVE TSX ; UNMAKE MOVE STX SP1 LDX SP2 ; EXCHANGE TXS ; STACKS PLA ; MOVEN STA MOVEN PLA ; CAPTURED STA PIECE ; PIECE TAX PLA ; FROM SQUARE STA BOARD,X PLA ; PIECE TAX PLA ; TO SOUARE STA SQUARE STA BOARD,X JMP STRV ; ; THIS ROUTINE MOVES PIECE ; TO SQUARE, PARAMETERS ; ARE SAVED IN A STACK TO UNMAKE ; THE MOVE LATER ; MOVE TSX STX SP1 ; SWITCH LDX SP2 ; STACKS TXS LDA SQUARE PHA ; TO SQUARE TAY LDX #$1F CHECK CMP BOARD,X ; CHECK FOR BEQ TAKE ; CAPTURE DEX BPL CHECK TAKE LDA #$CC STA BOARD,X TXA ; CAPTURED PHA ; PIECE LDX PIECE LDA BOARD,X STY BOARD,X ; FROM PHA ; SQUARE TXA PHA ; PIECE LDA MOVEN PHA ; MOVEN STRV TSX STX SP2 ; SWITCH LDX SP1 ; STACKS TXS ; BACK RTS ; ; CONTINUATION OF SUB STRATGY ; -CHECKS FOR CHECK OR CHECKMATE ; AND ASSIGNS VALUE TO MOVE ; CKMATE LDY BMAXC ; CAN BLK CAP CPX POINTS ; MY KING? BNE NOCHEK LDA #$00 ; GULP! BEQ RETV ; DUMB MOVE! ; NOCHEK LDX BMOB ; IS BLACK BNE RETV ; UNABLE TO LDX WMAXP ; MOVE AND BNE RETV ; KING IN CH? LDA #$FF ; YES! MATE ; RETV LDX #$04 ; RESTORE STX STATE ; STATE=4 ; ; THE VALUE OF THE MOVE (IN ACCU) ; IS COMPARED TO THE BEST MOVE AND ; REPLACES IT IF IT IS BETTER ; PUSH CMP BESTV ; IS THIS BEST BCC RETP ; MOVE SO FAR? BEQ RETP STA BESTV ; YES! LDA PIECE ; SAVE IT STA BESTP LDA SQUARE STA BESTM ; FLASH DISPLAY RETP LDA #"." ; print ... instead of flashing disp Jmp syschout ; print . and return ; ; MAIN PROGRAM TO PLAY CHESS ; PLAY FROM OPENING OR THINK ; GO LDX OMOVE ; OPENING? BMI NOOPEN ; -NO *ADD CHANGE FROM BPL LDA DIS3 ; -YES WAS CMP OPNING,X ; OPPONENT'S BNE END ; MOVE OK? DEX LDA OPNING,X ; GET NEXT STA DIS1 ; CANNED DEX ; OPENING MOVE LDA OPNING,X STA DIS3 ; DISPLAY IT DEX STX OMOVE ; MOVE IT BNE MV2 ; (JMP) ; END LDA #$FF ; *ADD - STOP CANNED MOVES STA OMOVE ; FLAG OPENING NOOPEN LDX #$0C ; FINISHED STX STATE ; STATE=C STX BESTV ; CLEAR BESTV LDX #$14 ; GENERATE P JSR GNMX ; MOVES ; LDX #$04 ; STATE=4 STX STATE ; GENERATE AND JSR GNMZ ; TEST AVAILABLE ; ; MOVES ; LDX BESTV ; GET BEST MOVE CPX #$0F ; IF NONE BCC MATE ; OH OH! ; MV2 LDX BESTP ; MOVE LDA BOARD,X ; THE STA BESTV ; BEST STX PIECE ; MOVE LDA BESTM STA SQUARE ; AND DISPLAY JSR MOVE ; IT JMP CHESS ; MATE LDA #$FF ; RESIGN RTS ; OR STALEMATE ; ; SUBROUTINE TO ENTER THE ; PLAYER'S MOVE ; DISMV LDX #$04 ; ROTATE DROL ASL DIS3 ; KEY ROL DIS2 ; INTO DEX ; DISPLAY BNE DROL ; ORA DIS3 STA DIS3 STA SQUARE RTS ; ; THE FOLLOWING SUBROUTINE ASSIGNS ; A VALUE TO THE MOVE UNDER ; CONSIDERATION AND RETURNS IT IN ; THE ACCUMULATOR ; STRATGY CLC LDA #$80 ADC WMOB ; PARAMETERS ADC WMAXC ; WITH WHEIGHT ADC WCC ; OF O25 ADC WCAP1 ADC WCAP2 SEC SBC PMAXC SBC PCC SBC BCAP0 SBC BCAP1 SBC BCAP2 SBC PMOB SBC BMOB BCS POS ; UNDERFLOW LDA #$00 ; PREVENTION POS LSR CLC ; ************** ADC #$40 ADC WMAXC ; PARAMETERS ADC WCC ; WITH WEIGHT SEC ; OF 05 SBC BMAXC LSR ; ************** CLC ADC #$90 ADC WCAP0 ; PARAMETERS ADC WCAP0 ; WITH WEIGHT ADC WCAP0 ; OF 10 ADC WCAP0 ADC WCAP1 SEC ; [UNDER OR OVER- SBC BMAXC ; FLOW MAY OCCUR SBC BMAXC ; FROM THIS SBC BMCC ; SECTION] SBC BMCC SBC BCAP1 LDX SQUARE ; *************** CPX #$33 BEQ POSN ; POSITION CPX #$34 ; BONUS FOR BEQ POSN ; MOVE TO CPX #$22 ; CENTRE BEQ POSN ; OR CPX #$25 ; OUT OF BEQ POSN ; BACK RANK LDX PIECE BEQ NOPOSN LDY BOARD,X CPY #$10 BPL NOPOSN POSN CLC ADC #$02 NOPOSN JMP CKMATE ; CONTINUE ;----------------------------------------------------------------- ; The following routines were added to allow text-based board ; display over a standard RS-232 port. ; POUT jsr pout9 ; print CRLF jsr pout13 ; print copyright JSR POUT10 ; print column labels LDY #$00 ; init board location JSR POUT5 ; print board horz edge POUT1 lDA #"|" ; print vert edge JSR syschout ; PRINT ONE ASCII CHR - SPACE LDX #$1F POUT2 TYA ; scan the pieces for a location match CMP BOARD,X ; match found? BEQ POUT4 ; yes; print the piece's color and type DEX ; no BPL POUT2 ; if not the last piece, try again tya ; empty square and #$01 ; odd or even column? sta temp ; save it tya ; is the row odd or even lsr ; shift column right 4 spaces lsr ; lsr ; lsr ; and #$01 ; strip LSB clc ; adc temp ; combine row & col to determine square color and #$01 ; is board square white or blk? bne pout25 ; white, print space lda #"*" ; black, print * db $2c ; used to skip over LDA #$20 POUT25 LDA #$20 ; ASCII space JSR syschout ; PRINT ONE ASCII CHR - SPACE JSR syschout ; PRINT ONE ASCII CHR - SPACE POUT3 INY ; TYA ; get row number AND #$08 ; have we completed the row? BEQ POUT1 ; no, do next column LDA #"|" ; yes, put the right edge on JSR syschout ; PRINT ONE ASCII CHR - | jsr pout12 ; print row number JSR POUT9 ; print CRLF JSR POUT5 ; print bottom edge of board CLC ; TYA ; ADC #$08 ; point y to beginning of next row TAY ; CPY #$80 ; was that the last row? BEQ POUT8 ; yes, print the LED values BNE POUT1 ; no, do new row POUT4 LDA REV ; print piece's color & type BEQ POUT41 ; LDA cpl+16,X ; BNE POUT42 ; POUT41 LDA cpl,x ; POUT42 JSR syschout ; lda cph,x ; jsr syschout ; BNE POUT3 ; branch always POUT5 TXA ; print "-----...-----" PHA LDX #$19 LDA #"-" POUT6 JSR syschout ; PRINT ONE ASCII CHR - "-" DEX BNE POUT6 PLA TAX JSR POUT9 RTS POUT8 jsr pout10 ; LDA $FB JSR syshexout ; PRINT 1 BYTE AS 2 HEX CHRS LDA #$20 JSR syschout ; PRINT ONE ASCII CHR - SPACE LDA $FA JSR syshexout ; PRINT 1 BYTE AS 2 HEX CHRS LDA #$20 JSR syschout ; PRINT ONE ASCII CHR - SPACE LDA $F9 JSR syshexout ; PRINT 1 BYTE AS 2 HEX CHRS POUT9 LDA #$0D JSR syschout ; PRINT ONE ASCII CHR - CR LDA #$0A JSR syschout ; PRINT ONE ASCII CHR - LF RTS pout10 ldx #$00 ; print the column labels POUT11 lda #$20 ; 00 01 02 03 ... 07 jsr syschout txa jsr syshexout INX CPX #$08 BNE POUT11 BEQ POUT9 POUT12 TYA and #$70 JSR syshexout rts Pout13 ldx #$00 ; Print the copyright banner Pout14 lda banner,x beq POUT15 jsr syschout inx bne POUT14 POUT15 rts KIN LDA #"?" JSR syschout ; PRINT ONE ASCII CHR - ? JSR syskin ; GET A KEYSTROKE FROM SYSTEM AND #$4F ; MASK 0-7, AND ALPHA'S RTS ; ; 6551 I/O Support Routines ; ; Init_6551 lda #$1F ; 19.2K/8/1 sta ACIActl ; control reg lda #$0B ; N parity/echo off/rx int off/ dtr active low sta ACIAcmd ; command reg rts ; done ; ; input chr from ACIA1 (waiting) ; syskin lda ACIASta ; Serial port status and #$08 ; is recvr full beq syskin ; no char to get Lda ACIAdat ; get chr RTS ; ; ; output to OutPut Port ; syschout PHA ; save registers ACIA_Out1 lda ACIASta ; serial port status and #$10 ; is tx buffer empty beq ACIA_Out1 ; no PLA ; get chr sta ACIAdat ; put character to Port RTS ; done syshexout PHA ; prints AA hex digits LSR ; MOVE UPPER NIBBLE TO LOWER LSR ; LSR ; LSR ; JSR PrintDig ; PLA ; PrintDig AND #$0F ; prints A hex nibble (low 4 bits) PHX TAY ; LDA Hexdigdata,Y ; PLX jmp syschout ; Hexdigdata asc "0123456789ABCDEF" banner asc "MicroChess (c) 1996-2002 Peter Jennings, peterj@benlo.com" db $0d, $0a, $00 cpl asc "WWWWWWWWWWWWWWWWBBBBBBBBBBBBBBBBWWWWWWWWWWWWWWWW" cph asc "KQCCBBRRPPPPPPPPKQCCBBRRPPPPPPPP" db $00 ; ; end of added code ; ; BLOCK DATA *= $1580 SETW db $03, $04, $00, $07, $02, $05, $01, $06 db $10, $17, $11, $16, $12, $15, $14, $13 db $73, $74, $70, $77, $72, $75, $71, $76 db $60, $67, $61, $66, $62, $65, $64, $63 MOVEX db $00, $F0, $FF, $01, $10, $11, $0F, $EF, $F1 db $DF, $E1, $EE, $F2, $12, $0E, $1F, $21 POINTS db $0B, $0A, $06, $06, $04, $04, $04, $04 db $02, $02, $02, $02, $02, $02, $02, $02 OPNING db $99, $25, $0B, $25, $01, $00, $33, $25 db $07, $36, $34, $0D, $34, $34, $0E, $52 db $25, $0D, $45, $35, $04, $55, $22, $06 db $43, $33, $0F, $CC ; ; ; end of file ; crasm/test/tstmacros.crasm0000600000175000017500000000112410107153777014272 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. nam essai macro page 0,132 depart = $1000 fin = $2000 fcb = db lda macro fcb $ad ddb \1 endm ref macro .L dw \1 if \1>0 ref \1-1 endc dw .L endm final macro dw \# if \#>=2 dl \1,\2 exitm endc asc "encore" endm page * = depart+fin mlist on start lda depart ref 4 asc "espoir" final depart mlist off ref 4 end final depart,fin ds 2 ds 100,3 enfin asc "je m'interesse encore au calcul" asc " et a l'affichage des trees.\0" crasm/test/stdnames.68010000600000175000017500000000266510107154457013371 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. ; Names for builin 6801 registers ; Bit testing macros dummy vectors = $fff0 * = vectors vector.sci dw 0 vector.tof dw 0 vector.ocf dw 0 vector.icf dw 0 vector.irq dw 0 vector.swi dw 0 vector.nmi dw 0 vector.reset dw 0 * = $0 ddr1 db 0 ddr2 db 0 dr1 db 0 dr2 db 0 ddr3 db 0 ddr4 db 0 dr3 db 0 dr4 db 0 tcsr db 0 counter dw 0 ocr dw 0 icr dw 0 p3csr db 0 rmcr db 0 trcsr db 0 rdr db 0 tdr db 0 ramcr db 0 p3csr.is3 = p3csr{7} p3csr.eis3i = p3csr{6} p3csr.os3 = p3csr{4} p3csr.le = p3csr{3} ramcr.stby = ramcr{7} ramcr.rami = ramcr{6} tcsr.icf = tcsr{7} tcsr.ocf = tcsr{6} tcsr.tof = tcsr{5} tcsr.eici = tcsr{4} tcsr.eoci = tcsr{3} tcsr.etoi = tcsr{2} tcsr.iedg = tcsr{1} tcsr.olvl = tcsr{0} rmcr.cc1 = rmcr{3} rmcr.cc0 = rmcr{2} rmcr.ss1 = rmcr{1} rmcr.ss0 = rmcr{0} trcsr.rdrf = trcsr{7} trcsr.orfe = trcsr{6} trcsr.tdre = trcsr{5} trcsr.rie = trcsr{4} trcsr.re = trcsr{3} trcsr.tie = trcsr{2} trcsr.te = trcsr{1} trcsr.wu = trcsr{0} ;; bset BITSPEC --- ;; Sets bit BITSPEC ;; Clobbers A. bset macro ldaa #1<< BIT(\1) oraa ADDR(\1) staa ADDR(\1) endm ;; bclr BITSPEC --- ;; Clears bit BITSPEC ;; Clobbers A. bclr macro ldaa # $ff ^ (1<< BIT(\1)) bnomask \1 anda ADDR(\1) staa ADDR(\1) endm ;; btst BITSPEC --- ;; Clears bit BITSPEC ;; Set/Reset Z bit. ;; Clobbers A. btst macro ldaa #1<< BIT(\1) bmask \1 anda ADDR(\1) endm codecrasm/test/copy.68000000600000175000017500000000074310110236526012507 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. cpu 6800 * = $8000 begin = $40 dest = $42 len = $44 ldx #$4000 stx begin ldx #$1430 stx len ldx #$6000 stx dest jsr copy wai code ; copy LEN bytes from BEGIN to DEST copy ldx begin sts begin txs ldx dest ldab len+1 ldaa len addb dest+1 adca dest stab dest+1 staa dest .1 cpx dest beq .2 pula staa 0,x inx bra .1 .2 tsx lds begin stx begin clr len clr len+1 rts code crasm/test/tstinclude.crasm0000600000175000017500000000020310107153777014426 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. ilist on include testfiles/tstmacros.crasm ilist off include testfiles/tstif.crasm crasm/test/opcode.z800000600000175000017500000001547310107153777013054 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. ; All Z80 opcodes cpu z80 *=4000H adr=12345 dd=23H n=45Q nn=23456 adc a,(hl) adc a,(ix+dd) adc a,(iy+dd) adc a,a adc a,b adc a,c adc a,d adc a,e adc a,h adc a,l adc a,n adc hl,bc adc hl,de adc hl,hl adc hl,sp add a,(hl) add a,(ix+dd) add a,(iy+dd) add a,a add a,b add a,c add a,d add a,e add a,h add a,l add a,n add hl,bc add hl,de add hl,hl add hl,sp add ix,bc add ix,de add ix,ix add ix,sp add iy,bc add iy,de add iy,iy add iy,sp and (hl) and (ix+dd) and (iy+dd) and a and b and c and d and e and h and l and n bit 0,(hl) bit 0,(ix+dd) bit 0,(iy+dd) bit 0,a bit 0,b bit 0,c bit 0,d bit 0,e bit 0,h bit 0,l bit 1,(hl) bit 1,(ix+dd) bit 1,(iy+dd) bit 1,a bit 1,b bit 1,c bit 1,d bit 1,e bit 1,h bit 1,l bit 2,(hl) bit 2,(ix+dd) bit 2,(iy+dd) bit 2,a bit 2,b bit 2,c bit 2,d bit 2,e bit 2,h bit 2,l bit 3,(hl) bit 3,(ix+dd) bit 3,(iy+dd) bit 3,a bit 3,b bit 3,c bit 3,d bit 3,e bit 3,h bit 3,l bit 4,(hl) bit 4,(ix+dd) bit 4,(iy+dd) bit 4,a bit 4,b bit 4,c bit 4,d bit 4,e bit 4,h bit 4,l bit 5,(hl) bit 5,(ix+dd) bit 5,(iy+dd) bit 5,a bit 5,b bit 5,c bit 5,d bit 5,e bit 5,h bit 5,l bit 6,(hl) bit 6,(ix+dd) bit 6,(iy+dd) bit 6,a bit 6,b bit 6,c bit 6,d bit 6,e bit 6,h bit 6,l bit 7,(hl) bit 7,(ix+dd) bit 7,(iy+dd) bit 7,a bit 7,b bit 7,c bit 7,d bit 7,e bit 7,h bit 7,l call adr call c,adr call m,adr call nc,adr call nz,adr call p,adr call pe,adr call po,adr call z,adr ccf cp (hl) cp (ix+dd) cp (iy+dd) cp a cp b cp c cp d cp e cp h cp l cp n cpd cpdr cpi cpir cpl daa dec (hl) dec (ix+dd) dec (iy+dd) dec a dec b dec bc dec c dec d dec de dec e dec h dec hl dec ix dec iy dec l dec sp di here1 djnz here1 ei ex (sp),hl ex (sp),ix ex (sp),iy ex af,af' ex de,hl exx halt im 0 im 1 im 2 in a,(c) in a,(n) in b,(c) in c,(c) in d,(c) in e,(c) in h,(c) in l,(c) inc (hl) inc (ix+dd) inc (iy+dd) inc a inc b inc bc inc c inc d inc de inc e inc h inc hl inc ix inc iy inc l inc sp ind indr ini inir jp (hl) jp (ix) jp (iy) jp adr jp c,adr jp m,adr jp nc,adr jp nz,adr jp p,adr jp pe,adr jp po,adr jp z,adr jr c,here2 here2 jr here2 jr nc,here2 jr nz,here2 jr z,here2 ld (bc),a ld (de),a ld (hl),a ld (hl),b ld (hl),c ld (hl),d ld (hl),e ld (hl),h ld (hl),l ld (hl),n ld (ix+dd),a ld (ix+dd),b ld (ix+dd),c ld (ix+dd),d ld (ix+dd),e ld (ix+dd),h ld (ix+dd),l ld (ix+dd),n ld (iy+dd),a ld (iy+dd),b ld (iy+dd),c ld (iy+dd),d ld (iy+dd),e ld (iy+dd),h ld (iy+dd),l ld (iy+dd),n ld (nn),a ld (nn),bc ld (nn),de ld (nn),hl ld (nn),ix ld (nn),iy ld (nn),sp ld a,(bc) ld a,(de) ld a,(hl) ld a,(ix+dd) ld a,(iy+dd) ld a,(nn) ld a,a ld a,b ld a,c ld a,d ld a,e ld a,h ld a,i ld a,l ld a,n ld a,r ld b,(hl) ld b,(ix+dd) ld b,(iy+dd) ld b,a ld b,b ld b,c ld b,d ld b,e ld b,h ld b,l ld b,n ld bc,(nn) ld bc,nn ld c,(hl) ld c,(ix+dd) ld c,(iy+dd) ld c,a ld c,b ld c,c ld c,d ld c,e ld c,h ld c,l ld c,n ld d,(hl) ld d,(ix+dd) ld d,(iy+dd) ld d,a ld d,b ld d,c ld d,d ld d,e ld d,h ld d,l ld d,n ld de,(nn) ld de,nn ld e,(hl) ld e,(ix+dd) ld e,(iy+dd) ld e,a ld e,b ld e,c ld e,d ld e,e ld e,h ld e,l ld e,n ld h,(hl) ld h,(ix+dd) ld h,(iy+dd) ld h,a ld h,b ld h,c ld h,d ld h,e ld h,h ld h,l ld h,n ld hl,(nn) ld hl,nn ld i,a ld ix,(nn) ld ix,nn ld iy,(nn) ld iy,nn ld l,(hl) ld l,(ix+dd) ld l,(iy+dd) ld l,a ld l,b ld l,c ld l,d ld l,e ld l,h ld l,l ld l,n ld r,a ld sp,(nn) ld sp,hl ld sp,ix ld sp,iy ld sp,nn ldd lddr ldi ldir neg nop or (hl) or (ix+dd) or (iy+dd) or a or b or c or d or e or h or l or n otdr otir out (c),a out (c),b out (c),c out (c),d out (c),e out (c),h out (c),l out (n),a outd outi pop af pop bc pop de pop hl pop ix pop iy push af push bc push de push hl push ix push iy res 0,(hl) res 0,(ix+dd) res 0,(iy+dd) res 0,a res 0,b res 0,c res 0,d res 0,e res 0,h res 0,l res 1,(hl) res 1,(ix+dd) res 1,(iy+dd) res 1,a res 1,b res 1,c res 1,d res 1,e res 1,h res 1,l res 2,(hl) res 2,(ix+dd) res 2,(iy+dd) res 2,a res 2,b res 2,c res 2,d res 2,e res 2,h res 2,l res 3,(hl) res 3,(ix+dd) res 3,(iy+dd) res 3,a res 3,b res 3,c res 3,d res 3,e res 3,h res 3,l res 4,(hl) res 4,(ix+dd) res 4,(iy+dd) res 4,a res 4,b res 4,c res 4,d res 4,e res 4,h res 4,l res 5,(hl) res 5,(ix+dd) res 5,(iy+dd) res 5,a res 5,b res 5,c res 5,d res 5,e res 5,h res 5,l res 6,(hl) res 6,(ix+dd) res 6,(iy+dd) res 6,a res 6,b res 6,c res 6,d res 6,e res 6,h res 6,l res 7,(hl) res 7,(ix+dd) res 7,(iy+dd) res 7,a res 7,b res 7,c res 7,d res 7,e res 7,h res 7,l ret ret c ret m ret nc ret nz ret p ret pe ret po ret z reti retn rl (hl) rl (ix+dd) rl (iy+dd) rl a rl b rl c rl d rl e rl h rl l rla rlc (hl) rlc (ix+dd) rlc (iy+dd) rlc a rlc b rlc c rlc d rlc e rlc h rlc l rlca rld rr (hl) rr (ix+dd) rr (iy+dd) rr a rr b rr c rr d rr e rr h rr l rra rrc (hl) rrc (ix+dd) rrc (iy+dd) rrc a rrc b rrc c rrc d rrc e rrc h rrc l rrca rrd rst 00H rst 08H rst 10H rst 18H rst 20H rst 28H rst 30H rst 38H sbc a,(hl) sbc a,(ix+dd) sbc a,(iy+dd) sbc a,a sbc a,b sbc a,c sbc a,d sbc a,e sbc a,h sbc a,l sbc a,n sbc hl,bc sbc hl,de sbc hl,hl sbc hl,sp scf set 0,(hl) set 0,(ix+dd) set 0,(iy+dd) set 0,a set 0,b set 0,c set 0,d set 0,e set 0,h set 0,l set 1,(hl) set 1,(ix+dd) set 1,(iy+dd) set 1,a set 1,b set 1,c set 1,d set 1,e set 1,h set 1,l set 2,(hl) set 2,(ix+dd) set 2,(iy+dd) set 2,a set 2,b set 2,c set 2,d set 2,e set 2,h set 2,l set 3,(hl) set 3,(ix+dd) set 3,(iy+dd) set 3,a set 3,b set 3,c set 3,d set 3,e set 3,h set 3,l set 4,(hl) set 4,(ix+dd) set 4,(iy+dd) set 4,a set 4,b set 4,c set 4,d set 4,e set 4,h set 4,l set 5,(hl) set 5,(ix+dd) set 5,(iy+dd) set 5,a set 5,b set 5,c set 5,d set 5,e set 5,h set 5,l set 6,(hl) set 6,(ix+dd) set 6,(iy+dd) set 6,a set 6,b set 6,c set 6,d set 6,e set 6,h set 6,l set 7,(hl) set 7,(ix+dd) set 7,(iy+dd) set 7,a set 7,b set 7,c set 7,d set 7,e set 7,h set 7,l sla (hl) sla (ix+dd) sla (iy+dd) sla a sla b sla c sla d sla e sla h sla l sra (hl) sra (ix+dd) sra (iy+dd) sra a sra b sra c sra d sra e sra h sra l srl (hl) srl (ix+dd) srl (iy+dd) srl a srl b srl c srl d srl e srl h srl l sub (hl) sub (ix+dd) sub (iy+dd) sub a sub b sub c sub d sub e sub h sub l sub n xor (hl) xor (ix+dd) xor (iy+dd) xor a xor b xor c xor d xor e xor h xor l xor n crasm/test/tstif.crasm0000600000175000017500000000056610107153777013415 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. * equ $2000 dw end1-4*2 end2 dw (end1-4)*2 end1 dw $ad if 1<2 if 1>2 dl 3000 else dw 4000 endc dw 1000 else if 1<>1 dw 6000/2 endc dw 2000 endc clist off if 1>2 dw 3000 else dw 4000 endc if 1<=1 dw 5000 if 1>2 dw 3000 else dw 4000 endc endc crasm/test/forth.68010000600000175000017500000001030610107153777012670 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. ; Beginnings of a forth kernel. ; Good test for macros. ; ; http://www.forth.org/ ; http://www.zetetics.com/bj/papers/moving1.htm cpu 6801 mlist off page 0,132 * = $1000 smudge = 1<<7 precedence = 1<<6 keep = 1<<5 ;; ********************************** ;; -- create INVOCNAME, WORDNAME [, FLAGS] ;; Create a forth word WORDNAME into vocabulary INVOCNAME ;; This macro outputs the word header and defines useful labels ;; nfa_WORDNAME - address of header ;; lfa_WORDNAME - address of pointer to previous word in vocabulary ;; cfa_WORDNAME - address of executable data (just after header) create macro .start = * if \3 nfa_\2 db .len | smudge | \3 else nfa_\2 db .len | smudge endc asc "\2" lfa_\2 dw lstw_\1 lstw_\1 = .start cfa_\2 = * .len = lfa_\2-nfa_\2 endm ;; ********************************** ;; -- createvoc INVOCNAME,VOCNAME ;; Create a forth vocabulary VOCNAME in vocabulary INVOCNAME ;; This macro outputs the word header and defines useful labels ;; nfa_VOCNAME - address of word header ;; lfa_VOCNAME - address of pointer to previous word in voc INVOCNAME ;; cfa_VOCNAME - address of word executable data (jsr dovoc) ;; pfa_VOCNAME - address of vocabulary data for VOCNAME ;; lst_VOCNAME - address of pointer to last word in vocabulary ;; vlnk_VOCNAME - address of pointer to parent vocabulary. ;; The following symbol is modified whenever ;; a word is added into the vocabulary VOCNAME ;; lstw_VOCNAME - address of last word in vocabulary VOCNAME ;; until one calls endvoc createvoc macro lstw_\2 = pfa_\1 create \1,\2 jsr dovoc pfa_\2 db smudge|1,' ' lst_\2 dw 0 vlnk_\2 dw pfa_\1 endm ;; ********************************** ;; -- endvoc VOCNAME ;; Terminates definition of vocabulary VOCNAME ;; This sets the value of pointer at address lst_VOCNAME ;; No words should be added to the vocabulary. endvoc macro asc "LYB Forth." .loc = * * = lst_\1 dw lstw_\1 * = .loc endm ;; ********************************** ;; -- createforth ;; Creates the initial vocabulary named FORTH. createforth macro lstw_forth = 0 nfa_forth db 6|smudge asc "forth" lfa_forth = 0 cfa_forth jsr dovoc pfa_forth db smudge|1,' ' lst_forth db 0 vlnk_forth dw 0 endm ;; ********************************** ;; -- start, end, compile ;; These macros are used to define a forth word. ;; Usage: ;; create INVOCNAME, WORDNAME ;; start ;; compile WORDNAME ;; compile WORDNAME ;; ... ;; end ;; What about constants... start macro jsr docol endm end macro dw endcol endm compile macro dw cfa_\1 endm ;; ********************************** ;; -- docol, endcol, next ;; The forth interpreter engine. ;; The forth data stack is the 6801 stack. ip = $80 ; instruction pointer rp = $82 ; return stack pointer dp = $84 ; used to save the data stack pointer ;; docol - start interpreting a forth thread docol ldd ip ldx rp std 0,x dex dex stx rp pulx stx ip ldx ,x jmp ,x ;; endcol -- return from interpreting a forth thread endcol ldx rp inx inx stx rp ldx ,x inx inx stx ip ldx ,x jmp ,x ;; next -- return from assembly code primitive next ldx ip inx inx stx ip ldx ,x jmp ,x ;; dovoc -- undefined yet dovoc rts ;; ********************************** ;; Forth words code createforth code create forth,dup pulx pshx pshx jmp next code create forth,drop pulx jmp next code create forth,ndrop pulx .1 beq .2 pula pula dex bra .1 .2 jmp next code create forth,swap pulx pula pulb pshx pshb psha jmp next code create forth,pick pula pulb lsrd sts dp addd dp std dp ldx dp ldx ,x pshx jmp next code create forth,over pula pulb pulx pshx pshb psha pshx jmp next code create forth,rot pulx stx dp pulx pula pulb pshx ldx dp pshx pshb psha jmp next ;; USER VOCABULARY code createvoc forth,uservoc code create uservoc,dupdrop,precedence start compile dup compile drop end endvoc uservoc ; Terminate vocabulary USERVOC endvoc forth ; Terminate vocabulry FORTH crasm/test/math16.65020000600000175000017500000000365710107153777012657 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. cpu 6502 ; 16 bit calculus functions. ; Two pseudoregisters: ACC, ARG ; Four temporary bytes: TEMP dummy * = $20 acc ds 2 arg ds 2 temp ds 4 movi macro lda #(\1) & $ff sta \2 lda #(\1) >> 8 sta (\2)+1 endm movm macro lda \1 sta \2 lda (\1)+1 sta (\2)+2 endm * = $8000 code add16 lda acc ; ACC <- ACC + ARG clc adc arg sta acc lda acc+1 adc arg+1 sta acc+1 rts clr16 lda #0 ; clear ACC sta acc sta acc+1 .1 rts abs16 bit acc+1 ; absolute value of ACC bpl .1 neg16 lda #0 ; negate ACC sec sbc acc sta acc lda #0 sbc acc+1 sta acc+1 rts neg16a lda #0 ; negate ARG sec sbc arg sta arg lda #0 sbc arg+1 sta arg+1 rts sub16 lda acc ; ACC <- ACC - ARG sec sbc arg sta acc lda acc+1 sbc arg+1 sta acc+1 rts code ovfl bit .ov1 .ov1 rts code muls16 lda acc+1 ; ACC <- ACC * ARG eor arg+1 sta temp+3 bit arg+1 bpl .0 jsr neg16a .0 jsr abs16 lda #$80 sta temp+1 lda #0 sta temp sta temp+2 .1 lsr acc+1 lsr acc bcc .2 pha lda temp+2 clc adc arg sta temp+2 pla adc arg+1 .2 ror ror temp+2 ror temp+1 ror temp bcc .1 ora temp+2 php movm temp,acc plp bne ovfl bit acc+1 bmi ovfl bit temp+3 bpl .3 jsr neg16 .3 rts code divmod movm acc,temp ; ACC <- ACC / ARG (unsigned) lda #$01 ; TEMP+2 <- ACC % ARG (unsigned) sta acc asl sta temp+2 sta temp+3 sta acc+1 lda arg ora arg beq ovfl .1 asl temp rol temp+1 rol temp+2 rol temp+3 lda temp+2 cmp arg lda temp+3 sbc arg+1 bcc .2 sta temp+3 lda temp+2 sbc arg sta temp+2 sec .2 rol acc rol acc+1 bcc .1 rts code divs16 lda acc+1 ; ACC <- ACC / ARG eor arg+1 pha bit arg+1 bpl .0 jsr neg16a .0 jsr abs16 jsr divmod pla bpl .1 jmp neg16 .1 rts code mod16 lda acc+1 ; ACC <- ACC % ARG pha bit arg+1 bpl .0 jsr neg16a .0 jsr abs16 jsr divmod movm temp+2,acc pla bpl .1 jmp neg16 .1 rts crasm/test/modem.68010000600000175000017500000005316310107153777012657 0ustar cmbcmb;;; Author: Leon Bottou ;;; Public Domain. ; Ceci est le code source du programme ; contenu dans un modem pilote par 6801. ; ; Le processeur (Motorola 6801) ; - communiquait avec l'ordinateur par ; son propre port serie a 1200 ou 9600 bauds ; selon l'etat du switch INSP ; - communiquait avec une puce modem EFCIS ; via un ACIA 6850 ; - Ses ports // controlaient divers ; parametres du circuit modem, et une LED ; ; Il y avait en outre ; - 4k de ROM (2532) de $f000 a $ffff ; - 2k de RAM CMOS (6116) de $d800 a $dfff ; - Une horloge temps reel 6818 sauvegardee ; ; Le programme ci dessous contient un Moniteur ; Hexa (Apple][ like) avec mini-assembleur ; et desassembleur, et le programme de gestion ; du modem. Au reset, le CPU branche sur l'un ou ; l'autre, selon l'etat d'un switch INMOD. ; Cible: TI ou Motorola 2532 ; placee aux adresses $F000->$FFFF ; Declarations output scode cpu 6801 fdb = dw ; equivalence de mnemoniques fcb = db fcc = db ; pour ne pas trop modifier... org macro * = \1 endm ; quelques registres du 6801 ; et leur signification ici. ddr1 equ $00 ddr2 equ $01 dr1 equ $02 ; /XRTS,HANG,/CTS,TEST,MC/BC,/CD,INMOD,INSP dr2 equ $03 ; b0: /LEDR tcsr equ $8 ; ICF,OCF,TOF,EICI,EOCI,ETOI,IEDG,OLVL tim equ $9 ocr equ $b rmcr equ $10 trcsr equ $11 ; RDRF,ORFE,TDRE,RIE,RE,TIE,TE,WU rdr equ $12 tdr equ $13 ; Les adresses de l'ACIA 6850 aciacr equ $bffe ; crW: RIE,0,TIE,P,P,P,D,D ( 01001 ) aciadr equ $bfff ; crR: IRQ,PE,OV,FE,/CTS,/DCD,TDRE,RDRF ; Deux octets de ram sauvegardee ; dans l'horloge 6818 sav1 equ $9fce ; RamOk:$87 sav2 equ $9fcf ; /LF,/XonXoff,RTS,0,ECHO,HALF,TEST,MCBC ; Les registres du 6818 hbase equ $9fc0 rega equ $9fca ; UIP,div2-0(010) rs3-0(0000) regb equ $9fcb ; SET,PIE,AIE,UIE,SQWE,DM,24/12,DSE regc equ $9fcc ; IRQF,PF,AF,UF, 0000 regd equ $9fcd ; VRT,0000000 ; Les adresses de base de : ; la RAM CMOS 6116 ; la RAM du 6818 sram equ $d800 hram equ $9fd0 ; La queue d'entree dans la 6116 dgo equ $dfae xgo equ $dfac ; Le buffer de ligne pour le moniteur inbuf equ $dfb1 endbuf equ $dfff ; Quelques emplacement dans ; la ram du 6801 possav equ $96 ocfv equ $80 tofv equ $82 icfv equ $84 nmiv equ $86 flashled equ $88 counter equ $88 flag equ $89 ; FLSH,-,+,.,:,sz2-0 mode equ $89 posxin equ $8a posin equ $8c rcvxin equ $8b rcvin equ $8d abort equ $1d xinmask equ $1f inmask equ $7f xsav equ $8e r0 equ $90 r1 equ $92 r2 equ $94 checksum equ $9e aciamode equ $9f ; dont la queue d'entree du modem, ; et la pile CPU xinqueue equ $a0 inqueue equ $df00 stkbase equ $ff ; Les vecteurs d'interruption org $fff0 fdb sciirq fdb ledirq fdb ocfirq fdb icfirq fdb aciairq fdb swiirq fdb nmiirq fdb reset ; Le programme lui meme org $f000 msga asc "\n\rMoniteur LYB.\0" msgb asc "Erreur\0" msgc asc "Erreur de Checksum\0" msgd asc "OVERFLOW\n\r\0" msgswi asc "\n\rSWI: SP P A B X\0" msgwr asc "S9030000FC\0" mydummy rti ocfirq ldx ocfv jmp 0,x icfirq ldx icfv jmp 0,x nmiirq ldx nmiv jmp 0,x swiirq ldx #msgswi jsr outmsg tsx ldx 5,x jsr prx jsr outsp tsx jsr prx jsr outsp ldab 0,x jsr prb jsr outsp ldab 2,x jsr prb ldab 1,x jsr prb jsr outsp ldx 3,x jsr prx jsr outcr jmp monloop2 ; Reset general reset lds #stkbase ldx #mydummy stx ocfv stx icfv stx nmiv stx tofv clra staa flashled staa posin staa posxin staa rcvin staa rcvxin ldaa sav1 cmpa #$87 beq reset2 clra staa sav2 reset2 anda regd anda #$80 staa flag oraa #$7 staa sav1 sei ldaa #$11 staa ddr2 ldaa #$f8 staa ddr1 ldaa #%10000000 staa dr1 ldaa #$01 staa dr2 ldaa #%011 staa aciacr ldaa #%01001 staa aciacr staa aciamode ldaa #%11010 staa trcsr ldab dr1 ldaa #%0110 ; 1200 bauds bitb #$01 beq reset3 ldaa #%0101 ; 9600 bauds reset3 staa rmcr ldaa #%0101 staa tcsr cli ldx #inbuf-1 reset1 inx clr 0,x cpx #endbuf bne reset1 bitb #$02 beq reset5 reset4 jmp modem reset5 jmp monloop ; SP de controle des irq eixin ldab #$80 orab aciamode bra setxcr dixin ldab #$7f andb aciamode setxcr stab aciamode stab aciacr rts ; SciIrq sciirq ldaa rcvin inca tab suba posin anda #inmask beq ovfl ldx #inqueue andb #inmask abx stab rcvin ldab trcsr ldab rdr stab 0,x cmpa #inmask-31 bne sciret cli ldab sav2 bitb #$40 bne noxoff ldaa #'S'-$40 jsr out noxoff ldab sav2 bitb #$20 beq sciret sei ldab dr1 orab #$20 stab dr1 sciret rti ovfl sei ldx #msgd ovfl2 ldaa trcsr bita #$20 beq ovfl2 ldaa 0,x beq sciret staa tdr inx bra ovfl2 ; Aciairq aciairq ldab rcvxin incb andb #xinmask tba suba posxin anda #xinmask beq ovfl ldx #xinqueue abx stab rcvxin ldaa aciacr ldaa aciadr staa 0,x rti ; StdIn in bsr intst beq in rdret rts ; Intst intst ldab posin tba suba rcvin nega anda #inmask beq rdret rdin incb andb #inmask stx xsav ldx #inqueue abx cmpa #$8 bne rdin2 ldaa sav2 bita #$40 bne noxon ldaa #'Q'-$40 jsr out noxon ldaa sav2 bita #$20 beq rdin2 sei ldaa dr1 anda #$df staa dr1 cli rdin2 sei inc posin ldaa 0,x ldx xsav bra retour ; Xout xout2 cli xout sei ldab #$2 bitb aciacr beq xout2 ldab aciacr staa aciadr cli rts ; Xin xin bsr xintst beq xin xinret rts ; Xintst xintst ldab posxin tba suba rcvxin anda #xinmask beq xinret incb andb #xinmask ldx #xinqueue abx sei stab posxin ldaa 0,x retour cli ldab #$ff rts ; StdOut out2 sei out cli ldab #$20 bitb trcsr beq out2 ldab trcsr staa tdr cli rts ; OUT ceci et cela outcr ldaa sav2 bmi outcr2 ldaa #$a bsr out outcr2 ldaa #$d bra out outbs ldaa #$08 bsr out bsr outsp ldaa #$08 bra out outmsg ldaa 0,x beq outcr bsr out inx bra outmsg outt ldaa #'-' bra out outsp ldaa #$20 bra out out2p ldaa #':' bra out prx stx xsav ldab xsav bsr prb ldab xsav+1 prb pshb addb checksum stab checksum pula psha lsra lsra lsra lsra bsr prb2 pula prb2 anda #$f oraa #$30 cmpa #$3a bcs prb3 adda #$7 prb3 bra out heure jsr outcr ldab sav1 ldaa #$20 cmpb #$87 beq heur1 ldaa #'#' heur1 jsr out ldx #hbase heur2 ldaa rega bmi heur2 ldab 7,x bsr prb bsr outt ldab 8,x bsr prb bsr outt ldab #$19 bsr prb ldab 9,x bsr prb bsr outsp ldab 4,x bsr prb bsr out2p ldab 2,x bsr prb bsr out2p ldab 0,x bra prb ; IRQ: ledirq 1/20s ledirq inc flashled ldaa tcsr ldx tim ldaa #$8 bita flashled bne led2 ldaa flag bmi tofirq ldaa #$1 oraa dr2 bra led3 led2 ldaa #$fe anda dr2 led3 staa dr2 tofirq ldx tofv jmp 0,x ; MONITEUR: rdline rdline2 ldaa #'\\' jsr out rdline jsr outcr rdnoret ldaa inbuf-1 jsr out ldx #inbuf rdloop jsr in cmpa #abort beq rdline2 cmpa #$09 bne rdline1 ldaa 0,x beq rdloop rdline1 cmpa #$08 bne rdline3 cpx #inbuf beq rdline jsr outbs dex bra rdloop rdline3 cmpa #$0a beq rdloop cmpa #$0d bne rdline4 rdend clr 0,x jmp outcr rdline4 cpx #endbuf bcc rdloop jsr out staa 0,x inx bra rdloop ; Conversion en majuscules maj cmpa #'a' bcs maj2 cmpa #'z' bhi maj2 suba #$20 maj2 rts ; Lecture d'un hhhh readhex ldaa flag anda #$f8 staa flag ldaa 0,x cmpa #'\'' bne readhex2 clr r1 ldaa 1,x staa r1+1 inc flag ldaa 2,x inx inx readhex5 inc flag ldab flag bitb #$70 bne readhex6 bitb #$6 beq readhex6 ldd r1 std r0 readhex6 ldaa 0,x inx bra maj readhex2 ldaa 0,x jsr maj ldab #$4 bitb flag bne readhex5 jsr conv bcc readhex5 ldaa #$7 bita flag bne readhex3 clra staa r1 staa r1+1 readhex3 inc flag aslb aslb aslb aslb ldaa #$4 readhex4 aslb rol r1+1 rol r1 deca bne readhex4 inx bra readhex2 conv tab subb #$30 cmpb #$11 bcc conv2 cmpb #$a rts conv2 subb #$7 cmpb #$10 rts ; MONITEUR boucle et xeqline monloop ldx #msga jsr outmsg monloop2 lds #stkbase ldaa #'*' staa inbuf-1 jsr rdline ldx inbuf cpx #$4154 bne goxeq jsr hayes bra monloop2 goxeq jsr xeqline bra monloop2 xeqline ldx #inbuf stx possav ldaa flag anda #$80 staa flag xeq2 ldx possav jsr readhex stx possav ldx #jtable xeq3 cmpa 0,x beq xeq5 tst 0,x beq err inx inx inx bra xeq3 err ldx #msgb jmp outmsg xeq5 ldx 1,x ldab flag tba anda #$80 staa flag jsr 0,x bra xeq2 ; Table des commandes jtable fcb 'H' fdb heure fcb ' ' fdb space fcb '?' fdb ascii fcb '.' fdb point fcb 'G' fdb go fcb 'R' fdb read fcb 'W' fdb write fcb ':' fdb patchmode fcb 'X' fdb modem fcb '>' fdb prr2 fcb '+' fdb plus fcb '-' fdb moins fcb 'M' fdb move fcb '<' fdb transf fcb 'Y' fdb goram fcb '=' fdb setregs fcb 'L' fdb dasm fcb '!' fdb masm fcb 0 fdb cr ; Commandes moniteur cr pula pula ldx possav dex cpx #inbuf bne space ldd r0 orab #$f std r1 dump2 ldaa r0+1 anda #$f bne dump3 dump ldx r0 jsr outcr jsr prx jsr outt dump3 jsr outsp ldx r0 stx r2 ldab 0,x jsr prb jsr nxtr0 bcs dump2 rts nxtr2 ldx r2 inx stx r2 nxtr0 ldd r0 ldx r0 inx stx r0 subd r1 rts point ldaa #$10 bra orflag plus ldaa #$20 bra orflag moins ldaa #$40 orflag oraa flag staa flag space2 rts space tba anda #$88 staa flag bitb #$6 beq space2 bitb #$8 bne patch bitb #$20 bne xplus bitb #$40 bne xmoins bra dump patch ldx r2 ldaa r1+1 staa 0,x bitb #$4 beq patch2 ldd r1 std 0,x inx patch2 inx stx r2 rts xplus ldd r0 addd r1 bra xarith xmoins ldd r0 subd r1 xarith std r0 std r1 ldx r0 ldaa #'=' jsr out jmp prx patchmode orab #$8 andb #$8f stab flag bitb #$6 beq patchmd2 ldd r0 std r2 patchmd2 rts prr2 ldx r2 jsr prx jmp out2p go ldaa #$7e staa r0-1 ldd dgo ldx xgo jsr r0-1 swi goram ldx r1 jmp 0,x move ldx r0 ldaa 0,x ldx r2 staa 0,x jsr nxtr2 bcs move rts transf bitb #6 beq transf2 ldd r0 std r2 transf2 rts ascii2 ldaa r0+1 anda #$1f bne ascii3 ascii ldx r0 jsr outcr jsr prx jsr outt ascii3 jsr outsp ldx r0 stx r2 ldab 0,x tba andb #$7f cmpb #$20 bcc ascii4 ldaa #'.' ascii4 jsr out jsr nxtr0 bcs ascii2 rts setregs bitb #$10 beq setacc ldd r1 std xgo setacc ldd r0 std dgo rts ; Transferts SCODE lenframe equ $98 bufbyte equ $99 address equ $9a write ldx r0 ldd r1 subd r0 tsta bne write1 cmpb #$f bcs write2 write1 ldab #$f write2 incb stab lenframe ldaa #'S' jsr out ldaa #'1' jsr out clr checksum ldab lenframe addb #$3 jsr prb jsr prx write3 ldab 0,x inx jsr prb dec lenframe bne write3 ldab checksum comb jsr prb jsr outcr2 dex stx r0 jsr nxtr0 bcs write ldx #msgwr jmp outmsg rberr pula pula readerr jsr err readerr2 jsr in cmpa #abort bne readerr2 rts readdone jsr in jsr conv bcs readdone rts rbyte jsr in jsr conv bcc rberr aslb aslb aslb aslb stab bufbyte jsr in jsr conv bcc rberr orab bufbyte tba adda checksum staa checksum rts read2 jsr in jsr conv bcs read2 read jsr in cmpa #$0a beq read cmpa #$0d beq read cmpa #'S' bne readerr jsr in jsr conv bcc readerr tstb beq read2 cmpb #$9 beq readdone clr checksum bsr rbyte subb #3 stab lenframe beq read2 bsr rbyte stab address bsr rbyte stab address+1 ldx address read3 bsr rbyte cpx r0 bcs read4 cpx r1 bhi read4 stab 0,x read4 inx dec lenframe bne read3 bsr rbyte ldab checksum comb beq read ldx #msgc jsr outmsg bra read ; Dessassembleur dasm bitb #$10 bne dasm4 bitb #$6 beq dasm2 ldd r0 std r2 dasm2 ldaa #$14 dasm3 psha jsr dasmins pula deca bne dasm3 rts dasm4 ldd r0 std r2 dasm5 jsr dasmins ldd r2 subd r1 bcs dasm5 rts ; Miniassembleur masm bitb #$6 beq masm2 ldd r0 std r2 masm2 ldx r2 jsr prx ldaa #'!' staa inbuf-1 jsr rdnoret ldx #inbuf-1 masm4 inx ldaa 0,x cmpa #$20 beq masm4 stx possav tsta beq masm3 jsr masmins bcs masm5 jsr dasmins bra masm2 masm5 jsr err bra masm2 masm3 jmp monloop2 ; Hayes msgh1 asc "ERROR\0" msgh2 asc "NO CONNECT\0" msgh3 asc "OK\0" msgh4 asc "\r\nEND OF CONNECTION\0" msghay asc "SmartModem non encore implemente\0" hayes ldx #msgh1 jsr outmsg ldx #msghay jmp outmsg ; Modem Manuel msg1 asc "C Connecte\0" msg2 asc "Attente de la porteuse\0" modemoff ldaa dr1 anda #$bf oraa #$80 staa dr1 ldx #msgh3 jmp outmsg validcd ldab counter addb #$22 ldaa #4 valid2 bita dr1 bne valid3 cmpb counter bcc valid2 bita dr1 valid3 rts testcd ldaa #4 bita dr1 beq test3 ldab counter addb #$19 test2 bita dr1 beq test3 cmpb counter bcc test2 bita dr1 test3 rts modemloop sei jsr eixin cli mloop1 jsr testcd bne endmloop ldaa #$2 bita aciacr beq mloop2 jsr intst beq mloop2 ldab sav2 bitb #$4 beq mloop11 jsr out mloop11 jsr xout mloop2 ldaa #$20 bita trcsr beq mloop1 jsr xintst beq mloop1 ldab sav2 bitb #8 beq mloop21 jsr xout mloop21 jsr out bra mloop1 endmloop sei jsr dixin cli rts modem lds #stkbase sei ldaa posxin staa rcvxin cli jsr setup ldx #msg2 jsr outmsg ldaa sav2 sei ldab dr1 andb #$c7 bita #1 beq modset1 orab #$8 modset1 bita #2 beq modset2 orab #$10 modset2 bita #4 beq modset3 andb #$7f modset3 orab #$40 stab dr1 cli waitcd jsr intst beq wait2 cmpa #abort beq remodem wait2 jsr validcd bne waitcd sei ldab dr1 andb #$7f stab dr1 cli ldab #$8 ldaa #'M' bitb dr1 bne modem5 ldaa #'B' modem5 jsr out ldx #msg1 jsr outmsg jsr modemloop remodem jsr modemoff jmp modem modem3 cmpa #$0d beq modem3 ; setup msgs1 asc "M)oniteur, T)est, E)cho, D)uplex, " asc "V)itesse, P)rotocole, C)onnection\0" msgs2 asc "Xon/Xoff \0" msgs3 asc "RTS/CTS \0" msgs5 asc " Test \0" msgs6 asc " Normal \0" msgs7 asc "Half \0" msgs8 asc "Full \0" msgs9 asc "Echo on \0" msgs10 asc "Echo off \0" pmsg ldaa 0,x beq pmsg2 jsr out inx bra pmsg pmsg2 rts modeline ldaa #$0C jsr out ldaa sav2 lsra eora sav2 ldx #$1200 bita #$1 beq modln2 ldx #$75 modln2 jsr prx ldaa #'/' jsr out ldx #$1200 ldaa sav2 bita #$1 bne modln3 ldx #$75 modln3 jsr prx ldx #msgs5 ldaa sav2 bita #$2 bne modln4 ldx #msgs6 modln4 jsr pmsg ldx #msgs7 ldaa sav2 bita #$4 bne modln5 ldx #msgs8 modln5 jsr pmsg ldx #msgs9 ldaa sav2 bita #$8 bne modln6 ldx #msgs10 modln6 jsr pmsg ldx #msgs2 ldaa sav2 bita #$40 bne modln7 jsr pmsg modln7 ldx #msgs3 ldaa sav2 bita #$20 beq modln8 jsr pmsg modln8 jsr outcr ldx #msgs1 jmp outmsg setup0 bitb #$2 beq setup1 andb #$F7 setup1 stab sav2 setup jsr modeline setupin jsr in jsr maj ldab sav2 cmpa #'M' bne setup2 jmp monloop setup2 cmpa #'T' bne setup3 eorb #2 bra setup0 setup3 cmpa #'D' bne setup4 eorb #4 bra setup0 setup4 cmpa #'E' bne setup5 eorb #8 bra setup0 setup5 cmpa #'P' bne setup6 addb #$20 bvc setup0 eorb #$80 bra setup0 setup6 cmpa #'V' bne setup7 andb #$f3 eorb #$1 bitb #$1 beq setup0 orab #$C bra setup0 setup7 cmpa #'C' beq setup8 cmpa #$0D bne setupin setup8 jmp outcr ; DASM mnemosav equ $9a formatsav equ $9b decode ldx #mycode abx ldaa 0,x cmpb #$8d beq decod2 cmpb #$60 bcs decod3 lsrb lsrb lsrb lsrb andb #$3 ldx #format tsta bpl decod4 orab #$4 decod4 abx anda #$7f beq decod5 ldab 0,x rts decod3 andb #$F0 cmpb #$20 beq decod2 decod5 ldab #$01 rts decod2 ldab #$72 rts dasmins ldx r2 ldab 0,x jsr decode staa mnemosav stab formatsav jsr prhexa jsr prmnemo jsr prargs ldab formatsav andb #$3 ldx r2 abx stx r2 jmp outcr prmnemo ldab mnemosav clra asld asld addd #mnemo std xsav ldx xsav ldab #$4 prmn2 pshb ldaa 0,x inx oraa #$20 jsr out pulb decb bne prmn2 out3bl ldab #$3 outnbl pshb jsr outsp pulb decb bne outnbl rts prhexa ldx r2 jsr prx jsr outt jsr outsp ldx r2 ldab 0,x jsr prb ldx r2 ldaa formatsav anda #$3 ldab #$a deca beq prhexa1 deca beq prhexa3 jsr outsp ldx 1,x jsr prx bra prhexa2 prhexa3 jsr out3bl ldab 1,x jsr prb prhexa2 ldab #$5 prhexa1 jmp outnbl prargs ldaa formatsav staa mnemosav cmpa #$72 beq relatif asl mnemosav bcc prargs2 ldaa #'#' jsr out prargs2 asl mnemosav bcc prargs3 ldaa #'$' jsr out prargs3 ldx r2 asl mnemosav bcc prargs4 ldab 1,x jsr prb prargs4 asl mnemosav bcc prargs5 ldx 1,x jsr prx prargs5 asl mnemosav bcc prargs6 ldaa #',' jsr out ldaa #'X' jsr out prargs6 rts relatif ldaa #'$' jsr out ldx r2 ldab 1,x clra tstb bpl relat2 coma relat2 addd r2 addd #$2 std xsav ldx xsav jmp prx ; MASM masmins jsr parse bcs masmerr clrb masmloop pshb jsr decode subd mnemosav beq masmfound pulb incb bne masmloop ldaa formatsav cmpa #$e2 bne ms2 ldaa #$d3 bra ms1 ms2 cmpa #$62 bne ms3 ldaa #$53 bra ms1 ms3 cmpa #$53 beq ms4 masmerr sec rts ms4 ldaa #$72 ms1 staa formatsav bra masmloop masmfound pulb ldx r2 stab 0,x ldaa formatsav cmpa #$72 beq masmrel anda #$3 cmpa #3 beq masmf2 cmpa #2 beq masmf1 clc rts masmrel ldd r1 subd #2 subd r2 tstb bpl masmrel2 coma masmrel2 tsta bne masmerr stab 1,x clc rts masmf1 ldab r1+1 stab 1,x clc rts masmf2 ldd r1 std 1,x clc rts nxtchar stx xsav ldx possav ldaa 0,x inx stx possav jsr maj ldx xsav rts parse ldaa #(mnemend-mnemo)>>2 staa mnemosav ldd possav std r1 parse2 dec mnemosav beq masmerr ldab mnemosav clra asld asld addd #mnemo std xsav ldx xsav ldaa 0,x beq masmerr ldd r1 std possav ldab #$4 parse1 ldaa 0,x cmpa #$20 beq parsed1 tstb beq parsed1 jsr nxtchar cmpa 0,x bne parse2 inx decb bra parse1 parsed1 clr formatsav parse3 jsr nxtchar cmpa #$20 beq parse3 cmpa #'#' bne parse4 ldaa #$80 oraa formatsav staa formatsav jsr nxtchar parse4 cmpa #'$' bne parse5 jsr nxtchar parse5 ldx possav dex jsr readhex ldab flag ldaa #$1 bitb #$6 beq parse6 ldaa #$62 bitb #$4 beq parse6 ldaa #$53 parse6 oraa formatsav staa formatsav dex ldaa 0,x cmpa #',' bne parse7 inx ldaa 0,x jsr maj cmpa #'X' bne parserr inx ldaa formatsav oraa #$0C staa formatsav parse7 ldaa 0,x inx cmpa #$20 beq parse7 tsta beq parseok cmpa #';' beq parseok parserr sec rts parseok clc rts ; Tables de DASM et MASM mnemo asc "??? " asc "STAA" asc "STAB" asc "STD " asc "STX " asc "STS " asc "LDAA" asc "LDAB" asc "LDD " asc "LDX " asc "LDS " asc "BITA" asc "BITB" asc "CMPA" asc "CMPB" asc "CPX " asc "ADDA" asc "ADDB" asc "ADDD" asc "SUBA" asc "SUBB" asc "SUBD" asc "ADCA" asc "ADCB" asc "SBCA" asc "SBCB" asc "EORA" asc "EORB" asc "ANDA" asc "ANDB" asc "ORAA" asc "ORAB" asc "ASR " asc "ASRA" asc "ASRB" asc "LSR " asc "LSRA" asc "LSRB" asc "LSRD" asc "ASL " asc "ASLA" asc "ASLB" asc "ASLD" asc "INC " asc "INCA" asc "INCB" asc "INS " asc "INX " asc "DEC " asc "DECA" asc "DECB" asc "DES " asc "DEX " asc "PSHA" asc "PSHB" asc "PSHX" asc "PULA" asc "PULB" asc "PULX" asc "SBA " asc "CBA " asc "ABA " asc "ABX " asc "MUL " asc "BRA " asc "BRN " asc "BHI " asc "BLS " asc "BCC " asc "BCS " asc "BNE " asc "BEQ " asc "BVC " asc "BVS " asc "BPL " asc "BMI " asc "BGE " asc "BLT " asc "BGT " asc "BLE " asc "BSR " asc "JSR " asc "JMP " asc "RTI " asc "WAIT" asc "SWI " asc "RTS " asc "TST " asc "TSTA" asc "TSTB" asc "ROL " asc "ROLA" asc "ROLB" asc "ROR " asc "RORA" asc "RORB" asc "TAB " asc "TBA " asc "TAP " asc "TPA " asc "TSX " asc "TXS " asc "DAA " asc "NEG " asc "NEGA" asc "NEGB" asc "COM " asc "COMA" asc "COMB" asc "CLR " asc "CLRA" asc "CLRB" asc "CLV " asc "SEV " asc "CLC " asc "SEC " asc "CLI " asc "SEI " asc "NOP " mnemend equ * mycode fcc $00,$76,$00,$00,$26,$2A,$62,$63 fcc $2F,$34,$70,$71,$72,$73,$74,$75 fcc $3B,$3C,$00,$00,$00,$00,$60,$61 fcc $00,$66,$00,$3D,$00,$00,$00,$00 fcc $40,$41,$42,$43,$44,$45,$46,$47 fcc $48,$49,$4A,$4B,$4C,$4D,$4E,$4F fcc $64,$2E,$38,$39,$33,$65,$35,$36 fcc $3A,$56,$3E,$53,$37,$3F,$54,$55 fcc $68,$00,$00,$6B,$24,$00,$5E,$21 fcc $28,$5B,$31,$00,$2C,$58,$00,$6E fcc $69,$00,$00,$6C,$25,$00,$5F,$22 fcc $29,$5C,$32,$00,$2D,$59,$00,$6F fcc $67,$00,$00,$6A,$23,$00,$5D,$20 fcc $27,$5A,$30,$00,$2B,$57,$52,$6D fcc $67,$00,$00,$6A,$23,$00,$5D,$20 fcc $27,$5A,$30,$00,$2B,$57,$52,$6D fcc $13,$0D,$18,$95,$1C,$0B,$06,$00 fcc $1A,$16,$1E,$10,$8F,$50,$8A,$00 fcc $13,$0D,$18,$15,$1C,$0B,$06,$01 fcc $1A,$16,$1E,$10,$0F,$51,$0A,$05 fcc $13,$0D,$18,$15,$1C,$0B,$06,$01 fcc $1A,$16,$1E,$10,$0F,$51,$0A,$05 fcc $13,$0D,$18,$15,$1C,$0B,$06,$01 fcc $1A,$16,$1E,$10,$0F,$51,$0A,$05 fcc $14,$0E,$19,$92,$1D,$0C,$07,$00 fcc $1B,$17,$1F,$11,$88,$00,$89,$00 fcc $14,$0E,$19,$12,$1D,$0C,$07,$02 fcc $1B,$17,$1F,$11,$08,$03,$09,$04 fcc $14,$0E,$19,$12,$1D,$0C,$07,$02 fcc $1B,$17,$1F,$11,$08,$03,$09,$04 fcc $14,$0E,$19,$12,$1D,$0C,$07,$02 fcc $1B,$17,$1F,$11,$08,$03,$09,$04 format fcc $E2,$62,$6E,$53,$D3 crasm/src/0000700000175000017500000000000012241521661011024 5ustar cmbcmbcrasm/src/label.h0000700000175000017500000000506310226331300012251 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* crasm: label.h definition des labels LYB 9/87 */ #ifndef LABEL_H #define LABEL_H #define LABLEN 48 struct label { struct label *left,*right; char name[LABLEN]; byte flags,type; short modifier; int (*ptr)(); int value; }; struct result { byte flags,type; short modifier; int (*ptr)(); long value; }; /* type */ #define L_MNEMO -1 #define L_MACRO 2 #define L_ABSOLUTE 3 #define L_RELATIVE 4 #define L_REGS 5 #define L_DIRECTBIT 6 /* etc... */ /* flags modifier < 0 => size field allowed 68k-like */ #define UNDEF (1<<0) #define FORWARD (1<<1) #define USED (1<<2) #define NOREDEF (1<<3) #define NOLABEL (1<<4) /* pour mnemos uniquement */ #define DEFLABEL (1<<5) #define DEFMACRO (1<<6) #define DEFCOND (1<<7) /* external: label.c */ extern int checklabel(char *name); extern struct label *searchlabel(char *name); extern struct label *findlabel(char *name); extern struct result *parse(char *expr); extern struct label *makelabel(char *name, unsigned char flags, unsigned char type); extern struct label *deflabel(char *name, unsigned char flags, unsigned char type, int value); extern void init_label_list(struct label *array); extern void undeflabels(struct label *q); /* external: xref.c */ extern void printlabel(struct label *label); extern void result(void); extern void xref(void); /* external: parse.c */ extern struct result *parse(char *expr); /* external: macros.c */ extern int macrocall(struct label *labmacro, int status, char *oper); /* external: pseudos.c */ extern void checktype(struct result *r, int type); /* common */ struct label *lroot; struct label *starlabel; #endif crasm/src/cpu.h0000700000175000017500000000342610226331267011776 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: cpu.h include pour les fichiers de definition de CPU */ #ifndef CPU_H #define CPU_H #include "dcl.h" #include "label.h" /***************************************************************************/ #define startmnemos(n) struct label n[] = { #define endmnemos {(void*)-1,(void*)-1} }; #define mnemo(n,c,p) {0,0,n,NOREDEF,L_MNEMO,p,c}, #define directive(n,c) {0,0,n,NOREDEF|NOLABEL,L_MNEMO,0,c}, #define address(n,a) {0,0,n,NOREDEF,L_ABSOLUTE,0,a}, #define directbit(n,a,b) {0,0,n,NOREDEF,L_DIRECTBIT,b,a}, #define regs(n,r) {0,0,n,NOREDEF,L_REGS,r,0,(1< #include "label.h" #define LABELARRAYSIZE 100 struct labelarray { int position; struct label label[LABELARRAYSIZE]; } *labelarray_inst = NULL; struct label *lroot = NULL; /* checklabel(name) Retourne TRUE si name est une chaine acceptable pour un label */ int checklabel(char *name) { register char c; if ( strlen(name)>LABLEN ) return FALSE; c=*name; if ( c=='*' && name[1]==0 ) return TRUE; if ( !isalpha(c) && c!='_' && c!='.' ) return FALSE; while (( c=*++name )!=0 ) if ( !isalnum(c) && c!='_' && c!='.' ) return FALSE; return TRUE; } /* searchlabel(name) Retourne NULL ou l'adresse du label 'name' stocke dans addrpos l'adresse du pointeur vers ce label */ static struct label **addrpos; static char localname[LABLEN+2]; struct label * searchlabel(char *name) { register struct label *q; register int r; register char *s; extern int segment; s=localname; if ( name[0]=='.' ) { sprintf(s,"%d",segment); while (*s) s++; }; while (s-localname < LABLEN) if (*name) *s++= toupper(*name++); else *s++= 0; s=localname; q = lroot; addrpos = &lroot; while ( q!=NULL && (r=strncmp(s,q->name,LABLEN))!=0 ) if (r>0) q=* (addrpos= &(q->right)) ; else q=* (addrpos= &(q->left )) ; return q; } /* makelabel(name,flags,type) Cree et place le label ci dessus. */ struct label * makelabel(char *name, unsigned char flags, unsigned char type) { register struct label *q; q=searchlabel(name); if ( q != NULL ) fatal("XX: makelabel"); if (labelarray_inst==NULL) { if ((labelarray_inst=malloc(sizeof *labelarray_inst))) memset(labelarray_inst, 0, sizeof(*labelarray_inst)); else fatal("no memory"); } q= &( labelarray_inst->label[ labelarray_inst->position++ ] ); if ( labelarray_inst->position >= LABELARRAYSIZE ) labelarray_inst=NULL; q->left=q->right=NULL; *addrpos=q; strncpy(q->name,localname,LABLEN); q->type = type; q->flags = flags; return q; } /* findlabel(name) Renvoie un pointeur sur le label 'name'. Si necessaire, cree un label UNDEF|FORWARD type L_ADDR: seule reference en avant autorisee. */ struct label * findlabel(char *name) { register struct label *q; q=searchlabel(name); if ( q==NULL ) q=makelabel(name, UNDEF|FORWARD|NOREDEF, asmflags&F_RELATIF ? L_RELATIVE : L_ABSOLUTE ); q->flags |= USED; return q; } /* deflabel(name,flags,type,value) Definit un label name, de type precise, pour une valeur val1. Si ce label existe deja, il doit etre redefini du meme type, et si ce type est L_ADDR, il doit etre indefini. */ struct label * deflabel(char *name, unsigned char flags, unsigned char type, int value) { register struct label *q; q=searchlabel(name); if (q==NULL) q = makelabel(name,UNDEF,type); if ( !(q->flags & UNDEF) ) if ( (q->flags & NOREDEF) || (flags & NOREDEF) ) { if ( q->type == L_ABSOLUTE || q->type == L_RELATIVE ) error("illegal label redefinition"); else error("attempt to redefine a keyword"); } q->flags &= USED | NOREDEF | FORWARD; flags &= ~USED; q->type = type; q->flags |= flags; q->ptr = NULL; q->value = value; return q; } /* init_label_list Ordonne en arbre un tableau de labels */ void init_label_list(struct label *array) { register int i,count,incr; register struct label *q; q=array; count=0; while ( q++->left != (void*)-1 ) count++; incr=1; array--; while (incr<=count) incr <<= 1; while (incr>1) { i=incr>>1; while (i<=count) { q = array+i; if ( searchlabel(q->name) != NULL ) { if ( q->flags & UNDEF ) q->flags &= ~UNDEF; else warning( "user's symbol overrides new keyword"); } else { *addrpos = q; strncpy(q->name,localname,LABLEN); }; i += incr; } incr >>= 1; } } /* undeflabels(lroot) UNDEF tous les labels de type positif, sauf les FORWARD */ void undeflabels(struct label *q) { extern struct label pseudos[]; if (q) { if ( !(q->flags & NOREDEF) || (q->flags & UNDEF) ) q->flags &= ~FORWARD; /* FORWARD ne subsiste que si on a - un label non redefinissable, - ce label est effectivement defini en avant quelque-part */ q->flags |= UNDEF; undeflabels(q->left); undeflabels(q->right); } for ( q=pseudos; q->left != (struct label*)-1; q++ ) q->flags &= ~UNDEF; } crasm/src/dcl.h0000700000175000017500000001177110226331300011737 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: dcl.h definition generales LYB 9/87 */ #ifndef DCL_H #define DCL_H #include #include #include #include #include #include #include #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif typedef signed char byte; /***************************************************************************/ int asmflags; int passnumber; int macrolevel; int advance; FILE *file,*scode; char *filename,*scodename; char curline[256]; int linenumber; char lineprefix; /* asmflags */ #define F_CPU_GV (1<<0) #define F_ORG_GV (1<<1) #define F_CODE_ON (1<<2) #define F_LIST_ON (1<<3) #define F_IFLIST_ON (1<<4) #define F_MACROLIST_ON (1<<6) #define F_INCLUDELIST_ON (1<<7) #define F_LOHI (1<<8) #define F_ADDR16 (1<<9) #define F_ADDR24 (1<<10) #define F_RELATIF (1<<11) #define F_CODE_HEX (1<<12) #define F_CODE_SCODE (1<<13) #define F_NOLIST (1<<16) #define F_NOWARNING (1<<17) #define F_NOERROR (1<<18) #define F_NOCODE (1<<19) /* plus CPU defined FLAGS */ int plen,ppos,llen,lpos; /***************************************************************************/ /* external: crasm.c */ extern void jmp_buf_copy(jmp_buf in, jmp_buf out); extern void crasm(int flag); extern void pass(int pass); extern int asmline(char *s, int status); extern void error(char *s); extern void warning(char *s); extern void fatal(char *s); extern void syntax(char *s); extern void fileerror(char *s); extern void setflag(int f); extern void clrflag(int f); /* external: filter.c */ extern void zerobuffer(void); extern int filter(char *s, char *fil, ...); extern void reverse(char *s); /* external: scode.c */ extern void flushscoderaw(void); extern void closescodefile(void); extern void setpc(long unsigned int addr); extern void insert8(unsigned char x); extern void insert16(short unsigned int x); extern void insert32(unsigned int x); /* external: output.c */ extern void settitle(char *s); extern void setpage(int xplen, int xllen); extern void outputraw(char *s); extern void outputEOP(void); extern void output(char *s); extern void outputcar(char c); extern void position(int n); extern void outputEOL(void); extern void outputline(void); extern void outputbyte(int b); extern void outputaddr(long int a); extern char hexa[]; /* external: macros.c */ extern void linegets(char *buffer, int length); extern int Xmacro(int status, char *label, char *mnemo, char *oper); extern int Xexitm(int status, char *label, char *mnemo, char *oper); extern int Xendm(int status, char *label, char *mnemo, char *oper); extern int Xif(int status, char *label, char *mnemo, char *oper); extern int Xelse(int status, char *label, char *mnemo, char *oper); extern int Xendc(int status, char *label, char *mnemo, char *oper); /* external: pseudos.c */ extern int Xequ(int modifier, char *label, char *mnemo, char *oper); extern int Xinclude(int modifier, char *label, char *mnemo, char *oper); extern int Xdc(int modifier, char *label, char *mnemo, char *oper); extern int Xds(int modifier, char *label, char *mnemo, char *oper); extern int Xalign(int modifier, char *label, char *mnemo, char *oper); extern int Xoutput(int modifier, char *label, char *mnemo, char *oper); extern int Xcpu(int modifier, char *label, char *mnemo, char *oper); extern int Xnam(int modifier, char *label, char *mnemo, char *oper); extern int Xasc(int modifier, char *label, char *mnemo, char *oper); extern int Xcode(int modifier, char *label, char *mnemo, char *oper); extern int Xdummy(int modifier, char *label, char *mnemo, char *oper); extern int Xskip(int modifier, char *label, char *mnemo, char *oper); extern int Xpage(int modifier, char *label, char *mnemo, char *oper); extern int Xlist(int modifier, char *label, char *mnemo, char *oper); extern int Xmlist(int modifier, char *label, char *mnemo, char *oper); extern int Xclist(int modifier, char *label, char *mnemo, char *oper); extern int Xilist(int modifier, char *label, char *mnemo, char *oper); extern int Xfail(int modifier, char *label, char *mnemo, char *oper); #endif crasm/src/cpu6800.c0000700000175000017500000002076712235464700012317 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* 6800, 6802, 6808, 6801, 6803 */ #include "cpu.h" static int branch(int code, char *label, char *mnemo, char *oper) /* relative branchs */ { byte d; int dd; extern long pc; struct result *r; r=parse(oper); /* operand search */ checktype(r,L_ABSOLUTE); /* is it a number? */ dd=r->value-pc-2; /* displacement calc */ d=dd; /* -> signed byte */ insert8(code); /* generate code */ insert8(dd); if ( d!=dd ) /* test operand after: */ error ("too long branch"); /* if an error occurs during */ /* the first pass, branch is */ return 0; /* always too bytes long */ } /* IMPORTANT: * * You had better generate code before signaling errors about * * the operand values. So the first pass calculates right * * forward references even when a ghost error occurs. */ static int single(int code, char *label, char *mnemo, char *oper) /* single byte instructions */ { insert8(code); if (oper) /* no operand ! */ error ("no operands allowed"); return 0; } static struct addmodes /* addressing modes filters */ { char *filt; /* and code shifts */ int add; } addmodes[] = { { "#_?", 0x00,}, { ",_x", 0x20,}, { "?_,_x", 0x20,}, { "?", 0x30,}, { NULL } }; static int findmode(char *oper, int *pvalue) /* test operands */ /* value -> *pvalue and */ /* if it is'nt a forward */ { /* reference, try direct */ register struct addmodes *q; /* addressing. */ register struct result *r; char *address; address="0"; for ( q=addmodes; q->filt ; q++ ) if ( filter(oper,q->filt,&address) ) { r=parse(address); checktype(r,L_ABSOLUTE); *pvalue=r->value; if ( q->add==0x30 ) if ( !(r->flags & FORWARD) && !(r->value & 0xff00) ) return 0x10; return q->add; } error("Unknown addressing mode"); return 0; } static void codemode(int code, int add, int value) /* generate code, given base */ /* opcode, addressing mode */ { /* shift and operand value. */ insert8(code+add); if ( !add && /* 16 bits immediate */ ( code==0x8c || code==0x8e || code==0xc3 || code==0xcc || code==0xce || code==0x83 ) ) insert16(value); else if (add==0x30) /* extended */ insert16(value); else { insert8(value); /* direct, indexed and */ if (value & 0xff00 ) /* 8 bits immediate */ { if (add==0x20) error ( "too long displacement" ); else warning("operand overflow"); } } } static int standard(int code, char *label, char *mnemo, char *oper) /* all addressing modes */ { register int add; int value; add = findmode (oper,&value); codemode(code,add,value); return 0; } static int standard2(int code, char *label, char *mnemo, char *oper) /* all but immediate */ { register int add; int value; add = findmode (oper,&value); codemode(code,add,value); if ( add==0 ) /* immediate -> error */ error("Bad addressing mode"); return 0; } static int standard3(int code, char *label, char *mnemo, char *oper) /* only indexed and extended */ { register int add; int value; add = findmode (oper,&value); if ( add == 0x10 ) add = 0x30; /* direct -> extended */ codemode(code,add,value); if ( add <= 0x10 ) /* immediate -> error */ error("Bad addressing mode"); return 0; } startmnemos(m6800) /* 6800 mnemonics */ mnemo ("bra", branch, 0x20) /* branchs */ mnemo ("bsr", branch, 0x8d) mnemo ("bhi", branch, 0x22) mnemo ("bls", branch, 0x23) mnemo ("bcc", branch, 0x24) mnemo ("bcs", branch, 0x25) mnemo ("bne", branch, 0x26) mnemo ("beq", branch, 0x27) mnemo ("bvc", branch, 0x28) mnemo ("bvs", branch, 0x29) mnemo ("bpl", branch, 0x2a) mnemo ("bmi", branch, 0x2b) mnemo ("bge", branch, 0x2c) mnemo ("blt", branch, 0x2d) mnemo ("bgt", branch, 0x2e) mnemo ("ble", branch, 0x8f) mnemo ("nop", single, 0x01) /* single byte instructions */ mnemo ("rti", single, 0x3b) mnemo ("rts", single, 0x39) mnemo ("swi", single, 0x3f) mnemo ("wai", single, 0x3e) mnemo ("aba", single, 0x1b) mnemo ("clra", single, 0x4f) mnemo ("clrb", single, 0x5f) mnemo ("cba", single, 0x11) mnemo ("coma", single, 0x43) mnemo ("comb", single, 0x53) mnemo ("nega", single, 0x40) mnemo ("negb", single, 0x50) mnemo ("daa", single, 0x19) mnemo ("deca", single, 0x4a) mnemo ("decb", single, 0x5a) mnemo ("inca", single, 0x4c) mnemo ("incb", single, 0x5c) mnemo ("psha", single, 0x36) mnemo ("pshb", single, 0x37) mnemo ("pula", single, 0x32) mnemo ("pulb", single, 0x33) mnemo ("rola", single, 0x49) mnemo ("rolb", single, 0x59) mnemo ("rora", single, 0x46) mnemo ("rorb", single, 0x56) mnemo ("asla", single, 0x48) mnemo ("aslb", single, 0x58) mnemo ("asra", single, 0x47) mnemo ("asrb", single, 0x57) mnemo ("lsra", single, 0x44) mnemo ("lsrb", single, 0x54) mnemo ("sba", single, 0x10) mnemo ("tab", single, 0x16) mnemo ("tba", single, 0x17) mnemo ("tsta", single, 0x4d) mnemo ("tstb", single, 0x5d) mnemo ("dex", single, 0x09) mnemo ("des", single, 0x34) mnemo ("inx", single, 0x08) mnemo ("ins", single, 0x31) mnemo ("tsx", single, 0x30) mnemo ("txs", single, 0x35) mnemo ("clc", single, 0x0c) mnemo ("clv", single, 0x0a) mnemo ("cli", single, 0x0e) mnemo ("sec", single, 0x0d) mnemo ("sev", single, 0x0b) mnemo ("sei", single, 0x0f) mnemo ("tap", single, 0x06) mnemo ("tpa", single, 0x07) mnemo ("neg", standard3, 0x40) /* memory instructions */ mnemo ("com", standard3, 0x43) mnemo ("lsr", standard3, 0x44) mnemo ("ror", standard3, 0x46) mnemo ("asr", standard3, 0x47) mnemo ("asl", standard3, 0x48) mnemo ("rol", standard3, 0x49) mnemo ("dec", standard3, 0x4a) mnemo ("inc", standard3, 0x4c) mnemo ("tst", standard3, 0x4d) mnemo ("jmp", standard3, 0x4e) mnemo ("clr", standard3, 0x4f) mnemo ("suba", standard, 0x80) /* accumulator & memory */ mnemo ("cmpa", standard, 0x81) /* instructions */ mnemo ("sbca", standard, 0x82) mnemo ("anda", standard, 0x84) mnemo ("bita", standard, 0x85) mnemo ("ldaa", standard, 0x86) mnemo ("staa", standard2, 0x87) /* store instructions are */ mnemo ("eora", standard, 0x88) /* never immediate */ mnemo ("adca", standard, 0x89) mnemo ("oraa", standard, 0x8a) mnemo ("adda", standard, 0x8b) mnemo ("cpx", standard, 0x8c) mnemo ("jsr", standard2, 0x8d) mnemo ("lds", standard, 0x8e) mnemo ("sts", standard2, 0x8f) mnemo ("subb", standard, 0xc0) mnemo ("cmpb", standard, 0xc1) mnemo ("sbcb", standard, 0xc2) mnemo ("andb", standard, 0xc4) mnemo ("bitb", standard, 0xc5) mnemo ("ldab", standard, 0xc6) mnemo ("stab", standard2, 0xc7) mnemo ("eorb", standard, 0xc8) mnemo ("adcb", standard, 0xc9) mnemo ("orab", standard, 0xca) mnemo ("addb", standard, 0xcb) mnemo ("ldx", standard, 0xce) mnemo ("stx", standard2, 0xcf) endmnemos startmnemos(m6801) mnemo ("lsrd", single, 0x04) /* 6801 special mnemonics */ mnemo ("asld", single, 0x05) mnemo ("brn", branch, 0x21) mnemo ("pulx", single, 0x38) mnemo ("abx", single, 0x3a) mnemo ("pshx", single, 0x3c) mnemo ("mul", single, 0x3d) mnemo ("subd", standard, 0x83) mnemo ("addd", standard, 0xc3) mnemo ("ldd", standard, 0xcc) mnemo ("std", standard2, 0xcd) endmnemos void init6800(int code) { setflag( F_ADDR16 ); /* 16 bits address */ clrflag( F_LOHI ); /* MSB first */ clrflag( F_RELATIF ); /* no translatable code */ bindvocabulary(m6800); /* add 6800 mnemos */ if (code==1) bindvocabulary(m6801); /* add 6801 mnemos if needed */ } crasm/src/crasm.c0000700000175000017500000002121612235044650012303 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: crasm.c noyau central LYB 9/87 */ #include "dcl.h" #include "version.h" #include "label.h" #define SCODE 1 #define LIST 2 #define XREF 4 #define WARN 8 #define INPUT 128 extern struct label *searchlabel(); extern struct label pseudos[]; jmp_buf errorjump; int errnumber,warnnumber; int segment; extern int includelevel, thiscall; void jmp_buf_copy(jmp_buf out, jmp_buf in) { #ifdef JBUFSIZE int i; for (i=0; i1 && !(flags&SCODE) ) { flags |= SCODE; scodename=*++argv; --argc; } break; default: syntax("Bad Option(s)"); } } else { if ( flags & INPUT ) syntax("One input only"); filename=*argv; flags |= INPUT; }; } if ( flags & INPUT ) crasm(flags); else syntax("No input!"); return 0; } void crasm(int flag) { init_label_list(pseudos); file=fopen(filename,"r"); if ( file==NULL ) fatal("can't open source file"); scode = NULL; llen=76; plen=66; ppos=0 ; lpos=0; #ifdef DEBUG asmflags = F_NOCODE; #else asmflags = F_NOLIST | F_NOWARNING| F_NOERROR | F_NOCODE; #endif pass(1); #ifdef DEBUG outputEOP(); asmflags &= ~ (F_NOLIST | F_NOWARNING | F_NOCODE | F_NOERROR ); #else asmflags &= ~F_NOERROR; if (flag & SCODE) asmflags &= ~F_NOCODE; if (flag & LIST) asmflags &= ~F_NOLIST; if (flag & WARN) asmflags &= ~F_NOWARNING; #endif undeflabels(lroot); pass(2); if ( scode ) closescodefile(); asmflags |= F_LIST_ON; if (errnumber==0 && flag & LIST) flag |= XREF; result(); if (errnumber && (flag & SCODE) ) remove(scodename); if (flag & XREF) xref(); } void pass(int n) { clearerr(file); rewind(file); asmflags |= F_CODE_ON; if ( ! (asmflags & F_NOLIST) ) asmflags |= F_LIST_ON; #ifdef DEBUG asmflags |= F_IFLIST_ON | F_MACROLIST_ON; #else asmflags &= ~ F_MACROLIST_ON; asmflags |= F_IFLIST_ON; #endif macrolevel =0; thiscall =0; segment =0; includelevel =0; linenumber =0; lineprefix =0; starlabel = findlabel("*"); starlabel->flags |= UNDEF; starlabel->flags &= ~NOREDEF; passnumber=n; fprintf(stderr,"Pass #%d\n",n); errnumber=warnnumber=0; while ( !feof(file) ) { if (setjmp(errorjump) ) errnumber++; linegets(curline,250); if (asmline(curline,3)) error("ELSE, ENDC, ENDM, EXITM illegal here"); } } static void herelabel(char *label) { if ( strcmp(label,"*") == 0 ) error ( "illegal star definition"); if ( asmflags & F_ORG_GV ) deflabel(label,NOREDEF, asmflags & F_RELATIF ? L_RELATIVE : L_ABSOLUTE, starlabel->value ); else error ( "undefinable label: no org given" ); if ( !(asmflags & F_CODE_ON) ) if ( macrolevel==0 || asmflags & F_MACROLIST_ON ) if ( lpos==0 ) { position(2); outputaddr(starlabel->value); }; } static struct label * findmnemo(char *mnemo) { char *aux1,*aux2; register struct label *labmnemo; labmnemo = searchlabel(mnemo); if ( labmnemo == NULL ) /* sizer 68k */ { if ( filter(mnemo,"?.?",&aux1,&aux2) ) if (( labmnemo = searchlabel(aux1) )) if (labmnemo->modifier >=0) labmnemo = NULL; }; if ( labmnemo ) if ( !(labmnemo->flags & UNDEF ) ) if ( labmnemo->type == L_MNEMO || labmnemo->type == L_MACRO ) return labmnemo; return NULL; } static int nospacein(char *s) { while( *s ) { if ( *s == ' ' || *s == '\t' ) return FALSE; s++; } return TRUE; } int asmline(char *s, int status) { char *label,*mnemo,*oper; register struct label *labmnemo; advance = 0; if (starlabel->flags & UNDEF) asmflags &= ~F_ORG_GV; else { asmflags |= F_ORG_GV; setpc ( starlabel->value ); }; zerobuffer(); /* on traite XXX ; REMARK puis les cas XXX = blanc */ if ( filter( s,"_?_;?",&label,&mnemo ) ) s=label; else { register char *p; p=s; while(*p) p++; while ( p>s && (*--p==' ' || *p=='\t') ) *p=0; while (*s==' ' || *s=='\t') s++; } if (*s==0) { if (status & 1) outputline(); return 0; } /* autorise: LABEL= MNEMO MNEMO LABEL MNEMO MNEMO OPERAND LABEL MNEMO OPERAND */ if (filter ( s, "?_=_?", &label,&oper ) && nospacein(label) ) { mnemo="equ"; labmnemo=findmnemo(mnemo); if (checklabel(label) == FALSE ) error("malformed label"); } else { label = mnemo = oper = NULL; start: if (filter(s,"? _?",&mnemo,&oper) && *mnemo && *oper) { labmnemo = findmnemo(mnemo); if ( labmnemo==NULL && label==NULL ) { label=mnemo; if (checklabel(label) == FALSE ) error("malformed label"); s=oper; goto start; } } else { labmnemo=findmnemo(mnemo=s); oper = NULL; } } if ( labmnemo==NULL ) error( "unknown macro or mnemonic"); if ( labmnemo->flags & NOLABEL ) if (label) error("labels not allowed here"); if ( labmnemo->flags & DEFLABEL ) { if (!label) error("label required here"); } else if (label) { if (status & 2) herelabel(label); } if ( labmnemo->flags & DEFCOND ) return (*labmnemo->ptr)( status, label,mnemo,oper ); if ( labmnemo->flags & DEFMACRO ) return (*labmnemo->ptr)( status, label,mnemo,oper ); if ( labmnemo->type == L_MACRO ) { if (!label && oper && !strncmp(oper,"MACRO",5)) error("macro is already defined"); if (status & 2) macrocall( labmnemo,status,oper ); else if (status & 1) outputline(); return 0; } else if ( labmnemo->type == L_MNEMO ) { if (status & 2) (*labmnemo->ptr)( labmnemo->modifier, label,mnemo,oper ); starlabel->value += advance; if ( status & 1 ) outputline(); return 0; } else fatal ("proc asmline failure"); return 0; } /* F_LIST_ON est pris en compte dans outputline() F_CODE_ON est pris en compte dans insertbyte() F_NOLIST est pris en compte dans LIST ON F_NOCODE est pris en compte dans CODE ON ou OFF F_NOERROR dans error F_NOWARNING dans warning */ /* ERRORS ROUTINES */ void error(char *s) { char raw[80]; int oldflags; char c = toupper(*s); oldflags=asmflags; if ( !(asmflags & F_NOERROR) ) { sprintf(raw,"%7d ERROR: %c%s",linenumber,c,s+1); for ( s=raw; s[1]==' '; s++ ) s[0]='>'; asmflags |= F_LIST_ON; outputraw(raw); } outputline(); if ( advance != 0 ) starlabel->value += advance; asmflags = oldflags; longjmp( errorjump, -1 ); } void warning(char *s) { char raw[80]; char c = toupper(*s); if ( !(asmflags & F_NOWARNING) ) { sprintf(raw,"%7d WARNING: %c%s",linenumber,c,s+1); for ( s=raw; s[1]==' '; s++ ) s[0]='>'; outputraw(raw); } } void fatal(char *s) { printf("FATAL ERROR: %s\n",s); exit(10); } void fileerror(char *s) { printf("FILE ERROR on %s file: %s\n", s, strerror(errno)); } /* aff CPU known */ extern struct cpulist { char *name; int code; int (*init)(); } cpulist[]; void syntax(char *s) { register struct cpulist *q; register int(*a)(); a=NULL; printf ("%s\n",s); printf ("Syntax: crasm [-slx] [-o SCODEFILE] INPUTFILE\n"); printf ("Crasm %s known CPUs:",CRASMVERSION); for ( q=cpulist; q->name ; q++ ) { if (a!=q->init) printf("\n\t"); printf(" %s",q->name); a=q->init; } printf("\n"); exit(10); } void setflag(int f) { asmflags |= f; } void clrflag(int f) { asmflags &= ~f; } crasm/src/filter.c0000700000175000017500000000737312235045533012474 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: filter.c comparaison et filtrage LYB 9/87 */ #include "dcl.h" #define WILDCARD '?' /* n'importe quoi. test () '' "" \x */ #define SPACES '_' /* saute X espaces, X>=0 */ char *bufferpos; char buffer[4000]; unsigned int chars_consumed_by_filter; /* zerobuffer() Efface les buffers de tous les filter(s,f) precedents */ void zerobuffer(void) { bufferpos=buffer; } /* filter(s,f, ..&{char*}..) Retourne TRUE si s correspond au filtre f. WILDCARD signifie n'importe quelle chaine, SPACES signifie un nombre quelconque de TABS ou SPACE, un au moins tient compte des '' "" et des () imbriquees. */ int filter(char *s, char *fil, ...) { va_list ap; register char *starts, *startf; register int quote; char *oldbufferpos; char *str_start = s; oldbufferpos=bufferpos; startf=starts= NULL; va_start(ap, fil); quote=0; do { if ( *fil==WILDCARD ) { char **strptr = va_arg(ap, char**); *bufferpos = 0; *strptr = ++bufferpos; chars_consumed_by_filter = (s - str_start); if (fil[1]==0) { while (*s) { *bufferpos++ = *s++; } *bufferpos = 0; va_end(ap); return TRUE; } else { startf = fil; starts = s; }; } else if ( *fil==SPACES ) { while ( *s==' ' || *s=='\t' ) s++; } else if ( !quote && ( toupper(*fil)==toupper(*s) || (*fil==' ' && *s=='\t') )) s++; else { if ( startf==NULL || *s==0 ) { *bufferpos=0; bufferpos=oldbufferpos; return FALSE; } if ( quote & 0x4 ) quote &= ~0x4; /* "\x" ok */ else switch ( *starts ) { case '\\': if (quote & 0x3) /* str only */ quote |= 0x4; break; case '\'': if ( !(quote & 0x2) ) /* 'x"x' ok */ quote ^= 0x1; break; case '\"': if ( !(quote & 0x1) ) /* "x'x" ok */ quote ^= 0x2; break; case '(' : if ( !(quote & 0x3) ) /* "x(x" ok */ quote += 0x8; /* bonnes () */ break; case ')' : if ( !(quote & 0x3) ) /* "x)x" ok */ quote -= 0x8; break; } *bufferpos++ = *starts; s=++starts; fil = startf; } } while ( *fil++ != 0 ); *bufferpos=0; va_end(ap); return TRUE; } void reverse(char *s) { register char *d,*f,c; register int quote = 0; f=d=s; while (*d) d++; while ( --d > f ) { c=*f; *f++=*d; *d=c; } for ( d=s; *d; d++ ) switch (*d) { case '\'': if ( ! quote ) quote |= 0x1; else if ( quote & 0x1 ) if ( d[1]!='\\' ) quote &= ~0x1; break; case '\"': if ( ! quote ) quote |= 0x2; else if ( quote & 0x2 ) if ( d[1]!='\\' ) quote &= ~0x2; break; case '\\': if ( quote ) { d[0]=d[-1]; d[-1]='\\'; } break; } } crasm/src/parse.c0000700000175000017500000001311112235044650012303 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: parse.c evaluation d'expressions LYB 9/87 */ #include "dcl.h" #include #include "label.h" extern void error(); extern void fatal(); /* La suite prouve que les methodes classiques ont du bon, et que j'ai eu tort de n'en pas vouloir. REVERSE est une horreur imposee par le sens d'unification de FILTER */ struct result calcresult; extern void opadd(struct result *presult, struct result *parg); extern void opsub(struct result *presult, struct result *parg); extern void opmul(struct result *presult, struct result *parg); extern void opdiv(struct result *presult, struct result *parg); extern void oprlist(struct result *presult, struct result *parg); extern void opminus(struct result *presult); extern void opor(struct result *presult, struct result *parg); extern void opand(struct result *presult, struct result *parg); extern void opxor(struct result *presult, struct result *parg); extern void oplsh(struct result *presult, struct result *parg); extern void oprsh(struct result *presult, struct result *parg); extern void opnot(struct result *presult); extern void opbit(struct result *presult, struct result *parg); extern void csthexa(struct result *presult, char *s); extern void cstdecimal(struct result *presult, char *s); extern void cstbinary(struct result *presult, char *s); extern void cstascii(struct result *presult, char *s); extern void cstlabel(struct result *presult, char *s); extern void cstoctal(struct result *presult, char *s); extern void opbitnumb(struct result *presult, struct result *parg); extern void opbitaddr(struct result *presult, struct result *parg); struct oplist { char *filtre; short type,nxt; void (*callop)(); /* (*callop)(&result,&arg ) */ } oplist[] = { /* ICI a l'envers , filtres des operations */ { "?_\\_?" ,2 ,1 /* rlist */ ,oprlist,}, { "?_+_?" ,2 ,2 /* add */ ,opadd,}, { "?_-_?" ,2 ,1 /* subtract, rrange */ ,opsub,}, { "?_*_?" ,2 ,2 /* multiply */ ,opmul,}, { "?_/_?" ,2 ,1 /* divide */ ,opdiv,}, { "?_|_?" ,2 ,3 /* logical OR */ ,opor,}, { "?_&_?" ,2 ,2 /* logical AND */ ,opand,}, { "?_^_?" ,2 ,1 /* logical XOR */ ,opxor,}, { "?_<<_?" ,2 ,2 /* lshift */ ,oplsh,}, { "?_>>_?" ,2 ,1 /* rshift */ ,oprsh,}, { "?_-" ,1 ,1 /* unary minus */ ,opminus,}, { "?_~" ,1 ,1 /* logical NOT */ ,opnot,}, { ")_?_(_TIB" ,1 ,1 /* bit number */ ,opbitnumb,}, { ")_?_(_RDDA" ,1 ,1 /* bit addr */ ,opbitaddr,}, { "}_?_{_?" ,2 ,1 /* directbit */ ,opbit,}, { ")_?_(" ,-1,1 /* parenthesis */ ,error,}, /* ICI on teste les labels */ { "" ,-3,1 /* label */ ,cstlabel,}, /* ICI a l'endroit constantes autres que ascii ou decimal */ { "$?" ,-2,1 /* hexadecimal */ ,csthexa,}, { "?H" ,-2,1 /* Intel hexa */ ,csthexa,}, { "0X?" ,-2,1 /* C hexa */ ,csthexa,}, { "%?" ,-2,1 /* binaire */ ,cstbinary,}, { "?B" ,-2,1 /* Intel binaire*/ ,cstbinary,}, { "0B?" ,-2,1 /* C binaire */ ,cstbinary,}, { "?Q" ,-2,1 /* Intel octal */ ,cstoctal,}, { NULL ,0 } }; static void parse2(char *expr, struct result *presult) { register char *c1 = 0; register char *c2 = 0; char *ca,*cb; register int i,j; struct result arg; struct oplist *q; q=oplist; while (q->type) { j=-1; switch ( q->type ) { case 2: /* diadiques */ for ( i=0; inxt; i++ ) { ca=cb=NULL; if ( filter(expr,q[i].filtre,&ca,&cb) ) if ( cbfiltre,&ca) || ca==NULL || !*ca ) break; parse2(ca, presult); (*q->callop)(presult); return; case -1: /* parentheses */ if ( !filter(expr,q->filtre,&ca) || ca==NULL || !*ca ) break; parse2(ca, presult); return; case -2: /* constante hex, bin ou octale */ if ( !filter(expr,q->filtre,&ca) || ca==NULL || !*ca ) break; (*q->callop)(presult,ca); reverse(expr); return; case -3: /* label */ reverse(expr); if ( checklabel(expr) ) { cstlabel (presult,expr); reverse(expr); return; } break; }; q += q->nxt; } /* Noop: c'est forcement un decimal ou une cst ascii */ if ( isdigit(*expr) ) { cstdecimal(presult,expr); reverse(expr); } else if (*expr=='\'' || *expr=='\"') { cstascii (presult,expr); reverse(expr); } else error ( "syntax error in an expression" ); } struct result * parse(char *expr) { char *dummy; if ( filter(expr,"(?)",&dummy) ) warning("external parenthesis ignored"); reverse(expr); parse2(expr,&calcresult); reverse(expr); return &calcresult; } crasm/src/cpulist.c0000700000175000017500000000307412235044650012663 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* Liste des CPUs connus */ #include "cpu.h" extern void init6800(int code); extern void init6502(int code); extern void initz80(int code); startcpu newcpu("6800" ,init6800,0) /* Motorola 8 bit family father */ newcpu("6801" ,init6800,1) /* 6800+rom+I/Os+16bits ALU */ newcpu("6803" ,init6800,1) /* ROMless 6801 */ newcpu("6500" ,init6502,0) /* First 6502 procs, without ROR */ newcpu("6502" ,init6502,1) /* Standard 6502 (Apple,Cbm..) */ newcpu("65C02" ,init6502,2) /* CMOS 6502, ext. instr. set */ newcpu("Z80" ,initz80 ,0) /* 8080 revisited */ endcpu crasm/src/Makefile0000600000175000017500000000070710107144711012466 0ustar cmbcmbSHELL =/bin/sh CFLAGS = -O LDFLAGS = LIBS = -lm RM = rm OBJ = crasm.o stdvocabulary.o pseudos.o macro.o label.o \ parse.o filter.o operator.o output.o xref.o scode.o CPU = cpulist.o cpu6800.o cpu6502.o cpuz80.o all: crasm crasm: $(OBJ) $(CPU) ${CC} ${CFLAGS} ${LDFLAGS} -o crasm $(OBJ) $(CPU) ${LIBS} @echo "done" clean: FORCE -${RM} 2>/dev/null *.o crasm FORCE: .PHONY: FORCE $(OBJ): dcl.h label.h $(CPU): cpu.h crasm/src/cpu6502.c0000700000175000017500000002201512235044650012300 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* 6502, 65C02 */ #include "cpu.h" #define mnemo2(n,t,b,f) mnemo( n, standard, (t<<8)|b|f ) #define F_noimm (1<<12) #define F_noacc (1<<13) #define F_noindx (1<<14) #define F_noindy (1<<15) /* n: name t: instruction type f: special remarks about the type b: base address : opcode = b+offset */ #define m2_offset (offsettable[ (code>>8) & 0xf ]) #define m2_base (code & 0xff) static int cpuflag; static int branch(int code, char *label, char *mnemo, char *oper) /* relative branchs */ { byte d; int dd; extern long pc; struct result *r; r=parse(oper); /* operand search */ checktype(r,L_ABSOLUTE); /* is it a number? */ dd=r->value-pc-2; /* displacement calc */ d=dd; /* -> signed byte */ insert8(code); /* generate code */ insert8(dd); if ( d!=dd ) /* test operand after: */ error ("too long branch"); /* if an error occurs during */ return 0; /* the first pass, branch is */ } /* always too bytes long */ /* IMPORTANT: * * You had better generate code before signaling errors about * * the operand values. So the first pass calculates right * * forward references even when a ghost error occurs. */ static int single(int code, char *label, char *mnemo, char *oper) /* single byte instructions */ { insert8(code); if (oper) /* no operand ! */ error ("no operands allowed"); return 0; } /* addressing modes description */ static struct addmodes { char *filter; short num; } addmodes[] = { { "(_?_,_X_)", 0,}, /* indirect pre-indexed */ { "@_?_,_X", 0,}, /* special syntax */ { "(_?_)_,_Y", 2,}, /* indirect post-indexed */ { "@_?_,_Y", 2,}, { "(_?_)", 4,}, /* indirect */ { "@_?", 4,}, { "_", 14,}, /* implicit */ { "#_?", 12,}, /* immediate */ { "?_,_X", 6,}, /* indexed by x */ { "?_,_Y", 8,}, /* indexed by y */ { "?", 10,}, /* direct or register */ { NULL,} }; /* add 1 to mode for 16bits operands */ /* mode 1 and 4 are 65c02 specific */ /* offsettable by type */ static unsigned char offsettable[][16]= { /* (.,x) (.),y (.) .,x .,y . #. _ (..,x) (..),y (..) ..,x ..,y .. #.. A */ {0x01,0x00,0x11,0x00,0x12,0x00,0x15,0x1d,0x00,0x19,0x05,0x0d,0x09,0x00,0x00,0x00,}, {0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x1e,0x16,0x1e,0x06,0x0e,0x02,0x00,0x00,0x0a,}, {0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x00,0x16,0x00,0x06,0x0e,0x00,0x00,0x00,0x00,}, {0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x1e,0x00,0x00,0x06,0x0e,0x6b,0x00,0x00,0x3a,}, {0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x1e,0x00,0x00,0x06,0x0e,0x00,0x00,0x00,0x7a,}, {0x00,0x7c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x00,}, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,}, {0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x9e,0x00,0x00,0x64,0x9c,0x00,0x00,0x00,0x00,}, }; /* 0: ora and eor adc lda cmp sbc (noimm):sta 1: (noimm|noindy):asl,rol,lsr,ror (noacc|noindx|noindy):cpx,cpy (noacc|noindx):ldx (noacc|noindy):ldy 2: (noindx)stx (noindy):sty 3: (noimm):inc (noacc):bit { INC A and DEC A are too } 4: (noimm):dec (noacc|noindx):tsb,trb { strange to group together } 5: jmp { modes: ABS (ABS) (ABS,X) } 6: jsr { only ABS } 7: stz { very strange opcodes for ZP ABS ZP,X ABS,X } */ static int standard(int code, char *label, char *mnemo, char *oper) { register int mode,opcode; char *toparse; int value = 0; /* search mode */ if (! oper) { mode = 14; } else { register struct addmodes *q; for ( q=addmodes; q->filter; q++ ) if ( filter( oper,q->filter,&toparse) ) break; if (! q->filter) error("unknown addressing mode"); mode=q->num; } /* special case */ if ( ( (code & F_noacc) && mode >= 14 ) || ( (code & F_noimm) && mode == 12 ) || ( (code & F_noindx) && mode == 6 ) || ( (code & F_noindy) && mode == 8 ) ) error("illegal addressing mode"); /* extract value */ if (mode < 14) { register struct result *r; r=parse(toparse); if ( mode == 10 && r->type == L_REGS && r->modifier == 0 ) mode = 15; else checktype(r,L_ABSOLUTE); value = r->value; if ( (value & 0xFF00) || (r->flags & FORWARD) ) { if (mode != 12) mode |= 1; else if (value & 0xFF00) warning("operand overflow"); } } /* generate opcode */ { register int offset; if (! (offset=m2_offset[mode]) ) /* if not found */ mode |= 1; /* test long version */ if (! (offset=m2_offset[mode]) ) error("illegal addressing mode"); insert8( opcode= (m2_base+offset) & 0xFF ); } /* generate operand */ if (mode < 14) { if (mode & 1) insert16(value); else insert8(value); } /* test specials modes */ if (cpuflag < 1) { if ( code== ( 0x60 | 0x100 | F_noimm | F_noindy ) ) error("no ROR instruction on 6500"); }; if (cpuflag < 2) { if ( mode==4 || opcode == 0x7c || opcode == 0x89 || opcode == 0x1a || opcode == 0x3a ) error("illegal use of 65C02 addressing mode"); }; return 0; } startmnemos(m6502) /* 6502 mnemonics */ mnemo ("bpl", branch, 0x10) /* branchs */ mnemo ("bmi", branch, 0x30) mnemo ("bvc", branch, 0x50) mnemo ("bvs", branch, 0x70) mnemo ("bcc", branch, 0x90) mnemo ("bcs", branch, 0xb0) mnemo ("bne", branch, 0xd0) mnemo ("beq", branch, 0xf0) /* pseudos branchs */ mnemo ("bhi", branch, 0xb0) /* A>=M unsigned */ mnemo ("blo", branch, 0x90) /* A< M unsigned */ mnemo ("bgt", branch, 0x10) /* A>=M signed */ mnemo ("ble", branch, 0x30) /* A< M signed */ mnemo ("nop", single, 0xea) /* single byte instructions */ mnemo ("brk", single, 0x00) mnemo ("rti", single, 0x40) mnemo ("rts", single, 0x60) mnemo ("pha", single, 0x48) mnemo ("pla", single, 0x68) mnemo ("php", single, 0x08) mnemo ("plp", single, 0x28) mnemo ("dex", single, 0xca) mnemo ("dey", single, 0x88) mnemo ("inx", single, 0xe8) mnemo ("iny", single, 0xc8) mnemo ("tsx", single, 0xba) mnemo ("txs", single, 0x9a) mnemo ("tax", single, 0xaa) mnemo ("txa", single, 0x8a) mnemo ("tay", single, 0xa8) mnemo ("tya", single, 0x98) mnemo ("clc", single, 0x18) mnemo ("clv", single, 0xb8) mnemo ("cli", single, 0x58) mnemo ("cld", single, 0xd8) mnemo ("sec", single, 0x38) mnemo ("sei", single, 0x78) mnemo ("sed", single, 0xf8) mnemo2 ("ora", 0,0x00 ,0 ) mnemo2 ("and", 0,0x20 ,0 ) mnemo2 ("eor", 0,0x40 ,0 ) mnemo2 ("adc", 0,0x60 ,0 ) mnemo2 ("sta", 0,0x80 ,F_noimm ) mnemo2 ("lda", 0,0xa0 ,0 ) mnemo2 ("cmp", 0,0xc0 ,0 ) mnemo2 ("sbc", 0,0xe0 ,0 ) mnemo2 ("asl", 1,0x00 ,F_noimm|F_noindy ) mnemo2 ("rol", 1,0x20 ,F_noimm|F_noindy ) mnemo2 ("lsr", 1,0x40 ,F_noimm|F_noindy ) mnemo2 ("ror", 1,0x60 ,F_noimm|F_noindy ) mnemo2 ("ldx", 1,0xa0 ,F_noacc|F_noindx ) mnemo2 ("ldy", 1,0x9e ,F_noacc|F_noindy ) mnemo2 ("cpx", 1,0xde ,F_noindy|F_noindx|F_noacc ) mnemo2 ("cpy", 1,0xbe ,F_noindy|F_noindx|F_noacc ) mnemo2 ("stx", 2,0x80 ,F_noindx ) mnemo2 ("sty", 2,0x7e ,F_noindy ) mnemo2 ("inc", 3,0xe0 ,F_noimm ) mnemo2 ("bit", 3,0x1e ,F_noacc ) mnemo2 ("dec", 4,0xc0 ,F_noimm ) mnemo2 ("jmp", 5,0x00 ,0 ) mnemo2 ("jsr", 6,0x00 ,0 ) regs ( "a", 0) /* 6502 registers. */ regs ( "x", 1) /* for register mode ops as */ regs ( "y", 2) /* ASL A, ROL A etc.. */ regs ( "p", 3) regs ( "s", 4) endmnemos startmnemos(m65c02) mnemo ("phx", single, 0xda) /* 65c02 special mnemonics */ mnemo ("plx", single, 0xfa) mnemo ("phy", single, 0x5a) mnemo ("ply", single, 0x7a) mnemo ("bra", branch, 0x80) mnemo2 ("stz", 7,0x00 ,0 ) mnemo2 ("tsb", 4,0xfe ,F_noacc|F_noindx ) mnemo2 ("trb", 4,0x0e ,F_noacc|F_noindx ) endmnemos void init6502(int code) { cpuflag=code; setflag( F_ADDR16 ); /* 16 bits address */ setflag( F_LOHI ); /* LSB first */ clrflag( F_RELATIF ); /* no translatable code */ bindvocabulary(m6502); /* add 6502 mnemos */ if (code==2) bindvocabulary(m65c02); /* add 65c02 mnemos if needed */ } crasm/src/xref.c0000700000175000017500000000573512235044650012152 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: xref.c sorties des references croisees LYB 9/87 */ #include "dcl.h" #include "label.h" extern unsigned long pc,codelen; extern int segment; #define RECLEN (LABLEN+13) char *msgs[] = { "Undefined","Mnemonic","Macro","Abs","Rel","Register(s)","Bit%d" }; void printlabel(struct label *label) { char buffer[RECLEN+2]; char *s,*b; int newpos; register int i; if ( lpos+RECLEN >= llen) outputEOL(); newpos=lpos+RECLEN; if (label->type != L_ABSOLUTE && label->type != L_RELATIVE ) if (label->flags & NOREDEF) return; if (label->type <0 ) label->type = 1; if (label->name[0] == '*' || label->name[0] <= '9' ) return; if ((label->flags & UNDEF) && !(label->flags & FORWARD)) label->type = 0; s=label->name; i=label->type; i= (i==3 || i==4 || i==6); if (! (label->flags & USED)) outputcar('?'); else if (label->flags & FORWARD) outputcar('^'); else outputcar(' '); if ( i ) outputaddr(label->value); sprintf(buffer,msgs[label->type],label->modifier); position(newpos-LABLEN-2-strlen(buffer)); output(buffer); position(newpos-LABLEN-1); b=buffer; for (i=0; ileft ); printlabel( label ); xref2 ( label->right ); }; } void result(void) { extern int errnumber,warnnumber; char buffer[40]; if ( plen-ppos < 10 ) { outputEOP(); outputEOL(); outputEOL(); }; outputEOL(); sprintf(buffer,"ERRORS: %4d",errnumber); output(buffer); outputEOL(); sprintf(buffer,"WARNINGS: %4d",warnnumber); output(buffer); outputEOL(); outputEOL(); if ( !errnumber ) { output( "Successful assembly..." ); outputEOL(); sprintf(buffer," Last address %8lx (%ld)",pc-1,pc-1); output(buffer); outputEOL(); sprintf(buffer," Code length %8lx (%ld)",codelen,codelen); output(buffer); outputEOL(); } else { output( "No code generated..." ); outputEOL(); } } void xref(void) { outputEOP(); xref2(lroot); outputEOL(); outputEOP(); } crasm/src/pseudos.c0000700000175000017500000001700012235044650012654 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM.C: pseudos.c execution des pseudos standard ( sauf IF..MACRO..CPU ) */ #include "dcl.h" #include "label.h" #include "cpu.h" extern int thiscall; /* label = value */ int Xequ(int modifier, char *label, char *mnemo, char *oper) { struct result *r; struct label *l; r=parse(oper); r->flags &= ~( UNDEF | USED | NOREDEF ); if ( r->type == L_ABSOLUTE || r->type == L_RELATIVE ) if ( macrolevel==0 || asmflags & F_MACROLIST_ON ) if ( lpos==0 ) { position(2); outputaddr(r->value); }; l = deflabel ( label,r->flags,r->type,r->value ); l->modifier = r->modifier; l->ptr = r->ptr; return 0; } void checktype(struct result *r, int type) { if ( r->type == type ) return; switch ( r->type ) { case L_MNEMO: error("illegal use of a mnemonic"); case L_MACRO: error("illegal use of a macro"); case L_ABSOLUTE: error("illegal use of an absolute reference"); case L_RELATIVE: error("illegal use of a relative reference"); case L_REGS: error("illegal use of registers"); case L_DIRECTBIT: error("illegal use of direct bit reference"); default: error( "Bad expression type" ); } } static void stocke(char *s, int modifier) { unsigned long mask = 0; struct result *r; r=parse(s); checktype(r,L_ABSOLUTE); switch (modifier) { case 1: mask = 0xffffff00; insert8(r->value); break; case 2: mask = 0xffff0000; asmflags ^= F_LOHI; insert16(r->value); asmflags ^= F_LOHI; break; case 3: mask = 0xffff0000; insert16(r->value); break; case 4: mask = 0; insert32(r->value); break; } if ( r->value & mask ) warning( "Operand overflow" ); } /* DCB DCW DCL datas */ int Xdc(int modifier, char *label, char *mnemo, char *oper) { char *s1,*s2; while ( filter( oper, "?_,_?", &s1,&s2 ) ) { oper=s2; stocke(s1,modifier); } stocke(oper,modifier); return 0; } /* DS size ou DS size,fill */ int Xds(int modifier, char *label, char *mnemo, char *oper) { struct result *r; register int i,init; char *s1,*s2; if (filter(oper,"?_,_?",&s1,&s2) ) { oper=s1; r=parse(s2); checktype(r,L_ABSOLUTE); init=r->value; if (init & 0xffffff00) warning("multiple byte initialiser"); } else init=0; r=parse(oper); checktype(r,L_ABSOLUTE); i=r->value; while ( i-- ) insert8(init); advance=r->value; return 0; } /* NAM title */ int Xnam(int modifier, char *label, char *mnemo, char *oper) { if (!oper) error("need an operand"); settitle(oper); return 0; } /* ASC string */ int Xasc(int modifier, char *label, char *mnemo, char *oper) { register char *s,r,delimiter; s=oper; delimiter=*s; if ( delimiter != '\'' && delimiter != '\"' ) error("Bad operand syntax"); while ( (r=*++s) != delimiter ) { if ( r=='\\' ) switch ( *++s) { case 't': r='\t'; break; case 'n': r='\n'; break; case 'r': r='\r'; break; case '0': r=0; break; case '\'': case '\"': case '\\': r=*s; break; default: error("Bad \\X character"); }; insert8(r); } if (*++s) error("syntax error"); return 0; } /* CODE or DUMMY */ extern int segment; int Xcode(int modifier, char *label, char *mnemo, char *oper) { if (oper && *oper ) error("no operand for CODE pseudo"); segment=++thiscall; asmflags |= F_CODE_ON; return 0; } int Xdummy(int modifier, char *label, char *mnemo, char *oper) { if (oper && *oper ) error("no operand for DUMMY pseudo"); segment=++thiscall; asmflags &= ~ F_CODE_ON; return 0; } /* LIST MLIST CLIST ILIST ON ou OFF */ int Xlist(int modifier, char *label, char *mnemo, char *oper) { if ( filter(oper,"_ON_") ) { if ( ! (asmflags & F_NOLIST) ) asmflags |= F_LIST_ON; } else if ( filter(oper,"_OFF_") ) asmflags &= ~ F_LIST_ON; else error("please: use option ON or OFF"); return 0; } int Xmlist(int modifier, char *label, char *mnemo, char *oper) { if ( filter(oper,"_ON_") ) asmflags |= F_MACROLIST_ON; else if ( filter(oper,"_OFF_") ) asmflags &= ~ F_MACROLIST_ON; else error("please: use option ON or OFF"); return 0; } int Xclist(int modifier, char *label, char *mnemo, char *oper) { if ( filter(oper,"_ON_") ) asmflags |= F_IFLIST_ON; else if ( filter(oper,"_OFF_") ) asmflags &= ~ F_IFLIST_ON; else error("please: use option ON or OFF"); return 0; } int Xilist(int modifier, char *label, char *mnemo, char *oper) { if ( filter(oper,"_ON_") ) asmflags |= F_INCLUDELIST_ON; else if ( filter(oper,"_OFF_") ) asmflags &= ~ F_INCLUDELIST_ON; else error("please: use option ON or OFF"); return 0; } /* PAGE ou PAGE plen,llen */ int Xpage(int modifier, char *label, char *mnemo, char *oper) { char *s1,*s2; register struct result *r; register int plen; if ( !oper ) { outputEOP(); return 0; } if ( !filter(oper,"?_,_?",&s1,&s2) ) error("syntax: PAGE or PAGE plen,llen "); checktype( r=parse(s1), L_ABSOLUTE ); plen=r->value; checktype( r=parse(s2), L_ABSOLUTE ); setpage(plen,r->value); return 0; } /* Xskip SKIP nn | SKIP PAGE */ int Xskip(int modifier, char *label, char *mnemo, char *oper) { register struct result *rr; register int r; checktype( rr=parse(oper), L_ABSOLUTE ); r=rr->value; if ( r>100 || r<0 ) warning("are you sure ?"); else while (r--) outputEOL(); return 0; } /* Xoutput OUTPUT SCODE | OUTPUT HEX */ int Xoutput(int modifier, char *label, char *mnemo, char *oper) { asmflags &= ~(F_CODE_HEX|F_CODE_SCODE); if (filter(oper,"_HEX_")) asmflags |= F_CODE_HEX; else if ( filter(oper,"_SCODE_") ) asmflags |= F_CODE_SCODE; else error("please, use options SCODE or HEX"); return 0; } /* Xalign ALIGN EVEN | ALIGN ODD */ int Xalign(int modifier, char *label, char *mnemo, char *oper) { extern unsigned long pc; if ( filter(oper,"_EVEN_")) { if ( pc & 1) insert8(0); } else if (filter(oper,"_ODD_")) { if ( !(pc & 1)) insert8(0); } else error("please, use options EVEN or ODD"); return 0; } /* CPU cpuname */ int Xcpu(int modifier, char *label, char *mnemo, char *oper) { struct cpulist *q; char *a; extern struct cpulist cpulist[]; if ( !oper ) error ( "Need CPU name" ); if ( asmflags & F_CPU_GV ) error ( "One CPU only!" ); q=cpulist; while ( q->name ) { if ( filter(oper,q->name,&a,&a,&a,&a) ) break; else q++; } if ( ! q->name ) error ( "Unknown CPU name" ); if ( passnumber==2 ) asmflags |= F_CPU_GV; (*q->init)(q->code); return 0; } /* FAIL error */ int Xfail(int modf, char *label, char *mnemo, char *oper) { if (oper && *oper) error(oper); else error("Fail instruction"); return 0; } crasm/src/scode.c0000700000175000017500000000674212235044650012302 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: scode.c sorties du scode LYB 9/87 */ #include "dcl.h" unsigned long pc; unsigned long codelen; unsigned long rawstart; int rawnumber; int rawextended; char raw[16]; extern int includelevel; void setpc(long unsigned int addr) { if ( addr != pc ) { flushscoderaw(); rawstart=pc=addr; rawnumber=0; } } void insert8(unsigned char x) { if ( ! (asmflags & F_ORG_GV) ) error ( "no org given"); if ( ! (asmflags & F_NOCODE) ) { if ( scode == NULL ) { scode = fopen ( scodename,"w" ); if ( scode == NULL ) fatal("can't open scode file"); rawextended = 0; } } if ( asmflags & F_CODE_ON ) { if ( scode != NULL ) { if ( rawnumber >= 16 ) flushscoderaw(); raw[rawnumber++]=x; } codelen++; outputbyte(x); } advance++; pc++; } void insert16(short unsigned int x) { if (asmflags & F_LOHI) { insert8(x); insert8(x>>8); } else { insert8(x>>8); insert8(x); } } void insert32(unsigned int x) { if (asmflags & F_LOHI) { insert16(x); insert16(x>>16); } else { insert16(x>>16); insert16(x); } } static unsigned char checksum; static void scodebyte(unsigned char b) { checksum += b; fputc( hexa[ (b>>4) & 0xf ] , scode ); fputc( hexa[ b & 0xf ] , scode ); if ( ferror(scode) ) fileerror(scodename); } void closescodefile(void) { flushscoderaw(); if ( asmflags & F_CODE_HEX ) fputs(":00000001FF\n",scode); else fputs("S9030000FC\n",scode); if ( scode ) fclose(scode); } void flushscoderaw(void) { register int i; if ( rawnumber ) { if ( asmflags & F_CODE_HEX ) { if ((rawextended ^ rawstart) & 0xffff0000) { fputs(":02000004",scode); checksum = (unsigned char)(0xFF + 0x02 + 0x04); scodebyte(rawstart>>24); scodebyte(rawstart>>16); scodebyte(~checksum); fputc('\n',scode); rawextended = rawstart; } fputc(':',scode); checksum = 0xFF; scodebyte(rawnumber); scodebyte(rawstart>>8); scodebyte(rawstart); scodebyte(0x00); } else { fputc('S',scode); checksum = 0; if (rawstart & 0xff000000) { fputc('3',scode); scodebyte(rawnumber+5); scodebyte(rawstart>>24); scodebyte(rawstart>>16); } else if (rawstart & 0xff0000) { fputc('2',scode); scodebyte(rawnumber+4); scodebyte(rawstart>>16); } else { fputc('1',scode); scodebyte(rawnumber+3); } scodebyte(rawstart>>8); scodebyte(rawstart); } for ( i=0; i #define NMARGIN 21 #define LMARGIN 28 /* output(s) position(n); outputEOL() outputEOP() outputline() outputraw(s) settitle(s) */ static int lastoffset; extern unsigned int chars_consumed_by_filter; char linebuffer[256]; char title[31] =""; int pagenumber = 0; void settitle(char *s) { static byte flag = 0; if (flag) warning ("title redefinition"); if (strlen(s) > 30) error ("too long title"); strcpy(title,s); if (passnumber == 2) flag = 1; } void setpage(int xplen, int xllen) { static byte flag = 0; if (flag) warning ("page redefinition"); if (xplen>200 || (xplen && xplen<10) || xllen<39 || xllen>1000 ) error ("illegal values"); plen=xplen; llen=xllen; if ( passnumber == 2 ) flag=1; } void outputraw(char *s) { register int i; if ( asmflags & F_LIST_ON ) { if ( ppos==0 ) { printf("Crasm %s: %30s",CRASMVERSION,title); for ( i=58; i=plen-2 && plen) { printf("\n\n"); ppos=0; } } if ( ferror(stdout) ) fileerror("output"); } void outputEOP(void) { if ( asmflags & F_LIST_ON ) { if ( plen ) while ( ppos ) outputEOL(); else printf("\n\n\n"); } } static char *outpat[]= { "_? _? _?", "_? _?", "_?", NULL }; void output(char *s) { while (*s) outputcar(*s++); } void outputcar(char c) { char *dummy; char **pat; if ( !isspace((unsigned char)c) ) { if ( lpos>=llen ) { outputEOL(); if ( filter(linebuffer+LMARGIN,"?;_?",&dummy,&dummy)) /* suite de commentaire */ position( chars_consumed_by_filter ); else if ( c==';' ) /* debut de commentaire */ position ( LMARGIN ); else if ( lastoffset >= LMARGIN ) position(lastoffset); else if ( c!=';' ) /* suite d'un champ quelconque */ for ( pat=outpat; *pat; pat++) { if ( filter( linebuffer+LMARGIN, *pat, &dummy,&dummy,&dummy) ) { position( chars_consumed_by_filter ); break; }; }; lastoffset=lpos; }; if ( isprint((unsigned char)c) || !isascii((unsigned char)c) ) linebuffer[lpos++]=c; linebuffer[lpos]=0; } else if ( c==' ' ) { if (lpos=llen ) fatal("line length must be greater"); while ( lpos4 ) i=4; linnum[i] = lineprefix; } else sprintf( linnum,"%5d",linenumber ); position(NMARGIN); output(linnum); position(LMARGIN); output(curline); outputEOL(); } /* special output */ char hexa[] = "0123456789ABCDEF"; extern long pc; void outputbyte(int b) { char buffer[3]; static int mypc; if ( advance>20 && lpos>NMARGIN-5 ) { if ( lpos <= NMARGIN-3 ) output("..."); return; }; if ( lpos > NMARGIN-3 ) outputEOL(); if ( pc != mypc && lpos != 0 ) outputEOL(); if ( lpos==0 ) outputaddr(pc); buffer[0]= hexa[(b >> 4 ) & 0xF]; buffer[1]= hexa[b&0xF]; buffer[2]= 0; output(buffer); mypc=pc+1; } void outputaddr(long int a) { char buffer[20]; register int i; register char *s; s=buffer; i = 28; if (asmflags & F_ADDR24) i = 20; else if (asmflags & F_ADDR16) i = 12; for ( ; i>=0; i-=4 ) *s++ = hexa [ (a>>i) & 0xF ]; *s++=' '; *s = 0 ; output(buffer); } crasm/src/version.h0000600000175000017500000000003312147251306012661 0ustar cmbcmb#define CRASMVERSION "1.7" crasm/src/macro.c0000700000175000017500000002750712235044650012310 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: macro.c gestion des macros et des pseudos conditionnelles LYB 9/87 */ #include "dcl.h" #include "label.h" #include #include #define MAXSOURCEDEEP 10 extern jmp_buf errorjump; extern int errnumber; /* code des instructions */ /* if, macro retournent 0 */ #define ENDC 0x11 #define ELSE 0x12 #define ENDM 0x21 #define EXITM 0x22 /* if, else, endc */ int Xelse(int status, char *label, char *mnemo, char *oper) { if ( oper ) error ( "no operand allowed for ELSE"); return ELSE; } int Xendc(int status, char *label, char *mnemo, char *oper) { if ( oper ) error ( "no operand allowed for ENDC"); return ENDC; } #define EQ 1 #define GT 2 #define LT 4 #define NE 8 static struct compar { char *comp; int flag; } compar[] = { { "?_>=_?", GT|EQ, }, { "?_<=_?", LT|EQ, }, { "?_==_?", EQ, }, /* habitues du C */ { "?_!=_?", NE, }, { "?_=_?", EQ, }, { "?_<>_?", NE, }, { "?_<_?", LT, }, { "?_>_?", GT, }, { NULL, NE } }; static struct result zero = { 0,L_ABSOLUTE,0,0 }; static int testtrue (char *oper) { char *s1,*s2; register struct compar *q; struct result r1,r2; if ( !oper || !*oper ) return FALSE; q=compar; while ( q->comp ) { if ( filter(oper,q->comp,&s1,&s2) ) break; q++; }; if ( !q->comp ) { r1=*parse(oper); r2=zero; } else { r1= *parse(s1); r2= *parse(s2); } if ( ( (r1.flags & UNDEF) && (r1.flags & FORWARD) ) || ( (r2.flags & UNDEF) && (r2.flags & FORWARD) ) ) error( "forward defined expressions are illegal here" ); if (r1.type != r2.type) error( "Uncomparable expressions" ); if ( q->flag & (GT | LT) ) { if ( (r1.type != L_ABSOLUTE) && (r1.type != L_RELATIVE) ) error ( "not a numeric expression" ); if ( (q->flag & GT) && (r1.value > r2.value) ) return TRUE; if ( (q->flag & LT) && (r1.value < r2.value) ) return TRUE; } if ( q->flag & EQ ) if ( r1.modifier == r2.modifier && r1.value == r2.value ) return TRUE; if ( q->flag & NE ) if ( r1.modifier != r2.modifier || r1.value != r2.value ) return TRUE; return FALSE; } int Xif(int status, char *label, char *mnemo, char *oper) { int flag; int mystatus; int booleanvalue; char oldprefix; jmp_buf errjmpsav; booleanvalue = FALSE; if ( status&2 ) booleanvalue = testtrue(oper); mystatus=0; if ( booleanvalue ) mystatus|=3; if ( asmflags & F_IFLIST_ON ) mystatus|=1; if ( asmflags & F_IFLIST_ON ) if (status & 1) outputline(); oldprefix = lineprefix; if ( status & 2) if ( ! (mystatus & 2) ) lineprefix = 'C'; jmp_buf_copy(errjmpsav,errorjump); do { if (setjmp(errorjump) ) errnumber++; linegets(curline,250); if (feof (file) ) { jmp_buf_copy(errorjump,errjmpsav); error("Unexpected End of File"); } flag=asmline(curline,status & mystatus); if ( !(status & mystatus & 2) ) if ( flag==EXITM ) flag=0; } while ( flag == 0); jmp_buf_copy(errorjump,errjmpsav); lineprefix = oldprefix; if ( flag == ENDM ) error ("ENDM illegal here"); if ( asmflags & F_IFLIST_ON ) if (status & 1) outputline(); if ( flag == ENDC ) return 0; if ( flag == EXITM ) return EXITM; mystatus = 0; if ( !booleanvalue ) mystatus |= 3; if ( asmflags & F_IFLIST_ON ) mystatus |= 1; if ( status & 2) if ( ! (mystatus & 2) ) lineprefix = 'C'; do { if (setjmp(errorjump) ) errnumber++; linegets(curline,250); if (feof (file) ) { jmp_buf_copy(errorjump,errjmpsav); error("Unexpected End of File"); } flag=asmline(curline,status & mystatus); if ( !(status & mystatus & 2) ) if ( flag==EXITM ) flag=0; } while ( flag == 0 ); jmp_buf_copy(errorjump,errjmpsav); lineprefix = oldprefix; if ( flag == ENDM || flag == ELSE) error ("ELSE or ENDM illegal here"); if ( asmflags & F_IFLIST_ON ) if (status & 1) outputline(); if ( flag == ENDC ) return 0; if ( flag == EXITM ) return EXITM; return 0; } /* MACRO, ENDM, EXITM */ /* On aborde la gestion des Macros */ struct macroline { struct macroline *next; char line[1 /* variable */ ]; }; int Xexitm(int status, char *label, char *mnemo, char *oper) { if (oper) error ( "no operand allowed in EXITM statement"); if (!macrolevel && (status & 1)) outputline(); return EXITM; } int Xendm(int status, char *label, char *mnemo, char *oper) { if (oper) error ( "no operand allowed in ENDM statement"); if (!macrolevel && (status & 1)) outputline(); return ENDM; } int Xmacro(int status, char *label, char *mnemo, char *oper) { jmp_buf errjmpsav; char *s1,*s2; struct macroline *startmacro; register struct macroline **where; char mname[LABLEN+1]; struct label *lbl = 0; where = &startmacro; strncpy(mname,label,LABLEN); mname[LABLEN]=0; if ( oper ) error ( "no operand allowed in macro statement" ); if ( macrolevel ) error ( "nested macro definition"); if ( status & 1 ) outputline(); if ( status & 2 ) { lbl = deflabel(mname,0,L_MACRO,0); lbl->ptr = 0; } jmp_buf_copy(errjmpsav,errorjump); do { if (setjmp(errorjump) ) errnumber++; zerobuffer(); linegets(curline,250); if (feof (file) ) { jmp_buf_copy(errorjump,errjmpsav); error("Unexpected End of File"); } if ( !filter(curline,"?_;?",&s1,&s2) ) s1=curline; if (status & 2) { *where= ( struct macroline *) malloc( sizeof( struct macroline ) + strlen( s1 ) ); (*where)->next = NULL; strcpy ( (*where)->line , s1 ); where = & ( (*where)->next ); }; if (status & 1) outputline(); } while ( ! filter(s1,"_?_ENDM_?",&s1,&s2 ) ); jmp_buf_copy(errorjump,errjmpsav); if ( *s1 || *s2 ) error ("illegal ENDM instruction"); if ( lbl ) lbl->ptr = (void*)startmacro; return 0; } /* linegets(buffer,length) access principal */ union { byte type; struct { byte type; byte oldlist,oldprefix; int oldlinnum; FILE *file; } filedesc; struct { byte type; byte oldlist,oldprefix; int oldlinnum; char (*replace)[60]; int numarg; struct macroline *mlineptr; } macrodesc; } source[MAXSOURCEDEEP]; int sourcelevel=-1; int includelevel; #define S_END 0 #define S_FILE 1 #define S_MACRO 2 void linegets(char *buffer, int length) { register int slevel; slevel=sourcelevel; if ( slevel<0 ) { slevel=sourcelevel=0; source[slevel].type = S_FILE; source[slevel].filedesc.file = file; }; while ( source[slevel].type == S_END ) { if ( slevel==0 ) { source[slevel].type = S_FILE; break; }; linenumber=source[slevel].filedesc.oldlinnum; lineprefix=source[slevel].filedesc.oldprefix; asmflags &= ~ F_LIST_ON; if ( source[slevel].filedesc.oldlist ) asmflags |= F_LIST_ON; includelevel--; fclose( source[slevel].filedesc.file ); sourcelevel=--slevel; }; if ( source[slevel].type == S_FILE ) { register char *s1,*s2; buffer[0] = 0; fgets(buffer,length,source[slevel].filedesc.file); s1=s2=buffer; while ( *s1 && *s1!='\n' && s1-bufferline; if (!q) fatal("internal macrocall error"); source[slevel].macrodesc.mlineptr=q->next; while ( *s2 ) { if ( s1-buffer > length-10 ) { warning ( "Too long line" ); break; } if ( *s2 != '\\' ) { *s1++=*s2++; continue; }; s2++; if ( *s2 == '#' ) { s2++; *s1++= numarg+'0'; } else if ( *s2>='1' && *s2<='9' ) { register char *s; s= replace[ *s2-'1' ]; if ( *s2++ <= numarg+'0') while ( *s ) { if (s1-buffer>length-10) break; *s1++=*s++; } } else *s1++='\\'; } *s1=0; } } /* include */ int Xinclude(int modifier, char *label, char *mnemo, char *oper) { FILE *f; register int slevel; if ( !oper) error("no filename"); f=fopen(oper,"r"); if ( f==NULL ) error("can't open include file"); slevel=sourcelevel+1; if ( slevel >= MAXSOURCEDEEP ) fatal ( "too many nested INCLUDEs and MACROs" ); source[slevel].type = S_FILE; source[slevel].filedesc.oldlinnum=linenumber; source[slevel].filedesc.oldprefix=lineprefix; source[slevel].filedesc.oldlist = (asmflags&F_LIST_ON) ? 1 : 0; source[slevel].filedesc.file = f; if ( asmflags & F_LIST_ON ) outputline(); linenumber = 0; sourcelevel=slevel; includelevel++; if ( !(asmflags & F_INCLUDELIST_ON ) ) asmflags &= ~F_LIST_ON; return 0; } /* macrocall */ int thiscall; extern int segment; int macrocall(struct label *labmacro, int status, char *oper) { char replace[9][60]; register int slevel,flag; int numarg,oldsegment,mystatus; jmp_buf errjmpsav; char curlinesav[256]; labmacro->flags |= USED; strcpy(curlinesav,curline); slevel=sourcelevel+1; if ( slevel >= MAXSOURCEDEEP ) fatal ( "too many nested INCLUDEs and MACROs" ); source[slevel].type = S_MACRO; source[slevel].macrodesc.oldlinnum=linenumber; source[slevel].macrodesc.oldprefix=lineprefix; source[slevel].macrodesc.oldlist = (asmflags&F_LIST_ON) ? 1 : 0; numarg=0; oldsegment=segment; while ( oper && *oper ) { char *arg1,*arg2; if ( numarg > 8 ) error ( "Too many arguments in a macro call" ); if ( filter ( oper,"?_,_?",&arg1,&arg2 ) ) { oper = arg2; strncpy(replace[numarg],arg1,59); replace[numarg++][59]=0; } else { strncpy(replace[numarg],oper,59); replace[numarg++][59]=0; oper = NULL; }; }; source[slevel].macrodesc.mlineptr = (struct macroline * ) labmacro->ptr; source[slevel].macrodesc.numarg = numarg; source[slevel].macrodesc.replace = replace; if ( asmflags & F_MACROLIST_ON ) if ( status & 1 ) outputline(); lineprefix = 'M'; sourcelevel=slevel; macrolevel++; segment=++thiscall; mystatus = 2; if ( (asmflags & F_MACROLIST_ON ) ) mystatus |= 1; jmp_buf_copy(errjmpsav,errorjump); do { if (setjmp(errorjump) ) errnumber++; linegets(curline,250); flag=asmline(curline,status & mystatus); } while ( flag == 0 ); macrolevel--; linenumber=source[slevel].filedesc.oldlinnum; lineprefix=source[slevel].filedesc.oldprefix; asmflags &= ~ F_LIST_ON; if ( source[slevel].filedesc.oldlist ) asmflags |= F_LIST_ON; sourcelevel=--slevel; segment=oldsegment; jmp_buf_copy(errorjump,errjmpsav); if ( flag != ENDM && flag != EXITM ) error("ELSE or ENDC illegal here"); if ( !(asmflags & F_MACROLIST_ON ) ) { strcpy(curline,curlinesav); if ( status & 1) outputline(); }; return 0; } crasm/src/operator.c0000700000175000017500000001631412235044650013034 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM: operator.c evaluation d'expressions LYB 9/87 */ #include "dcl.h" #include #include "label.h" /**************************************** Usage general */ static void cst(struct result *presult, long int val) { presult->flags=0; presult->type =L_ABSOLUTE; presult->value=val; } static char overflow[] = "overflow"; static char badtype[] = "illegal operator"; /**************************************** Constantes */ void cstdecimal(struct result *presult, char *s) { register unsigned long val; register int r; val=0; while (*s) { if ( !isdigit(*s) ) error("bad decimal number"); r = *s-'0'; if ( val> 0xffffffff/10 ) error(overflow); val *= 10; if ( val> 0xffffffff-r ) error(overflow); val += r; s++; }; cst (presult,val); } void csthexa(struct result *presult, char *s) { register unsigned long val; register int r; val=0; while (*s) { if ( !isxdigit(*s) ) error("bad hexadecimal number"); if ( *s>='a' ) r = *s-'a'+10; else if (*s>='A' ) r = *s-'A'+10; else r = *s-'0'; if ( val> 0xfffffff ) error(overflow); val = (val<<4)+r; s++; }; cst (presult,val); } void cstoctal(struct result *presult, char *s) { register unsigned long val; register int r; val=0; while (*s) { if ( *s<'0' || *s>'7' ) error("bad octal number"); r = *s-'0'; if ( val> 0x1fffffff ) error(overflow); val = (val<<3)+r; s++; }; cst (presult,val); } void cstbinary(struct result *presult, char *s) { register unsigned long val; register int r; val=0; while (*s) { if ( *s!='1' && *s!='0' ) error("bad binary number"); r = *s-'0'; if ( val> 0xefffffff ) error(overflow); val = (val<<1) + r; s++; }; cst (presult,val); } void cstascii(struct result *presult, char *s) { register unsigned long val; register int r; register char delimit; val=0; delimit=*s; while (*++s != delimit) { if ( !isprint(*s) ) error("bad ascii constant"); r = *s; if ( r == '\\' ) switch(*++s) { case 't': r='\t'; break; case 'n': r='\n'; break; case 'r': r='\r'; break; case '0': r='\0'; break; case '\"': case '\\': case '\'': r=*s; break; default: error("Bad \\X sequence"); }; if ( val> 0xffffff ) error(overflow); val = (val<<8) + r; }; if (*++s) error("syntax error"); cst (presult,val); } void cstlabel(struct result *presult, char *s) { register struct label *q; q=findlabel(s); presult->flags = q->flags; presult->type = q->type; presult->value = q->value; presult->modifier = q->modifier; presult->ptr = q->ptr; if ( (q->flags & UNDEF) && !(q->flags & FORWARD) ) error ("Undefined label"); } /**************************************** Ops monadiques */ void opminus(struct result *presult) { checktype(presult,L_ABSOLUTE); presult->value = -presult->value; } void opnot(struct result *presult) { checktype(presult,L_ABSOLUTE); presult->value = ~presult->value; } /**************************************** Ops diadiques */ void opadd(struct result *presult, struct result *parg) { presult->value += parg->value; presult->flags |= parg->flags; if ( presult->type == L_ABSOLUTE && parg->type == L_ABSOLUTE ) presult->type=L_ABSOLUTE; else if ( ( presult->type == L_ABSOLUTE && parg->type == L_RELATIVE ) || ( presult->type == L_ABSOLUTE && parg->type == L_RELATIVE ) ) presult->type = L_RELATIVE; else error(badtype); } void opsub(struct result *presult, struct result *parg) { presult->flags |= parg->flags; if ( (presult->type == parg->type ) && ( presult->type == L_RELATIVE || presult->type == L_ABSOLUTE ) ) presult->type = L_ABSOLUTE; else if ( presult->type == L_RELATIVE && parg->type == L_ABSOLUTE ) presult->type = L_RELATIVE; else if ( presult->type == L_REGS && parg->type == L_REGS ) { register int lo,hi; lo=hi=0; while ( 1<value && lo < 32 ) lo++; while ( 1<value && hi < 32 ) hi++; if ( hi>31 || hivalue |= 1<type != L_REGS) presult->value -= parg->value; } void opbit(struct result *presult, struct result *parg) { checktype(presult,L_ABSOLUTE); checktype(parg ,L_ABSOLUTE); presult->flags |= parg->flags; presult->type = L_DIRECTBIT; presult->modifier = parg->value; if ( parg->value > 32 ) error(overflow); } void opbitaddr(struct result *presult, struct result *parg) { checktype(presult,L_DIRECTBIT); presult->type=L_ABSOLUTE; presult->modifier=0; } void opbitnumb(struct result *presult, struct result *parg) { checktype(presult,L_DIRECTBIT); presult->type=L_ABSOLUTE; presult->value=presult->modifier; presult->modifier=0; } void opmul(struct result *presult, struct result *parg) { checktype(presult,L_ABSOLUTE); checktype(parg ,L_ABSOLUTE); presult->flags |= parg->flags; presult->value *= parg->value; } void opdiv(struct result *presult, struct result *parg) { presult->flags |= parg->flags; checktype(presult,L_ABSOLUTE); checktype(parg ,L_ABSOLUTE); presult->value /= parg->value; } void oprlist(struct result *presult, struct result *parg) { presult->flags |= parg->flags; checktype(presult,L_REGS); checktype(parg ,L_REGS); presult->value |= parg->value; } void opor(struct result *presult, struct result *parg) { checktype(presult,L_ABSOLUTE); checktype(parg ,L_ABSOLUTE); presult->flags |= parg->flags; presult->value |= parg->value; } void opand(struct result *presult, struct result *parg) { checktype(presult,L_ABSOLUTE); checktype(parg ,L_ABSOLUTE); presult->flags |= parg->flags; presult->value &= parg->value; } void opxor(struct result *presult, struct result *parg) { checktype(presult,L_ABSOLUTE); checktype(parg ,L_ABSOLUTE); presult->flags |= parg->flags; presult->value ^= parg->value; } void oplsh(struct result *presult, struct result *parg) { checktype(presult,L_ABSOLUTE); checktype(parg ,L_ABSOLUTE); presult->flags |= parg->flags; presult->value <<= parg->value; } void oprsh(struct result *presult, struct result *parg) { checktype(presult,L_ABSOLUTE); checktype(parg ,L_ABSOLUTE); presult->flags |= parg->flags; presult->value >>= parg->value; } crasm/src/stdvocabulary.c0000700000175000017500000000441112235044650014056 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* CRASM.C stdvocabulary.c definition des pseudos standard */ #include "dcl.h" #include "label.h" #define defpseudo(n,f,c) {0,0,n,f|NOREDEF,L_MNEMO,0,c}, #define defspecial(n,f,c,m) {0,0,n,f|NOREDEF,L_MNEMO,m,c}, struct label pseudos[] = { defpseudo( "EQU" ,DEFLABEL , Xequ ) defpseudo( "ASC" ,0 , Xasc ) defpseudo( "ALIGN" ,0 , Xalign ) defpseudo( "CLIST" ,NOLABEL , Xclist ) defpseudo( "CODE" ,NOLABEL , Xcode ) defpseudo( "CPU" ,NOLABEL , Xcpu ) defspecial("DB" ,0 , Xdc , 1 ) defspecial("DDB" ,0 , Xdc , 2 ) defspecial("DL" ,0 , Xdc , 4 ) defspecial("DW" ,0 , Xdc , 3 ) defpseudo( "DUMMY" ,NOLABEL , Xdummy ) defpseudo( "DS" ,0 , Xds ) defpseudo( "ELSE" ,NOLABEL | DEFCOND , Xelse ) defpseudo( "ENDC" ,NOLABEL | DEFCOND , Xendc ) defpseudo( "ENDM" ,NOLABEL | DEFMACRO , Xendm ) defpseudo( "EXITM" ,NOLABEL | DEFMACRO , Xexitm ) defpseudo( "FAIL" ,NOLABEL , Xfail ) defpseudo( "IF" ,NOLABEL | DEFCOND , Xif ) defpseudo( "ILIST" ,NOLABEL , Xilist ) defpseudo( "INCLUDE" ,NOLABEL , Xinclude ) defpseudo( "LIST" ,NOLABEL , Xlist ) defpseudo( "MACRO" ,DEFLABEL | DEFMACRO , Xmacro ) defpseudo( "MLIST" ,NOLABEL , Xmlist ) defpseudo( "NAM" ,NOLABEL , Xnam ) defpseudo( "PAGE" ,NOLABEL , Xpage ) defpseudo( "OUTPUT" ,NOLABEL , Xoutput ) defpseudo( "SKIP" ,NOLABEL , Xskip ) {(void*)-1,(void*)-1} }; crasm/src/cpuz80.c0000700000175000017500000003474612235044650012343 0ustar cmbcmb/* Copyright (C) 1987- Leon Bottou * * This is free documentation; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * The GNU General Public License's references to "object code" * and "executables" are to be interpreted as the output of any * document formatting or typesetting system, including * intermediate and printed output. * * This manual is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this manual. Otherwise check the web site * of the Free Software Foundation at http://www.fsf.org. */ /* Z80 */ #include "cpu.h" static int offset,offsetflag,indexflag; static int arg, arg8flag, arg16flag; #define isreg8(n) (n>=0 && n<8) /* registres a 8 bits */ #define isreg16(n) (n>=8 && n<16) /* registres a 16 bits */ #define isspecialreg(b) (n>=16) /* registres speciaux */ #define IX 0xdd #define IY 0xfd #define HL 0xff #define ACCUMULATOR 7 #define MREGISTER 6 #define HLREGISTER 10 #define MEMORY -1 #define IMDATA -2 #define SPBC -4 #define SPDE -5 #define CLRALL indexflag=offsetflag=arg8flag=arg16flag=0 static char *needreg8 = "operates with reg8 or (HL),(IX+nn),(IY+nn)"; static char *needacc = "operates on A only"; static char *badop = "illegal addressing mode"; /* GETREG prend un registre ou un mode d'addressage */ static char *indexed[] = { "(_IX_)", "(_IY_)", "(_IX_+_?_)", "(_IY_+_?_)", "(_IX_-_?_)", "(_IY_-_?_)" }; static int getreg(char *oper) { register struct result *r; register int i; char *oper2; for (i=0; i<6; i++) if (filter (oper,indexed[i],&oper2)) { offset = 0; if ( i>1) { r=parse(oper2); checktype(r,L_ABSOLUTE); offset = r->value; if (i>3) offset = -offset; }; if (indexflag || offsetflag ) error(badop); offsetflag=TRUE; indexflag = i&1 ? IY : IX; return MREGISTER; }; if (filter(oper,"(_HL_)")) { if (indexflag && indexflag != HL) error(badop); indexflag=HL; return MREGISTER; } if (filter(oper,"(_BC_)")) return SPBC; if (filter(oper,"(_DE_)")) return SPDE; if (filter(oper,"(_?_)",&oper2)) { r=parse(oper2); checktype(r,L_ABSOLUTE); if (arg8flag || arg16flag) error(badop); arg16flag=TRUE; arg=r->value; return MEMORY; } r=parse(oper); if (r->type == L_ABSOLUTE) { if (arg8flag || arg16flag) error(badop); arg16flag=TRUE; arg=r->value; return IMDATA; }; checktype(r,L_REGS); if ( r->value != (1 << r->modifier) ) error ("illegal register list"); if (r->modifier==12 || r->modifier==13 || r->modifier==HLREGISTER ) { switch (r->modifier) { case 12: i=IX; break; case 13: i=IY; break; default: i=HL; break; } if (indexflag && indexflag != i) error(badop); indexflag=i; return HLREGISTER; } return r->modifier; } static int docode(int code) { if (indexflag==IX || indexflag==IY || offsetflag ) insert8(indexflag); if (code & 0xff00) insert8(code>>8); else insert8(code); if (offsetflag) { insert8(offset); if (offset != (byte) offset) warning ("offset overflow"); } if (code & 0xff00) insert8(code); if (arg8flag) { insert8(arg); if (arg & 0xff00) warning ("argument overflow"); } else if (arg16flag) insert16(arg); return 0; } static int relbranch(int code, char *label, char *mnemo, char *oper) /* relative branchs */ { byte d; int dd; extern long pc; struct result *r; r=parse(oper); /* operand search */ checktype(r,L_ABSOLUTE); /* is it a number? */ dd=r->value-pc-2; /* displacement calc */ d=dd; /* -> signed byte */ insert8(code); /* generate code */ insert8(dd); if ( d!=dd ) /* test operand after: */ error ("too long branch"); /* if an error occurs during */ return 0; /* the first pass, branch is */ } /* always too bytes long */ /* IMPORTANT: * * You had better generate code before signaling errors about * * the operand values. So the first pass calculates right * * forward references even when a ghost error occurs. */ static int simple(int code, char *label, char *mnemo, char *oper) /* simple instruction */ { if (code & 0xff00) insert8(code>>8); insert8(code); if (oper) /* no operand ! */ error ("no operands allowed"); return 0; } static int im(int code, char *label, char *mnemo, char *oper) { register struct result *r; r=parse(oper); checktype(r,L_ABSOLUTE); switch (r->value) { case 0: insert16(0x46ed); break; case 1: insert16(0x56ed); break; case 2: insert16(0x5eed); break; default: insert16(0); error( "Bad interruption mode" ); } return 0; } static int rst(int code, char *label, char *mnemo, char *oper) { register struct result *r; r=parse(oper); checktype(r,L_ABSOLUTE); if (! (r->value & 0xfff8)) r->value <<= 3; insert8( 0xc7 | r->value ); if ( r->value & 0xffc7 ) error("Bad RST vector"); return 0; } static char *condcodes[] = { "NZ","Z","NC","C","PO","PE","P","M",NULL }; static int searchcond(int maxcond, char *oper, char **pres) { register char **q; char *ccode; if ( filter(oper,"?_,_?",&ccode,pres) ) { for ( q=condcodes; maxcond--; q++ ) if ( filter( ccode,*q) ) return q-condcodes; error ("Bad condition code"); } *pres=oper; return -1; } static int jr(int code, char *label, char *mnemo, char *oper) { char *operand2; code=0x20+ ( searchcond(4,oper,&operand2) << 3 ); return relbranch(code,label,mnemo,operand2); } static int ret(int code, char *label, char *mnemo, char *oper) { register char **q; if ( !oper || !*oper ) insert8(0xc9); else { for ( q=condcodes; *q; q++ ) if ( filter( oper,*q) ) { insert8(0xc0+ ((q-condcodes)<<3) ); return 0; } error ("Bad condition code"); } return 0; } static int call(int code, char *label, char *mnemo, char *oper) { char *operand2; register int cond; register struct result *r; cond = searchcond(8,oper,&operand2) << 3; r=parse(operand2); checktype(r,L_ABSOLUTE); if (cond >=0 ) insert8 (0xc4 + cond ); else insert8 (0xcd ); insert16 (r->value); return 0; } static int jp(int code, char *label, char *mnemo, char *oper) { char *operand2; register int cond; register struct result *r; CLRALL; if ( filter (oper,"(_?_)",&operand2) ) { if (getreg(operand2) == HLREGISTER) docode(0xe9); else error("illegal indirection"); } else { cond = searchcond(8,oper,&operand2) << 3; r=parse(operand2); checktype(r,L_ABSOLUTE); if (cond >=0 ) insert8 (0xc2 + cond ); else insert8 (0xc3 ); insert16 (r->value); } return 0; } static int ex(int code, char *label, char *mnemo, char *oper) { char *oper2; CLRALL; if (filter (oper,"DE_,_HL") || filter (oper,"HL_,_DE")) return docode(0xeb); if ( filter(oper, "(_SP_)_,_?" , &oper2) || filter(oper, "?_,_(_SP_)" , &oper2) ) if ( getreg(oper2)==HLREGISTER ) return docode(0xe3); /* EX AF,AF' ' is a special filter char. So, if there is one in OPER, then OPER is OPER+SPACES+REMARK... We have to manage with */ if ( filter(oper,"AF_,_AF'_?",&oper2 ) || filter(oper,"AF'_,_AF_?",&oper2 ) ) if ( oper2==NULL || !*oper2 || *oper2==';' ) return docode(0x08); error("Illegal EX instruction"); return 0; } static int inout(int code, char *label, char *mnemo, char *oper) { char *op1,*op2; register int reg; CLRALL; if ( (!(code & 8)) ? filter(oper,"(?)_,_?",&op1,&op2) : filter(oper,"?_,_(?)",&op2,&op1) ) { reg=getreg(op1); if (reg==IMDATA) { reg=getreg(op2); if (reg != ACCUMULATOR ) error(needacc); arg8flag=TRUE; docode(code); } else if ( reg==1 ) { reg=getreg(op2); if ( !isreg8(reg) || reg==6 ) error("operates on reg8 only"); reg <<= 3; if (! (code & 8)) reg += 1; docode(0xed40+reg); } else error("port is (C) or (nn)"); } else error(badop); return 0; } static int bitop(int code, char *label, char *mnemo, char *oper) { register struct result *r; char *oper1,*oper2; register int bit,reg; CLRALL; if ( !filter(oper,"?_,_?",&oper1,&oper2)) error("two operands required"); r=parse(oper1); checktype(r,L_ABSOLUTE); bit=r->value; if (bit <0 || bit >7 ) error("illegal bit number"); reg=getreg(oper2); if (! isreg8(reg) ) error(needreg8); docode(code+reg+(bit<<3)); return 0; } static int onreg8(int code, char *label, char *mnemo, char *oper) { register int reg; CLRALL; reg=getreg(oper); if (!isreg8(reg)) error(needreg8); return docode(code+reg); } static int logical(int code, char *label, char *mnemo, char *oper) { register int reg; char *op1,*op2; CLRALL; if (filter (oper,"?_,_?",&op1,&op2) ) { if (getreg(op1) != ACCUMULATOR) error(needacc); oper=op2; warning("One operand only. but i understand!"); } reg=getreg(oper); if (reg == IMDATA) { reg=0x46; arg8flag=TRUE; } return docode(code+reg); } static int stackop(int code, char *label, char *mnemo, char *oper) { register int reg; CLRALL; reg=getreg(oper); if (reg==19) reg=11; else if (reg==11) reg=19; if (!isreg16(reg)) error("Operates with AF,BC,DE,HL,IX,IY"); return docode(code+ (reg<<4) ); } static int arith(int code, char *label, char *mnemo, char *oper) { register int reg; char *op1,*op2; CLRALL; if (!filter(oper,"?_,_?",&op1,&op2)) error(badop); reg=getreg(op1); if (reg==ACCUMULATOR) logical(code,label,mnemo,op2); else if (reg==HLREGISTER) { if ( indexflag!=HL && code != 0x80 ) error("illegal index operation"); switch(code) { case 0x80: code=0x09 -0x80; break; case 0x88: code=0xed4a-0x80; break; case 0x98: code=0xed42-0x80; break; }; reg=getreg(op2); if (!isreg16(reg) ) error(badop); docode(code+ (reg<<4) ); } else error(badop); return 0; } static int incr(int code, char *label, char *mnemo, char *oper) { register int reg; CLRALL; reg=getreg(oper); if (isreg8(reg)) { code >>=8; docode( (reg<<3) + code); } else if (isreg16(reg)) { code &= 0xff; reg -=8; docode(code+ (reg<<4)); } else error(badop); return 0; } static int ld(int code, char *label, char *mnemo, char *oper) { register int reg1,reg2; char *op1,*op2; if (!filter(oper,"?_,_?",&op1,&op2)) error(badop); CLRALL; reg1=getreg(op1); reg2=getreg(op2); if ( isreg8(reg1) ) { if ( isreg8(reg2) ) { if (reg1==reg2 && reg1==MREGISTER) error(badop); return docode( 0x40+ (reg1<<3) + reg2 ); } if ( reg2==IMDATA ) { arg8flag=TRUE; return docode( 0x06 + (reg1<<3) ); }; if (reg1 == ACCUMULATOR) { if ( reg2 == MEMORY ) return docode(0x3a); if ( reg2 == SPBC ) return docode(0x0a); if ( reg2 == SPDE ) return docode(0x1a); if ( reg2 == 17 ) return docode(0xed57); if ( reg2 == 18 ) return docode(0xed5f); }; }; if ( isreg16(reg1) ) { if (reg2 == IMDATA) return docode( 0x01 + ( (reg1-8)<<4 ) ); if (reg2 == MEMORY ) { if (reg1 == HLREGISTER ) return docode(0x2a); else return docode(0xed4b+ ((reg1-8)<<4) ); }; if (reg2 == HLREGISTER && reg1 == 11 ) return docode(0xf9); } if ( reg1 == MEMORY ) { if (reg2 == ACCUMULATOR ) return docode(0x32); if (reg2 == HLREGISTER ) return docode(0x22); if ( isreg16(reg2) ) return docode(0xed43+ ((reg2-8)<<4) ); }; if ( reg2 == ACCUMULATOR ) { if (reg1 == SPBC) return docode(0x02); if (reg1 == SPDE) return docode(0x12); if (reg1 == 17) return docode(0xed47); if (reg1 == 18) return docode(0xed4f); } error(badop); return 0; } startmnemos(mz80) /* Z80 mnemonics */ regs ("a", 7) /* registres */ regs ("b", 0) regs ("c", 1) regs ("d", 2) regs ("e", 3) regs ("h", 4) regs ("l", 5) regs ("bc", 8) regs ("de", 9) regs ("hl", 10) regs ("sp", 11) regs ("ix", 12) regs ("iy", 13) regs ("f", 16) regs ("i", 17) regs ("r", 18) regs ("af", 19) mnemo ("ccf", simple, 0x3f ) /* instructions without oper */ mnemo ("cpd", simple, 0xeda9) mnemo ("cpdr", simple, 0xed89) mnemo ("cpi", simple, 0xeda1) mnemo ("cpir", simple, 0xedb1) mnemo ("cpl", simple, 0x2f ) mnemo ("daa", simple, 0x27 ) mnemo ("exx", simple, 0xd9 ) mnemo ("halt", simple, 0x76 ) mnemo ("ind", simple, 0xedaa) mnemo ("indr", simple, 0xedba) mnemo ("ini", simple, 0xeda2) mnemo ("inir", simple, 0xedb2) mnemo ("di", simple, 0xf3 ) mnemo ("ei", simple, 0xfb ) mnemo ("ldd", simple, 0xeda8) mnemo ("lddr", simple, 0xedb8) mnemo ("ldi", simple, 0xeda0) mnemo ("ldir", simple, 0xedb0) mnemo ("neg", simple, 0xed44) mnemo ("nop", simple, 0x00 ) mnemo ("otdr", simple, 0xedbb) mnemo ("otir", simple, 0xedb3) mnemo ("outd", simple, 0xedab) mnemo ("outi", simple, 0xeda3) mnemo ("reti", simple, 0xed4d) mnemo ("retn", simple, 0xed45) mnemo ("rla", simple, 0x17 ) mnemo ("rlca", simple, 0x07 ) mnemo ("rld", simple, 0xed6f) mnemo ("rra", simple, 0x1f ) mnemo ("rrca", simple, 0x0f ) mnemo ("rrd", simple, 0xed67) mnemo ("scf", simple, 0x37 ) mnemo ("im", im, 0 ) /* Specials */ mnemo ("rst", rst, 0 ) mnemo ("djnz", relbranch, 0x10 ) mnemo ("jr", jr, 0 ) mnemo ("jp", jp, 0 ) mnemo ("call", call, 0 ) mnemo ("ret" , ret, 0 ) mnemo ("ex", ex, 0 ) mnemo ("in", inout, 0xdb ) mnemo ("out", inout, 0xd3 ) mnemo ("bit", bitop, 0xcb40) /* Quasi regulars */ mnemo ("set", bitop, 0xcbc0) mnemo ("res", bitop, 0xcb80) mnemo ("sla", onreg8, 0xcb20) mnemo ("sra", onreg8, 0xcb28) mnemo ("srl", onreg8, 0xcb38) mnemo ("rl", onreg8, 0xcb10) mnemo ("rr", onreg8, 0xcb18) mnemo ("rlc", onreg8, 0xcb00) mnemo ("rrc", onreg8, 0xcb08) mnemo ("or", logical, 0xb0 ) mnemo ("and", logical, 0xa0 ) mnemo ("xor", logical, 0xa8 ) mnemo ("sub", logical, 0x90 ) mnemo ("cp", logical, 0xb8 ) mnemo ("push", stackop, 0xc5-0x80) mnemo ("pop", stackop, 0xc1-0x80) mnemo ("adc", arith, 0x88) /* no index */ mnemo ("sbc", arith, 0x98) /* no index */ mnemo ("add", arith, 0x80) /* index ok */ mnemo ("inc", incr, 0x0403) /* (*8) */ mnemo ("dec", incr, 0x050b) mnemo ("ld", ld, 0) /* heavy magic !! */ endmnemos void initz80(int code) { setflag( F_CODE_HEX ); /* Intel hex by default */ setflag( F_ADDR16 ); /* 16 bits address */ setflag( F_LOHI ); /* LSB first */ clrflag( F_RELATIF ); /* no translatable code */ bindvocabulary(mz80); /* add Z80 mnemos */ } crasm/crasm.html0000600000175000017500000003775712143653424012261 0ustar cmbcmbManpage of CRASM

CRASM

Cross assembler for 6800/6801/6803/6502/65C02/Z80.

SourceForge.net Logo   Summary   Download   Examples


 

SYNOPSIS

crasm [-o codefile] [-slx] asmfile

Assemble the microprocessor program asmfile and produce output file codefile in Intel HEX or Motorola S Code format. A program listing and a symbol table are also produced on the standard output. The current version of crasm can assemble programs for the 6800, 6801, 6803, 6502, 65C02, and Z80 processors. The full list is printed when you invoke crasm without arguments.

 

OPTIONS

-o codefile
Specify the name of the output file. No output file is produced without this option.
-s
Disable warnings.
-l
Disable program listing output.
-x
Disable symbol table output.

 

SYNTAX

Each line of the assembly program should follow one of the following templates, where the brackets delimit optional parts.

[;comment]
label = expression [;comment]
[label] mnemonic operand [;comment]

Comments are introduced by a semicolon (;) and extend to the end of the line. Labels are identifiers containing up to 36 alphanumeric characters (including period and underscore). Labels cannot start with a digit. The format of the mnemonics and operands field depends on the selected micro-processor. A few mnemonics are valid for all processors and are used to give directives to the assembled. These are known as "pseudo-mnemonics".

 

Labels

Labels are identifiers representing
- an absolute address,
- a relative address (position independent code),
- a register,
- a list of registers,
- a specific bit at a specific address,
- or a mnemonic.

Most labels are composed of at most 36 alphanumeric characters, periods (.) or underscores (_). Labels cannot start with a digit. They are case insensitive.

Labels starting with a period (.) are local labels whose scope is either limited to the macro in which they are defined, or to the code segment delimited by the pseudo-mnemonics CODE or DUMMY.

The predefined "star" label (*) represents the current program counter, that is to say, the address where the next assembly code instruction will be encoded. Other predefined labels include all pseudo-mnemonics, micro-processor specific mnemonics and register names.

 

Constants

The assembled recognizes numerical constants expressed in decimal, hexadecimal, octal, binary, or ascii.

TypeFormatExamples
decimaldddd1234, 675, 12, 1, but not 0.12.
hexadecimal$dddd$fd12, $2AC, $0.
ddddH03H, 2da7H, 0FC84H, but not FC84H.
0Xdddd0x03, 0x2AC, 0Xfc84.
octalddddQ377Q, 012412Q.
binary%dddd%01110110, %1100.
ddddB01110110B, 1100B.
0Bdddd0b1100
ascii'cccc''a', 'AB', '"', '\n', '\''.
"cccc""a", "AB", "'", "\n", "\"".

 

Expressions

Like labels, expressions can represent an absolute address (abs), a relative address for position independent code (rel), a register (reg), or a list of registers (reglist), or a reference to a specific bit at a specific address (bspec).

The following operators are recognized on expressions.

SyntaxResultDescription
abs{abs}bspecbit reference, e.g. pia{3}
ADDR(abs)absaddress from a bit reference
BIT(abs)absbit number from a bit reference
absabstwo's complement
absabsone's complement
abs << absabsleft shift
abs >> absabsright shift
abs | absabsbitwise or
abs & absabsbitwise and
abs ^ absabsbitwise xor
abs * absabsmultiplication
abs * absabsdivision
abs + absabsaddition
rel + absreladdition
abs - absabssubtraction
rel - absrelsubtraction
rel - relrelsubtraction
reg - regreglistregister range
reglist \ regreglistregister list construction

The table lists operators in order of decreasing precedence. Parenthesis can be used to avoid ambiguities. A warning is generated when an entire expression is surrounded with parenthesis and can be confused with a micro-processor addressing mode.

Examples:

(base+$12) >> 8 & 0xff00
'A'-80H
(base+0x12)

The last example causes a warning because the parenthesis were not necessary and might suggest a micro-processor addressing mode.

All arithmetic expressions are evaluated on 32 bits. Arithmetic operations overflow silently. The arithmetic values are then truncated to the size implied by the micro-processor mnemonic. This truncation might cause a warning message.

Examples: all the following instructions

(6502) lda #$1234
(6800) ldaa $1234,x
(Z80)  ld (ix+0C2H),b

cause a warning

>>> WARNING: Operand overflow

However expression

$1123454 * 1298992

overflows silently.

 

Pseudo-mnemonics

The following pseudo-mnemonics are always recognized.

CPU cpuname
Indicates the selected micro-processor type. This must appear before anu micro-processor specific instruction. The possible values of cpuname are listed when you invoke crasm without arguments. The current list includes 6800, 6801, 6803, 6502, 65C02, and Z80

OUTPUT binformat
Indicates the format of the output file. Argument binformat can take values SCODE for producing an output file using Motorola's S code, or HEX for Intel's Hex format. The default depends on the selected micro-processor.

CODE
Delimit the scope of local labels and introduce a program section.

DUMMY
Delimit the scope of local labels and introduce a fake program section whose sole effect is to define labels without generating code.

label EQU expression
label = expression
Define the value of label label. Labels defined using these directives can be redefined later in the program.

[label] DB expression[,...,expression]
Insert the specified data bytes (8 bits).

[label] DW expression[,...,expression]
Insert the specified data words (16 bits). The byte ordering depends on the selected micro-processor.

[label] DL expression[,...,expression]
Insert the specified data longs (32 bits). The byte ordering depends on the selected micro-processor.

[label] DDB expression[,...,expression]
Insert the specified double bytes (16 bits). The byte ordering is the opposite of the usual byte ordering for the selected micro-processor.

[label] ASC stringconstant
Insert the ascii representation of the string stringconstant . The string must be delimited by double quotes. The C escape sequences \r, \n, \t, \0, \', \", and \\ are recognized.

[label] DS countexpr,[valexpr]
Insere countexpr bytes with value valexpr. The default value is zero.

[label] ALIGN EVEN
[label] ALIGN ODD
Insert a null byte in order to make the program counter even or odd.

IF condexpr
 ...
ELSE
 ...
ENDC
Conditional assembly: If expression condexpr is non zero, process the lines located between the IF and the ELSE pseudo-mnemonics. Otherwise process the lines located between the ELSE and the ENDC pseudo-mnemonics. Conditional assembly instructions can be nested. The ELSE part can be omitted.

label MACRO
        ...
ENDM
Define a new mnemonic label equivalent to all the instructions located between the MACRO and ENDM pseudo-mnemonics. Invocations of the macro can specify a list of comma separated operands. The character sequences \1, \2, ... \N in the macro definition are replaced by the supplied operands. The character sequence \0 is replaced by the number of supplied operands.

EXITM
This pseudo mnemonic can be used inside a macro definition to exit the macro. This is useful in conjunction with the conditional assembly pseudo-mnemonics.

INCLUDE filename
Force the assembler to process file named filename at the current point.

LIST ON
LIST OFF
Enable or disable the production of a listing (default is on.)

CLIST ON
CLIST OFF
Enable or disable the production of a listing for the non active branches of a conditional assembly construct (default is on.)

ILIST ON
ILIST OFF
Enable or disable the production of a listing for included files (default is off.)

MLIST ON
MLIST OFF
Enable or disable the production of a listing for the macro expansions (default is off.)

NAM title
Provide name title for the header of the listing pages.

PAGE
Start a new listing page.

PAGE columns,rows
Specify the size of a listing page.

SKIP number
Skip number lines.

FAIL message
Generate an error message message.

 

EXAMPLE

Here is a small 6502 program:

              cpu 6502
          cout = $fded ; display a character
             * = $300  ; assemble at $300
               code
          pstring  ldy #0
          .1       lda message,y
                   beq .2
                   jsr cout
                   iny
          .2       bne .1
                   rts
          message  asc "This is the message "
               code

Assembling this program gives the following listing:

Crasm LYB 1.3:                                                   page  1

                         1
                         2              cpu 6502
  FDED                   3            cout = $fded ; display a character
  0300                   4               * = $300  ; assemble at $300
                         5                 code
0300 A000                6            pstring  ldy #0
0302 B90E03              7            .1       lda message,y
0305 E004                8                     beq .2
0307 20EDFD              9                     jsr cout
030A C8                 10                     iny
030B D0F5               11            .2       bne .1
030D 60                 12                     rts
030E 54686973206973
0315 20746865206D65
031C 737361676500       13            message  asc "This is the message\0"
                        14                 code
                        15

ERRORS:       0
WARNINGS:     0

Successful assembly...
 Last address      321 (801)
 Code length        44 (68)



Crasm LYB 1.3:                                                   page  2

 FDED   Abs COUT
^030E   Abs MESSAGE
?0300   Abs PSTRING
and the following S Code file:
S1130300A000B90E03E00420EDFDC8D0F5605468E8
S1130310697320697320746865206D657373616700
S1050320650072
S9030000FC
 

CREDITS

Leon Bottou, September 1987.


 

Index

SYNOPSIS
OPTIONS
SYNTAX
Labels
Constants
Expressions
Pseudo-mnemonics
EXAMPLE
CREDITS
crasm/README0000600000175000017500000000074312235465054011131 0ustar cmbcmbCRASM is a portable cross-assembler for the 6800, 6801, 6803, 6502, 65C02, and Z80. Changelog: 1.7: Fixed handling of extended ASCII characters in input files (Windows-specific) Fixed uninitialized memory in label array (was sometimes causing "too far branch" errors) 1.6: Fixed mishandled SUBD immediate (6801/6803) Fixed incorrect opcodes for MUL and RTI (6801/6803) Fixed documentation for DS pseudo Updated version number in page headers on output crasm/crasm.10000600000175000017500000002710412143653424011436 0ustar cmbcmb.\" Copyright (C) 1987- Leon Bottou .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual. Otherwise check the web site .\" of the Free Software Foundation at http://www.fsf.org. .\" .TH CRASM 1 "1/9/1987" "Crasm-1.3" "Crasm-1.3" .de SS .SH \\0\\0\\0\\$* .. .SH NAME crasm \- Cross assembler for 6800/6801/6803/6502/65C02/Z80 .SH SYNOPSIS .BI "crasm [-o " "codefile" "] [-slx] " "asmfile" Assemble the microprocessor program .I asmfile and produce output file .I codefile in Intel HEX or Motorola S Code format. A program listing and a symbol table are also produced on the standard output. The current version of .B crasm can assemble programs for the .BR 6800, .BR 6801, .BR 6803, .BR 6502, .BR 65C02, and .BR Z80 processors. The full list is printed when you invoke .B crasm without arguments. .SH OPTIONS .TP .BI "-o " codefile Specify the name of the output file. No output file is produced without this option. .TP .BI "-s" Disable warnings. .TP .BI "-l" Disable program listing output. .TP .BI "-x" Disable symbol table output. .PP .SH SYNTAX Each line of the assembly program should follow one of the following templates, where the brackets delimit optional parts. .IP "" .BI "[;" comment "]" .br .BI "" label " = " expression " [;" comment "]" .br .BI "[" label "] " mnemonic " " operand " [;" comment "]" .PP Comments are introduced by a semicolon .BR "" "(" ";" ")" and extend to the end of the line. Labels are identifiers containing up to 36 alphanumeric characters (including period and underscore). Labels cannot start with a digit. The format of the mnemonics and operands field depends on the selected micro-processor. A few mnemonics are valid for all processors and are used to give directives to the assembled. These are known as "pseudo-mnemonics". .SS Labels Labels are identifiers representing .br \(em an absolute address, .br \(em a relative address (position independent code), .br \(em a register, .br \(em a list of registers, .br \(em a specific bit at a specific address, .br \(em or a mnemonic. .PP Most labels are composed of at most 36 alphanumeric characters, periods .BR "" "(" "." ")" or underscores .BR "" "(" "_" ")." Labels cannot start with a digit. They are case insensitive. .PP Labels starting with a period .BR "" "(" "." ")" are local labels whose scope is either limited to the macro in which they are defined, or to the code segment delimited by the pseudo-mnemonics .B CODE or .BR DUMMY . .PP The predefined "star" label .BR "" "(" "*" ")" represents the current program counter, that is to say, the address where the next assembly code instruction will be encoded. Other predefined labels include all pseudo-mnemonics, micro-processor specific mnemonics and register names. .SS Constants The assembled recognizes numerical constants expressed in decimal, hexadecimal, octal, binary, or ascii. .PP .TS center,box; lfB lfB lfB l l l l l l l l l l l l l l l l l l l l l l l l l l l . Type Format Examples = decimal \fIdddd \fB1234\fR,\fB 675\fR,\fB 12\fR,\fB 1\fR, but not \fB0.12\fR. = hexadecimal \fB$\fIdddd \fB$fd12\fR,\fB $2AC\fR,\fB $0\fR. \fIdddd\fBH\fR \fB03H\fR,\fB 2da7H\fR,\fB 0FC84H\fR, but not \fBFC84H\fR. \fB0X\fIdddd \fB0x03\fR,\fB 0x2AC\fR,\fB 0Xfc84\fR. = octal \fIdddd\fBQ\fR \fB377Q\fR,\fB 012412Q\fR. = binary \fB%\fIdddd \fB%01110110\fR,\fB %1100\fR. \fIdddd\fBB\fR \fB01110110B\fR,\fB 1100B\fR. \fB0B\fIdddd \fB0b1100\fR = ascii \fB'\fIcccc\fB'\fR \fB'a'\fR,\fB 'AB'\fR,\fB '"'\fR,\fB '\\n'\fR,\fB '\\''\fR. \fB"\fIcccc\fB"\fR \fB"\\t"\fR,\fB "\\""\fR,\fB "a'b"\fR. .TE .PP .SS Expressions Like labels, expressions can represent an absolute address .RI ( abs ), a relative address for position independent code .RI ( rel ), a register .RI ( reg ), or a list of registers .RI ( reglist ), or a reference to a specific bit at a specific address .RI ( bspec ). The following operators are recognized on expressions. .TS center,box; lfB lfB lfB l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l . Syntax Result Description = \fIabs\fB{\fIabs\fB}\fR \fIbspec\fR bit reference, e.g. \fBpia{3}\fR \fBADDR(\fIabs\fB)\fR \fIabs\fR address from a bit reference \fBBIT(\fIabs\fB)\fR \fIabs\fR bit number from a bit reference = \fB- \fIabs \fIabs\fR two's complement \fB~ \fIabs \fIabs\fR one's complement = \fIabs\fB << \fIabs\fR \fIabs\fR left shift \fIabs\fB >> \fIabs\fR \fIabs\fR right shift = \fIabs\fB | \fIabs\fR \fIabs\fR bitwise or \fIabs\fB & \fIabs\fR \fIabs\fR bitwise and \fIabs\fB ^ \fIabs\fR \fIabs\fR bitwise xor = \fIabs\fB * \fIabs\fR \fIabs\fR multiplication \fIabs\fB * \fIabs\fR \fIabs\fR division = \fIabs\fB + \fIabs\fR \fIabs\fR addition \fIrel\fB + \fIabs\fR \fIrel\fR addition \fIabs\fB - \fIabs\fR \fIabs\fR subtraction \fIrel\fB - \fIabs\fR \fIrel\fR subtraction \fIrel\fB - \fIrel\fR \fIabs\fR subtraction = \fIreg\fB - \fIreg\fR \fIreglist\fR register range \fIreglist\fB \\ \fIreg\fR \fIreglist\fR register list .TE .PP The table lists operators in order of decreasing precedence. Parenthesis can be used to avoid ambiguities. A warning is generated when an entire expression is surrounded with parenthesis and can be confused with a micro-processor addressing mode. .PP Examples: .IP "" \fB (base+$12) >> 8 & 0xff00 \fR .br \fB 'A'-80H \fR .br \fB (base+0x12) \fR .PP The last example causes a warning because the parenthesis were not necessary and might suggest a micro-processor addressing mode. .PP All arithmetic expressions are evaluated on 32 bits. Arithmetic operations overflow silently. The arithmetic values are then truncated to the size implied by the micro-processor mnemonic. This truncation might cause a warning message. Examples: all the following instructions .IP "" (6502) \fBlda #$1234\fR .br (6800) \fBldaa $1234,x\fR .br (Z80) \fBld (ix+0C2H),b\fR .PP cause a warning .IP "" .B >>> WARNING: Operand overflow .PP However expression .IP "" .B $1123454 * 1298992 .PP overflows silently. .SS Pseudo-mnemonics The following pseudo-mnemonics are always recognized. .PP .BI "CPU " cpuname .in +7n Indicates the selected micro-processor type. This must appear before anu micro-processor specific instruction. The possible values of .I cpuname are listed when you invoke .B crasm without arguments. The current list includes .BR 6800, .BR 6801, .BR 6803, .BR 6502, .BR 65C02, and .BR Z80 .in -7n .PP .BI "OUTPUT " binformat .in +7n Indicates the format of the output file. Argument .I binformat can take values .B SCODE for producing an output file using Motorola's S code, or .B HEX for Intel's Hex format. The default depends on the selected micro-processor. .in -7n .PP .BI CODE .in +7n Delimit the scope of local labels and introduce a program section. .TP .BI DUMMY Delimit the scope of local labels and introduce a fake program section whose sole effect is to define labels without generating code. .in -7n .PP .BI "" label " EQU " expression .br .BI "" label " = " expression .in +7n Define the value of label .IR label . Labels defined using these directives can be redefined later in the program. .in -7n .PP .BI "[" label "] DB " expression "[,...," expression "]" .in +7n Insert the specified data bytes (8 bits). .in -7n .PP .BI "[" label "] DW " expression "[,...," expression "]" .in +7n Insert the specified data words (16 bits). The byte ordering depends on the selected micro-processor. .in -7n .PP .BI "[" label "] DL " expression "[,...," expression "]" .in +7n Insert the specified data longs (32 bits). The byte ordering depends on the selected micro-processor. .in -7n .PP .BI "[" label "] DDB " expression "[,...," expression "]" .in +7n Insert the specified double bytes (16 bits). The byte ordering is the opposite of the usual byte ordering for the selected micro-processor. .in -7n .PP .BI "[" label "] ASC " stringconstant .in +7n Insert the ascii representation of the string .I stringconstant . The string must be delimited by double quotes. The C escape sequences \fB\\r\fR, \fB\\n\fR, \fB\\t\fR, \fB\\0\fR, \fB\\'\fR, \fB\\"\fR, and \fB\\\\\fR are recognized. .in -7n .PP .BI "[" label "] DS " countexpr ",[" valexpr "]" .in +7n Insere .I countexpr bytes with value .IR valexpr . The default value is zero. .in -7n .PP .BI "[" label "] ALIGN EVEN" .br .BI "[" label "] ALIGN ODD" .in +7n Insert a null byte in order to make the program counter even or odd. .in -7n .PP .BI "IF " condexpr .br ... .br .BI "ELSE" .br ... .br .BI "ENDC" .in +7n Conditional assembly: If expression .I condexpr is non zero, process the lines located between the .B IF and the .BR ELSE pseudo-mnemonics. Otherwise process the lines located between the .B ELSE and the .BR ENDC pseudo-mnemonics. Conditional assembly instructions can be nested. The .B ELSE part can be omitted. .in -7n .PP .BI "" "label" " MACRO" .br ... .br .BI " ENDM" .br .in +7n Define a new mnemonic .I label equivalent to all the instructions located between the .B MACRO and .B ENDM pseudo-mnemonics. Invocations of the macro can specify a list of comma separated operands. The character sequences \fB\\1\fR, \fB\\2\fR, ... \fB\\\fIN\fR in the macro definition are replaced by the supplied operands. The character sequence \fB\\0\fR is replaced by the number of supplied operands. .in -7n .PP .BI "EXITM" .in +7n This pseudo mnemonic can be used inside a macro definition to exit the macro. This is useful in conjunction with the conditional assembly pseudo-mnemonics. .in -7n .PP .BI "INCLUDE " filename .in +7n Force the assembler to process file named .I filename at the current point. .in -7n .PP .BR "LIST ON" .br .BR "LIST OFF" .in +7n Enable or disable the production of a listing (default is on.) .in -7n .PP .BR "CLIST ON" .br .BR "CLIST OFF" .in +7n Enable or disable the production of a listing for the non active branches of a conditional assembly construct (default is on.) .in -7n .PP .BR "ILIST ON" .br .BR "ILIST OFF" .in +7n Enable or disable the production of a listing for included files (default is off.) .in -7n .PP .BR "MLIST ON" .br .BR "MLIST OFF" .in +7n Enable or disable the production of a listing for the macro expansions (default is off.) .in -7n .PP .BR "NAM " title .in +7n Provide name .I title for the header of the listing pages. .in -7n .PP .BR "PAGE" .in +7n Start a new listing page. .in -7n .PP .BR "PAGE " columns "," rows .in +7n Specify the size of a listing page. .in -7n .PP .BR "SKIP " number .in +7n Skip .I number lines. .in -7n .PP .BR "FAIL " message .in +7n Generate an error message .IR message . .in -7n .PP .SH EXAMPLE .PP Here is a small 6502 program: .IP "" 2 \fB cpu 6502 .br cout = $fded ; display a character .br * = $300 ; assemble at $300 .br code .br pstring ldy #0 .br .1 lda message,y .br beq .2 .br jsr cout .br iny .br .2 bne .1 .br rts .br message asc "This is the message\0" .br code \fR .PP .SH CREDITS Leon Bottou, September 1987.